summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rwxr-xr-xbin/syncqt.pl7
-rw-r--r--config.tests/common/aesni/aesni.cpp49
-rw-r--r--config.tests/common/aesni/aesni.pro3
-rw-r--r--config.tests/common/rdrnd/rdrnd.cpp56
-rw-r--r--config.tests/common/rdrnd/rdrnd.pro3
-rw-r--r--config.tests/common/shani/shani.cpp50
-rw-r--r--config.tests/common/shani/shani.pro3
-rw-r--r--config.tests/qpa/vulkan/vulkan.cpp58
-rw-r--r--config.tests/qpa/vulkan/vulkan.pro1
-rw-r--r--config.tests/unix/cxx11_random/cxx11_random.cpp (renamed from src/tools/uic/cpp/cppextractimages.h)43
-rw-r--r--config.tests/unix/cxx11_random/cxx11_random.pro1
-rw-r--r--config.tests/unix/futimens/futimens.cpp47
-rw-r--r--config.tests/unix/futimens/futimens.pro1
-rw-r--r--config.tests/unix/futimes/futimes.cpp47
-rw-r--r--config.tests/unix/futimes/futimes.pro1
-rw-r--r--config.tests/unix/getauxval/getauxval.cpp (renamed from src/tools/uic/cpp/cppwriteicondeclaration.h)41
-rw-r--r--config.tests/unix/getauxval/getauxval.pro1
-rw-r--r--config.tests/unix/getentropy/getentropy.cpp (renamed from src/tools/uic/cpp/cppwriteicondeclaration.cpp)44
-rw-r--r--config.tests/unix/getentropy/getentropy.pro1
-rw-r--r--config.tests/unix/opengles32/opengles32.cpp47
-rw-r--r--config.tests/unix/opengles32/opengles32.pro7
-rw-r--r--config.tests/unix/openssl11/openssl.cpp48
-rw-r--r--config.tests/unix/openssl11/openssl.pro2
-rw-r--r--config.tests/x11/xrender/xrender.cpp52
-rw-r--r--config.tests/x11/xrender/xrender.pro3
-rw-r--r--configure.json48
-rw-r--r--doc/global/config.qdocconf4
-rw-r--r--doc/global/qt-cpp-defines.qdocconf1
-rw-r--r--examples/dbus/remotecontrolledcar/car/car.cpp8
-rw-r--r--examples/embedded/lightmaps/lightmaps.cpp6
-rw-r--r--examples/embedded/lightmaps/slippymap.cpp14
-rw-r--r--examples/embedded/raycasting/raycasting.cpp7
-rw-r--r--examples/examples.pro6
-rw-r--r--examples/opengl/hellowindow/hellowindow.cpp27
-rw-r--r--examples/opengl/hellowindow/hellowindow.h2
-rw-r--r--examples/opengl/legacy/framebufferobject2/glwidget.cpp5
-rw-r--r--examples/opengl/legacy/grabber/glwidget.cpp16
-rw-r--r--examples/opengl/legacy/pbuffers2/glwidget.cpp35
-rw-r--r--examples/opengl/legacy/samplebuffers/glwidget.cpp26
-rw-r--r--examples/opengl/qopenglwidget/glwidget.cpp32
-rw-r--r--examples/opengl/qopenglwidget/main.cpp2
-rw-r--r--examples/opengl/qopenglwindow/background.frag2
-rw-r--r--examples/opengl/threadedqopenglwidget/glwidget.cpp26
-rw-r--r--examples/sql/doc/src/drilldown.qdoc2
-rw-r--r--examples/touch/pinchzoom/mouse.cpp15
-rw-r--r--examples/vulkan/doc/images/hellovulkancubes.pngbin0 -> 98495 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkantexture.pngbin0 -> 10259 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkantriangle.pngbin0 -> 30952 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkanwidget.pngbin0 -> 25256 bytes
-rw-r--r--examples/vulkan/doc/images/hellovulkanwindow.pngbin0 -> 2736 bytes
-rw-r--r--examples/vulkan/doc/src/hellovulkancubes.qdoc58
-rw-r--r--examples/vulkan/doc/src/hellovulkantexture.qdoc41
-rw-r--r--examples/vulkan/doc/src/hellovulkantriangle.qdoc49
-rw-r--r--examples/vulkan/doc/src/hellovulkanwidget.qdoc49
-rw-r--r--examples/vulkan/doc/src/hellovulkanwindow.qdoc101
-rw-r--r--examples/vulkan/hellovulkancubes/camera.cpp112
-rw-r--r--examples/vulkan/hellovulkancubes/camera.h80
-rw-r--r--examples/vulkan/hellovulkancubes/color.frag12
-rw-r--r--examples/vulkan/hellovulkancubes/color.vert14
-rw-r--r--examples/vulkan/hellovulkancubes/color_frag.spvbin0 -> 616 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong.frag39
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong.vert32
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong_frag.spvbin0 -> 3364 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/color_phong_vert.spvbin0 -> 2268 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/color_vert.spvbin0 -> 744 bytes
-rw-r--r--examples/vulkan/hellovulkancubes/hellovulkancubes.pro24
-rw-r--r--examples/vulkan/hellovulkancubes/hellovulkancubes.qrc10
-rw-r--r--examples/vulkan/hellovulkancubes/main.cpp92
-rw-r--r--examples/vulkan/hellovulkancubes/mainwindow.cpp117
-rw-r--r--examples/vulkan/hellovulkancubes/mainwindow.h83
-rw-r--r--examples/vulkan/hellovulkancubes/mesh.cpp98
-rw-r--r--examples/vulkan/hellovulkancubes/mesh.h79
-rw-r--r--examples/vulkan/hellovulkancubes/renderer.cpp1048
-rw-r--r--examples/vulkan/hellovulkancubes/renderer.h158
-rw-r--r--examples/vulkan/hellovulkancubes/shader.cpp94
-rw-r--r--examples/vulkan/hellovulkancubes/shader.h77
-rw-r--r--examples/vulkan/hellovulkancubes/vulkanwindow.cpp134
-rw-r--r--examples/vulkan/hellovulkancubes/vulkanwindow.h85
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.cpp828
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.h108
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.pro7
-rw-r--r--examples/vulkan/hellovulkantexture/hellovulkantexture.qrc7
-rw-r--r--examples/vulkan/hellovulkantexture/main.cpp91
-rw-r--r--examples/vulkan/hellovulkantexture/qt256.pngbin0 -> 6208 bytes
-rw-r--r--examples/vulkan/hellovulkantexture/texture.frag12
-rw-r--r--examples/vulkan/hellovulkantexture/texture.vert18
-rw-r--r--examples/vulkan/hellovulkantexture/texture_frag.spvbin0 -> 556 bytes
-rw-r--r--examples/vulkan/hellovulkantexture/texture_vert.spvbin0 -> 968 bytes
-rw-r--r--examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro12
-rw-r--r--examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc6
-rw-r--r--examples/vulkan/hellovulkantriangle/main.cpp100
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp185
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.h100
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro16
-rw-r--r--examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc6
-rw-r--r--examples/vulkan/hellovulkanwidget/main.cpp112
-rw-r--r--examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp128
-rw-r--r--examples/vulkan/hellovulkanwindow/hellovulkanwindow.h77
-rw-r--r--examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro6
-rw-r--r--examples/vulkan/hellovulkanwindow/main.cpp (renamed from src/corelib/doc/snippets/signalmapper/filereader.cpp)90
-rw-r--r--examples/vulkan/shared/block.bufbin0 -> 4256 bytes
-rw-r--r--examples/vulkan/shared/block.txt100
-rw-r--r--examples/vulkan/shared/color.frag10
-rw-r--r--examples/vulkan/shared/color.vert18
-rw-r--r--examples/vulkan/shared/color_frag.spvbin0 -> 496 bytes
-rw-r--r--examples/vulkan/shared/color_vert.spvbin0 -> 960 bytes
-rw-r--r--examples/vulkan/shared/objconvert.js241
-rw-r--r--examples/vulkan/shared/qt_logo.bufbin0 -> 125600 bytes
-rw-r--r--examples/vulkan/shared/qt_logo.txt2912
-rw-r--r--examples/vulkan/shared/trianglerenderer.cpp513
-rw-r--r--examples/vulkan/shared/trianglerenderer.h85
-rw-r--r--examples/vulkan/vulkan.pro10
-rw-r--r--examples/widgets/animation/stickman/stickman.cpp10
-rw-r--r--examples/widgets/doc/src/painterpaths.qdoc11
-rw-r--r--examples/widgets/doc/src/tablet.qdoc13
-rw-r--r--examples/widgets/effects/blurpicker/blurpicker.cpp9
-rw-r--r--examples/widgets/effects/lighting/lighting.cpp7
-rw-r--r--examples/widgets/graphicsview/boxes/glbuffers.cpp4
-rw-r--r--examples/widgets/graphicsview/boxes/scene.cpp5
-rw-r--r--examples/widgets/graphicsview/boxes/scene.h2
-rw-r--r--examples/widgets/graphicsview/boxes/trackball.cpp8
-rw-r--r--examples/widgets/graphicsview/collidingmice/mouse.cpp15
-rw-r--r--examples/widgets/graphicsview/diagramscene/arrow.cpp17
-rw-r--r--examples/widgets/graphicsview/elasticnodes/edge.cpp28
-rw-r--r--examples/widgets/itemviews/chart/pieview.cpp12
-rw-r--r--examples/widgets/itemviews/storageview/storagemodel.cpp30
-rw-r--r--examples/widgets/mainwindows/mainwindow/mainwindow.cpp1
-rw-r--r--examples/widgets/painting/composition/composition.cpp2
-rw-r--r--examples/widgets/painting/painterpaths/window.cpp10
-rw-r--r--examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp8
-rw-r--r--examples/widgets/widgets/tablet/tabletcanvas.cpp52
-rw-r--r--examples/widgets/widgets/tablet/tabletcanvas.h2
-rw-r--r--examples/xml/dombookmarks/mainwindow.cpp44
-rw-r--r--examples/xml/dombookmarks/mainwindow.h9
-rw-r--r--examples/xml/dombookmarks/xbeltree.cpp74
-rw-r--r--examples/xml/dombookmarks/xbeltree.h11
-rw-r--r--examples/xml/saxbookmarks/mainwindow.cpp67
-rw-r--r--examples/xml/saxbookmarks/mainwindow.h13
-rw-r--r--examples/xml/saxbookmarks/xbelgenerator.cpp18
-rw-r--r--examples/xml/saxbookmarks/xbelgenerator.h6
-rw-r--r--examples/xml/saxbookmarks/xbelhandler.cpp28
-rw-r--r--examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc2
-rw-r--r--examples/xml/streambookmarks/mainwindow.cpp75
-rw-r--r--examples/xml/streambookmarks/mainwindow.h13
-rw-r--r--examples/xml/streambookmarks/xbelreader.cpp36
-rw-r--r--examples/xml/streambookmarks/xbelreader.h4
-rw-r--r--examples/xml/streambookmarks/xbelwriter.cpp29
-rw-r--r--examples/xml/streambookmarks/xbelwriter.h6
-rw-r--r--mkspecs/common/gcc-base.conf3
-rw-r--r--mkspecs/common/linux.conf1
-rw-r--r--mkspecs/common/msvc-desktop.conf3
-rw-r--r--mkspecs/common/msvc-version.conf1
-rw-r--r--mkspecs/common/qcc-base.conf2
-rw-r--r--mkspecs/common/windows-vulkan.conf5
-rw-r--r--mkspecs/common/winrt_winphone/qmake.conf2
-rw-r--r--mkspecs/devices/linux-rasp-pi-g++/qmake.conf5
-rw-r--r--mkspecs/devices/linux-tinkerboard-g++/qmake.conf20
-rw-r--r--mkspecs/devices/linux-tinkerboard-g++/qplatformdefs.h40
-rw-r--r--mkspecs/features/ctest_testcase_common.prf16
-rw-r--r--mkspecs/features/qmltestcase.prf20
-rw-r--r--mkspecs/features/qt_common.prf5
-rw-r--r--mkspecs/features/qt_module.prf2
-rw-r--r--mkspecs/features/qt_module_headers.prf29
-rw-r--r--mkspecs/features/simd.prf3
-rw-r--r--mkspecs/features/uic.prf4
-rw-r--r--mkspecs/features/uikit/bitcode.prf2
-rw-r--r--mkspecs/features/uikit/default_post.prf2
-rw-r--r--mkspecs/features/uikit/default_pre.prf4
-rw-r--r--mkspecs/features/uikit/watchos_coretext.prf15
-rw-r--r--mkspecs/features/unix/separate_debug_info.prf12
-rw-r--r--mkspecs/linux-icc-k1om/qmake.conf21
-rw-r--r--mkspecs/linux-icc-k1om/qplatformdefs.h40
-rw-r--r--mkspecs/linux-icc/qmake.conf3
-rw-r--r--mkspecs/macx-icc/qmake.conf3
-rw-r--r--mkspecs/win32-g++/qmake.conf3
-rw-r--r--mkspecs/win32-icc-k1om/qmake.conf15
-rw-r--r--mkspecs/win32-icc-k1om/qplatformdefs.h40
-rw-r--r--mkspecs/win32-icc/qmake.conf3
-rw-r--r--qmake/Makefile.unix356
-rw-r--r--qmake/Makefile.unix.unix2
-rw-r--r--qmake/Makefile.unix.win322
-rw-r--r--qmake/Makefile.win324
-rw-r--r--qmake/doc/src/qmake-manual.qdoc22
-rw-r--r--qmake/generators/win32/msvc_objectmodel.cpp2
-rw-r--r--qmake/generators/win32/msvc_vcproj.cpp2
-rw-r--r--qmake/library/proitems.h1
-rw-r--r--qmake/library/qmakebuiltins.cpp63
-rw-r--r--qmake/library/qmakeevaluator.cpp6
-rw-r--r--qmake/option.cpp17
-rw-r--r--qmake/project.cpp4
-rw-r--r--qmake/qmake.pri9
-rw-r--r--src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro16
-rw-r--r--src/3rdparty/iaccessible2/generated/x86/ia2_api_all.h4
-rw-r--r--src/3rdparty/iaccessible2/generated/x86/ia2_api_all_i.c6
-rw-r--r--src/3rdparty/icc/LICENSE.txt10
-rw-r--r--src/3rdparty/icc/qt_attribution.json15
-rw-r--r--src/3rdparty/icc/sRGB2014.iccbin0 -> 3024 bytes
-rw-r--r--src/3rdparty/sqlite.pri2
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java33
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java44
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java1
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java8
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java72
-rw-r--r--src/android/templates/AndroidManifest.xml2
-rw-r--r--src/corelib/codecs/qtextcodec.cpp49
-rw-r--r--src/corelib/codecs/qtextcodec.h13
-rw-r--r--src/corelib/configure.json69
-rw-r--r--src/corelib/corelib.pro2
-rw-r--r--src/corelib/debug_script.py98
-rw-r--r--src/corelib/doc/snippets/code/doc_src_qpair.cpp7
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qlocale.cpp17
-rw-r--r--src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp5
-rw-r--r--src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp16
-rw-r--r--src/corelib/doc/snippets/qstring/main.cpp17
-rw-r--r--src/corelib/doc/snippets/qversionnumber/main.cpp8
-rw-r--r--src/corelib/doc/src/objectmodel/signalsandslots.qdoc22
-rw-r--r--src/corelib/global/global.pri20
-rw-r--r--src/corelib/global/minimum-linux.S105
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h6
-rw-r--r--src/corelib/global/qendian.h235
-rw-r--r--src/corelib/global/qendian.qdoc369
-rw-r--r--src/corelib/global/qendian_p.h142
-rw-r--r--src/corelib/global/qfloat16.cpp24
-rw-r--r--src/corelib/global/qglobal.cpp307
-rw-r--r--src/corelib/global/qglobal.h48
-rw-r--r--src/corelib/global/qlogging.cpp28
-rw-r--r--src/corelib/global/qnamespace.h9
-rw-r--r--src/corelib/global/qnamespace.qdoc19
-rw-r--r--src/corelib/global/qnumeric.h18
-rw-r--r--src/corelib/global/qnumeric_p.h54
-rw-r--r--src/corelib/global/qrandom.cpp1049
-rw-r--r--src/corelib/global/qrandom.h154
-rw-r--r--src/corelib/global/qrandom_p.h (renamed from src/corelib/tools/qpodlist_p.h)71
-rw-r--r--src/corelib/global/qtypeinfo.h10
-rw-r--r--src/corelib/io/io.pri8
-rw-r--r--src/corelib/io/qabstractfileengine.cpp46
-rw-r--r--src/corelib/io/qabstractfileengine_p.h9
-rw-r--r--src/corelib/io/qdatastream.cpp1
-rw-r--r--src/corelib/io/qdatastream.h5
-rw-r--r--src/corelib/io/qdebug.cpp15
-rw-r--r--src/corelib/io/qdebug.h3
-rw-r--r--src/corelib/io/qfile.cpp114
-rw-r--r--src/corelib/io/qfile.h1
-rw-r--r--src/corelib/io/qfiledevice.cpp70
-rw-r--r--src/corelib/io/qfiledevice.h11
-rw-r--r--src/corelib/io/qfileinfo.cpp162
-rw-r--r--src/corelib/io/qfileinfo.h11
-rw-r--r--src/corelib/io/qfileinfo_p.h25
-rw-r--r--src/corelib/io/qfilesystemengine.cpp222
-rw-r--r--src/corelib/io/qfilesystemengine_p.h9
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp616
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp317
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h59
-rw-r--r--src/corelib/io/qfsfileengine.cpp35
-rw-r--r--src/corelib/io/qfsfileengine_p.h2
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp151
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp56
-rw-r--r--src/corelib/io/qlockfile_unix.cpp12
-rw-r--r--src/corelib/io/qprocess.cpp90
-rw-r--r--src/corelib/io/qprocess.h1
-rw-r--r--src/corelib/io/qprocess_p.h6
-rw-r--r--src/corelib/io/qprocess_unix.cpp129
-rw-r--r--src/corelib/io/qprocess_win.cpp127
-rw-r--r--src/corelib/io/qresource.cpp50
-rw-r--r--src/corelib/io/qsavefile.cpp39
-rw-r--r--src/corelib/io/qsettings.cpp80
-rw-r--r--src/corelib/io/qsettings.h2
-rw-r--r--src/corelib/io/qsettings_p.h3
-rw-r--r--src/corelib/io/qstandardpaths.cpp6
-rw-r--r--src/corelib/io/qstandardpaths_unix.cpp8
-rw-r--r--src/corelib/io/qstandardpaths_win.cpp10
-rw-r--r--src/corelib/io/qstorageinfo.cpp35
-rw-r--r--src/corelib/io/qstorageinfo.h7
-rw-r--r--src/corelib/io/qtemporarydir.cpp83
-rw-r--r--src/corelib/io/qtemporaryfile.cpp319
-rw-r--r--src/corelib/io/qtemporaryfile.h4
-rw-r--r--src/corelib/io/qtemporaryfile_p.h34
-rw-r--r--src/corelib/io/qtextstream.cpp3
-rw-r--r--src/corelib/io/qtldurl.cpp42
-rw-r--r--src/corelib/io/qwindowspipereader.cpp13
-rw-r--r--src/corelib/io/qwindowspipewriter.cpp8
-rw-r--r--src/corelib/io/qwindowspipewriter_p.h1
-rw-r--r--src/corelib/io/qwinoverlappedionotifier.cpp428
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp385
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.h4
-rw-r--r--src/corelib/itemmodels/qstringlistmodel.cpp2
-rw-r--r--src/corelib/json/qjson.cpp13
-rw-r--r--src/corelib/json/qjson_p.h129
-rw-r--r--src/corelib/json/qjsonarray.cpp21
-rw-r--r--src/corelib/json/qjsonarray.h22
-rw-r--r--src/corelib/json/qjsondocument.cpp74
-rw-r--r--src/corelib/json/qjsondocument.h23
-rw-r--r--src/corelib/json/qjsonobject.cpp22
-rw-r--r--src/corelib/json/qjsonobject.h21
-rw-r--r--src/corelib/json/qjsonvalue.cpp78
-rw-r--r--src/corelib/json/qjsonvalue.h29
-rw-r--r--src/corelib/kernel/kernel.pri3
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.cpp3
-rw-r--r--src/corelib/kernel/qabstracteventdispatcher.h2
-rw-r--r--src/corelib/kernel/qcore_mac.cpp10
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm79
-rw-r--r--src/corelib/kernel/qcore_mac_p.h56
-rw-r--r--src/corelib/kernel/qcore_unix.cpp33
-rw-r--r--src/corelib/kernel/qcore_unix_p.h24
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp62
-rw-r--r--src/corelib/kernel/qcoreapplication.h1
-rw-r--r--src/corelib/kernel/qcoreapplication_p.h10
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp60
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h1
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp67
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h2
-rw-r--r--src/corelib/kernel/qfunctions_fake_env_p.h2
-rw-r--r--src/corelib/kernel/qjnihelpers.cpp40
-rw-r--r--src/corelib/kernel/qjnihelpers_p.h16
-rw-r--r--src/corelib/kernel/qmath.h24
-rw-r--r--src/corelib/kernel/qmath.qdoc19
-rw-r--r--src/corelib/kernel/qmetaobject.cpp99
-rw-r--r--src/corelib/kernel/qmetaobject_p.h3
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder.cpp36
-rw-r--r--src/corelib/kernel/qmetaobjectbuilder_p.h3
-rw-r--r--src/corelib/kernel/qmetatype.cpp1
-rw-r--r--src/corelib/kernel/qmetatype.h47
-rw-r--r--src/corelib/kernel/qobject.cpp2
-rw-r--r--src/corelib/kernel/qobject.h4
-rw-r--r--src/corelib/kernel/qobject_impl.h78
-rw-r--r--src/corelib/kernel/qobject_p.h3
-rw-r--r--src/corelib/kernel/qobjectdefs.h89
-rw-r--r--src/corelib/kernel/qobjectdefs_impl.h94
-rw-r--r--src/corelib/kernel/qsignalmapper.cpp8
-rw-r--r--src/corelib/kernel/qsignalmapper.h6
-rw-r--r--src/corelib/kernel/qtimer.h8
-rw-r--r--src/corelib/kernel/qvariant.cpp162
-rw-r--r--src/corelib/kernel/qvariant_p.h10
-rw-r--r--src/corelib/kernel/qwineventnotifier.cpp60
-rw-r--r--src/corelib/kernel/qwineventnotifier_p.h (renamed from src/corelib/io/qwinoverlappedionotifier_p.h)47
-rw-r--r--src/corelib/mimetypes/qmimeprovider.cpp8
-rw-r--r--src/corelib/mimetypes/qmimeprovider_p.h2
-rw-r--r--src/corelib/mimetypes/qmimetype.cpp90
-rw-r--r--src/corelib/mimetypes/qmimetype.h18
-rw-r--r--src/corelib/mimetypes/qmimetypeparser.cpp1
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp8
-rw-r--r--src/corelib/plugin/quuid.cpp313
-rw-r--r--src/corelib/plugin/quuid.h3
-rw-r--r--src/corelib/thread/qmutex.cpp2
-rw-r--r--src/corelib/thread/qresultstore.h2
-rw-r--r--src/corelib/thread/qsemaphore.cpp153
-rw-r--r--src/corelib/thread/qsemaphore.h39
-rw-r--r--src/corelib/thread/qthread.cpp47
-rw-r--r--src/corelib/thread/qthread.h124
-rw-r--r--src/corelib/thread/qthread_p.h4
-rw-r--r--src/corelib/thread/qthread_unix.cpp151
-rw-r--r--src/corelib/thread/qthread_win.cpp4
-rw-r--r--src/corelib/thread/qthreadpool.cpp33
-rw-r--r--src/corelib/thread/qthreadpool.h4
-rw-r--r--src/corelib/thread/qthreadpool_p.h12
-rw-r--r--src/corelib/tools/qbytearray.cpp100
-rw-r--r--src/corelib/tools/qbytearray.h85
-rw-r--r--src/corelib/tools/qchar.cpp23
-rw-r--r--src/corelib/tools/qchar.h7
-rw-r--r--src/corelib/tools/qdatetime.cpp198
-rw-r--r--src/corelib/tools/qdatetime.h9
-rw-r--r--src/corelib/tools/qdatetimeparser.cpp1005
-rw-r--r--src/corelib/tools/qdatetimeparser_p.h40
-rw-r--r--src/corelib/tools/qhash.cpp178
-rw-r--r--src/corelib/tools/qhash.h11
-rw-r--r--src/corelib/tools/qhashfunctions.h8
-rw-r--r--src/corelib/tools/qiterator.h151
-rw-r--r--src/corelib/tools/qlinkedlist.h4
-rw-r--r--src/corelib/tools/qlist.h6
-rw-r--r--src/corelib/tools/qlocale.cpp443
-rw-r--r--src/corelib/tools/qlocale.h36
-rw-r--r--src/corelib/tools/qlocale.qdoc2
-rw-r--r--src/corelib/tools/qlocale_data_p.h9174
-rw-r--r--src/corelib/tools/qlocale_mac.mm4
-rw-r--r--src/corelib/tools/qlocale_p.h62
-rw-r--r--src/corelib/tools/qlocale_win.cpp6
-rw-r--r--src/corelib/tools/qmap.cpp67
-rw-r--r--src/corelib/tools/qmap.h10
-rw-r--r--src/corelib/tools/qrect.h2
-rw-r--r--src/corelib/tools/qregularexpression.cpp172
-rw-r--r--src/corelib/tools/qregularexpression.h15
-rw-r--r--src/corelib/tools/qringbuffer_p.h2
-rw-r--r--src/corelib/tools/qscopedpointer.cpp6
-rw-r--r--src/corelib/tools/qscopedpointer.h13
-rw-r--r--src/corelib/tools/qsimd_p.h10
-rw-r--r--src/corelib/tools/qstring.cpp1410
-rw-r--r--src/corelib/tools/qstring.h243
-rw-r--r--src/corelib/tools/qstringalgorithms.h82
-rw-r--r--src/corelib/tools/qstringalgorithms_p.h8
-rw-r--r--src/corelib/tools/qstringbuilder.h7
-rw-r--r--src/corelib/tools/qstringiterator.qdoc8
-rw-r--r--src/corelib/tools/qstringiterator_p.h10
-rw-r--r--src/corelib/tools/qstringlist.cpp34
-rw-r--r--src/corelib/tools/qstringlist.h7
-rw-r--r--src/corelib/tools/qstringliteral.h128
-rw-r--r--src/corelib/tools/qstringview.cpp777
-rw-r--r--src/corelib/tools/qstringview.h305
-rw-r--r--src/corelib/tools/qtimezone.cpp7
-rw-r--r--src/corelib/tools/qtimezone.h8
-rw-r--r--src/corelib/tools/qtimezoneprivate.cpp2
-rw-r--r--src/corelib/tools/qtimezoneprivate_data_p.h5
-rw-r--r--src/corelib/tools/qtimezoneprivate_icu.cpp5
-rw-r--r--src/corelib/tools/qtimezoneprivate_mac.mm88
-rw-r--r--src/corelib/tools/qtimezoneprivate_tz.cpp40
-rw-r--r--src/corelib/tools/qtimezoneprivate_win.cpp2
-rw-r--r--src/corelib/tools/qvarlengtharray.h5
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc6
-rw-r--r--src/corelib/tools/qvector.h9
-rw-r--r--src/corelib/tools/qvector.qdoc7
-rw-r--r--src/corelib/tools/qversionnumber.cpp53
-rw-r--r--src/corelib/tools/qversionnumber.h4
-rw-r--r--src/corelib/tools/tools.pri5
-rw-r--r--src/corelib/xml/qxmlstream.cpp70
-rw-r--r--src/corelib/xml/qxmlstream.g105
-rw-r--r--src/corelib/xml/qxmlstream_p.h73
-rw-r--r--src/corelib/xml/qxmlutils.cpp37
-rw-r--r--src/corelib/xml/qxmlutils_p.h7
-rw-r--r--src/dbus/qdbusserver.cpp8
-rw-r--r--src/gui/configure.json54
-rw-r--r--src/gui/doc/qtgui.qdocconf1
-rw-r--r--src/gui/doc/src/external-resources.qdoc10
-rw-r--r--src/gui/doc/src/qtgui.qdoc35
-rw-r--r--src/gui/gui.pro1
-rw-r--r--src/gui/image/qbmphandler.cpp4
-rw-r--r--src/gui/image/qicon.cpp7
-rw-r--r--src/gui/image/qiconloader.cpp14
-rw-r--r--src/gui/image/qiconloader_p.h3
-rw-r--r--src/gui/image/qimage.cpp43
-rw-r--r--src/gui/image/qimage.h7
-rw-r--r--src/gui/image/qimage_conversions.cpp64
-rw-r--r--src/gui/image/qimage_darwin.mm2
-rw-r--r--src/gui/image/qimage_p.h4
-rw-r--r--src/gui/image/qimagereader.cpp11
-rw-r--r--src/gui/image/qimagewriter.cpp10
-rw-r--r--src/gui/image/qimagewriter.h3
-rw-r--r--src/gui/image/qmovie.cpp48
-rw-r--r--src/gui/image/qmovie.h2
-rw-r--r--src/gui/image/qpicture.cpp2
-rw-r--r--src/gui/image/qpicture.h12
-rw-r--r--src/gui/image/qpixmap.cpp71
-rw-r--r--src/gui/image/qpixmap_blitter.cpp4
-rw-r--r--src/gui/image/qplatformpixmap.cpp76
-rw-r--r--src/gui/image/qplatformpixmap.h8
-rw-r--r--src/gui/image/qxpmhandler.cpp5
-rw-r--r--src/gui/kernel/qclipboard.cpp2
-rw-r--r--src/gui/kernel/qcursor.cpp48
-rw-r--r--src/gui/kernel/qcursor.h4
-rw-r--r--src/gui/kernel/qdnd.cpp5
-rw-r--r--src/gui/kernel/qdnd_p.h1
-rw-r--r--src/gui/kernel/qevent.cpp6
-rw-r--r--src/gui/kernel/qguiapplication.cpp109
-rw-r--r--src/gui/kernel/qguiapplication_p.h1
-rw-r--r--src/gui/kernel/qkeysequence.cpp18
-rw-r--r--src/gui/kernel/qkeysequence_p.h2
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp20
-rw-r--r--src/gui/kernel/qoffscreensurface.h3
-rw-r--r--src/gui/kernel/qopenglcontext.cpp55
-rw-r--r--src/gui/kernel/qopenglcontext.h7
-rw-r--r--src/gui/kernel/qpalette.cpp8
-rw-r--r--src/gui/kernel/qplatformcursor.cpp41
-rw-r--r--src/gui/kernel/qplatformcursor.h17
-rw-r--r--src/gui/kernel/qplatformdialoghelper.cpp26
-rw-r--r--src/gui/kernel/qplatformdialoghelper.h5
-rw-r--r--src/gui/kernel/qplatformdrag.h1
-rw-r--r--src/gui/kernel/qplatformintegration.cpp31
-rw-r--r--src/gui/kernel/qplatformintegration.h10
-rw-r--r--src/gui/kernel/qplatformmenu.cpp31
-rw-r--r--src/gui/kernel/qplatformmenu.h18
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon.cpp11
-rw-r--r--src/gui/kernel/qplatformsystemtrayicon.h2
-rw-r--r--src/gui/kernel/qplatformtheme.cpp4
-rw-r--r--src/gui/kernel/qplatformtheme.h3
-rw-r--r--src/gui/kernel/qplatformwindow.cpp29
-rw-r--r--src/gui/kernel/qplatformwindow.h4
-rw-r--r--src/gui/kernel/qscreen.cpp4
-rw-r--r--src/gui/kernel/qsimpledrag.cpp7
-rw-r--r--src/gui/kernel/qsimpledrag_p.h1
-rw-r--r--src/gui/kernel/qstylehints.cpp11
-rw-r--r--src/gui/kernel/qstylehints.h2
-rw-r--r--src/gui/kernel/qsurface.cpp2
-rw-r--r--src/gui/kernel/qsurface.h1
-rw-r--r--src/gui/kernel/qsurfaceformat.cpp69
-rw-r--r--src/gui/kernel/qsurfaceformat.h9
-rw-r--r--src/gui/kernel/qwindow.cpp298
-rw-r--r--src/gui/kernel/qwindow.h10
-rw-r--r--src/gui/kernel/qwindow_p.h12
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp57
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h29
-rw-r--r--src/gui/kernel/qwindowsysteminterface_p.h12
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp6
-rw-r--r--src/gui/math3d/qquaternion.cpp4
-rw-r--r--src/gui/opengl/qopengl.h4
-rw-r--r--src/gui/opengl/qopenglextrafunctions.h496
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp582
-rw-r--r--src/gui/opengl/qopengltexture.cpp50
-rw-r--r--src/gui/opengl/qopengltexture.h9
-rw-r--r--src/gui/painting/painting.pri3
-rw-r--r--src/gui/painting/qbackingstore.cpp129
-rw-r--r--src/gui/painting/qbackingstore.h4
-rw-r--r--src/gui/painting/qbrush.cpp2
-rw-r--r--src/gui/painting/qcolor.cpp33
-rw-r--r--src/gui/painting/qcolor.h16
-rw-r--r--src/gui/painting/qcompositionfunctions.cpp792
-rw-r--r--src/gui/painting/qcoregraphics.mm2
-rw-r--r--src/gui/painting/qcosmeticstroker.cpp2
-rw-r--r--src/gui/painting/qdrawhelper.cpp670
-rw-r--r--src/gui/painting/qdrawhelper_avx2.cpp2
-rw-r--r--src/gui/painting/qdrawhelper_p.h4
-rw-r--r--src/gui/painting/qdrawhelper_sse2.cpp4
-rw-r--r--src/gui/painting/qemulationpaintengine.cpp84
-rw-r--r--src/gui/painting/qgrayraster.c809
-rw-r--r--src/gui/painting/qpagedpaintdevice.cpp12
-rw-r--r--src/gui/painting/qpagedpaintdevice.h2
-rw-r--r--src/gui/painting/qpaintengine.cpp8
-rw-r--r--src/gui/painting/qpaintengine_p.h25
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp10
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h2
-rw-r--r--src/gui/painting/qpainter.cpp8
-rw-r--r--src/gui/painting/qpdf.cpp305
-rw-r--r--src/gui/painting/qpdf.qrc7
-rw-r--r--src/gui/painting/qpdf_p.h11
-rw-r--r--src/gui/painting/qpdfa_metadata.xml16
-rw-r--r--src/gui/painting/qpdfwriter.cpp31
-rw-r--r--src/gui/painting/qpdfwriter.h3
-rw-r--r--src/gui/painting/qplatformbackingstore.cpp45
-rw-r--r--src/gui/painting/qplatformbackingstore.h5
-rw-r--r--src/gui/painting/qpolygon.cpp43
-rw-r--r--src/gui/painting/qpolygon.h4
-rw-r--r--src/gui/text/qdistancefield.cpp12
-rw-r--r--src/gui/text/qfont.cpp5
-rw-r--r--src/gui/text/qfont.h8
-rw-r--r--src/gui/text/qfontengine.cpp4
-rw-r--r--src/gui/text/qfontengine_p.h6
-rw-r--r--src/gui/text/qfontmetrics.cpp2
-rw-r--r--src/gui/text/qfontsubset.cpp8
-rw-r--r--src/gui/text/qstatictext.h2
-rw-r--r--src/gui/text/qtextdocument.cpp2
-rw-r--r--src/gui/text/qtextdocument_p.cpp2
-rw-r--r--src/gui/text/qtextengine.cpp87
-rw-r--r--src/gui/text/qtextengine_p.h17
-rw-r--r--src/gui/text/qtextformat.cpp34
-rw-r--r--src/gui/text/qtexthtmlparser.cpp14
-rw-r--r--src/gui/text/qtexthtmlparser_p.h1
-rw-r--r--src/gui/text/qtextlayout.cpp58
-rw-r--r--src/gui/text/qtextoption.cpp33
-rw-r--r--src/gui/text/qtextoption.h14
-rw-r--r--src/gui/util/qshaderformat.cpp130
-rw-r--r--src/gui/util/qshaderformat_p.h109
-rw-r--r--src/gui/util/qshadergenerator.cpp351
-rw-r--r--src/gui/util/qshadergenerator_p.h75
-rw-r--r--src/gui/util/qshadergraph.cpp262
-rw-r--r--src/gui/util/qshadergraph_p.h123
-rw-r--r--src/gui/util/qshadergraphloader.cpp251
-rw-r--r--src/gui/util/qshadergraphloader_p.h99
-rw-r--r--src/gui/util/qshaderlanguage.cpp56
-rw-r--r--src/gui/util/qshaderlanguage_p.h163
-rw-r--r--src/gui/util/qshadernode.cpp172
-rw-r--r--src/gui/util/qshadernode_p.h128
-rw-r--r--src/gui/util/qshadernodeport.cpp55
-rw-r--r--src/gui/util/qshadernodeport_p.h88
-rw-r--r--src/gui/util/qshadernodesloader.cpp274
-rw-r--r--src/gui/util/qshadernodesloader_p.h95
-rw-r--r--src/gui/util/qvalidator.cpp12
-rw-r--r--src/gui/util/util.pri20
-rw-r--r--src/gui/vulkan/KHRONOS_LICENSE.txt20
-rw-r--r--src/gui/vulkan/qplatformvulkaninstance.cpp88
-rw-r--r--src/gui/vulkan/qplatformvulkaninstance.h91
-rw-r--r--src/gui/vulkan/qt_attribution.json17
-rw-r--r--src/gui/vulkan/qvulkanfunctions.cpp177
-rw-r--r--src/gui/vulkan/qvulkaninstance.cpp894
-rw-r--r--src/gui/vulkan/qvulkaninstance.h198
-rw-r--r--src/gui/vulkan/qvulkanwindow.cpp2720
-rw-r--r--src/gui/vulkan/qvulkanwindow.h161
-rw-r--r--src/gui/vulkan/qvulkanwindow_p.h188
-rw-r--r--src/gui/vulkan/vk.xml5269
-rw-r--r--src/gui/vulkan/vulkan.pri55
-rw-r--r--src/network/access/access.pri6
-rw-r--r--src/network/access/qhsts.cpp61
-rw-r--r--src/network/access/qhsts_p.h7
-rw-r--r--src/network/access/qhstsstore.cpp202
-rw-r--r--src/network/access/qhstsstore_p.h93
-rw-r--r--src/network/access/qhttpmultipart.cpp21
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp8
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp23
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h4
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp16
-rw-r--r--src/network/access/qhttpthreaddelegate_p.h4
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp22
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp46
-rw-r--r--src/network/access/qnetworkaccessmanager.h3
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h2
-rw-r--r--src/network/access/qnetworkreply.cpp6
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp17
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h5
-rw-r--r--src/network/bearer/qnetworkconfiguration.cpp2
-rw-r--r--src/network/configure.json14
-rw-r--r--src/network/kernel/kernel.pri2
-rw-r--r--src/network/kernel/qhostinfo.cpp21
-rw-r--r--src/network/kernel/qhostinfo.h9
-rw-r--r--src/network/kernel/qnetworkinterface_win.cpp58
-rw-r--r--src/network/kernel/qnetworkproxy.cpp48
-rw-r--r--src/network/kernel/qnetworkproxy.h9
-rw-r--r--src/network/socket/qabstractsocket.cpp13
-rw-r--r--src/network/socket/qlocalserver.cpp40
-rw-r--r--src/network/socket/qlocalserver.h2
-rw-r--r--src/network/socket/qlocalsocket.cpp14
-rw-r--r--src/network/socket/qlocalsocket_win.cpp4
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp3
-rw-r--r--src/network/socket/qnativesocketengine_win.cpp4
-rw-r--r--src/network/socket/qtcpserver_p.h3
-rw-r--r--src/network/ssl/qsslcertificate_openssl.cpp57
-rw-r--r--src/network/ssl/qsslcertificate_qt.cpp17
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp309
-rw-r--r--src/network/ssl/qsslcontext_openssl11.cpp277
-rw-r--r--src/network/ssl/qsslcontext_opensslpre11.cpp354
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters_openssl.cpp38
-rw-r--r--src/network/ssl/qsslellipticcurve.h1
-rw-r--r--src/network/ssl/qsslellipticcurve_openssl.cpp8
-rw-r--r--src/network/ssl/qsslkey_openssl.cpp79
-rw-r--r--src/network/ssl/qsslsocket.cpp13
-rw-r--r--src/network/ssl/qsslsocket_mac.cpp24
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp382
-rw-r--r--src/network/ssl/qsslsocket_openssl11.cpp285
-rw-r--r--src/network/ssl/qsslsocket_openssl11_symbols_p.h132
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h8
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp499
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h122
-rw-r--r--src/network/ssl/qsslsocket_opensslpre11.cpp424
-rw-r--r--src/network/ssl/qsslsocket_opensslpre11_symbols_p.h230
-rw-r--r--src/network/ssl/qsslsocket_p.h1
-rw-r--r--src/network/ssl/ssl.pri18
-rw-r--r--src/platformheaders/cocoafunctions/qcocoawindowfunctions.h6
-rw-r--r--src/platformsupport/clipboard/clipboard.pro1
-rw-r--r--src/platformsupport/clipboard/qmacmime.mm85
-rw-r--r--src/platformsupport/edid/edid.pro13
-rw-r--r--src/platformsupport/edid/qedidparser.cpp177
-rw-r--r--src/platformsupport/edid/qedidparser_p.h78
-rw-r--r--src/platformsupport/edid/qedidvendortable_p.h2296
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp56
-rw-r--r--src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h3
-rw-r--r--src/platformsupport/fbconvenience/qfbwindow.cpp2
-rw-r--r--src/platformsupport/fbconvenience/qfbwindow_p.h4
-rw-r--r--src/platformsupport/fontdatabases/mac/coretext.pri16
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h8
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp16
-rw-r--r--src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h2
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience.cpp48
-rw-r--r--src/platformsupport/glxconvenience/qglxconvenience_p.h15
-rw-r--r--src/platformsupport/graphics/qrasterbackingstore.cpp28
-rw-r--r--src/platformsupport/graphics/qrasterbackingstore_p.h1
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp15
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h3
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp6
-rw-r--r--src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h3
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp2
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp24
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice_p.h3
-rw-r--r--src/platformsupport/linuxaccessibility/atspiadaptor.cpp130
-rw-r--r--src/platformsupport/platformsupport.pro4
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu.cpp20
-rw-r--r--src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h16
-rw-r--r--src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp2
-rw-r--r--src/platformsupport/themes/genericunix/qgenericunixthemes.cpp8
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp357
-rw-r--r--src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h106
-rw-r--r--src/platformsupport/vkconvenience/vkconvenience.pro16
-rw-r--r--src/plugins/bearer/linux_common/qofonoservice_linux.cpp2
-rw-r--r--src/plugins/generic/tuiotouch/qoscbundle.cpp6
-rw-r--r--src/plugins/generic/tuiotouch/qoscmessage.cpp2
-rw-r--r--src/plugins/generic/tuiotouch/qtuiohandler.cpp41
-rw-r--r--src/plugins/imageformats/gif/main.h4
-rw-r--r--src/plugins/imageformats/gif/qgifhandler.cpp4
-rw-r--r--src/plugins/imageformats/gif/qgifhandler_p.h22
-rw-r--r--src/plugins/imageformats/ico/ico.pro1
-rw-r--r--src/plugins/imageformats/ico/main.h4
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp128
-rw-r--r--src/plugins/imageformats/ico/qicohandler.h18
-rw-r--r--src/plugins/imageformats/jpeg/main.h4
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler_p.h14
-rw-r--r--src/plugins/platforms/android/android.pro9
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp3
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp17
-rw-r--r--src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp6
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp37
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.h7
-rw-r--r--src/plugins/platforms/android/qandroidplatformmenu.cpp11
-rw-r--r--src/plugins/platforms/android/qandroidplatformmenu.h3
-rw-r--r--src/plugins/platforms/android/qandroidplatformmenuitem.cpp11
-rw-r--r--src/plugins/platforms/android/qandroidplatformmenuitem.h3
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp22
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.h4
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkaninstance.cpp66
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkaninstance.h63
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp210
-rw-r--r--src/plugins/platforms/android/qandroidplatformvulkanwindow.h91
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.cpp5
-rw-r--r--src/plugins/platforms/android/qandroidplatformwindow.h4
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm145
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoadrag.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm18
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoahelpers.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm10
-rw-r--r--src/plugins/platforms/cocoa/qcocoakeymapper.mm8
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.h6
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoamimetypes.mm92
-rw-r--r--src/plugins/platforms/cocoa/qcocoanativeinterface.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoasystemsettings.mm104
-rw-r--r--src/plugins/platforms/cocoa/qcocoatheme.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.h129
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm1316
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h11
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm249
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.h108
-rw-r--r--src/plugins/platforms/cocoa/qnswindow.mm374
-rw-r--r--src/plugins/platforms/direct2d/direct2d.pro2
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfswindow.cpp17
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp5
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h1
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp82
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h5
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp4
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp57
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h11
-rw-r--r--src/plugins/platforms/haiku/qhaikuwindow.cpp23
-rw-r--r--src/plugins/platforms/haiku/qhaikuwindow.h4
-rw-r--r--src/plugins/platforms/ios/qiosclipboard.mm14
-rw-r--r--src/plugins/platforms/ios/qiosmenu.h8
-rw-r--r--src/plugins/platforms/ios/qiosmenu.mm22
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm7
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm4
-rw-r--r--src/plugins/platforms/ios/qioswindow.h2
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm28
-rw-r--r--src/plugins/platforms/ios/quiview.mm19
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.cpp12
-rw-r--r--src/plugins/platforms/mirclient/qmirclientwindow.h2
-rw-r--r--src/plugins/platforms/offscreen/qoffscreencommon.h1
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.cpp12
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.h4
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.cpp23
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenwindow.h2
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.cpp27
-rw-r--r--src/plugins/platforms/qnx/qqnxwindow.h4
-rw-r--r--src/plugins/platforms/windows/accessible/accessible.pri15
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.cpp190
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.h47
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp10
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp138
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h36
-rw-r--r--src/plugins/platforms/windows/qtwindowsglobal.h8
-rw-r--r--src/plugins/platforms/windows/qwindowscombase.h112
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp101
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.h8
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.cpp30
-rw-r--r--src/plugins/platforms/windows/qwindowscursor.h7
-rw-r--r--src/plugins/platforms/windows/qwindowsdialoghelpers.cpp36
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.cpp69
-rw-r--r--src/plugins/platforms/windows/qwindowsdrag.h11
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp72
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.h7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.cpp30
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h8
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.cpp962
-rw-r--r--src/plugins/platforms/windows/qwindowsmenu.h243
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowsmousehandler.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsnativeinterface.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowsole.cpp62
-rw-r--r--src/plugins/platforms/windows/qwindowsole.h17
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.cpp443
-rw-r--r--src/plugins/platforms/windows/qwindowssystemtrayicon.h103
-rw-r--r--src/plugins/platforms/windows/qwindowstabletsupport.cpp12
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.cpp70
-rw-r--r--src/plugins/platforms/windows/qwindowstheme.h10
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.cpp136
-rw-r--r--src/plugins/platforms/windows/qwindowsvulkaninstance.h76
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp322
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.h38
-rw-r--r--src/plugins/platforms/windows/windows.pri13
-rw-r--r--src/plugins/platforms/windows/windows.pro2
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.cpp6
-rw-r--r--src/plugins/platforms/winrt/qwinrtdrag.h1
-rw-r--r--src/plugins/platforms/winrt/qwinrtfileengine.cpp3
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.cpp21
-rw-r--r--src/plugins/platforms/winrt/qwinrtwindow.h2
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h17
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp1
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp30
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h1
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp13
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp18
-rw-r--r--src/plugins/platforms/xcb/nativepainting/nativepainting.pri22
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp203
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qbackingstore_x11_p.h70
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qcolormap_x11.cpp644
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qcolormap_x11_p.h75
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp2837
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h118
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp2108
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h160
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qt_x11_p.h193
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qtessellator.cpp1494
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qtessellator_p.h83
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp315
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.h96
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp102
-rw-r--r--src/plugins/platforms/xcb/qxcbclipboard.cpp86
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp424
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h134
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp817
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp131
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp32
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp63
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h7
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp94
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp52
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp592
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h69
-rw-r--r--src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp38
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkaninstance.cpp156
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkaninstance.h79
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkanwindow.cpp88
-rw-r--r--src/plugins/platforms/xcb/qxcbvulkanwindow.h65
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp642
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h8
-rw-r--r--src/plugins/platforms/xcb/qxcbwmsupport.cpp21
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp43
-rw-r--r--src/plugins/platforms/xcb/xcb_qpa_lib.pro16
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3menu.cpp22
-rw-r--r--src/plugins/platformthemes/gtk3/qgtk3menu.h8
-rw-r--r--src/plugins/plugins.pro1
-rw-r--r--src/plugins/sqldrivers/db2/qsql_db2.cpp14
-rw-r--r--src/plugins/sqldrivers/ibase/qsql_ibase.cpp9
-rw-r--r--src/plugins/sqldrivers/mysql/qsql_mysql.cpp3
-rw-r--r--src/plugins/sqldrivers/odbc/qsql_odbc.cpp7
-rw-r--r--src/plugins/sqldrivers/psql/qsql_psql.cpp12
-rw-r--r--src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp110
-rw-r--r--src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp2
-rw-r--r--src/plugins/sqldrivers/tds/qsql_tds.cpp4
-rw-r--r--src/plugins/styles/android/android.pro16
-rw-r--r--src/plugins/styles/android/androidstyle.json3
-rw-r--r--src/plugins/styles/android/main.cpp64
-rw-r--r--src/plugins/styles/android/qandroidstyle.cpp (renamed from src/widgets/styles/qandroidstyle.cpp)4
-rw-r--r--src/plugins/styles/android/qandroidstyle_p.h (renamed from src/widgets/styles/qandroidstyle_p.h)6
-rw-r--r--src/plugins/styles/mac/mac.pro19
-rw-r--r--src/plugins/styles/mac/macstyle.json3
-rw-r--r--src/plugins/styles/mac/main.mm65
-rw-r--r--src/plugins/styles/mac/qmacstyle.qdoc (renamed from src/widgets/styles/qmacstyle.qdoc)2
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm (renamed from src/widgets/styles/qmacstyle_mac.mm)2689
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p.h (renamed from src/widgets/styles/qmacstyle_mac_p.h)11
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac_p_p.h (renamed from src/widgets/styles/qmacstyle_mac_p_p.h)62
-rw-r--r--src/plugins/styles/styles.pro8
-rw-r--r--src/plugins/styles/windowsvista/main.cpp64
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle.cpp (renamed from src/widgets/styles/qwindowsvistastyle.cpp)4
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle_p.h (renamed from src/widgets/styles/qwindowsvistastyle_p.h)6
-rw-r--r--src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h (renamed from src/widgets/styles/qwindowsvistastyle_p_p.h)6
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle.cpp (renamed from src/widgets/styles/qwindowsxpstyle.cpp)12
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle_p.h (renamed from src/widgets/styles/qwindowsxpstyle_p.h)7
-rw-r--r--src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h (renamed from src/widgets/styles/qwindowsxpstyle_p_p.h)6
-rw-r--r--src/plugins/styles/windowsvista/windowsvista.pro22
-rw-r--r--src/plugins/styles/windowsvista/windowsvistastyle.json3
-rw-r--r--src/printsupport/kernel/qcups.cpp2
-rw-r--r--src/printsupport/kernel/qprintengine_pdf.cpp4
-rw-r--r--src/printsupport/kernel/qprintengine_pdf_p.h2
-rw-r--r--src/printsupport/kernel/qprinter.cpp33
-rw-r--r--src/printsupport/kernel/qprinter.h3
-rw-r--r--src/printsupport/kernel/qprinter_p.h4
-rw-r--r--src/sql/doc/snippets/code/doc_src_sql-driver.cpp5
-rw-r--r--src/sql/doc/src/sql-driver.qdoc16
-rw-r--r--src/sql/kernel/qsqldatabase.cpp1
-rw-r--r--src/sql/kernel/qsqlerror.cpp34
-rw-r--r--src/sql/kernel/qsqlerror.h7
-rw-r--r--src/sql/kernel/qsqlfield.cpp42
-rw-r--r--src/sql/kernel/qsqlfield.h5
-rw-r--r--src/sql/kernel/qsqlrecord.cpp17
-rw-r--r--src/sql/models/qsqlquerymodel.cpp24
-rw-r--r--src/sql/models/qsqlquerymodel.h24
-rw-r--r--src/src.pro8
-rw-r--r--src/testlib/qtest.h29
-rw-r--r--src/testlib/qtestblacklist.cpp14
-rw-r--r--src/testlib/qtestcase.cpp103
-rw-r--r--src/testlib/qtestcase.h22
-rw-r--r--src/testlib/qtestcase.qdoc34
-rw-r--r--src/testlib/qtestkeyboard.h20
-rw-r--r--src/tools/bootstrap/bootstrap.pro6
-rw-r--r--src/tools/moc/generator.cpp33
-rw-r--r--src/tools/moc/generator.h1
-rw-r--r--src/tools/moc/main.cpp4
-rw-r--r--src/tools/moc/moc.cpp10
-rw-r--r--src/tools/moc/moc.h3
-rw-r--r--src/tools/moc/moc.pro1
-rw-r--r--src/tools/qdbuscpp2xml/qdbuscpp2xml.pro1
-rw-r--r--src/tools/qdbusxml2cpp/qdbusxml2cpp.pro1
-rw-r--r--src/tools/qlalr/qlalr.pro1
-rw-r--r--src/tools/qvkgen/qvkgen.cpp530
-rw-r--r--src/tools/qvkgen/qvkgen.pro6
-rw-r--r--src/tools/rcc/rcc.pro1
-rw-r--r--src/tools/uic/cpp/cpp.pri12
-rw-r--r--src/tools/uic/cpp/cppextractimages.cpp140
-rw-r--r--src/tools/uic/cpp/cppwritedeclaration.cpp63
-rw-r--r--src/tools/uic/cpp/cppwritedeclaration.h3
-rw-r--r--src/tools/uic/cpp/cppwriteicondata.cpp172
-rw-r--r--src/tools/uic/cpp/cppwriteicondata.h68
-rw-r--r--src/tools/uic/cpp/cppwriteiconinitialization.cpp102
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.cpp22
-rw-r--r--src/tools/uic/cpp/cppwriteincludes.h5
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp235
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.h16
-rw-r--r--src/tools/uic/customwidgetsinfo.cpp12
-rw-r--r--src/tools/uic/customwidgetsinfo.h2
-rw-r--r--src/tools/uic/databaseinfo.cpp4
-rw-r--r--src/tools/uic/main.cpp5
-rw-r--r--src/tools/uic/option.h4
-rw-r--r--src/tools/uic/treewalker.cpp29
-rw-r--r--src/tools/uic/treewalker.h7
-rw-r--r--src/tools/uic/ui4.cpp5165
-rw-r--r--src/tools/uic/ui4.h2292
-rw-r--r--src/tools/uic/uic.cpp7
-rw-r--r--src/tools/uic/uic.h7
-rw-r--r--src/tools/uic/uic.pro1
-rw-r--r--src/tools/uic/utils.h13
-rw-r--r--src/widgets/configure.json10
-rw-r--r--src/widgets/dialogs/qfilesystemmodel.cpp16
-rw-r--r--src/widgets/dialogs/qinputdialog.cpp61
-rw-r--r--src/widgets/dialogs/qinputdialog.h8
-rw-r--r--src/widgets/dialogs/qprogressdialog.cpp2
-rw-r--r--src/widgets/dialogs/qwizard.cpp29
-rw-r--r--src/widgets/doc/images/stylesheet-coffee-xp.pngbin14200 -> 0 bytes
-rw-r--r--src/widgets/doc/images/windowsxp-tabwidget.pngbin5220 -> 0 bytes
-rw-r--r--src/widgets/doc/images/windowsxp-treeview.pngbin5795 -> 0 bytes
-rw-r--r--src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc4
-rw-r--r--src/widgets/doc/snippets/macmainwindow.mm2
-rw-r--r--src/widgets/doc/src/qtwidgets-index.qdoc4
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/gallery.qdoc4
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc39
-rw-r--r--src/widgets/doc/src/widgets-and-layouts/widgets.qdoc2
-rw-r--r--src/widgets/graphicsview/qgraphicswidget_p.cpp3
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp22
-rw-r--r--src/widgets/itemviews/qabstractitemview.h1
-rw-r--r--src/widgets/itemviews/qcolumnview.cpp6
-rw-r--r--src/widgets/itemviews/qdirmodel.cpp17
-rw-r--r--src/widgets/itemviews/qheaderview.cpp16
-rw-r--r--src/widgets/itemviews/qitemdelegate.cpp2
-rw-r--r--src/widgets/itemviews/qlistview.cpp3
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp18
-rw-r--r--src/widgets/itemviews/qlistwidget.h11
-rw-r--r--src/widgets/itemviews/qtablewidget.cpp18
-rw-r--r--src/widgets/itemviews/qtablewidget.h10
-rw-r--r--src/widgets/itemviews/qtreeview.cpp2
-rw-r--r--src/widgets/itemviews/qtreewidget.cpp19
-rw-r--r--src/widgets/itemviews/qtreewidget.h10
-rw-r--r--src/widgets/kernel/qaction.cpp45
-rw-r--r--src/widgets/kernel/qaction.h3
-rw-r--r--src/widgets/kernel/qaction_p.h3
-rw-r--r--src/widgets/kernel/qapplication.cpp12
-rw-r--r--src/widgets/kernel/qapplication_p.h2
-rw-r--r--src/widgets/kernel/qboxlayout.cpp28
-rw-r--r--src/widgets/kernel/qdesktopwidget.qdoc2
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp10
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp134
-rw-r--r--src/widgets/kernel/qopenglwidget.h3
-rw-r--r--src/widgets/kernel/qwidget.cpp81
-rw-r--r--src/widgets/kernel/qwidget_p.h21
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp26
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h6
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp98
-rw-r--r--src/widgets/kernel/qwidgetwindow_p.h3
-rw-r--r--src/widgets/kernel/qwindowcontainer.cpp13
-rw-r--r--src/widgets/styles/images/fusion_arrow.pngbin295 -> 0 bytes
-rw-r--r--src/widgets/styles/qcommonstyle.cpp8
-rw-r--r--src/widgets/styles/qcommonstyle_p.h2
-rw-r--r--src/widgets/styles/qfusionstyle.cpp262
-rw-r--r--src/widgets/styles/qfusionstyle_p.h2
-rw-r--r--src/widgets/styles/qstyle.cpp18
-rw-r--r--src/widgets/styles/qstyle.h2
-rw-r--r--src/widgets/styles/qstyle.qrc1
-rw-r--r--src/widgets/styles/qstyleanimation_p.h13
-rw-r--r--src/widgets/styles/qstylefactory.cpp61
-rw-r--r--src/widgets/styles/qstylehelper.cpp29
-rw-r--r--src/widgets/styles/qstylehelper_p.h23
-rw-r--r--src/widgets/styles/qstyleoption.cpp12
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp6
-rw-r--r--src/widgets/styles/qstylesheetstyle_default.cpp4
-rw-r--r--src/widgets/styles/qwindowsstyle_p.h2
-rw-r--r--src/widgets/styles/qwindowsstyle_p_p.h2
-rw-r--r--src/widgets/styles/styles.pri23
-rw-r--r--src/widgets/util/qcompleter.cpp47
-rw-r--r--src/widgets/util/qcompleter_p.h4
-rw-r--r--src/widgets/util/qsystemtrayicon.cpp24
-rw-r--r--src/widgets/util/qsystemtrayicon_win.cpp591
-rw-r--r--src/widgets/util/util.pri4
-rw-r--r--src/widgets/widgets/qcombobox.cpp34
-rw-r--r--src/widgets/widgets/qcombobox_p.h3
-rw-r--r--src/widgets/widgets/qdatetimeedit.cpp5
-rw-r--r--src/widgets/widgets/qdialogbuttonbox.cpp2
-rw-r--r--src/widgets/widgets/qdialogbuttonbox.h6
-rw-r--r--src/widgets/widgets/qdockarealayout.cpp129
-rw-r--r--src/widgets/widgets/qdockarealayout_p.h5
-rw-r--r--src/widgets/widgets/qdockwidget.cpp14
-rw-r--r--src/widgets/widgets/qlineedit.cpp48
-rw-r--r--src/widgets/widgets/qlineedit.h2
-rw-r--r--src/widgets/widgets/qmainwindow.cpp257
-rw-r--r--src/widgets/widgets/qmainwindowlayout.cpp701
-rw-r--r--src/widgets/widgets/qmainwindowlayout_p.h313
-rw-r--r--src/widgets/widgets/qmdiarea.cpp3
-rw-r--r--src/widgets/widgets/qmdisubwindow.cpp58
-rw-r--r--src/widgets/widgets/qmenu.cpp20
-rw-r--r--src/widgets/widgets/qmenu.h8
-rw-r--r--src/widgets/widgets/qmenu_p.h2
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp30
-rw-r--r--src/widgets/widgets/qplaintextedit.h12
-rw-r--r--src/widgets/widgets/qprogressbar.cpp2
-rw-r--r--src/widgets/widgets/qpushbutton.cpp4
-rw-r--r--src/widgets/widgets/qsplashscreen.cpp2
-rw-r--r--src/widgets/widgets/qtabbar_p.h4
-rw-r--r--src/widgets/widgets/qtextedit.cpp29
-rw-r--r--src/widgets/widgets/qtextedit.h12
-rw-r--r--src/widgets/widgets/qtoolbar.cpp1
-rw-r--r--src/widgets/widgets/qtoolbar.h4
-rw-r--r--src/widgets/widgets/qwidgetanimator.cpp4
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp5
-rw-r--r--sync.profile8
-rw-r--r--tests/auto/concurrent/qtconcurrentmap/BLACKLIST2
-rw-r--r--tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp7
-rw-r--r--tests/auto/corelib/global/global.pro1
-rw-r--r--tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp67
-rw-r--r--tests/auto/corelib/global/qrandomgenerator/qrandomgenerator.pro4
-rw-r--r--tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp703
-rw-r--r--tests/auto/corelib/global/qtendian/qtendian.pro2
-rw-r--r--tests/auto/corelib/global/qtendian/tst_qtendian.cpp84
-rw-r--r--tests/auto/corelib/io/io.pro9
-rw-r--r--tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp15
-rw-r--r--tests/auto/corelib/io/qdebug/tst_qdebug.cpp41
-rw-r--r--tests/auto/corelib/io/qfile/tst_qfile.cpp1
-rw-r--r--tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp297
-rw-r--r--tests/auto/corelib/io/qfilesystemmetadata/tst_qfilesystemmetadata.cpp6
-rw-r--r--tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp2
-rw-r--r--tests/auto/corelib/io/qprocess/testDetached/main.cpp85
-rw-r--r--tests/auto/corelib/io/qprocess/tst_qprocess.cpp68
-rw-r--r--tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp60
-rw-r--r--tests/auto/corelib/io/qsettings/tst_qsettings.cpp76
-rw-r--r--tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp32
-rw-r--r--tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp4
-rw-r--r--tests/auto/corelib/io/qurl/tst_qurl.cpp17
-rw-r--r--tests/auto/corelib/io/qwinoverlappedionotifier/qwinoverlappedionotifier.pro4
-rw-r--r--tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp331
-rw-r--r--tests/auto/corelib/itemmodels/itemmodels.pro1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp165
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/.gitignore1
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/qsortfilterproxymodel_recursive.pro8
-rw-r--r--tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp727
-rw-r--r--tests/auto/corelib/json/tst_qtjson.cpp120
-rw-r--r--tests/auto/corelib/kernel/qmath/tst_qmath.cpp29
-rw-r--r--tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp262
-rw-r--r--tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp10
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp24
-rw-r--r--tests/auto/corelib/kernel/qobject/tst_qobject.cpp42
-rw-r--r--tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp11
-rw-r--r--tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp47
-rw-r--r--tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp93
-rw-r--r--tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp88
-rw-r--r--tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp40
-rw-r--r--tests/auto/corelib/plugin/quuid/tst_quuid.cpp56
-rw-r--r--tests/auto/corelib/plugin/quuid/tst_quuid_darwin.mm12
-rw-r--r--tests/auto/corelib/thread/qfuture/tst_qfuture.cpp2
-rw-r--r--tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp50
-rw-r--r--tests/auto/corelib/thread/qthread/qthread.pro2
-rw-r--r--tests/auto/corelib/thread/qthread/tst_qthread.cpp259
-rw-r--r--tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp68
-rw-r--r--tests/auto/corelib/tools/containerapisymmetry/.gitignore1
-rw-r--r--tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro7
-rw-r--r--tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp100
-rw-r--r--tests/auto/corelib/tools/qchar/tst_qchar.cpp29
-rw-r--r--tests/auto/corelib/tools/qdate/tst_qdate.cpp2
-rw-r--r--tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp94
-rw-r--r--tests/auto/corelib/tools/qhash/tst_qhash.cpp55
-rw-r--r--tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp28
-rw-r--r--tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp17
-rw-r--r--tests/auto/corelib/tools/qlocale/tst_qlocale.cpp99
-rw-r--r--tests/auto/corelib/tools/qmap/tst_qmap.cpp54
-rw-r--r--tests/auto/corelib/tools/qrect/tst_qrect.cpp32
-rw-r--r--tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp3
-rw-r--r--tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp2
-rw-r--r--tests/auto/corelib/tools/qstring/tst_qstring.cpp58
-rw-r--r--tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro1
-rw-r--r--tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp780
-rw-r--r--tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp12
-rw-r--r--tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp9
-rw-r--r--tests/auto/corelib/tools/qstringref/tst_qstringref.cpp4
-rw-r--r--tests/auto/corelib/tools/qstringview/.gitignore1
-rw-r--r--tests/auto/corelib/tools/qstringview/qstringview.pro6
-rw-r--r--tests/auto/corelib/tools/qstringview/tst_qstringview.cpp555
-rw-r--r--tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp154
-rw-r--r--tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp2
-rw-r--r--tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp8
-rw-r--r--tests/auto/corelib/tools/tools.pro2
-rw-r--r--tests/auto/gui/gui.pro3
-rw-r--r--tests/auto/gui/image/qicon/tst_qicon.cpp10
-rw-r--r--tests/auto/gui/image/qiconhighdpi/icons/misc/button.9.pngbin0 -> 329 bytes
-rw-r--r--tests/auto/gui/image/qiconhighdpi/icons/misc/button@2x.9.pngbin0 -> 616 bytes
-rw-r--r--tests/auto/gui/image/qiconhighdpi/tst_qiconhighdpi.cpp19
-rw-r--r--tests/auto/gui/image/qiconhighdpi/tst_qiconhighdpi.qrc2
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp128
-rw-r--r--tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp18
-rw-r--r--tests/auto/gui/kernel/kernel.pro1
-rw-r--r--tests/auto/gui/kernel/qcursor/qcursor.pro6
-rw-r--r--tests/auto/gui/kernel/qcursor/tst_qcursor.cpp123
-rw-r--r--tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp12
-rw-r--r--tests/auto/gui/kernel/qwindow/BLACKLIST4
-rw-r--r--tests/auto/gui/kernel/qwindow/tst_qwindow.cpp53
-rw-r--r--tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp4
-rw-r--r--tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp2
-rw-r--r--tests/auto/gui/painting/qcolor/tst_qcolor.cpp27
-rw-r--r--tests/auto/gui/painting/qpainter/tst_qpainter.cpp53
-rw-r--r--tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp42
-rw-r--r--tests/auto/gui/painting/qtransform/tst_qtransform.cpp5
-rw-r--r--tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp105
-rw-r--r--tests/auto/gui/qvulkan/qvulkan.pro9
-rw-r--r--tests/auto/gui/qvulkan/tst_qvulkan.cpp435
-rw-r--r--tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp6
-rw-r--r--tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp49
-rw-r--r--tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp4
-rw-r--r--tests/auto/gui/text/qtextscriptengine/BLACKLIST2
-rw-r--r--tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp60
-rw-r--r--tests/auto/gui/util/qshadergenerator/qshadergenerator.pro5
-rw-r--r--tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp895
-rw-r--r--tests/auto/gui/util/qshadergraph/qshadergraph.pro5
-rw-r--r--tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp779
-rw-r--r--tests/auto/gui/util/qshadergraphloader/qshadergraphloader.pro5
-rw-r--r--tests/auto/gui/util/qshadergraphloader/tst_qshadergraphloader.cpp625
-rw-r--r--tests/auto/gui/util/qshadernodes/qshadernodes.pro5
-rw-r--r--tests/auto/gui/util/qshadernodes/tst_qshadernodes.cpp548
-rw-r--r--tests/auto/gui/util/qshadernodesloader/qshadernodesloader.pro5
-rw-r--r--tests/auto/gui/util/qshadernodesloader/tst_qshadernodesloader.cpp323
-rw-r--r--tests/auto/gui/util/util.pro5
-rw-r--r--tests/auto/network/access/hsts/tst_qhsts.cpp72
-rw-r--r--tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp25
-rw-r--r--tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp114
-rw-r--r--tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp2
-rw-r--r--tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp69
-rw-r--r--tests/auto/opengl/qgl/tst_qgl.cpp2
-rw-r--r--tests/auto/other/lancelot/scripts/gradientxform_device.qps67
-rw-r--r--tests/auto/other/lancelot/scripts/gradientxform_logical.qps67
-rw-r--r--tests/auto/other/lancelot/scripts/gradientxform_object.qps68
-rw-r--r--tests/auto/other/macnativeevents/BLACKLIST20
-rw-r--r--tests/auto/other/macnativeevents/macnativeevents.pro3
-rw-r--r--tests/auto/other/macnativeevents/qnativeevents.cpp4
-rw-r--r--tests/auto/other/macnativeevents/qnativeevents.h4
-rw-r--r--tests/auto/other/macnativeevents/qnativeevents_mac.cpp42
-rw-r--r--tests/auto/other/macnativeevents/tst_macnativeevents.cpp6
-rw-r--r--tests/auto/other/modeltest/dynamictreemodel.cpp301
-rw-r--r--tests/auto/other/modeltest/dynamictreemodel.h192
-rw-r--r--tests/auto/other/modeltest/modeltest.cpp350
-rw-r--r--tests/auto/other/modeltest/modeltest.h61
-rw-r--r--tests/auto/other/modeltest/tst_modeltest.cpp39
-rw-r--r--tests/auto/other/qaccessibilitymac/qaccessibilitymac.pro1
-rw-r--r--tests/auto/other/qfocusevent/tst_qfocusevent.cpp2
-rw-r--r--tests/auto/shared/platformclipboard.h10
-rw-r--r--tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp34
-rw-r--r--tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp21
-rw-r--r--tests/auto/sql/kernel/qsqlfield/tst_qsqlfield.cpp36
-rw-r--r--tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp21
-rw-r--r--tests/auto/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp18
-rw-r--r--tests/auto/testlib/selftests/expected_pairdiagnostics.lightxml30
-rw-r--r--tests/auto/testlib/selftests/expected_pairdiagnostics.teamcity12
-rw-r--r--tests/auto/testlib/selftests/expected_pairdiagnostics.txt14
-rw-r--r--tests/auto/testlib/selftests/expected_pairdiagnostics.xml33
-rw-r--r--tests/auto/testlib/selftests/expected_pairdiagnostics.xunitxml21
-rwxr-xr-xtests/auto/testlib/selftests/generate_expected_output.py96
-rw-r--r--tests/auto/testlib/selftests/pairdiagnostics/pairdiagnostics.pro6
-rw-r--r--tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp (renamed from src/tools/uic/cpp/cppwriteiconinitialization.h)61
-rw-r--r--tests/auto/testlib/selftests/selftests.pri1
-rw-r--r--tests/auto/testlib/selftests/selftests.qrc5
-rw-r--r--tests/auto/testlib/selftests/tst_selftests.cpp1
-rw-r--r--tests/auto/tools/moc/error-on-wrong-notify.h2
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp22
-rw-r--r--tests/auto/tools/qmakelib/evaltest.cpp38
-rw-r--r--tests/auto/tools/uic/baseline/config.ui.h9
-rw-r--r--tests/auto/tools/uic/baseline/default.ui.h37
-rw-r--r--tests/auto/tools/uic/baseline/embeddeddialog.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/pagefold.ui.h43
-rw-r--r--tests/auto/tools/uic/baseline/previewwidget.ui.h9
-rw-r--r--tests/auto/tools/uic/baseline/stylesheeteditor.ui.h15
-rw-r--r--tests/auto/tools/uic/baseline/validators.ui.h12
-rw-r--r--tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h40
-rw-r--r--tests/auto/tools/uic/tst_uic.cpp5
-rw-r--r--tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp43
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp6
-rw-r--r--tests/auto/widgets/gestures/gestures.pro6
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp2
-rw-r--r--tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp8
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp2
-rw-r--r--tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp3
-rw-r--r--tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp65
-rw-r--r--tests/auto/widgets/kernel/kernel.pro4
-rw-r--r--tests/auto/widgets/kernel/qaction/tst_qaction.cpp35
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST (renamed from tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST)0
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/qgesturerecognizer.pro (renamed from tests/auto/widgets/gestures/qgesturerecognizer/qgesturerecognizer.pro)0
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp (renamed from tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp)0
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST2
-rw-r--r--tests/auto/widgets/kernel/qwidget/qwidget.pro2
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp12
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp70
-rw-r--r--tests/auto/widgets/styles/qmacstyle/qmacstyle.pro2
-rw-r--r--tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp43
-rw-r--r--tests/auto/widgets/styles/qstyle/tst_qstyle.cpp40
-rw-r--r--tests/auto/widgets/widgets.pro1
-rw-r--r--tests/auto/widgets/widgets/qcombobox/BLACKLIST4
-rw-r--r--tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp58
-rw-r--r--tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp21
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_noshadow_0_0.pngbin103 -> 103 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_noshadow_0_1.pngbin103 -> 103 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_noshadow_0_2.pngbin103 -> 103 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_noshadow_1_0.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_noshadow_1_1.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_noshadow_1_2.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_noshadow_2_0.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_noshadow_2_1.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_noshadow_2_2.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_plain_0_0.pngbin103 -> 103 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_plain_0_1.pngbin103 -> 103 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_plain_0_2.pngbin103 -> 103 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_plain_1_0.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_plain_1_1.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_plain_1_2.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_plain_2_0.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_plain_2_1.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_plain_2_2.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_raised_0_0.pngbin103 -> 103 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_raised_0_1.pngbin129 -> 128 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_raised_0_2.pngbin126 -> 126 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_raised_1_0.pngbin135 -> 135 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_raised_1_1.pngbin158 -> 158 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_raised_1_2.pngbin162 -> 162 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_raised_2_0.pngbin148 -> 148 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_raised_2_1.pngbin182 -> 182 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_raised_2_2.pngbin182 -> 182 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_sunken_0_0.pngbin103 -> 103 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_sunken_0_1.pngbin129 -> 128 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_sunken_0_2.pngbin126 -> 126 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_sunken_1_0.pngbin138 -> 138 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_sunken_1_1.pngbin159 -> 159 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_sunken_1_2.pngbin163 -> 163 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_sunken_2_0.pngbin148 -> 148 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_sunken_2_1.pngbin182 -> 182 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/box_sunken_2_2.pngbin182 -> 182 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_0.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_1.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_2.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_0.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_1.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_2.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_0.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_1.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_2.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_0.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_1.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_2.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_0.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_1.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_2.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_0.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_1.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_2.pngbin114 -> 114 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.pngbin148 -> 146 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.pngbin148 -> 146 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.pngbin148 -> 146 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.pngbin148 -> 146 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.pngbin148 -> 146 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.pngbin148 -> 146 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.pngbin148 -> 146 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.pngbin148 -> 146 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.pngbin148 -> 146 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.pngbin154 -> 152 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.pngbin154 -> 152 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.pngbin154 -> 152 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.pngbin154 -> 152 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.pngbin154 -> 152 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.pngbin154 -> 152 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.pngbin154 -> 152 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.pngbin154 -> 152 bytes
-rw-r--r--tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.pngbin154 -> 152 bytes
-rw-r--r--tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp4
-rw-r--r--tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp18
-rw-r--r--tests/auto/widgets/widgets/qmenu/BLACKLIST7
-rw-r--r--tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp35
-rw-r--r--tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp72
-rw-r--r--tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp39
-rw-r--r--tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp3
-rw-r--r--tests/baselineserver/shared/baselineprotocol.cpp2
-rw-r--r--tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp7
-rw-r--r--tests/manual/filetest/main.cpp55
-rw-r--r--tests/manual/manual.pro2
-rw-r--r--tests/manual/qvulkaninstance/main.cpp713
-rw-r--r--tests/manual/qvulkaninstance/qvulkaninstance.pro6
-rw-r--r--tests/manual/windowflags/controllerwindow.cpp102
-rw-r--r--tests/manual/windowflags/controllerwindow.h11
-rw-r--r--tests/manual/windowflags/main.cpp1
-rw-r--r--tests/manual/windowflags/previewwindow.cpp20
-rw-r--r--tests/manual/windowflags/previewwindow.h4
-rwxr-xr-xutil/edid/qedidvendortable.py123
-rwxr-xr-xutil/local_database/cldr2qlocalexml.py638
-rwxr-xr-x[-rw-r--r--]util/local_database/cldr2qtimezone.py74
-rw-r--r--util/local_database/enumdata.py2
-rw-r--r--util/local_database/localexml.py239
-rwxr-xr-xutil/local_database/qlocalexml2cpp.py542
1325 files changed, 84502 insertions, 29576 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 9f7fc2fa1f..5153f8139f 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -4,4 +4,4 @@ CONFIG += warning_clean
QT_SOURCE_TREE = $$PWD
QT_BUILD_TREE = $$shadowed($$PWD)
-MODULE_VERSION = 5.9.2
+MODULE_VERSION = 5.10.0
diff --git a/bin/syncqt.pl b/bin/syncqt.pl
index 372aa2b331..d62ffcbc37 100755
--- a/bin/syncqt.pl
+++ b/bin/syncqt.pl
@@ -1004,13 +1004,16 @@ foreach my $lib (@modules_to_sync) {
@headers = grep(!/^qt[a-z0-9]+-config(_p)?\.h$/, @headers);
if (defined $inject_headers{$subdir}) {
foreach my $if (@{$inject_headers{$subdir}}) {
- @headers = grep(!/^\Q$if\E$/, @headers); #in case we configure'd previously
+ my $cif = $if;
+ $cif =~ s/^\^//;
+ @headers = grep(!/^\Q$cif\E$/, @headers); #in case we configure'd previously
push @headers, "*".$if;
}
}
my $header_dirname = "";
foreach my $header (@headers) {
my $shadow = ($header =~ s/^\*//);
+ my $no_stamp = $shadow && ($header =~ s/^\^//);
$header = 0 if ($header =~ /^ui_.*\.h$/);
foreach (@ignore_headers) {
$header = 0 if($header eq $_);
@@ -1106,7 +1109,7 @@ foreach my $lib (@modules_to_sync) {
$pri_install_pfiles.= "$pri_install_iheader ";;
}
$pri_injections .= fixPaths($iheader, "$out_basedir/include/$lib")
- .":".fixPaths($oheader, "$out_basedir/include/$lib")
+ .":".($no_stamp ? "^" : "").fixPaths($oheader, "$out_basedir/include/$lib")
.$injection." " if ($shadow);
}
diff --git a/config.tests/common/aesni/aesni.cpp b/config.tests/common/aesni/aesni.cpp
new file mode 100644
index 0000000000..a177183c72
--- /dev/null
+++ b/config.tests/common/aesni/aesni.cpp
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <wmmintrin.h>
+
+int main(int, char**)
+{
+ __m128i a = _mm_setzero_si128();
+ __m128i b = _mm_aesenc_si128(a, a);
+ __m128i c = _mm_aesdec_si128(a, b);
+ (void)c;
+ return 0;
+}
diff --git a/config.tests/common/aesni/aesni.pro b/config.tests/common/aesni/aesni.pro
new file mode 100644
index 0000000000..49cb132ef7
--- /dev/null
+++ b/config.tests/common/aesni/aesni.pro
@@ -0,0 +1,3 @@
+SOURCES = aesni.cpp
+!defined(QMAKE_CFLAGS_AESNI, "var"): error("This compiler does not support AES New Instructions")
+else: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_AESNI
diff --git a/config.tests/common/rdrnd/rdrnd.cpp b/config.tests/common/rdrnd/rdrnd.cpp
new file mode 100644
index 0000000000..597f7257bf
--- /dev/null
+++ b/config.tests/common/rdrnd/rdrnd.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <immintrin.h>
+
+int main(int, char**)
+{
+ unsigned short us;
+ unsigned int ui;
+ if (_rdrand16_step(&us))
+ return 1;
+ if (_rdrand32_step(&ui))
+ return 1;
+#if defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64)
+ unsigned long long ull;
+ if (_rdrand64_step(&ull))
+ return 1;
+#endif
+ return 0;
+}
diff --git a/config.tests/common/rdrnd/rdrnd.pro b/config.tests/common/rdrnd/rdrnd.pro
new file mode 100644
index 0000000000..37e636dc3f
--- /dev/null
+++ b/config.tests/common/rdrnd/rdrnd.pro
@@ -0,0 +1,3 @@
+SOURCES += rdrnd.cpp
+!defined(QMAKE_CFLAGS_RDRND, "var"): error("This compiler does not support the RDRAND instruction")
+else: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_RDRND
diff --git a/config.tests/common/shani/shani.cpp b/config.tests/common/shani/shani.cpp
new file mode 100644
index 0000000000..0fe6e87dd8
--- /dev/null
+++ b/config.tests/common/shani/shani.cpp
@@ -0,0 +1,50 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <immintrin.h>
+
+int main(int, char**)
+{
+ __m128i a = _mm_setzero_si128();
+ __m128i b = _mm_sha1rnds4_epu32(a, a, 0);
+ __m128i c = _mm_sha1msg1_epu32(a, b);
+ __m128i d = _mm_sha256msg2_epu32(b, c);
+ (void)d;
+ return 0;
+}
diff --git a/config.tests/common/shani/shani.pro b/config.tests/common/shani/shani.pro
new file mode 100644
index 0000000000..278f49ef90
--- /dev/null
+++ b/config.tests/common/shani/shani.pro
@@ -0,0 +1,3 @@
+SOURCES = shani.cpp
+!defined(QMAKE_CFLAGS_SHANI, "var"): error("This compiler does not support Secure Hash Algorithm extensions")
+else: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SHANI
diff --git a/config.tests/qpa/vulkan/vulkan.cpp b/config.tests/qpa/vulkan/vulkan.cpp
new file mode 100644
index 0000000000..22f5edf9f2
--- /dev/null
+++ b/config.tests/qpa/vulkan/vulkan.cpp
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// This is a header-only test. Qt does not rely on linking to a Vulkan library directly.
+
+#include <vulkan/vulkan.h>
+
+// The pData parameter has changed from uint32_t* to void* at some point.
+// Ensure the headers have the updated one to prevent compile errors later on.
+PFN_vkCmdUpdateBuffer cmdUpdBuf;
+void testUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize dataSize, const void* pData)
+{
+ cmdUpdBuf(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
+}
+
+int main(int, char **)
+{
+ VkInstanceCreateInfo info;
+ testUpdateBuffer(0, 0, 0, 0, 0);
+
+ return 0;
+}
diff --git a/config.tests/qpa/vulkan/vulkan.pro b/config.tests/qpa/vulkan/vulkan.pro
new file mode 100644
index 0000000000..5f05bc49aa
--- /dev/null
+++ b/config.tests/qpa/vulkan/vulkan.pro
@@ -0,0 +1 @@
+SOURCES = vulkan.cpp
diff --git a/src/tools/uic/cpp/cppextractimages.h b/config.tests/unix/cxx11_random/cxx11_random.cpp
index d012de8d0a..d6872667fd 100644
--- a/src/tools/uic/cpp/cppextractimages.h
+++ b/config.tests/unix/cxx11_random/cxx11_random.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the tools applications of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
@@ -26,39 +26,10 @@
**
****************************************************************************/
-#ifndef CPPEXTRACTIMAGES_H
-#define CPPEXTRACTIMAGES_H
+#include <random>
-#include "treewalker.h"
-#include <qdir.h>
-
-QT_BEGIN_NAMESPACE
-
-class QTextStream;
-class Driver;
-class Uic;
-
-struct Option;
-
-namespace CPP {
-
-class ExtractImages : public TreeWalker
+int main()
{
-public:
- ExtractImages(const Option &opt);
-
- void acceptUI(DomUI *node) Q_DECL_OVERRIDE;
- void acceptImages(DomImages *images) Q_DECL_OVERRIDE;
- void acceptImage(DomImage *image) Q_DECL_OVERRIDE;
-
-private:
- QTextStream *m_output;
- const Option &m_option;
- QDir m_imagesDir;
-};
-
-} // namespace CPP
-
-QT_END_NAMESPACE
-
-#endif // CPPEXTRACTIMAGES_H
+ std::mt19937 mt(0);
+ return 0;
+}
diff --git a/config.tests/unix/cxx11_random/cxx11_random.pro b/config.tests/unix/cxx11_random/cxx11_random.pro
new file mode 100644
index 0000000000..0cd5fff9d9
--- /dev/null
+++ b/config.tests/unix/cxx11_random/cxx11_random.pro
@@ -0,0 +1 @@
+SOURCES = cxx11_random.cpp
diff --git a/config.tests/unix/futimens/futimens.cpp b/config.tests/unix/futimens/futimens.cpp
new file mode 100644
index 0000000000..1b66386ca1
--- /dev/null
+++ b/config.tests/unix/futimens/futimens.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Raphael Gozzo <raphael.rg91@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <sys/stat.h>
+
+int main(int, char **)
+{
+ futimens(-1,0);
+ return 0;
+}
+
diff --git a/config.tests/unix/futimens/futimens.pro b/config.tests/unix/futimens/futimens.pro
new file mode 100644
index 0000000000..eb3ccc56c5
--- /dev/null
+++ b/config.tests/unix/futimens/futimens.pro
@@ -0,0 +1 @@
+SOURCES += futimens.cpp
diff --git a/config.tests/unix/futimes/futimes.cpp b/config.tests/unix/futimes/futimes.cpp
new file mode 100644
index 0000000000..553b39068e
--- /dev/null
+++ b/config.tests/unix/futimes/futimes.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 Raphael Gozzo <raphael.rg91@gmail.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <sys/time.h>
+
+int main(int, char **)
+{
+ futimes(-1,0);
+ return 0;
+}
+
diff --git a/config.tests/unix/futimes/futimes.pro b/config.tests/unix/futimes/futimes.pro
new file mode 100644
index 0000000000..8e7f2c0f62
--- /dev/null
+++ b/config.tests/unix/futimes/futimes.pro
@@ -0,0 +1 @@
+SOURCES += futimes.cpp
diff --git a/src/tools/uic/cpp/cppwriteicondeclaration.h b/config.tests/unix/getauxval/getauxval.cpp
index 6483b8bf4a..62f71e95d2 100644
--- a/src/tools/uic/cpp/cppwriteicondeclaration.h
+++ b/config.tests/unix/getauxval/getauxval.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the tools applications of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
@@ -26,38 +26,9 @@
**
****************************************************************************/
-#ifndef CPPWRITEICONDECLARATION_H
-#define CPPWRITEICONDECLARATION_H
+#include <sys/auxv.h>
-#include "treewalker.h"
-
-QT_BEGIN_NAMESPACE
-
-class QTextStream;
-class Driver;
-class Uic;
-
-struct Option;
-
-namespace CPP {
-
-class WriteIconDeclaration : public TreeWalker
+int main()
{
-public:
- WriteIconDeclaration(Uic *uic);
-
- void acceptUI(DomUI *node) Q_DECL_OVERRIDE;
- void acceptImages(DomImages *images) Q_DECL_OVERRIDE;
- void acceptImage(DomImage *image) Q_DECL_OVERRIDE;
-
-private:
- Driver *driver;
- QTextStream &output;
- const Option &option;
-};
-
-} // namespace CPP
-
-QT_END_NAMESPACE
-
-#endif // CPPWRITEICONDECLARATION_H
+ return getauxval(AT_NULL);
+}
diff --git a/config.tests/unix/getauxval/getauxval.pro b/config.tests/unix/getauxval/getauxval.pro
new file mode 100644
index 0000000000..ea46cb0bae
--- /dev/null
+++ b/config.tests/unix/getauxval/getauxval.pro
@@ -0,0 +1 @@
+SOURCES = getauxval.cpp
diff --git a/src/tools/uic/cpp/cppwriteicondeclaration.cpp b/config.tests/unix/getentropy/getentropy.cpp
index 5264e3de54..6cb4dc3a95 100644
--- a/src/tools/uic/cpp/cppwriteicondeclaration.cpp
+++ b/config.tests/unix/getentropy/getentropy.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the tools applications of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
@@ -26,42 +26,10 @@
**
****************************************************************************/
-#include "cppwriteicondeclaration.h"
-#include "driver.h"
-#include "ui4.h"
-#include "uic.h"
+#include <unistd.h>
-#include <qtextstream.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace CPP {
-
-WriteIconDeclaration::WriteIconDeclaration(Uic *uic)
- : driver(uic->driver()), output(uic->output()), option(uic->option())
-{
-}
-
-void WriteIconDeclaration::acceptUI(DomUI *node)
+int main()
{
- TreeWalker::acceptUI(node);
+ char buf[32];
+ return getentropy(buf, sizeof(buf));
}
-
-void WriteIconDeclaration::acceptImages(DomImages *images)
-{
- TreeWalker::acceptImages(images);
-}
-
-void WriteIconDeclaration::acceptImage(DomImage *image)
-{
- QString name = image->attributeName();
- if (name.isEmpty())
- return;
-
- driver->insertPixmap(name);
- output << option.indent << option.indent << name << "_ID,\n";
-}
-
-} // namespace CPP
-
-QT_END_NAMESPACE
diff --git a/config.tests/unix/getentropy/getentropy.pro b/config.tests/unix/getentropy/getentropy.pro
new file mode 100644
index 0000000000..bdd626b513
--- /dev/null
+++ b/config.tests/unix/getentropy/getentropy.pro
@@ -0,0 +1 @@
+SOURCES = getentropy.cpp
diff --git a/config.tests/unix/opengles32/opengles32.cpp b/config.tests/unix/opengles32/opengles32.cpp
new file mode 100644
index 0000000000..0505510464
--- /dev/null
+++ b/config.tests/unix/opengles32/opengles32.cpp
@@ -0,0 +1,47 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <GLES3/gl32.h>
+
+int main(int, char **)
+{
+ glFramebufferTexture(GL_TEXTURE_2D, GL_DEPTH_STENCIL_ATTACHMENT, 1, 0);
+
+ return 0;
+}
diff --git a/config.tests/unix/opengles32/opengles32.pro b/config.tests/unix/opengles32/opengles32.pro
new file mode 100644
index 0000000000..c95ba83364
--- /dev/null
+++ b/config.tests/unix/opengles32/opengles32.pro
@@ -0,0 +1,7 @@
+# The library is expected to be the same as in ES 2.0 (libGLESv2).
+# The difference is the header and the presence of the functions in
+# the library.
+
+SOURCES = opengles32.cpp
+
+CONFIG -= qt
diff --git a/config.tests/unix/openssl11/openssl.cpp b/config.tests/unix/openssl11/openssl.cpp
new file mode 100644
index 0000000000..c20cc59deb
--- /dev/null
+++ b/config.tests/unix/openssl11/openssl.cpp
@@ -0,0 +1,48 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <openssl/opensslv.h>
+
+#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L
+# error "OpenSSL >= 1.1 is required"
+#endif
+
+int main()
+{
+}
diff --git a/config.tests/unix/openssl11/openssl.pro b/config.tests/unix/openssl11/openssl.pro
new file mode 100644
index 0000000000..a023aee4aa
--- /dev/null
+++ b/config.tests/unix/openssl11/openssl.pro
@@ -0,0 +1,2 @@
+SOURCES = openssl.cpp
+CONFIG -= x11 qt
diff --git a/config.tests/x11/xrender/xrender.cpp b/config.tests/x11/xrender/xrender.cpp
new file mode 100644
index 0000000000..35203cc02c
--- /dev/null
+++ b/config.tests/x11/xrender/xrender.cpp
@@ -0,0 +1,52 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the config.tests of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <X11/Xlib.h>
+#include <X11/extensions/Xrender.h>
+
+#if RENDER_MAJOR == 0 && RENDER_MINOR < 5
+# error "Required Xrender version 0.6 not found."
+#else
+int main(int, char **)
+{
+ XRenderPictFormat *format;
+ format = 0;
+ return 0;
+}
+#endif
diff --git a/config.tests/x11/xrender/xrender.pro b/config.tests/x11/xrender/xrender.pro
new file mode 100644
index 0000000000..ab5c5efa77
--- /dev/null
+++ b/config.tests/x11/xrender/xrender.pro
@@ -0,0 +1,3 @@
+SOURCES = xrender.cpp
+CONFIG += x11
+CONFIG -= qt
diff --git a/configure.json b/configure.json
index 6221c9803a..803178a597 100644
--- a/configure.json
+++ b/configure.json
@@ -441,6 +441,11 @@
]
}
},
+ "aesni": {
+ "label": "AES new instructions",
+ "type": "compile",
+ "test": "common/aesni"
+ },
"f16c": {
"label": "F16C instructions",
"type": "compile",
@@ -459,6 +464,16 @@
]
}
},
+ "rdrnd": {
+ "label": "RDRAND instruction",
+ "type": "compile",
+ "test": "common/rdrnd"
+ },
+ "shani": {
+ "label": "SHA new instructions",
+ "type": "compile",
+ "test": "common/shani"
+ },
"avx": {
"label": "AVX instructions",
"type": "compile",
@@ -991,6 +1006,7 @@
"condition": "features.avx && tests.avx2",
"output": [
"privateConfig",
+ "privateFeature",
{ "type": "define", "name": "QT_COMPILER_SUPPORTS_AVX2", "value": 1 }
]
},
@@ -1066,6 +1082,30 @@
{ "type": "define", "name": "QT_COMPILER_SUPPORTS_AVX512VBMI", "value": 1 }
]
},
+ "aesni": {
+ "label": "AES",
+ "condition": "features.sse2 && tests.aesni",
+ "output": [
+ "privateConfig",
+ { "type": "define", "name": "QT_COMPILER_SUPPORTS_AES", "value": 1 }
+ ]
+ },
+ "rdrnd": {
+ "label": "RDRAND",
+ "condition": "tests.rdrnd",
+ "output": [
+ "privateConfig",
+ { "type": "define", "name": "QT_COMPILER_SUPPORTS_RDRND", "value": 1 }
+ ]
+ },
+ "shani": {
+ "label": "SHA",
+ "condition": "features.sse2 && tests.shani",
+ "output": [
+ "privateConfig",
+ { "type": "define", "name": "QT_COMPILER_SUPPORTS_SHA", "value": 1 }
+ ]
+ },
"mips_dsp": {
"label": "DSP",
"condition": "arch.mips && tests.mips_dsp",
@@ -1333,7 +1373,7 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
{
"message": "AVX",
"type": "featureList",
- "args": "avx avx2 f16c",
+ "args": "avx avx2",
"condition": "(arch.i386 || arch.x86_64)"
},
{
@@ -1343,6 +1383,12 @@ Configure with '-qreal float' to create a build that is binary-compatible with 5
"condition": "(arch.i386 || arch.x86_64)"
},
{
+ "message": "Other x86",
+ "type": "featureList",
+ "args": "aesni f16c rdrnd shani",
+ "condition": "(arch.i386 || arch.x86_64)"
+ },
+ {
"type": "feature",
"args": "neon",
"condition": "arch.arm || arch.arm64"
diff --git a/doc/global/config.qdocconf b/doc/global/config.qdocconf
index 0c22d70529..a18396876d 100644
--- a/doc/global/config.qdocconf
+++ b/doc/global/config.qdocconf
@@ -13,3 +13,7 @@ navigation.homepage = "Qt $QT_VER"
sourcedirs += includes $$BUILDDIR
url = http://doc.qt.io/qt-5
+
+# Uncomment the following two lines to generate documentation marked as \internal
+# alias.internal = disable
+# macro.internal.HTML = "<span style="color:red">[internal]</span>"
diff --git a/doc/global/qt-cpp-defines.qdocconf b/doc/global/qt-cpp-defines.qdocconf
index e185c20b8f..4dbe144913 100644
--- a/doc/global/qt-cpp-defines.qdocconf
+++ b/doc/global/qt-cpp-defines.qdocconf
@@ -113,7 +113,6 @@ Cpp.ignoretokens += \
Q_GUI_EXPORT_STYLE_POCKETPC \
Q_GUI_EXPORT_STYLE_SGI \
Q_GUI_EXPORT_STYLE_WINDOWS \
- Q_GUI_EXPORT_STYLE_WINDOWSXP \
Q_INLINE_TEMPLATE \
Q_INTERNAL_WIN_NO_THROW \
Q_INVOKABLE \
diff --git a/examples/dbus/remotecontrolledcar/car/car.cpp b/examples/dbus/remotecontrolledcar/car/car.cpp
index 67daac79ba..2de4e6447a 100644
--- a/examples/dbus/remotecontrolledcar/car/car.cpp
+++ b/examples/dbus/remotecontrolledcar/car/car.cpp
@@ -50,9 +50,7 @@
#include "car.h"
#include <QtWidgets/QtWidgets>
-#include <math.h>
-
-static const double Pi = 3.14159265358979323846264338327950288419717;
+#include <qmath.h>
QRectF Car::boundingRect() const
{
@@ -135,10 +133,10 @@ void Car::timerEvent(QTimerEvent *event)
Q_UNUSED(event);
const qreal axelDistance = 54;
- qreal wheelsAngleRads = (wheelsAngle * Pi) / 180;
+ qreal wheelsAngleRads = qDegreesToRadians(wheelsAngle);
qreal turnDistance = ::cos(wheelsAngleRads) * axelDistance * 2;
qreal turnRateRads = wheelsAngleRads / turnDistance; // rough estimate
- qreal turnRate = (turnRateRads * 180) / Pi;
+ qreal turnRate = qRadiansToDegrees(turnRateRads);
qreal rotation = speed * turnRate;
setTransform(QTransform().rotate(rotation), true);
diff --git a/examples/embedded/lightmaps/lightmaps.cpp b/examples/embedded/lightmaps/lightmaps.cpp
index a8bc13beaf..6334530c3a 100644
--- a/examples/embedded/lightmaps/lightmaps.cpp
+++ b/examples/embedded/lightmaps/lightmaps.cpp
@@ -52,15 +52,9 @@
#include <QtWidgets>
#include <QtNetwork>
-#include <math.h>
-
#include "lightmaps.h"
#include "slippymap.h"
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
// how long (milliseconds) the user need to hold (after a tap on the screen)
// before triggering the magnifying glass feature
// 701, a prime number, is the sum of 229, 233, 239
diff --git a/examples/embedded/lightmaps/slippymap.cpp b/examples/embedded/lightmaps/slippymap.cpp
index 7e847c2501..ff43261700 100644
--- a/examples/embedded/lightmaps/slippymap.cpp
+++ b/examples/embedded/lightmaps/slippymap.cpp
@@ -48,15 +48,10 @@
**
****************************************************************************/
-#include <math.h>
-
#include <QtWidgets>
#include <QtNetwork>
#include "slippymap.h"
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
+#include "qmath.h"
uint qHash(const QPoint& p)
{
@@ -68,10 +63,10 @@ const int tdim = 256;
QPointF tileForCoordinate(qreal lat, qreal lng, int zoom)
{
+ qreal radianLat = qDegreesToRadians(lat);
qreal zn = static_cast<qreal>(1 << zoom);
qreal tx = (lng + 180.0) / 360.0;
- qreal ty = (1.0 - log(tan(lat * M_PI / 180.0) +
- 1.0 / cos(lat * M_PI / 180.0)) / M_PI) / 2.0;
+ qreal ty = 0.5 - log(tan(radianLat) + 1.0 / cos(radianLat)) / M_PI / 2.0;
return QPointF(tx * zn, ty * zn);
}
@@ -86,8 +81,7 @@ qreal latitudeFromTile(qreal ty, int zoom)
{
qreal zn = static_cast<qreal>(1 << zoom);
qreal n = M_PI - 2 * M_PI * ty / zn;
- qreal lng = 180.0 / M_PI * atan(0.5 * (exp(n) - exp(-n)));
- return lng;
+ return qRadiansToDegrees(atan(sinh(n)));
}
diff --git a/examples/embedded/raycasting/raycasting.cpp b/examples/embedded/raycasting/raycasting.cpp
index 992c383db1..d37b9f5d2e 100644
--- a/examples/embedded/raycasting/raycasting.cpp
+++ b/examples/embedded/raycasting/raycasting.cpp
@@ -50,12 +50,7 @@
#include <QtCore>
#include <QtWidgets>
-
-#include <math.h>
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
+#include <qmath.h>
#define WORLD_SIZE 8
int world_map[WORLD_SIZE][WORLD_SIZE] = {
diff --git a/examples/examples.pro b/examples/examples.pro
index a3851c6d81..4ec5ca60e2 100644
--- a/examples/examples.pro
+++ b/examples/examples.pro
@@ -14,7 +14,11 @@ qtHaveModule(concurrent): SUBDIRS += qtconcurrent
qtHaveModule(sql): SUBDIRS += sql
qtHaveModule(widgets): SUBDIRS += widgets
qtHaveModule(xml): SUBDIRS += xml
-qtHaveModule(gui): SUBDIRS += gui opengl
+qtHaveModule(gui) {
+ SUBDIRS += gui
+ qtConfig(opengl): SUBDIRS += opengl
+ qtConfig(vulkan): SUBDIRS += vulkan
+}
aggregate.files = aggregate/examples.pro
aggregate.path = $$[QT_INSTALL_EXAMPLES]
diff --git a/examples/opengl/hellowindow/hellowindow.cpp b/examples/opengl/hellowindow/hellowindow.cpp
index dc48cc4b76..048190d766 100644
--- a/examples/opengl/hellowindow/hellowindow.cpp
+++ b/examples/opengl/hellowindow/hellowindow.cpp
@@ -93,6 +93,8 @@ HelloWindow::HelloWindow(const QSharedPointer<Renderer> &renderer, QScreen *scre
void HelloWindow::exposeEvent(QExposeEvent *)
{
m_renderer->setAnimating(this, isExposed());
+ if (isExposed())
+ m_renderer->render();
}
void HelloWindow::mousePressEvent(QMouseEvent *)
@@ -276,21 +278,20 @@ void Renderer::createGeometry()
extrude(x4, y4, y4, x4);
extrude(y4, x4, y3, x3);
- const qreal Pi = 3.14159f;
const int NumSectors = 100;
-
+ const qreal sectorAngle = 2 * qreal(M_PI) / NumSectors;
for (int i = 0; i < NumSectors; ++i) {
- qreal angle1 = (i * 2 * Pi) / NumSectors;
- qreal x5 = 0.30 * qSin(angle1);
- qreal y5 = 0.30 * qCos(angle1);
- qreal x6 = 0.20 * qSin(angle1);
- qreal y6 = 0.20 * qCos(angle1);
-
- qreal angle2 = ((i + 1) * 2 * Pi) / NumSectors;
- qreal x7 = 0.20 * qSin(angle2);
- qreal y7 = 0.20 * qCos(angle2);
- qreal x8 = 0.30 * qSin(angle2);
- qreal y8 = 0.30 * qCos(angle2);
+ qreal angle = i * sectorAngle;
+ qreal x5 = 0.30 * qSin(angle);
+ qreal y5 = 0.30 * qCos(angle);
+ qreal x6 = 0.20 * qSin(angle);
+ qreal y6 = 0.20 * qCos(angle);
+
+ angle += sectorAngle;
+ qreal x7 = 0.20 * qSin(angle);
+ qreal y7 = 0.20 * qCos(angle);
+ qreal x8 = 0.30 * qSin(angle);
+ qreal y8 = 0.30 * qCos(angle);
quad(x5, y5, x6, y6, x7, y7, x8, y8);
diff --git a/examples/opengl/hellowindow/hellowindow.h b/examples/opengl/hellowindow/hellowindow.h
index 1372152e93..e92e45a125 100644
--- a/examples/opengl/hellowindow/hellowindow.h
+++ b/examples/opengl/hellowindow/hellowindow.h
@@ -70,7 +70,7 @@ public:
void setAnimating(HelloWindow *window, bool animating);
-private slots:
+public slots:
void render();
private:
diff --git a/examples/opengl/legacy/framebufferobject2/glwidget.cpp b/examples/opengl/legacy/framebufferobject2/glwidget.cpp
index ac8deddd1f..f14d31aff6 100644
--- a/examples/opengl/legacy/framebufferobject2/glwidget.cpp
+++ b/examples/opengl/legacy/framebufferobject2/glwidget.cpp
@@ -50,8 +50,7 @@
#include "glwidget.h"
#include <QtGui/QImage>
-
-#include <math.h>
+#include <qmath.h>
static GLint cubeArray[][3] = {
{0, 0, 0}, {0, 1, 0}, {1, 1, 0}, {1, 0, 0},
@@ -253,6 +252,6 @@ void GLWidget::drawCube(int i, GLfloat z, GLfloat rotation, GLfloat jmp, GLfloat
xOffs[i] = xOffs[i] > 1.0f ? 1.0f : -1.0f;
}
xOffs[i] += xInc[i];
- yOffs[i] = qAbs(cos((-3.141592f * jmp) * xOffs[i]) * amp) - 1;
+ yOffs[i] = qAbs(cos((-GLfloat(M_PI) * jmp) * xOffs[i]) * amp) - 1;
rot[i] += rotation;
}
diff --git a/examples/opengl/legacy/grabber/glwidget.cpp b/examples/opengl/legacy/grabber/glwidget.cpp
index 958b8055cd..6be4d30597 100644
--- a/examples/opengl/legacy/grabber/glwidget.cpp
+++ b/examples/opengl/legacy/grabber/glwidget.cpp
@@ -52,8 +52,7 @@
#include <QMouseEvent>
#include <QTimer>
-
-#include <math.h>
+#include <qmath.h>
GLWidget::GLWidget(QWidget *parent)
: QGLWidget(parent)
@@ -190,8 +189,6 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
GLdouble outerRadius, GLdouble thickness,
GLdouble toothSize, GLint toothCount)
{
- const double Pi = 3.14159265358979323846;
-
GLuint list = glGenLists(1);
glNewList(list, GL_COMPILE);
glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, reflectance);
@@ -199,7 +196,8 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
GLdouble r0 = innerRadius;
GLdouble r1 = outerRadius - toothSize / 2.0;
GLdouble r2 = outerRadius + toothSize / 2.0;
- GLdouble delta = (2.0 * Pi / toothCount) / 4.0;
+ GLdouble toothAngle = 2 * M_PI / toothCount;
+ GLdouble delta = toothAngle / 4.0;
GLdouble z = thickness / 2.0;
glShadeModel(GL_FLAT);
@@ -211,7 +209,7 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
glBegin(GL_QUAD_STRIP);
for (int j = 0; j <= toothCount; ++j) {
- GLdouble angle = 2.0 * Pi * j / toothCount;
+ GLdouble angle = j * toothAngle;
glVertex3d(r0 * cos(angle), r0 * sin(angle), sign * z);
glVertex3d(r1 * cos(angle), r1 * sin(angle), sign * z);
glVertex3d(r0 * cos(angle), r0 * sin(angle), sign * z);
@@ -221,7 +219,7 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
glBegin(GL_QUADS);
for (int j = 0; j < toothCount; ++j) {
- GLdouble angle = 2.0 * Pi * j / toothCount;
+ GLdouble angle = j * toothAngle;
glVertex3d(r1 * cos(angle), r1 * sin(angle), sign * z);
glVertex3d(r2 * cos(angle + delta), r2 * sin(angle + delta), sign * z);
glVertex3d(r2 * cos(angle + 2 * delta), r2 * sin(angle + 2 * delta), sign * z);
@@ -233,7 +231,7 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
glBegin(GL_QUAD_STRIP);
for (int i = 0; i < toothCount; ++i) {
for (int j = 0; j < 2; ++j) {
- GLdouble angle = 2.0 * Pi * (i + j / 2.0) / toothCount;
+ GLdouble angle = (i + j / 2.0) * toothAngle;
GLdouble s1 = r1;
GLdouble s2 = r2;
if (j == 1)
@@ -257,7 +255,7 @@ GLuint GLWidget::makeGear(const GLfloat *reflectance, GLdouble innerRadius,
glBegin(GL_QUAD_STRIP);
for (int i = 0; i <= toothCount; ++i) {
- GLdouble angle = i * 2.0 * Pi / toothCount;
+ GLdouble angle = i * toothAngle;
glNormal3d(-cos(angle), -sin(angle), 0.0);
glVertex3d(r0 * cos(angle), r0 * sin(angle), +z);
glVertex3d(r0 * cos(angle), r0 * sin(angle), -z);
diff --git a/examples/opengl/legacy/pbuffers2/glwidget.cpp b/examples/opengl/legacy/pbuffers2/glwidget.cpp
index c99f9e40fa..c710d03cab 100644
--- a/examples/opengl/legacy/pbuffers2/glwidget.cpp
+++ b/examples/opengl/legacy/pbuffers2/glwidget.cpp
@@ -49,10 +49,9 @@
****************************************************************************/
#include <QtGui/QImage>
+#include <qmath.h>
#include "glwidget.h"
-#include <math.h>
-
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
#endif
@@ -291,8 +290,6 @@ void GLWidget::restoreGLState()
glPopAttrib();
}
-#define PI 3.14159
-
void GLWidget::timerEvent(QTimerEvent *)
{
if (QApplication::mouseButtons() != 0)
@@ -305,31 +302,27 @@ void GLWidget::timerEvent(QTimerEvent *)
else if (!scale_in && scale < .5f)
scale_in = true;
- scale = scale_in ? scale + scale*0.01f : scale-scale*0.01f;
+ scale *= scale_in ? 1.01f : 0.99f;
rot_z += 0.3f;
rot_x += 0.1f;
- int dx, dy; // disturbance point
- float s, v, W, t;
- int i, j;
- static float wt[128][128];
+ static float wt = 0.0;
+ wt += 0.1f;
+
const int width = logo.width();
+ const int dx = width >> 1, dy = dx; // disturbance point
+ const float v = -4; // wave speed
+ const float W = .3f;
const int AMP = 5;
- dx = dy = width >> 1;
-
- W = .3f;
- v = -4; // wave speed
-
- for (i = 0; i < width; ++i) {
- for ( j = 0; j < width; ++j) {
- s = sqrt((double) ((j - dx) * (j - dx) + (i - dy) * (i - dy)));
- wt[i][j] += 0.1f;
- t = s / v;
+ for (int i = 0; i < width; ++i) {
+ for (int j = 0; j < width; ++j) {
+ const float s = hypot(j - dx, i - dy);
+ const double raw = AMP * sin(2 * M_PI * W * (wt + s / v));
if (s != 0)
- wave[i*width + j] = AMP * sin(2 * PI * W * (wt[i][j] + t)) / (0.2*(s + 2));
+ wave[i * width + j] = raw / (0.2 * (s + 2));
else
- wave[i*width + j] = AMP * sin(2 * PI * W * (wt[i][j] + t));
+ wave[i * width + j] = raw;
}
}
}
diff --git a/examples/opengl/legacy/samplebuffers/glwidget.cpp b/examples/opengl/legacy/samplebuffers/glwidget.cpp
index 14c59c9143..da30de4d55 100644
--- a/examples/opengl/legacy/samplebuffers/glwidget.cpp
+++ b/examples/opengl/legacy/samplebuffers/glwidget.cpp
@@ -49,7 +49,7 @@
****************************************************************************/
#include "glwidget.h"
-#include <math.h>
+#include <qmath.h>
#ifndef GL_MULTISAMPLE
#define GL_MULTISAMPLE 0x809D
@@ -116,7 +116,6 @@ void GLWidget::timerEvent(QTimerEvent *)
void GLWidget::makeObject()
{
QColor qtGreen(QColor::fromCmykF(0.40, 0.0, 1.0, 0.0));
- const double Pi = 3.14159265358979323846;
const int NumSectors = 15;
GLdouble x1 = +0.06;
GLdouble y1 = -0.14;
@@ -130,18 +129,19 @@ void GLWidget::makeObject()
list = glGenLists(1);
glNewList(list, GL_COMPILE);
{
+ const double sectorAngle = 2 * M_PI / NumSectors;
for (int i = 0; i < NumSectors; ++i) {
- double angle1 = (i * 2 * Pi) / NumSectors;
- GLdouble x5 = 0.30 * sin(angle1);
- GLdouble y5 = 0.30 * cos(angle1);
- GLdouble x6 = 0.20 * sin(angle1);
- GLdouble y6 = 0.20 * cos(angle1);
-
- double angle2 = ((i + 1) * 2 * Pi) / NumSectors;
- GLdouble x7 = 0.20 * sin(angle2);
- GLdouble y7 = 0.20 * cos(angle2);
- GLdouble x8 = 0.30 * sin(angle2);
- GLdouble y8 = 0.30 * cos(angle2);
+ double angle = i * sectorAngle;
+ GLdouble x5 = 0.30 * sin(angle);
+ GLdouble y5 = 0.30 * cos(angle);
+ GLdouble x6 = 0.20 * sin(angle);
+ GLdouble y6 = 0.20 * cos(angle);
+
+ angle += sectorAngle;
+ GLdouble x7 = 0.20 * sin(angle);
+ GLdouble y7 = 0.20 * cos(angle);
+ GLdouble x8 = 0.30 * sin(angle);
+ GLdouble y8 = 0.30 * cos(angle);
qglColor(qtGreen);
quad(GL_QUADS, x5, y5, x6, y6, x7, y7, x8, y8);
diff --git a/examples/opengl/qopenglwidget/glwidget.cpp b/examples/opengl/qopenglwidget/glwidget.cpp
index 21d922d713..40a1258dd5 100644
--- a/examples/opengl/qopenglwidget/glwidget.cpp
+++ b/examples/opengl/qopenglwidget/glwidget.cpp
@@ -54,13 +54,17 @@
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QCoreApplication>
-#include <math.h>
+#include <qmath.h>
#include "mainwindow.h"
#include "bubble.h"
const int bubbleNum = 8;
+#ifndef GL_SRGB8_ALPHA8
+#define GL_SRGB8_ALPHA8 0x8C43
+#endif
+
GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background)
: m_mainWindow(mw),
m_showBubbles(true),
@@ -75,6 +79,8 @@ GLWidget::GLWidget(MainWindow *mw, bool button, const QColor &background)
m_background(background)
{
setMinimumSize(300, 250);
+ if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
+ setTextureFormat(GL_SRGB8_ALPHA8);
}
GLWidget::~GLWidget()
@@ -449,21 +455,21 @@ void GLWidget::createGeometry()
extrude(x4, y4, y4, x4);
extrude(y4, x4, y3, x3);
- const qreal Pi = 3.14159f;
const int NumSectors = 100;
+ const qreal sectorAngle = 2 * qreal(M_PI) / NumSectors;
for (int i = 0; i < NumSectors; ++i) {
- qreal angle1 = (i * 2 * Pi) / NumSectors;
- qreal x5 = 0.30 * sin(angle1);
- qreal y5 = 0.30 * cos(angle1);
- qreal x6 = 0.20 * sin(angle1);
- qreal y6 = 0.20 * cos(angle1);
-
- qreal angle2 = ((i + 1) * 2 * Pi) / NumSectors;
- qreal x7 = 0.20 * sin(angle2);
- qreal y7 = 0.20 * cos(angle2);
- qreal x8 = 0.30 * sin(angle2);
- qreal y8 = 0.30 * cos(angle2);
+ qreal angle = i * sectorAngle;
+ qreal x5 = 0.30 * sin(angle);
+ qreal y5 = 0.30 * cos(angle);
+ qreal x6 = 0.20 * sin(angle);
+ qreal y6 = 0.20 * cos(angle);
+
+ angle += sectorAngle;
+ qreal x7 = 0.20 * sin(angle);
+ qreal y7 = 0.20 * cos(angle);
+ qreal x8 = 0.30 * sin(angle);
+ qreal y8 = 0.30 * cos(angle);
quad(x5, y5, x6, y6, x7, y7, x8, y8);
diff --git a/examples/opengl/qopenglwidget/main.cpp b/examples/opengl/qopenglwidget/main.cpp
index d7aa791142..f9b5731b8f 100644
--- a/examples/opengl/qopenglwidget/main.cpp
+++ b/examples/opengl/qopenglwidget/main.cpp
@@ -61,6 +61,8 @@ int main( int argc, char ** argv )
QSurfaceFormat format;
format.setDepthBufferSize(24);
format.setStencilBufferSize(8);
+ if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
+ format.setColorSpace(QSurfaceFormat::sRGBColorSpace);
if (QCoreApplication::arguments().contains(QStringLiteral("--multisample")))
format.setSamples(4);
QSurfaceFormat::setDefaultFormat(format);
diff --git a/examples/opengl/qopenglwindow/background.frag b/examples/opengl/qopenglwindow/background.frag
index eecb6d3120..4af85aae8e 100644
--- a/examples/opengl/qopenglwindow/background.frag
+++ b/examples/opengl/qopenglwindow/background.frag
@@ -1,4 +1,4 @@
-#define M_PI 3.1415926535897932384626433832795
+#define M_PI 3.14159265358979323846
#define SPEED 10000.0
uniform int currentTime;
diff --git a/examples/opengl/threadedqopenglwidget/glwidget.cpp b/examples/opengl/threadedqopenglwidget/glwidget.cpp
index f9738db2e5..cc528a734a 100644
--- a/examples/opengl/threadedqopenglwidget/glwidget.cpp
+++ b/examples/opengl/threadedqopenglwidget/glwidget.cpp
@@ -49,7 +49,7 @@
****************************************************************************/
#include "glwidget.h"
-#include <math.h>
+#include <qmath.h>
#include <QGuiApplication>
GLWidget::GLWidget(QWidget *parent)
@@ -282,21 +282,21 @@ void Renderer::createGeometry()
extrude(x4, y4, y4, x4);
extrude(y4, x4, y3, x3);
- const qreal Pi = 3.14159f;
const int NumSectors = 100;
+ const qreal sectorAngle = 2 * qreal(M_PI) / NumSectors;
for (int i = 0; i < NumSectors; ++i) {
- qreal angle1 = (i * 2 * Pi) / NumSectors;
- qreal x5 = 0.30 * sin(angle1);
- qreal y5 = 0.30 * cos(angle1);
- qreal x6 = 0.20 * sin(angle1);
- qreal y6 = 0.20 * cos(angle1);
-
- qreal angle2 = ((i + 1) * 2 * Pi) / NumSectors;
- qreal x7 = 0.20 * sin(angle2);
- qreal y7 = 0.20 * cos(angle2);
- qreal x8 = 0.30 * sin(angle2);
- qreal y8 = 0.30 * cos(angle2);
+ qreal angle = i * sectorAngle;
+ qreal x5 = 0.30 * sin(angle);
+ qreal y5 = 0.30 * cos(angle);
+ qreal x6 = 0.20 * sin(angle);
+ qreal y6 = 0.20 * cos(angle);
+
+ angle += sectorAngle;
+ qreal x7 = 0.20 * sin(angle);
+ qreal y7 = 0.20 * cos(angle);
+ qreal x8 = 0.30 * sin(angle);
+ qreal y8 = 0.30 * cos(angle);
quad(x5, y5, x6, y6, x7, y7, x8, y8);
diff --git a/examples/sql/doc/src/drilldown.qdoc b/examples/sql/doc/src/drilldown.qdoc
index 1fcac41eeb..29c0b613f6 100644
--- a/examples/sql/doc/src/drilldown.qdoc
+++ b/examples/sql/doc/src/drilldown.qdoc
@@ -163,7 +163,7 @@
submitted to the database until the user expliclity requests a
submit (the alternative is QDataWidgetMapper::AutoSubmit,
automatically submitting changes when the corresponding widget
- looses focus). Finally, we specify the item delegate the mapper
+ loses focus). Finally, we specify the item delegate the mapper
view should use for its items. The QSqlRelationalDelegate class
represents a delegate that unlike the default delegate, enables
combobox functionality for fields that are foreign keys into other
diff --git a/examples/touch/pinchzoom/mouse.cpp b/examples/touch/pinchzoom/mouse.cpp
index f063e96654..7f8c238e6f 100644
--- a/examples/touch/pinchzoom/mouse.cpp
+++ b/examples/touch/pinchzoom/mouse.cpp
@@ -53,11 +53,10 @@
#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOption>
+#include <qmath.h>
-#include <math.h>
-
-static const double Pi = 3.14159265358979323846264338327950288419717;
-static double TwoPi = 2.0 * Pi;
+const qreal Pi = M_PI;
+const qreal TwoPi = 2 * M_PI;
static qreal normalizeAngle(qreal angle)
{
@@ -139,9 +138,7 @@ void Mouse::timerEvent(QTimerEvent *)
//! [5]
QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));
if (lineToCenter.length() > 150) {
- qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length());
- if (lineToCenter.dy() < 0)
- angleToCenter = TwoPi - angleToCenter;
+ qreal angleToCenter = std::atan2(lineToCenter.dy(), lineToCenter.dx());
angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);
if (angleToCenter < Pi && angleToCenter > Pi / 4) {
@@ -170,9 +167,7 @@ void Mouse::timerEvent(QTimerEvent *)
continue;
QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));
- qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length());
- if (lineToMouse.dy() < 0)
- angleToMouse = TwoPi - angleToMouse;
+ qreal angleToMouse = std::atan2(lineToMouse.dy(), lineToMouse.dx());
angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);
if (angleToMouse >= 0 && angleToMouse < Pi / 2) {
diff --git a/examples/vulkan/doc/images/hellovulkancubes.png b/examples/vulkan/doc/images/hellovulkancubes.png
new file mode 100644
index 0000000000..c3d819c047
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkancubes.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkantexture.png b/examples/vulkan/doc/images/hellovulkantexture.png
new file mode 100644
index 0000000000..0cb47a70be
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkantexture.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkantriangle.png b/examples/vulkan/doc/images/hellovulkantriangle.png
new file mode 100644
index 0000000000..f88b27a873
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkantriangle.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkanwidget.png b/examples/vulkan/doc/images/hellovulkanwidget.png
new file mode 100644
index 0000000000..b85d4dc596
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkanwidget.png
Binary files differ
diff --git a/examples/vulkan/doc/images/hellovulkanwindow.png b/examples/vulkan/doc/images/hellovulkanwindow.png
new file mode 100644
index 0000000000..c55029312c
--- /dev/null
+++ b/examples/vulkan/doc/images/hellovulkanwindow.png
Binary files differ
diff --git a/examples/vulkan/doc/src/hellovulkancubes.qdoc b/examples/vulkan/doc/src/hellovulkancubes.qdoc
new file mode 100644
index 0000000000..934d2015a1
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkancubes.qdoc
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkancubes
+ \title Hello Vulkan Cubes Example
+ \ingroup examples-vulkan
+ \brief Shows the basics of using QVulkanWindow
+
+ The \e{Hello Vulkan Cubes Example} shows more advanced usage of QVulkanWindow.
+
+ \image hellovulkancubes.png
+
+ In this example there is a mesh loaded from a file and two different
+ materials and corresponding graphics pipelines. The rounded cubes are drawn
+ using instancing and feature a Phong lighting model with a single
+ directional light.
+
+ Unlike hellovulkantexture and hellovulkantriangle, the uniform buffer
+ handling takes an alternative approach here: dynamic uniform buffers are
+ used instead of multiple descriptor sets.
+
+ The example requires QtConcurrent since it demonstrates simple usage of
+ QtConcurrent::run(), QFuture, and QFutureWatcher in combination of
+ QVulkanWindow. Mesh and shader data loading, the potentially expensive
+ graphics pipeline construction, and the building of the frame command buffer
+ are all done in separate worker threads.
+
+ The scene is embedded into a widget-based user interface. The QVulkanWindow
+ subclass handles mouse and keyboard input as well since it provides a
+ first-person style camera in order to allow moving around in the scene.
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/doc/src/hellovulkantexture.qdoc b/examples/vulkan/doc/src/hellovulkantexture.qdoc
new file mode 100644
index 0000000000..d0e0ca90a8
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkantexture.qdoc
@@ -0,0 +1,41 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkantexture
+ \ingroup examples-vulkan
+ \title Hello Vulkan Texture Vulkan Example
+ \brief Shows the basics of rendering with textures in a QVulkanWindow
+
+ The \e{Hello Vulkan Texture Example} builds on \l hellovulkantriangle. Here
+ instead of drawing a single triangle, a triangle strip is drawn in order to
+ get a quad on the screen. This is then textured using a QImage loaded from
+ a .png image file.
+
+ \image hellovulkantexture.png
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/doc/src/hellovulkantriangle.qdoc b/examples/vulkan/doc/src/hellovulkantriangle.qdoc
new file mode 100644
index 0000000000..81af776ea1
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkantriangle.qdoc
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkantriangle
+ \ingroup examples-vulkan
+ \title Hello Vulkan Triangle Example
+ \brief Shows the basics of rendering with QVulkanWindow and the Vulkan API
+
+ The \e{Hello Vulkan Triangle Example} builds on \l hellovulkanwindow. This
+ time a full graphics pipeline is created, including a vertex and fragment
+ shader. This pipeline is then used to render a triangle.
+
+ \image hellovulkantriangle.png
+
+ The example also demonstrates multisample antialiasing. Based on the
+ supported sample counts reported by QVulkanWindow::supportedSampleCounts()
+ the example chooses between 8x, 4x, or no multisampling. Once configured
+ via QVulkanWindow::setSamples(), QVulkanWindow takes care of the rest: the
+ additional multisample color buffers are created automatically, and
+ resolving into the swapchain buffers is performed at the end of the default
+ render pass for each frame.
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/doc/src/hellovulkanwidget.qdoc b/examples/vulkan/doc/src/hellovulkanwidget.qdoc
new file mode 100644
index 0000000000..7987bdeff9
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkanwidget.qdoc
@@ -0,0 +1,49 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkanwidget
+ \ingroup examples-vulkan
+ \title Hello Vulkan Widget Example
+ \brief Shows the usage of QVulkanWindow in QWidget applications
+
+ The \e{Hello Vulkan Widget Example} is a variant of \l hellovulkantriangle
+ that embeds the QVulkanWindow into a QWidget-based user interface using
+ QWidget::createWindowContainer().
+
+ \image hellovulkanwidget.png
+
+ The code to set up the Vulkan pipeline and render the triangle is the same
+ as in \l hellovulkantriangle. In addition, this example demonstrates
+ another feature of QVulkanWindow: reading the image content back from the
+ color buffer into a QImage. By clicking the Grab button, the example
+ renders the next frame and follows it up with a transfer operation in order
+ to get the swapchain color buffer content copied into host accessible
+ memory. The image is then saved to disk via QImage::save().
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/doc/src/hellovulkanwindow.qdoc b/examples/vulkan/doc/src/hellovulkanwindow.qdoc
new file mode 100644
index 0000000000..06cc9c1c28
--- /dev/null
+++ b/examples/vulkan/doc/src/hellovulkanwindow.qdoc
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \example hellovulkanwindow
+ \title Hello Vulkan Window Example
+ \ingroup examples-vulkan
+ \brief Shows the basics of using QVulkanWindow
+
+ The \e{Hello Vulkan Window Example} shows the basics of using QVulkanWindow
+ in order to display rendering with the Vulkan graphics API on systems that
+ support this.
+
+ \image hellovulkanwindow.png
+
+ In this example there will be no actual rendering: it simply begins and
+ ends a render pass, which results in clearing the buffers to a fixed value.
+ The color buffer clear value changes on every frame.
+
+ \section1 Startup
+
+ Each Qt application using Vulkan will have to have a \c{Vulkan instance}
+ which encapsulates application-level state and initializes a Vulkan library.
+
+ A QVulkanWindow must always be associated with a QVulkanInstance and hence
+ the example performs instance creation before the window. The
+ QVulkanInstance object must also outlive the window.
+
+ \snippet hellovulkanwindow/main.cpp 0
+
+ The example enables validation layers, when supported. When the requested
+ layers are not present, the request will be ignored. Additional layers and
+ extensions can be enabled in a similar manner.
+
+ \snippet hellovulkanwindow/main.cpp 1
+
+ Once the instance is ready, it is time to create a window. Note that \c w
+ lives on the stack and is declared after \c inst.
+
+ \section1 The QVulkanWindow Subclass
+
+ To add custom functionality to a QVulkanWindow, subclassing is used. This
+ follows the existing patterns from QOpenGLWindow and QOpenGLWidget.
+ However, QVulkanWindow utilizes a separate QVulkanWindowRenderer object.
+ This resembles QQuickFramebufferObject, and allows better separation of the
+ functions that are supposed to be reimplemented.
+
+ \snippet hellovulkanwindow/hellovulkanwindow.h 0
+
+ The QVulkanWindow subclass reimplements the factory function
+ QVulkanWindow::createRenderer(). This simply returns a new instance of the
+ QVulkanWindowRenderer subclass. In order to be able to access various
+ Vulkan resources via the window object, a pointer to the window is passed
+ and stored via the constructor.
+
+ \snippet hellovulkanwindow/hellovulkanwindow.cpp 0
+
+ Graphics resource creation and destruction is typically done in one of the
+ init - resource functions.
+
+ \snippet hellovulkanwindow/hellovulkanwindow.cpp 1
+
+ \section1 The Actual Rendering
+
+ QVulkanWindow subclasses queue their draw calls in their reimplementation
+ of QVulkanWindowRenderer::startNextFrame(). Once done, they are required to
+ call back QVulkanWindow::frameReady(). The example has no asynchronous
+ command generation, so the frameReady() call is made directly from
+ startNextFrame().
+
+ \snippet hellovulkanwindow/hellovulkanwindow.cpp 2
+
+ To get continuous updates, the example simply invokes
+ QWindow::requestUpdate() in order to schedule a repaint.
+
+ \include examples-run.qdocinc
+*/
diff --git a/examples/vulkan/hellovulkancubes/camera.cpp b/examples/vulkan/hellovulkancubes/camera.cpp
new file mode 100644
index 0000000000..64dee03154
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/camera.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "camera.h"
+
+Camera::Camera(const QVector3D &pos)
+ : m_forward(0.0f, 0.0f, -1.0f),
+ m_right(1.0f, 0.0f, 0.0f),
+ m_up(0.0f, 1.0f, 0.0f),
+ m_pos(pos),
+ m_yaw(0.0f),
+ m_pitch(0.0f)
+{
+}
+
+static inline void clamp360(float *v)
+{
+ if (*v > 360.0f)
+ *v -= 360.0f;
+ if (*v < -360.0f)
+ *v += 360.0f;
+}
+
+void Camera::yaw(float degrees)
+{
+ m_yaw += degrees;
+ clamp360(&m_yaw);
+ m_yawMatrix.setToIdentity();
+ m_yawMatrix.rotate(m_yaw, 0, 1, 0);
+
+ QMatrix4x4 rotMat = m_pitchMatrix * m_yawMatrix;
+ m_forward = (QVector4D(0.0f, 0.0f, -1.0f, 0.0f) * rotMat).toVector3D();
+ m_right = (QVector4D(1.0f, 0.0f, 0.0f, 0.0f) * rotMat).toVector3D();
+}
+
+void Camera::pitch(float degrees)
+{
+ m_pitch += degrees;
+ clamp360(&m_pitch);
+ m_pitchMatrix.setToIdentity();
+ m_pitchMatrix.rotate(m_pitch, 1, 0, 0);
+
+ QMatrix4x4 rotMat = m_pitchMatrix * m_yawMatrix;
+ m_forward = (QVector4D(0.0f, 0.0f, -1.0f, 0.0f) * rotMat).toVector3D();
+ m_up = (QVector4D(0.0f, 1.0f, 0.0f, 0.0f) * rotMat).toVector3D();
+}
+
+void Camera::walk(float amount)
+{
+ m_pos[0] += amount * m_forward.x();
+ m_pos[2] += amount * m_forward.z();
+}
+
+void Camera::strafe(float amount)
+{
+ m_pos[0] += amount * m_right.x();
+ m_pos[2] += amount * m_right.z();
+}
+
+QMatrix4x4 Camera::viewMatrix() const
+{
+ QMatrix4x4 m = m_pitchMatrix * m_yawMatrix;
+ m.translate(-m_pos);
+ return m;
+}
diff --git a/examples/vulkan/hellovulkancubes/camera.h b/examples/vulkan/hellovulkancubes/camera.h
new file mode 100644
index 0000000000..c5c579f066
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/camera.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef CAMERA_H
+#define CAMERA_H
+
+#include <QVector3D>
+#include <QMatrix4x4>
+
+class Camera
+{
+public:
+ Camera(const QVector3D &pos);
+
+ void yaw(float degrees);
+ void pitch(float degrees);
+ void walk(float amount);
+ void strafe(float amount);
+
+ QMatrix4x4 viewMatrix() const;
+
+private:
+ QVector3D m_forward;
+ QVector3D m_right;
+ QVector3D m_up;
+ QVector3D m_pos;
+ float m_yaw;
+ float m_pitch;
+ QMatrix4x4 m_yawMatrix;
+ QMatrix4x4 m_pitchMatrix;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/color.frag b/examples/vulkan/hellovulkancubes/color.frag
new file mode 100644
index 0000000000..3b04955963
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color.frag
@@ -0,0 +1,12 @@
+#version 440
+
+layout(push_constant) uniform PC {
+ layout(offset = 64) vec3 color;
+} pc;
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(pc.color, 1.0);
+}
diff --git a/examples/vulkan/hellovulkancubes/color.vert b/examples/vulkan/hellovulkancubes/color.vert
new file mode 100644
index 0000000000..19bf815819
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color.vert
@@ -0,0 +1,14 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+layout(push_constant) uniform PC {
+ mat4 mvp;
+} pc;
+
+void main()
+{
+ gl_Position = pc.mvp * position;
+}
diff --git a/examples/vulkan/hellovulkancubes/color_frag.spv b/examples/vulkan/hellovulkancubes/color_frag.spv
new file mode 100644
index 0000000000..bd72984ffe
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_frag.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/color_phong.frag b/examples/vulkan/hellovulkancubes/color_phong.frag
new file mode 100644
index 0000000000..8b0c715f3b
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong.frag
@@ -0,0 +1,39 @@
+#version 440
+
+layout(location = 0) in vec3 vECVertNormal;
+layout(location = 1) in vec3 vECVertPos;
+layout(location = 2) flat in vec3 vDiffuseAdjust;
+
+layout(std140, binding = 1) uniform buf {
+ vec3 ECCameraPosition;
+ vec3 ka;
+ vec3 kd;
+ vec3 ks;
+ // Have one light only for now.
+ vec3 ECLightPosition;
+ vec3 attenuation;
+ vec3 color;
+ float intensity;
+ float specularExp;
+} ubuf;
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ vec3 unnormL = ubuf.ECLightPosition - vECVertPos;
+ float dist = length(unnormL);
+ float att = 1.0 / (ubuf.attenuation.x + ubuf.attenuation.y * dist + ubuf.attenuation.z * dist * dist);
+
+ vec3 N = normalize(vECVertNormal);
+ vec3 L = normalize(unnormL);
+ float NL = max(0.0, dot(N, L));
+ vec3 dColor = att * ubuf.intensity * ubuf.color * NL;
+
+ vec3 R = reflect(-L, N);
+ vec3 V = normalize(ubuf.ECCameraPosition - vECVertPos);
+ float RV = max(0.0, dot(R, V));
+ vec3 sColor = att * ubuf.intensity * ubuf.color * pow(RV, ubuf.specularExp);
+
+ fragColor = vec4(ubuf.ka + (ubuf.kd + vDiffuseAdjust) * dColor + ubuf.ks * sColor, 1.0);
+}
diff --git a/examples/vulkan/hellovulkancubes/color_phong.vert b/examples/vulkan/hellovulkancubes/color_phong.vert
new file mode 100644
index 0000000000..a1d1552685
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong.vert
@@ -0,0 +1,32 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec3 normal;
+
+// Instanced attributes to variate the translation of the model and the diffuse
+// color of the material.
+layout(location = 2) in vec3 instTranslate;
+layout(location = 3) in vec3 instDiffuseAdjust;
+
+out gl_PerVertex { vec4 gl_Position; };
+layout(location = 0) out vec3 vECVertNormal;
+layout(location = 1) out vec3 vECVertPos;
+layout(location = 2) flat out vec3 vDiffuseAdjust;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 vp;
+ mat4 model;
+ mat3 modelNormal;
+} ubuf;
+
+void main()
+{
+ vECVertNormal = normalize(ubuf.modelNormal * normal);
+ mat4 t = mat4(1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ instTranslate.x, instTranslate.y, instTranslate.z, 1);
+ vECVertPos = vec3(t * ubuf.model * position);
+ vDiffuseAdjust = instDiffuseAdjust;
+ gl_Position = ubuf.vp * t * ubuf.model * position;
+}
diff --git a/examples/vulkan/hellovulkancubes/color_phong_frag.spv b/examples/vulkan/hellovulkancubes/color_phong_frag.spv
new file mode 100644
index 0000000000..a1a413533b
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong_frag.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/color_phong_vert.spv b/examples/vulkan/hellovulkancubes/color_phong_vert.spv
new file mode 100644
index 0000000000..3ede21e007
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_phong_vert.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/color_vert.spv b/examples/vulkan/hellovulkancubes/color_vert.spv
new file mode 100644
index 0000000000..3f708b7d07
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/color_vert.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkancubes/hellovulkancubes.pro b/examples/vulkan/hellovulkancubes/hellovulkancubes.pro
new file mode 100644
index 0000000000..f9a9c3cff1
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/hellovulkancubes.pro
@@ -0,0 +1,24 @@
+QT += widgets concurrent
+
+HEADERS += \
+ mainwindow.h \
+ vulkanwindow.h \
+ renderer.h \
+ mesh.h \
+ shader.h \
+ camera.h
+
+SOURCES += \
+ main.cpp \
+ mainwindow.cpp \
+ vulkanwindow.cpp \
+ renderer.cpp \
+ mesh.cpp \
+ shader.cpp \
+ camera.cpp
+
+RESOURCES += hellovulkancubes.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkancubes
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkancubes/hellovulkancubes.qrc b/examples/vulkan/hellovulkancubes/hellovulkancubes.qrc
new file mode 100644
index 0000000000..7b085e1875
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/hellovulkancubes.qrc
@@ -0,0 +1,10 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="block.buf">../shared/block.buf</file>
+ <file alias="qt_logo.buf">../shared/qt_logo.buf</file>
+ <file>color_phong_vert.spv</file>
+ <file>color_phong_frag.spv</file>
+ <file>color_vert.spv</file>
+ <file>color_frag.spv</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkancubes/main.cpp b/examples/vulkan/hellovulkancubes/main.cpp
new file mode 100644
index 0000000000..4ec4d48645
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/main.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QLoggingCategory>
+#include "mainwindow.h"
+#include "vulkanwindow.h"
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+
+ const bool dbg = qEnvironmentVariableIntValue("QT_VK_DEBUG");
+
+ QVulkanInstance inst;
+
+ if (dbg) {
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+ }
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow *vulkanWindow = new VulkanWindow(dbg);
+ vulkanWindow->setVulkanInstance(&inst);
+
+ MainWindow mainWindow(vulkanWindow);
+ mainWindow.resize(1024, 768);
+ mainWindow.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkancubes/mainwindow.cpp b/examples/vulkan/hellovulkancubes/mainwindow.cpp
new file mode 100644
index 0000000000..2be7d237af
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/mainwindow.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mainwindow.h"
+#include "vulkanwindow.h"
+#include <QApplication>
+#include <QLabel>
+#include <QPushButton>
+#include <QLCDNumber>
+#include <QCheckBox>
+#include <QGridLayout>
+
+MainWindow::MainWindow(VulkanWindow *vulkanWindow)
+{
+ QWidget *wrapper = QWidget::createWindowContainer(vulkanWindow);
+ wrapper->setFocusPolicy(Qt::StrongFocus);
+ wrapper->setFocus();
+
+ infoLabel = new QLabel;
+ infoLabel->setFrameStyle(QFrame::Box | QFrame::Raised);
+ infoLabel->setAlignment(Qt::AlignCenter);
+ infoLabel->setText(tr("This example demonstrates instanced drawing\nof a mesh loaded from a file.\n"
+ "Uses a Phong material with a single light.\n"
+ "Also demonstrates dynamic uniform buffers\nand a bit of threading with QtConcurrent.\n"
+ "Uses 4x MSAA when available.\n"
+ "Comes with an FPS camera.\n"
+ "Hit [Shift+]WASD to walk and strafe.\nPress and move mouse to look around.\n"
+ "Click Add New to increase the number of instances."));
+
+ meshSwitch = new QCheckBox(tr("&Use Qt logo"));
+ meshSwitch->setFocusPolicy(Qt::NoFocus); // do not interfere with vulkanWindow's keyboard input
+
+ counterLcd = new QLCDNumber(5);
+ counterLcd->setSegmentStyle(QLCDNumber::Filled);
+ counterLcd->display(m_count);
+
+ newButton = new QPushButton(tr("&Add new"));
+ newButton->setFocusPolicy(Qt::NoFocus);
+ quitButton = new QPushButton(tr("&Quit"));
+ quitButton->setFocusPolicy(Qt::NoFocus);
+ pauseButton = new QPushButton(tr("&Pause"));
+ pauseButton->setFocusPolicy(Qt::NoFocus);
+
+ connect(quitButton, &QPushButton::clicked, qApp, &QCoreApplication::quit);
+ connect(newButton, &QPushButton::clicked, vulkanWindow, [=] {
+ vulkanWindow->addNew();
+ m_count = vulkanWindow->instanceCount();
+ counterLcd->display(m_count);
+ });
+ connect(pauseButton, &QPushButton::clicked, vulkanWindow, &VulkanWindow::togglePaused);
+ connect(meshSwitch, &QCheckBox::clicked, vulkanWindow, &VulkanWindow::meshSwitched);
+
+ QGridLayout *layout = new QGridLayout;
+ layout->addWidget(infoLabel, 0, 2);
+ layout->addWidget(meshSwitch, 1, 2);
+ layout->addWidget(createLabel(tr("INSTANCES")), 2, 2);
+ layout->addWidget(counterLcd, 3, 2);
+ layout->addWidget(newButton, 4, 2);
+ layout->addWidget(pauseButton, 5, 2);
+ layout->addWidget(quitButton, 6, 2);
+ layout->addWidget(wrapper, 0, 0, 7, 2);
+ setLayout(layout);
+}
+
+QLabel *MainWindow::createLabel(const QString &text)
+{
+ QLabel *lbl = new QLabel(text);
+ lbl->setAlignment(Qt::AlignHCenter | Qt::AlignBottom);
+ return lbl;
+}
diff --git a/examples/vulkan/hellovulkancubes/mainwindow.h b/examples/vulkan/hellovulkancubes/mainwindow.h
new file mode 100644
index 0000000000..4109709959
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/mainwindow.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MAINWINDOW_H
+#define MAINWINDOW_H
+
+#include <QWidget>
+
+QT_BEGIN_NAMESPACE
+class QLCDNumber;
+class QLabel;
+class QPushButton;
+class QCheckBox;
+QT_END_NAMESPACE
+
+class VulkanWindow;
+
+class MainWindow : public QWidget
+{
+public:
+ MainWindow(VulkanWindow *vulkanWindow);
+
+private:
+ QLabel *createLabel(const QString &text);
+
+ QLabel *infoLabel;
+ QCheckBox *meshSwitch;
+ QLCDNumber *counterLcd;
+ QPushButton *newButton;
+ QPushButton *quitButton;
+ QPushButton *pauseButton;
+
+ int m_count = 128;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/mesh.cpp b/examples/vulkan/hellovulkancubes/mesh.cpp
new file mode 100644
index 0000000000..fcc45bfd57
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/mesh.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mesh.h"
+#include <QtConcurrentRun>
+#include <QFile>
+
+void Mesh::load(const QString &fn)
+{
+ reset();
+ m_maybeRunning = true;
+ m_future = QtConcurrent::run([fn]() {
+ MeshData md;
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to open %s", qPrintable(fn));
+ return md;
+ }
+ QByteArray buf = f.readAll();
+ const char *p = buf.constData();
+ quint32 format;
+ memcpy(&format, p, 4);
+ if (format != 1) {
+ qWarning("Invalid format in %s", qPrintable(fn));
+ return md;
+ }
+ int ofs = 4;
+ memcpy(&md.vertexCount, p + ofs, 4);
+ ofs += 4;
+ memcpy(md.aabb, p + ofs, 6 * 4);
+ ofs += 6 * 4;
+ const int byteCount = md.vertexCount * 8 * 4;
+ md.geom.resize(byteCount);
+ memcpy(md.geom.data(), p + ofs, byteCount);
+ return md;
+ });
+}
+
+MeshData *Mesh::data()
+{
+ if (m_maybeRunning && !m_data.isValid())
+ m_data = m_future.result();
+
+ return &m_data;
+}
+
+void Mesh::reset()
+{
+ *data() = MeshData();
+ m_maybeRunning = false;
+}
diff --git a/examples/vulkan/hellovulkancubes/mesh.h b/examples/vulkan/hellovulkancubes/mesh.h
new file mode 100644
index 0000000000..cb6ee9c830
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/mesh.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MESH_H
+#define MESH_H
+
+#include <QString>
+#include <QFuture>
+
+struct MeshData
+{
+ bool isValid() const { return vertexCount > 0; }
+ int vertexCount = 0;
+ float aabb[6];
+ QByteArray geom; // x, y, z, u, v, nx, ny, nz
+};
+
+class Mesh
+{
+public:
+ void load(const QString &fn);
+ MeshData *data();
+ bool isValid() { return data()->isValid(); }
+ void reset();
+
+private:
+ bool m_maybeRunning = false;
+ QFuture<MeshData> m_future;
+ MeshData m_data;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/renderer.cpp b/examples/vulkan/hellovulkancubes/renderer.cpp
new file mode 100644
index 0000000000..523511337d
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/renderer.cpp
@@ -0,0 +1,1048 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "renderer.h"
+#include <QVulkanFunctions>
+#include <QtConcurrentRun>
+#include <QTime>
+
+static float quadVert[] = {
+ -1, -1, 0,
+ -1, 1, 0,
+ 1, -1, 0,
+ 1, 1, 0
+};
+
+#define DBG Q_UNLIKELY(m_window->isDebugEnabled())
+
+const int MAX_INSTANCES = 16384;
+const VkDeviceSize PER_INSTANCE_DATA_SIZE = 6 * sizeof(float); // instTranslate, instDiffuseAdjust
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+Renderer::Renderer(VulkanWindow *w, int initialCount)
+ : m_window(w),
+ // Have the light positioned just behind the default camera position, looking forward.
+ m_lightPos(0.0f, 0.0f, 25.0f),
+ m_cam(QVector3D(0.0f, 0.0f, 20.0f)), // starting camera position
+ m_instCount(initialCount)
+{
+ qsrand(QTime(0, 0, 0).secsTo(QTime::currentTime()));
+
+ m_floorModel.translate(0, -5, 0);
+ m_floorModel.rotate(-90, 1, 0, 0);
+ m_floorModel.scale(20, 100, 1);
+
+ m_blockMesh.load(QStringLiteral(":/block.buf"));
+ m_logoMesh.load(QStringLiteral(":/qt_logo.buf"));
+
+ QObject::connect(&m_frameWatcher, &QFutureWatcherBase::finished, [this] {
+ if (m_framePending) {
+ m_framePending = false;
+ m_window->frameReady();
+ m_window->requestUpdate();
+ }
+ });
+}
+
+void Renderer::preInitResources()
+{
+ const QVector<int> sampleCounts = m_window->supportedSampleCounts();
+ if (DBG)
+ qDebug() << "Supported sample counts:" << sampleCounts;
+ if (sampleCounts.contains(4)) {
+ if (DBG)
+ qDebug("Requesting 4x MSAA");
+ m_window->setSampleCount(4);
+ }
+}
+
+void Renderer::initResources()
+{
+ if (DBG)
+ qDebug("Renderer init");
+
+ m_animating = true;
+ m_framePending = false;
+
+ QVulkanInstance *inst = m_window->vulkanInstance();
+ VkDevice dev = m_window->device();
+ const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
+ const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
+
+ m_devFuncs = inst->deviceFunctions(dev);
+
+ // Note the std140 packing rules. A vec3 still has an alignment of 16,
+ // while a mat3 is like 3 * vec3.
+ m_itemMaterial.vertUniSize = aligned(2 * 64 + 48, uniAlign); // see color_phong.vert
+ m_itemMaterial.fragUniSize = aligned(6 * 16 + 12 + 2 * 4, uniAlign); // see color_phong.frag
+
+ if (!m_itemMaterial.vs.isValid())
+ m_itemMaterial.vs.load(inst, dev, QStringLiteral(":/color_phong_vert.spv"));
+ if (!m_itemMaterial.fs.isValid())
+ m_itemMaterial.fs.load(inst, dev, QStringLiteral(":/color_phong_frag.spv"));
+
+ if (!m_floorMaterial.vs.isValid())
+ m_floorMaterial.vs.load(inst, dev, QStringLiteral(":/color_vert.spv"));
+ if (!m_floorMaterial.fs.isValid())
+ m_floorMaterial.fs.load(inst, dev, QStringLiteral(":/color_frag.spv"));
+
+ m_pipelinesFuture = QtConcurrent::run(this, &Renderer::createPipelines);
+}
+
+void Renderer::createPipelines()
+{
+ VkDevice dev = m_window->device();
+
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ VkResult err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline cache: %d", err);
+
+ createItemPipeline();
+ createFloorPipeline();
+}
+
+void Renderer::createItemPipeline()
+{
+ VkDevice dev = m_window->device();
+
+ // Vertex layout.
+ VkVertexInputBindingDescription vertexBindingDesc[] = {
+ {
+ 0, // binding
+ 8 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ },
+ {
+ 1,
+ 6 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_INSTANCE
+ }
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0 // offset
+ },
+ { // normal
+ 1,
+ 0,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 5 * sizeof(float)
+ },
+ { // instTranslate
+ 2,
+ 1,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0
+ },
+ { // instDiffuseAdjust
+ 3,
+ 1,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 3 * sizeof(float)
+ }
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = sizeof(vertexBindingDesc) / sizeof(vertexBindingDesc[0]);
+ vertexInputInfo.pVertexBindingDescriptions = vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = sizeof(vertexAttrDesc) / sizeof(vertexAttrDesc[0]);
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Descriptor set layout.
+ VkDescriptorPoolSize descPoolSizes[] = {
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, 2 }
+ };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descPoolInfo.maxSets = 1; // a single set is enough due to the dynamic uniform buffer
+ descPoolInfo.poolSizeCount = sizeof(descPoolSizes) / sizeof(descPoolSizes[0]);
+ descPoolInfo.pPoolSizes = descPoolSizes;
+ VkResult err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_itemMaterial.descPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor pool: %d", err);
+
+ VkDescriptorSetLayoutBinding layoutBindings[] =
+ {
+ {
+ 0, // binding
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ 1, // descriptorCount
+ VK_SHADER_STAGE_VERTEX_BIT,
+ nullptr
+ },
+ {
+ 1,
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
+ 1,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ nullptr
+ }
+ };
+ VkDescriptorSetLayoutCreateInfo descLayoutInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ nullptr,
+ 0,
+ sizeof(layoutBindings) / sizeof(layoutBindings[0]),
+ layoutBindings
+ };
+ err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_itemMaterial.descSetLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor set layout: %d", err);
+
+ VkDescriptorSetAllocateInfo descSetAllocInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ nullptr,
+ m_itemMaterial.descPool,
+ 1,
+ &m_itemMaterial.descSetLayout
+ };
+ err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_itemMaterial.descSet);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate descriptor set: %d", err);
+
+ // Graphics pipeline.
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &m_itemMaterial.descSetLayout;
+
+ err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_itemMaterial.pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ m_itemMaterial.vs.data()->shaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ m_itemMaterial.fs.data()->shaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_BACK_BIT;
+ rs.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms.rasterizationSamples = m_window->sampleCountFlagBits();
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_itemMaterial.pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_itemMaterial.pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+}
+
+void Renderer::createFloorPipeline()
+{
+ VkDevice dev = m_window->device();
+
+ // Vertex layout.
+ VkVertexInputBindingDescription vertexBindingDesc = {
+ 0, // binding
+ 3 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0 // offset
+ },
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = 1;
+ vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = sizeof(vertexAttrDesc) / sizeof(vertexAttrDesc[0]);
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Do not bother with uniform buffers and descriptors, all the data fits
+ // into the spec mandated minimum of 128 bytes for push constants.
+ VkPushConstantRange pcr[] = {
+ // mvp
+ {
+ VK_SHADER_STAGE_VERTEX_BIT,
+ 0,
+ 64
+ },
+ // color
+ {
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ 64,
+ 12
+ }
+ };
+
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.pushConstantRangeCount = sizeof(pcr) / sizeof(pcr[0]);
+ pipelineLayoutInfo.pPushConstantRanges = pcr;
+
+ VkResult err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_floorMaterial.pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ m_floorMaterial.vs.data()->shaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ m_floorMaterial.fs.data()->shaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_BACK_BIT;
+ rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms.rasterizationSamples = m_window->sampleCountFlagBits();
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_floorMaterial.pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_floorMaterial.pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+}
+
+void Renderer::initSwapChainResources()
+{
+ m_proj = m_window->clipCorrectionMatrix();
+ const QSize sz = m_window->swapChainImageSize();
+ m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 1000.0f);
+ markViewProjDirty();
+}
+
+void Renderer::releaseSwapChainResources()
+{
+ // It is important to finish the pending frame right here since this is the
+ // last opportunity to act with all resources intact.
+ m_frameWatcher.waitForFinished();
+ // Cannot count on the finished() signal being emitted before returning
+ // from here.
+ if (m_framePending) {
+ m_framePending = false;
+ m_window->frameReady();
+ }
+}
+
+void Renderer::releaseResources()
+{
+ if (DBG)
+ qDebug("Renderer release");
+
+ m_pipelinesFuture.waitForFinished();
+
+ VkDevice dev = m_window->device();
+
+ if (m_itemMaterial.descSetLayout) {
+ m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_itemMaterial.descSetLayout, nullptr);
+ m_itemMaterial.descSetLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.descPool) {
+ m_devFuncs->vkDestroyDescriptorPool(dev, m_itemMaterial.descPool, nullptr);
+ m_itemMaterial.descPool = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_itemMaterial.pipeline, nullptr);
+ m_itemMaterial.pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_itemMaterial.pipelineLayout, nullptr);
+ m_itemMaterial.pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_floorMaterial.pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_floorMaterial.pipeline, nullptr);
+ m_floorMaterial.pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_floorMaterial.pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_floorMaterial.pipelineLayout, nullptr);
+ m_floorMaterial.pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineCache) {
+ m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
+ m_pipelineCache = VK_NULL_HANDLE;
+ }
+
+ if (m_blockVertexBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_blockVertexBuf, nullptr);
+ m_blockVertexBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_logoVertexBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_logoVertexBuf, nullptr);
+ m_logoVertexBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_floorVertexBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_floorVertexBuf, nullptr);
+ m_floorVertexBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_uniBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_uniBuf, nullptr);
+ m_uniBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_bufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
+ m_bufMem = VK_NULL_HANDLE;
+ }
+
+ if (m_instBuf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_instBuf, nullptr);
+ m_instBuf = VK_NULL_HANDLE;
+ }
+
+ if (m_instBufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_instBufMem, nullptr);
+ m_instBufMem = VK_NULL_HANDLE;
+ }
+
+ if (m_itemMaterial.vs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_itemMaterial.vs.data()->shaderModule, nullptr);
+ m_itemMaterial.vs.reset();
+ }
+ if (m_itemMaterial.fs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_itemMaterial.fs.data()->shaderModule, nullptr);
+ m_itemMaterial.fs.reset();
+ }
+
+ if (m_floorMaterial.vs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_floorMaterial.vs.data()->shaderModule, nullptr);
+ m_floorMaterial.vs.reset();
+ }
+ if (m_floorMaterial.fs.isValid()) {
+ m_devFuncs->vkDestroyShaderModule(dev, m_floorMaterial.fs.data()->shaderModule, nullptr);
+ m_floorMaterial.fs.reset();
+ }
+}
+
+void Renderer::ensureBuffers()
+{
+ if (m_blockVertexBuf)
+ return;
+
+ VkDevice dev = m_window->device();
+ const int concurrentFrameCount = m_window->concurrentFrameCount();
+
+ // Vertex buffer for the block.
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ const int blockMeshByteCount = m_blockMesh.data()->vertexCount * 8 * sizeof(float);
+ bufInfo.size = blockMeshByteCount;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_blockVertexBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex buffer: %d", err);
+
+ VkMemoryRequirements blockVertMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_blockVertexBuf, &blockVertMemReq);
+
+ // Vertex buffer for the logo.
+ const int logoMeshByteCount = m_logoMesh.data()->vertexCount * 8 * sizeof(float);
+ bufInfo.size = logoMeshByteCount;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+ err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_logoVertexBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex buffer: %d", err);
+
+ VkMemoryRequirements logoVertMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_logoVertexBuf, &logoVertMemReq);
+
+ // Vertex buffer for the floor.
+ bufInfo.size = sizeof(quadVert);
+ err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_floorVertexBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create vertex buffer: %d", err);
+
+ VkMemoryRequirements floorVertMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_floorVertexBuf, &floorVertMemReq);
+
+ // Uniform buffer. Instead of using multiple descriptor sets, we take a
+ // different approach: have a single dynamic uniform buffer and specify the
+ // active-frame-specific offset at the time of binding the descriptor set.
+ bufInfo.size = (m_itemMaterial.vertUniSize + m_itemMaterial.fragUniSize) * concurrentFrameCount;
+ bufInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+ err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_uniBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create uniform buffer: %d", err);
+
+ VkMemoryRequirements uniMemReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_uniBuf, &uniMemReq);
+
+ // Allocate memory for everything at once.
+ VkDeviceSize logoVertStartOffset = aligned(0 + blockVertMemReq.size, logoVertMemReq.alignment);
+ VkDeviceSize floorVertStartOffset = aligned(logoVertStartOffset + logoVertMemReq.size, floorVertMemReq.alignment);
+ m_itemMaterial.uniMemStartOffset = aligned(floorVertStartOffset + floorVertMemReq.size, uniMemReq.alignment);
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ m_itemMaterial.uniMemStartOffset + uniMemReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_blockVertexBuf, m_bufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind vertex buffer memory: %d", err);
+ err = m_devFuncs->vkBindBufferMemory(dev, m_logoVertexBuf, m_bufMem, logoVertStartOffset);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind vertex buffer memory: %d", err);
+ err = m_devFuncs->vkBindBufferMemory(dev, m_floorVertexBuf, m_bufMem, floorVertStartOffset);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind vertex buffer memory: %d", err);
+ err = m_devFuncs->vkBindBufferMemory(dev, m_uniBuf, m_bufMem, m_itemMaterial.uniMemStartOffset);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind uniform buffer memory: %d", err);
+
+ // Copy vertex data.
+ quint8 *p;
+ err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, m_itemMaterial.uniMemStartOffset, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, m_blockMesh.data()->geom.constData(), blockMeshByteCount);
+ memcpy(p + logoVertStartOffset, m_logoMesh.data()->geom.constData(), logoMeshByteCount);
+ memcpy(p + floorVertStartOffset, quadVert, sizeof(quadVert));
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ // Write descriptors for the uniform buffers in the vertex and fragment shaders.
+ VkDescriptorBufferInfo vertUni = { m_uniBuf, 0, m_itemMaterial.vertUniSize };
+ VkDescriptorBufferInfo fragUni = { m_uniBuf, m_itemMaterial.vertUniSize, m_itemMaterial.fragUniSize };
+
+ VkWriteDescriptorSet descWrite[2];
+ memset(descWrite, 0, sizeof(descWrite));
+ descWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[0].dstSet = m_itemMaterial.descSet;
+ descWrite[0].dstBinding = 0;
+ descWrite[0].descriptorCount = 1;
+ descWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ descWrite[0].pBufferInfo = &vertUni;
+
+ descWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[1].dstSet = m_itemMaterial.descSet;
+ descWrite[1].dstBinding = 1;
+ descWrite[1].descriptorCount = 1;
+ descWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
+ descWrite[1].pBufferInfo = &fragUni;
+
+ m_devFuncs->vkUpdateDescriptorSets(dev, 2, descWrite, 0, nullptr);
+}
+
+void Renderer::ensureInstanceBuffer()
+{
+ if (m_instCount == m_preparedInstCount && m_instBuf)
+ return;
+
+ Q_ASSERT(m_instCount <= MAX_INSTANCES);
+
+ VkDevice dev = m_window->device();
+
+ // allocate only once, for the maximum instance count
+ if (!m_instBuf) {
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ bufInfo.size = MAX_INSTANCES * PER_INSTANCE_DATA_SIZE;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
+
+ // Keep a copy of the data since we may lose all graphics resources on
+ // unexpose, and reinitializing to new random positions afterwards
+ // would not be nice.
+ m_instData.resize(bufInfo.size);
+
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_instBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create instance buffer: %d", err);
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_instBuf, &memReq);
+ if (DBG)
+ qDebug("Allocating %u bytes for instance data", uint32_t(memReq.size));
+
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_instBufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_instBuf, m_instBufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind instance buffer memory: %d", err);
+ }
+
+ if (m_instCount != m_preparedInstCount) {
+ if (DBG)
+ qDebug("Preparing instances %d..%d", m_preparedInstCount, m_instCount - 1);
+ char *p = m_instData.data();
+ p += m_preparedInstCount * PER_INSTANCE_DATA_SIZE;
+ auto gen = [](float a, float b) { return float((qrand() % int(b - a + 1)) + a); };
+ for (int i = m_preparedInstCount; i < m_instCount; ++i) {
+ // Apply a random translation to each instance of the mesh.
+ float t[] = { gen(-5, 5), gen(-4, 6), gen(-30, 5) };
+ memcpy(p, t, 12);
+ // Apply a random adjustment to the diffuse color for each instance. (default is 0.7)
+ float d[] = { gen(-6, 3) / 10.0f, gen(-6, 3) / 10.0f, gen(-6, 3) / 10.0f };
+ memcpy(p + 12, d, 12);
+ p += PER_INSTANCE_DATA_SIZE;
+ }
+ m_preparedInstCount = m_instCount;
+ }
+
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_instBufMem, 0, m_instCount * PER_INSTANCE_DATA_SIZE, 0,
+ reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, m_instData.constData(), m_instData.size());
+ m_devFuncs->vkUnmapMemory(dev, m_instBufMem);
+}
+
+void Renderer::getMatrices(QMatrix4x4 *vp, QMatrix4x4 *model, QMatrix3x3 *modelNormal, QVector3D *eyePos)
+{
+ model->setToIdentity();
+ if (m_useLogo)
+ model->rotate(90, 1, 0, 0);
+ model->rotate(m_rotation, 1, 1, 0);
+
+ *modelNormal = model->normalMatrix();
+
+ QMatrix4x4 view = m_cam.viewMatrix();
+ *vp = m_proj * view;
+
+ *eyePos = view.inverted().column(3).toVector3D();
+}
+
+void Renderer::writeFragUni(quint8 *p, const QVector3D &eyePos)
+{
+ float ECCameraPosition[] = { eyePos.x(), eyePos.y(), eyePos.z() };
+ memcpy(p, ECCameraPosition, 12);
+ p += 16;
+
+ // Material
+ float ka[] = { 0.05f, 0.05f, 0.05f };
+ memcpy(p, ka, 12);
+ p += 16;
+
+ float kd[] = { 0.7f, 0.7f, 0.7f };
+ memcpy(p, kd, 12);
+ p += 16;
+
+ float ks[] = { 0.66f, 0.66f, 0.66f };
+ memcpy(p, ks, 12);
+ p += 16;
+
+ // Light parameters
+ float ECLightPosition[] = { m_lightPos.x(), m_lightPos.y(), m_lightPos.z() };
+ memcpy(p, ECLightPosition, 12);
+ p += 16;
+
+ float att[] = { 1, 0, 0 };
+ memcpy(p, att, 12);
+ p += 16;
+
+ float color[] = { 1.0f, 1.0f, 1.0f };
+ memcpy(p, color, 12);
+ p += 12; // next we have two floats which have an alignment of 4, hence 12 only
+
+ float intensity = 0.8f;
+ memcpy(p, &intensity, 4);
+ p += 4;
+
+ float specularExp = 150.0f;
+ memcpy(p, &specularExp, 4);
+ p += 4;
+}
+
+void Renderer::startNextFrame()
+{
+ // For demonstration purposes offload the command buffer generation onto a
+ // worker thread and continue with the frame submission only when it has
+ // finished.
+ Q_ASSERT(!m_framePending);
+ m_framePending = true;
+ QFuture<void> future = QtConcurrent::run(this, &Renderer::buildFrame);
+ m_frameWatcher.setFuture(future);
+}
+
+void Renderer::buildFrame()
+{
+ QMutexLocker locker(&m_guiMutex);
+
+ ensureBuffers();
+ ensureInstanceBuffer();
+ m_pipelinesFuture.waitForFinished();
+
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+ const QSize sz = m_window->swapChainImageSize();
+
+ VkClearColorValue clearColor = { 0.67f, 0.84f, 0.9f, 1.0f };
+ VkClearDepthStencilValue clearDS = { 1, 0 };
+ VkClearValue clearValues[3];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearValues[2].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = m_window->sampleCountFlagBits() > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ VkViewport viewport = {
+ 0, 0,
+ float(sz.width()), float(sz.height()),
+ 0, 1
+ };
+ m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
+
+ VkRect2D scissor = {
+ { 0, 0 },
+ { uint32_t(sz.width()), uint32_t(sz.height()) }
+ };
+ m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
+
+ buildDrawCallsForFloor();
+ buildDrawCallsForItems();
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+}
+
+void Renderer::buildDrawCallsForItems()
+{
+ VkDevice dev = m_window->device();
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_itemMaterial.pipeline);
+
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, m_useLogo ? &m_logoVertexBuf : &m_blockVertexBuf, &vbOffset);
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 1, 1, &m_instBuf, &vbOffset);
+
+ // Now provide offsets so that the two dynamic buffers point to the
+ // beginning of the vertex and fragment uniform data for the current frame.
+ uint32_t frameUniOffset = m_window->currentFrame() * (m_itemMaterial.vertUniSize + m_itemMaterial.fragUniSize);
+ uint32_t frameUniOffsets[] = { frameUniOffset, frameUniOffset };
+ m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_itemMaterial.pipelineLayout, 0, 1,
+ &m_itemMaterial.descSet, 2, frameUniOffsets);
+
+ if (m_animating)
+ m_rotation += 0.5;
+
+ if (m_animating || m_vpDirty) {
+ if (m_vpDirty)
+ --m_vpDirty;
+ QMatrix4x4 vp, model;
+ QMatrix3x3 modelNormal;
+ QVector3D eyePos;
+ getMatrices(&vp, &model, &modelNormal, &eyePos);
+
+ // Map the uniform data for the current frame, ignore the geometry data at
+ // the beginning and the uniforms for other frames.
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem,
+ m_itemMaterial.uniMemStartOffset + frameUniOffset,
+ m_itemMaterial.vertUniSize + m_itemMaterial.fragUniSize,
+ 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+
+ // Vertex shader uniforms
+ memcpy(p, vp.constData(), 64);
+ memcpy(p + 64, model.constData(), 64);
+ const float *mnp = modelNormal.constData();
+ memcpy(p + 128, mnp, 12);
+ memcpy(p + 128 + 16, mnp + 3, 12);
+ memcpy(p + 128 + 32, mnp + 6, 12);
+
+ // Fragment shader uniforms
+ p += m_itemMaterial.vertUniSize;
+ writeFragUni(p, eyePos);
+
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+ }
+
+ m_devFuncs->vkCmdDraw(cb, (m_useLogo ? m_logoMesh.data() : m_blockMesh.data())->vertexCount, m_instCount, 0, 0);
+}
+
+void Renderer::buildDrawCallsForFloor()
+{
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_floorMaterial.pipeline);
+
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_floorVertexBuf, &vbOffset);
+
+ QMatrix4x4 mvp = m_proj * m_cam.viewMatrix() * m_floorModel;
+ m_devFuncs->vkCmdPushConstants(cb, m_floorMaterial.pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0, 64, mvp.constData());
+ float color[] = { 0.67f, 1.0f, 0.2f };
+ m_devFuncs->vkCmdPushConstants(cb, m_floorMaterial.pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 64, 12, color);
+
+ m_devFuncs->vkCmdDraw(cb, 4, 1, 0, 0);
+}
+
+void Renderer::addNew()
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_instCount = qMin(m_instCount + 16, MAX_INSTANCES);
+}
+
+void Renderer::yaw(float degrees)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.yaw(degrees);
+ markViewProjDirty();
+}
+
+void Renderer::pitch(float degrees)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.pitch(degrees);
+ markViewProjDirty();
+}
+
+void Renderer::walk(float amount)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.walk(amount);
+ markViewProjDirty();
+}
+
+void Renderer::strafe(float amount)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_cam.strafe(amount);
+ markViewProjDirty();
+}
+
+void Renderer::setUseLogo(bool b)
+{
+ QMutexLocker locker(&m_guiMutex);
+ m_useLogo = b;
+ if (!m_animating)
+ m_window->requestUpdate();
+}
diff --git a/examples/vulkan/hellovulkancubes/renderer.h b/examples/vulkan/hellovulkancubes/renderer.h
new file mode 100644
index 0000000000..60bb48377e
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/renderer.h
@@ -0,0 +1,158 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef RENDERER_H
+#define RENDERER_H
+
+#include "vulkanwindow.h"
+#include "mesh.h"
+#include "shader.h"
+#include "camera.h"
+#include <QFutureWatcher>
+#include <QMutex>
+
+class Renderer : public QVulkanWindowRenderer
+{
+public:
+ Renderer(VulkanWindow *w, int initialCount);
+
+ void preInitResources() override;
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+ bool animating() const { return m_animating; }
+ void setAnimating(bool a) { m_animating = a; }
+
+ int instanceCount() const { return m_instCount; }
+ void addNew();
+
+ void yaw(float degrees);
+ void pitch(float degrees);
+ void walk(float amount);
+ void strafe(float amount);
+
+ void setUseLogo(bool b);
+
+private:
+ void createPipelines();
+ void createItemPipeline();
+ void createFloorPipeline();
+ void ensureBuffers();
+ void ensureInstanceBuffer();
+ void getMatrices(QMatrix4x4 *mvp, QMatrix4x4 *model, QMatrix3x3 *modelNormal, QVector3D *eyePos);
+ void writeFragUni(quint8 *p, const QVector3D &eyePos);
+ void buildFrame();
+ void buildDrawCallsForItems();
+ void buildDrawCallsForFloor();
+
+ void markViewProjDirty() { m_vpDirty = m_window->concurrentFrameCount(); }
+
+ VulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+
+ bool m_useLogo = false;
+ Mesh m_blockMesh;
+ Mesh m_logoMesh;
+ VkBuffer m_blockVertexBuf = VK_NULL_HANDLE;
+ VkBuffer m_logoVertexBuf = VK_NULL_HANDLE;
+ struct {
+ VkDeviceSize vertUniSize;
+ VkDeviceSize fragUniSize;
+ VkDeviceSize uniMemStartOffset;
+ Shader vs;
+ Shader fs;
+ VkDescriptorPool descPool = VK_NULL_HANDLE;
+ VkDescriptorSetLayout descSetLayout = VK_NULL_HANDLE;
+ VkDescriptorSet descSet;
+ VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline pipeline = VK_NULL_HANDLE;
+ } m_itemMaterial;
+
+ VkBuffer m_floorVertexBuf = VK_NULL_HANDLE;
+ struct {
+ Shader vs;
+ Shader fs;
+ VkPipelineLayout pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline pipeline = VK_NULL_HANDLE;
+ } m_floorMaterial;
+
+ VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
+ VkBuffer m_uniBuf = VK_NULL_HANDLE;
+
+ VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
+ QFuture<void> m_pipelinesFuture;
+
+ QVector3D m_lightPos;
+ Camera m_cam;
+
+ QMatrix4x4 m_proj;
+ int m_vpDirty = 0;
+ QMatrix4x4 m_floorModel;
+
+ bool m_animating;
+ float m_rotation = 0.0f;
+
+ int m_instCount;
+ int m_preparedInstCount = 0;
+ QByteArray m_instData;
+ VkBuffer m_instBuf = VK_NULL_HANDLE;
+ VkDeviceMemory m_instBufMem = VK_NULL_HANDLE;
+
+ QFutureWatcher<void> m_frameWatcher;
+ bool m_framePending;
+
+ QMutex m_guiMutex;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/shader.cpp b/examples/vulkan/hellovulkancubes/shader.cpp
new file mode 100644
index 0000000000..e1c01c6842
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/shader.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "shader.h"
+#include <QtConcurrentRun>
+#include <QFile>
+#include <QVulkanDeviceFunctions>
+
+void Shader::load(QVulkanInstance *inst, VkDevice dev, const QString &fn)
+{
+ reset();
+ m_maybeRunning = true;
+ m_future = QtConcurrent::run([inst, dev, fn]() {
+ ShaderData sd;
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to open %s", qPrintable(fn));
+ return sd;
+ }
+ QByteArray blob = f.readAll();
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = blob.size();
+ shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
+ VkResult err = inst->deviceFunctions(dev)->vkCreateShaderModule(dev, &shaderInfo, nullptr, &sd.shaderModule);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create shader module: %d", err);
+ return sd;
+ }
+ return sd;
+ });
+}
+
+ShaderData *Shader::data()
+{
+ if (m_maybeRunning && !m_data.isValid())
+ m_data = m_future.result();
+
+ return &m_data;
+}
+
+void Shader::reset()
+{
+ *data() = ShaderData();
+ m_maybeRunning = false;
+}
diff --git a/examples/vulkan/hellovulkancubes/shader.h b/examples/vulkan/hellovulkancubes/shader.h
new file mode 100644
index 0000000000..265868d2b0
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/shader.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SHADER_H
+#define SHADER_H
+
+#include <QVulkanInstance>
+#include <QFuture>
+
+struct ShaderData
+{
+ bool isValid() const { return shaderModule != VK_NULL_HANDLE; }
+ VkShaderModule shaderModule = VK_NULL_HANDLE;
+};
+
+class Shader
+{
+public:
+ void load(QVulkanInstance *inst, VkDevice dev, const QString &fn);
+ ShaderData *data();
+ bool isValid() { return data()->isValid(); }
+ void reset();
+
+private:
+ bool m_maybeRunning = false;
+ QFuture<ShaderData> m_future;
+ ShaderData m_data;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkancubes/vulkanwindow.cpp b/examples/vulkan/hellovulkancubes/vulkanwindow.cpp
new file mode 100644
index 0000000000..9a4eaf1901
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/vulkanwindow.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "vulkanwindow.h"
+#include "renderer.h"
+#include <QMouseEvent>
+#include <QKeyEvent>
+
+VulkanWindow::VulkanWindow(bool dbg)
+ : m_debug(dbg)
+{
+}
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ m_renderer = new Renderer(this, 128);
+ return m_renderer;
+}
+
+void VulkanWindow::addNew()
+{
+ m_renderer->addNew();
+}
+
+void VulkanWindow::togglePaused()
+{
+ m_renderer->setAnimating(!m_renderer->animating());
+}
+
+void VulkanWindow::meshSwitched(bool enable)
+{
+ m_renderer->setUseLogo(enable);
+}
+
+void VulkanWindow::mousePressEvent(QMouseEvent *e)
+{
+ m_pressed = true;
+ m_lastPos = e->pos();
+}
+
+void VulkanWindow::mouseReleaseEvent(QMouseEvent *)
+{
+ m_pressed = false;
+}
+
+void VulkanWindow::mouseMoveEvent(QMouseEvent *e)
+{
+ if (!m_pressed)
+ return;
+
+ int dx = e->pos().x() - m_lastPos.x();
+ int dy = e->pos().y() - m_lastPos.y();
+
+ if (dy)
+ m_renderer->pitch(dy / 10.0f);
+
+ if (dx)
+ m_renderer->yaw(dx / 10.0f);
+
+ m_lastPos = e->pos();
+}
+
+void VulkanWindow::keyPressEvent(QKeyEvent *e)
+{
+ const float amount = e->modifiers().testFlag(Qt::ShiftModifier) ? 1.0f : 0.1f;
+ switch (e->key()) {
+ case Qt::Key_W:
+ m_renderer->walk(amount);
+ break;
+ case Qt::Key_S:
+ m_renderer->walk(-amount);
+ break;
+ case Qt::Key_A:
+ m_renderer->strafe(-amount);
+ break;
+ case Qt::Key_D:
+ m_renderer->strafe(amount);
+ break;
+ default:
+ break;
+ }
+}
+
+int VulkanWindow::instanceCount() const
+{
+ return m_renderer->instanceCount();
+}
diff --git a/examples/vulkan/hellovulkancubes/vulkanwindow.h b/examples/vulkan/hellovulkancubes/vulkanwindow.h
new file mode 100644
index 0000000000..d085c0bde7
--- /dev/null
+++ b/examples/vulkan/hellovulkancubes/vulkanwindow.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef VULKANWINDOW_H
+#define VULKANWINDOW_H
+
+#include <QVulkanWindow>
+
+class Renderer;
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ VulkanWindow(bool dbg);
+
+ QVulkanWindowRenderer *createRenderer() override;
+
+ bool isDebugEnabled() const { return m_debug; }
+ int instanceCount() const;
+
+public slots:
+ void addNew();
+ void togglePaused();
+ void meshSwitched(bool enable);
+
+private:
+ void mousePressEvent(QMouseEvent *) override;
+ void mouseReleaseEvent(QMouseEvent *) override;
+ void mouseMoveEvent(QMouseEvent *) override;
+ void keyPressEvent(QKeyEvent *) override;
+
+ bool m_debug;
+ Renderer *m_renderer;
+ bool m_pressed = false;
+ QPoint m_lastPos;
+};
+
+#endif
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp b/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp
new file mode 100644
index 0000000000..086bca781f
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.cpp
@@ -0,0 +1,828 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "hellovulkantexture.h"
+#include <QVulkanFunctions>
+#include <QCoreApplication>
+#include <QFile>
+
+// Use a triangle strip to get a quad.
+//
+// Note that the vertex data and the projection matrix assume OpenGL. With
+// Vulkan Y is negated in clip space and the near/far plane is at 0/1 instead
+// of -1/1. These will be corrected for by an extra transformation when
+// calculating the modelview-projection matrix.
+static float vertexData[] = {
+ // x, y, z, u, v
+ -1, -1, 0, 0, 1,
+ -1, 1, 0, 0, 0,
+ 1, -1, 0, 1, 1,
+ 1, 1, 0, 1, 0
+};
+
+static const int UNIFORM_DATA_SIZE = 16 * sizeof(float);
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new VulkanRenderer(this);
+}
+
+VulkanRenderer::VulkanRenderer(QVulkanWindow *w)
+ : m_window(w)
+{
+}
+
+VkShaderModule VulkanRenderer::createShader(const QString &name)
+{
+ QFile file(name);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to read shader %s", qPrintable(name));
+ return VK_NULL_HANDLE;
+ }
+ QByteArray blob = file.readAll();
+ file.close();
+
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = blob.size();
+ shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
+ VkShaderModule shaderModule;
+ VkResult err = m_devFuncs->vkCreateShaderModule(m_window->device(), &shaderInfo, nullptr, &shaderModule);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create shader module: %d", err);
+ return VK_NULL_HANDLE;
+ }
+
+ return shaderModule;
+}
+
+bool VulkanRenderer::createTexture(const QString &name)
+{
+ QImage img(name);
+ if (img.isNull()) {
+ qWarning("Failed to load image %s", qPrintable(name));
+ return false;
+ }
+
+ // Convert to byte ordered RGBA8. Use premultiplied alpha, see pColorBlendState in the pipeline.
+ img = img.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
+
+ QVulkanFunctions *f = m_window->vulkanInstance()->functions();
+ VkDevice dev = m_window->device();
+
+ const bool srgb = QCoreApplication::arguments().contains(QStringLiteral("--srgb"));
+ if (srgb)
+ qDebug("sRGB swapchain was requested, making texture sRGB too");
+
+ m_texFormat = srgb ? VK_FORMAT_R8G8B8A8_SRGB : VK_FORMAT_R8G8B8A8_UNORM;
+
+ // Now we can either map and copy the image data directly, or have to go
+ // through a staging buffer to copy and convert into the internal optimal
+ // tiling format.
+ VkFormatProperties props;
+ f->vkGetPhysicalDeviceFormatProperties(m_window->physicalDevice(), m_texFormat, &props);
+ const bool canSampleLinear = (props.linearTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
+ const bool canSampleOptimal = (props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT);
+ if (!canSampleLinear && !canSampleOptimal) {
+ qWarning("Neither linear nor optimal image sampling is supported for RGBA8");
+ return false;
+ }
+
+ static bool alwaysStage = qEnvironmentVariableIntValue("QT_VK_FORCE_STAGE_TEX");
+
+ if (canSampleLinear && !alwaysStage) {
+ if (!createTextureImage(img.size(), &m_texImage, &m_texMem,
+ VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_SAMPLED_BIT,
+ m_window->hostVisibleMemoryIndex()))
+ return false;
+
+ if (!writeLinearImage(img, m_texImage, m_texMem))
+ return false;
+
+ m_texLayoutPending = true;
+ } else {
+ if (!createTextureImage(img.size(), &m_texStaging, &m_texStagingMem,
+ VK_IMAGE_TILING_LINEAR, VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
+ m_window->hostVisibleMemoryIndex()))
+ return false;
+
+ if (!createTextureImage(img.size(), &m_texImage, &m_texMem,
+ VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
+ m_window->deviceLocalMemoryIndex()))
+ return false;
+
+ if (!writeLinearImage(img, m_texStaging, m_texStagingMem))
+ return false;
+
+ m_texStagingPending = true;
+ }
+
+ VkImageViewCreateInfo viewInfo;
+ memset(&viewInfo, 0, sizeof(viewInfo));
+ viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ viewInfo.image = m_texImage;
+ viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ viewInfo.format = m_texFormat;
+ viewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ viewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ viewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ viewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ viewInfo.subresourceRange.levelCount = viewInfo.subresourceRange.layerCount = 1;
+
+ VkResult err = m_devFuncs->vkCreateImageView(dev, &viewInfo, nullptr, &m_texView);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create image view for texture: %d", err);
+ return false;
+ }
+
+ m_texSize = img.size();
+
+ return true;
+}
+
+bool VulkanRenderer::createTextureImage(const QSize &size, VkImage *image, VkDeviceMemory *mem,
+ VkImageTiling tiling, VkImageUsageFlags usage, uint32_t memIndex)
+{
+ VkDevice dev = m_window->device();
+
+ VkImageCreateInfo imageInfo;
+ memset(&imageInfo, 0, sizeof(imageInfo));
+ imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imageInfo.imageType = VK_IMAGE_TYPE_2D;
+ imageInfo.format = m_texFormat;
+ imageInfo.extent.width = size.width();
+ imageInfo.extent.height = size.height();
+ imageInfo.extent.depth = 1;
+ imageInfo.mipLevels = 1;
+ imageInfo.arrayLayers = 1;
+ imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ imageInfo.tiling = tiling;
+ imageInfo.usage = usage;
+ imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+
+ VkResult err = m_devFuncs->vkCreateImage(dev, &imageInfo, nullptr, image);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create linear image for texture: %d", err);
+ return false;
+ }
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetImageMemoryRequirements(dev, *image, &memReq);
+
+ VkMemoryAllocateInfo allocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ memIndex
+ };
+ qDebug("allocating %u bytes for texture image", uint32_t(memReq.size));
+
+ err = m_devFuncs->vkAllocateMemory(dev, &allocInfo, nullptr, mem);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to allocate memory for linear image: %d", err);
+ return false;
+ }
+
+ err = m_devFuncs->vkBindImageMemory(dev, *image, *mem, 0);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to bind linear image memory: %d", err);
+ return false;
+ }
+
+ return true;
+}
+
+bool VulkanRenderer::writeLinearImage(const QImage &img, VkImage image, VkDeviceMemory memory)
+{
+ VkDevice dev = m_window->device();
+
+ VkImageSubresource subres = {
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ 0, // mip level
+ 0
+ };
+ VkSubresourceLayout layout;
+ m_devFuncs->vkGetImageSubresourceLayout(dev, image, &subres, &layout);
+
+ uchar *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, memory, layout.offset, layout.size, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to map memory for linear image: %d", err);
+ return false;
+ }
+
+ for (int y = 0; y < img.height(); ++y) {
+ const uchar *line = img.constScanLine(y);
+ memcpy(p, line, img.width() * 4);
+ p += layout.rowPitch;
+ }
+
+ m_devFuncs->vkUnmapMemory(dev, memory);
+ return true;
+}
+
+void VulkanRenderer::ensureTexture()
+{
+ if (!m_texLayoutPending && !m_texStagingPending)
+ return;
+
+ Q_ASSERT(m_texLayoutPending != m_texStagingPending);
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+
+ VkImageMemoryBarrier barrier;
+ memset(&barrier, 0, sizeof(barrier));
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.levelCount = barrier.subresourceRange.layerCount = 1;
+
+ if (m_texLayoutPending) {
+ m_texLayoutPending = false;
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ barrier.image = m_texImage;
+
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+ } else {
+ m_texStagingPending = false;
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_HOST_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ barrier.image = m_texStaging;
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.image = m_texImage;
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+
+ VkImageCopy copyInfo;
+ memset(&copyInfo, 0, sizeof(copyInfo));
+ copyInfo.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyInfo.srcSubresource.layerCount = 1;
+ copyInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyInfo.dstSubresource.layerCount = 1;
+ copyInfo.extent.width = m_texSize.width();
+ copyInfo.extent.height = m_texSize.height();
+ copyInfo.extent.depth = 1;
+ m_devFuncs->vkCmdCopyImage(cb, m_texStaging, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ m_texImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copyInfo);
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
+ barrier.image = m_texImage;
+ m_devFuncs->vkCmdPipelineBarrier(cb,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+ }
+}
+
+void VulkanRenderer::initResources()
+{
+ qDebug("initResources");
+
+ VkDevice dev = m_window->device();
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(dev);
+
+ // The setup is similar to hellovulkantriangle. The difference is the
+ // presence of a second vertex attribute (texcoord), a sampler, and that we
+ // need blending.
+
+ const int concurrentFrameCount = m_window->concurrentFrameCount();
+ const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
+ const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
+ qDebug("uniform buffer offset alignment is %u", (uint) uniAlign);
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ // Our internal layout is vertex, uniform, uniform, ... with each uniform buffer start offset aligned to uniAlign.
+ const VkDeviceSize vertexAllocSize = aligned(sizeof(vertexData), uniAlign);
+ const VkDeviceSize uniformAllocSize = aligned(UNIFORM_DATA_SIZE, uniAlign);
+ bufInfo.size = vertexAllocSize + concurrentFrameCount * uniformAllocSize;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_buf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create buffer: %d", err);
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_buf, &memReq);
+
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_buf, m_bufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind buffer memory: %d", err);
+
+ quint8 *p;
+ err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, memReq.size, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, vertexData, sizeof(vertexData));
+ QMatrix4x4 ident;
+ memset(m_uniformBufInfo, 0, sizeof(m_uniformBufInfo));
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ const VkDeviceSize offset = vertexAllocSize + i * uniformAllocSize;
+ memcpy(p + offset, ident.constData(), 16 * sizeof(float));
+ m_uniformBufInfo[i].buffer = m_buf;
+ m_uniformBufInfo[i].offset = offset;
+ m_uniformBufInfo[i].range = uniformAllocSize;
+ }
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ VkVertexInputBindingDescription vertexBindingDesc = {
+ 0, // binding
+ 5 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 0
+ },
+ { // texcoord
+ 1,
+ 0,
+ VK_FORMAT_R32G32_SFLOAT,
+ 3 * sizeof(float)
+ }
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = 1;
+ vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = 2;
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Sampler.
+ VkSamplerCreateInfo samplerInfo;
+ memset(&samplerInfo, 0, sizeof(samplerInfo));
+ samplerInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
+ samplerInfo.magFilter = VK_FILTER_NEAREST;
+ samplerInfo.minFilter = VK_FILTER_NEAREST;
+ samplerInfo.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ samplerInfo.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ samplerInfo.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE;
+ err = m_devFuncs->vkCreateSampler(dev, &samplerInfo, nullptr, &m_sampler);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create sampler: %d", err);
+
+ // Texture.
+ if (!createTexture(QStringLiteral(":/qt256.png")))
+ qFatal("Failed to create texture");
+
+ // Set up descriptor set and its layout.
+ VkDescriptorPoolSize descPoolSizes[2] = {
+ { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uint32_t(concurrentFrameCount) },
+ { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, uint32_t(concurrentFrameCount) }
+ };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descPoolInfo.maxSets = concurrentFrameCount;
+ descPoolInfo.poolSizeCount = 2;
+ descPoolInfo.pPoolSizes = descPoolSizes;
+ err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_descPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor pool: %d", err);
+
+ VkDescriptorSetLayoutBinding layoutBinding[2] =
+ {
+ {
+ 0, // binding
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ 1, // descriptorCount
+ VK_SHADER_STAGE_VERTEX_BIT,
+ nullptr
+ },
+ {
+ 1, // binding
+ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ 1, // descriptorCount
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ nullptr
+ }
+ };
+ VkDescriptorSetLayoutCreateInfo descLayoutInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ nullptr,
+ 0,
+ 2, // bindingCount
+ layoutBinding
+ };
+ err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_descSetLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor set layout: %d", err);
+
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ VkDescriptorSetAllocateInfo descSetAllocInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ nullptr,
+ m_descPool,
+ 1,
+ &m_descSetLayout
+ };
+ err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_descSet[i]);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate descriptor set: %d", err);
+
+ VkWriteDescriptorSet descWrite[2];
+ memset(descWrite, 0, sizeof(descWrite));
+ descWrite[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[0].dstSet = m_descSet[i];
+ descWrite[0].dstBinding = 0;
+ descWrite[0].descriptorCount = 1;
+ descWrite[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ descWrite[0].pBufferInfo = &m_uniformBufInfo[i];
+
+ VkDescriptorImageInfo descImageInfo = {
+ m_sampler,
+ m_texView,
+ VK_IMAGE_LAYOUT_GENERAL
+ };
+
+ descWrite[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite[1].dstSet = m_descSet[i];
+ descWrite[1].dstBinding = 1;
+ descWrite[1].descriptorCount = 1;
+ descWrite[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
+ descWrite[1].pImageInfo = &descImageInfo;
+
+ m_devFuncs->vkUpdateDescriptorSets(dev, 2, descWrite, 0, nullptr);
+ }
+
+ // Pipeline cache
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline cache: %d", err);
+
+ // Pipeline layout
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &m_descSetLayout;
+ err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ // Shaders
+ VkShaderModule vertShaderModule = createShader(QStringLiteral(":/texture_vert.spv"));
+ VkShaderModule fragShaderModule = createShader(QStringLiteral(":/texture_frag.spv"));
+
+ // Graphics pipeline
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ vertShaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ fragShaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ // The viewport and scissor will be set dynamically via vkCmdSetViewport/Scissor.
+ // This way the pipeline does not need to be touched when resizing the window.
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_BACK_BIT;
+ rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ ms.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT;
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ // assume pre-multiplied alpha, blend, write out all of rgba
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ att.blendEnable = VK_TRUE;
+ att.srcColorBlendFactor = VK_BLEND_FACTOR_ONE;
+ att.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ att.colorBlendOp = VK_BLEND_OP_ADD;
+ att.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
+ att.dstAlphaBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
+ att.alphaBlendOp = VK_BLEND_OP_ADD;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+
+ if (vertShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, vertShaderModule, nullptr);
+ if (fragShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, fragShaderModule, nullptr);
+}
+
+void VulkanRenderer::initSwapChainResources()
+{
+ qDebug("initSwapChainResources");
+
+ // Projection matrix
+ m_proj = m_window->clipCorrectionMatrix(); // adjust for Vulkan-OpenGL clip space differences
+ const QSize sz = m_window->swapChainImageSize();
+ m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void VulkanRenderer::releaseSwapChainResources()
+{
+ qDebug("releaseSwapChainResources");
+}
+
+void VulkanRenderer::releaseResources()
+{
+ qDebug("releaseResources");
+
+ VkDevice dev = m_window->device();
+
+ if (m_sampler) {
+ m_devFuncs->vkDestroySampler(dev, m_sampler, nullptr);
+ m_sampler = VK_NULL_HANDLE;
+ }
+
+ if (m_texStaging) {
+ m_devFuncs->vkDestroyImage(dev, m_texStaging, nullptr);
+ m_texStaging = VK_NULL_HANDLE;
+ }
+
+ if (m_texStagingMem) {
+ m_devFuncs->vkFreeMemory(dev, m_texStagingMem, nullptr);
+ m_texStagingMem = VK_NULL_HANDLE;
+ }
+
+ if (m_texView) {
+ m_devFuncs->vkDestroyImageView(dev, m_texView, nullptr);
+ m_texView = VK_NULL_HANDLE;
+ }
+
+ if (m_texImage) {
+ m_devFuncs->vkDestroyImage(dev, m_texImage, nullptr);
+ m_texImage = VK_NULL_HANDLE;
+ }
+
+ if (m_texMem) {
+ m_devFuncs->vkFreeMemory(dev, m_texMem, nullptr);
+ m_texMem = VK_NULL_HANDLE;
+ }
+
+ if (m_pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_pipeline, nullptr);
+ m_pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_pipelineLayout, nullptr);
+ m_pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineCache) {
+ m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
+ m_pipelineCache = VK_NULL_HANDLE;
+ }
+
+ if (m_descSetLayout) {
+ m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_descSetLayout, nullptr);
+ m_descSetLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_descPool) {
+ m_devFuncs->vkDestroyDescriptorPool(dev, m_descPool, nullptr);
+ m_descPool = VK_NULL_HANDLE;
+ }
+
+ if (m_buf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_buf, nullptr);
+ m_buf = VK_NULL_HANDLE;
+ }
+
+ if (m_bufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
+ m_bufMem = VK_NULL_HANDLE;
+ }
+}
+
+void VulkanRenderer::startNextFrame()
+{
+ VkDevice dev = m_window->device();
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+ const QSize sz = m_window->swapChainImageSize();
+
+ // Add the necessary barriers and do the host-linear -> device-optimal copy, if not yet done.
+ ensureTexture();
+
+ VkClearColorValue clearColor = { 0, 0, 0, 1 };
+ VkClearDepthStencilValue clearDS = { 1, 0 };
+ VkClearValue clearValues[2];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem, m_uniformBufInfo[m_window->currentFrame()].offset,
+ UNIFORM_DATA_SIZE, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ QMatrix4x4 m = m_proj;
+ m.rotate(m_rotation, 0, 0, 1);
+ memcpy(p, m.constData(), 16 * sizeof(float));
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ // Not exactly a real animation system, just advance on every frame for now.
+ m_rotation += 1.0f;
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
+ m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1,
+ &m_descSet[m_window->currentFrame()], 0, nullptr);
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset);
+
+ VkViewport viewport;
+ viewport.x = viewport.y = 0;
+ viewport.width = sz.width();
+ viewport.height = sz.height();
+ viewport.minDepth = 0;
+ viewport.maxDepth = 1;
+ m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
+
+ VkRect2D scissor;
+ scissor.offset.x = scissor.offset.y = 0;
+ scissor.extent.width = viewport.width;
+ scissor.extent.height = viewport.height;
+ m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
+
+ m_devFuncs->vkCmdDraw(cb, 4, 1, 0, 0);
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+
+ m_window->frameReady();
+ m_window->requestUpdate(); // render continuously, throttled by the presentation rate
+}
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.h b/examples/vulkan/hellovulkantexture/hellovulkantexture.h
new file mode 100644
index 0000000000..a8c96d1987
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QVulkanWindow>
+#include <QImage>
+
+class VulkanRenderer : public QVulkanWindowRenderer
+{
+public:
+ VulkanRenderer(QVulkanWindow *w);
+
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+private:
+ VkShaderModule createShader(const QString &name);
+ bool createTexture(const QString &name);
+ bool createTextureImage(const QSize &size, VkImage *image, VkDeviceMemory *mem,
+ VkImageTiling tiling, VkImageUsageFlags usage, uint32_t memIndex);
+ bool writeLinearImage(const QImage &img, VkImage image, VkDeviceMemory memory);
+ void ensureTexture();
+
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+
+ VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
+ VkBuffer m_buf = VK_NULL_HANDLE;
+ VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkDescriptorPool m_descPool = VK_NULL_HANDLE;
+ VkDescriptorSetLayout m_descSetLayout = VK_NULL_HANDLE;
+ VkDescriptorSet m_descSet[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
+ VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline m_pipeline = VK_NULL_HANDLE;
+
+ VkSampler m_sampler = VK_NULL_HANDLE;
+ VkImage m_texImage = VK_NULL_HANDLE;
+ VkDeviceMemory m_texMem = VK_NULL_HANDLE;
+ bool m_texLayoutPending = false;
+ VkImageView m_texView = VK_NULL_HANDLE;
+ VkImage m_texStaging = VK_NULL_HANDLE;
+ VkDeviceMemory m_texStagingMem = VK_NULL_HANDLE;
+ bool m_texStagingPending = false;
+ QSize m_texSize;
+ VkFormat m_texFormat;
+
+ QMatrix4x4 m_proj;
+ float m_rotation = 0.0f;
+};
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+};
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.pro b/examples/vulkan/hellovulkantexture/hellovulkantexture.pro
new file mode 100644
index 0000000000..59bfcda715
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.pro
@@ -0,0 +1,7 @@
+HEADERS += hellovulkantexture.h
+SOURCES += hellovulkantexture.cpp main.cpp
+RESOURCES += hellovulkantexture.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkantexture
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkantexture/hellovulkantexture.qrc b/examples/vulkan/hellovulkantexture/hellovulkantexture.qrc
new file mode 100644
index 0000000000..04e7cda859
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/hellovulkantexture.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file>texture_vert.spv</file>
+ <file>texture_frag.spv</file>
+ <file>qt256.png</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkantexture/main.cpp b/examples/vulkan/hellovulkantexture/main.cpp
new file mode 100644
index 0000000000..1144463b70
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/main.cpp
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QVulkanInstance>
+#include <QLoggingCategory>
+#include "hellovulkantexture.h"
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+ if (QCoreApplication::arguments().contains(QStringLiteral("--srgb")))
+ w.setPreferredColorFormats(QVector<VkFormat>() << VK_FORMAT_B8G8R8A8_SRGB);
+
+ w.resize(1024, 768);
+ w.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkantexture/qt256.png b/examples/vulkan/hellovulkantexture/qt256.png
new file mode 100644
index 0000000000..30c621c9c6
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/qt256.png
Binary files differ
diff --git a/examples/vulkan/hellovulkantexture/texture.frag b/examples/vulkan/hellovulkantexture/texture.frag
new file mode 100644
index 0000000000..e6021fe905
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture.frag
@@ -0,0 +1,12 @@
+#version 440
+
+layout(location = 0) in vec2 v_texcoord;
+
+layout(location = 0) out vec4 fragColor;
+
+layout(binding = 1) uniform sampler2D tex;
+
+void main()
+{
+ fragColor = texture(tex, v_texcoord);
+}
diff --git a/examples/vulkan/hellovulkantexture/texture.vert b/examples/vulkan/hellovulkantexture/texture.vert
new file mode 100644
index 0000000000..de486cb772
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec2 texcoord;
+
+layout(location = 0) out vec2 v_texcoord;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_texcoord = texcoord;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/examples/vulkan/hellovulkantexture/texture_frag.spv b/examples/vulkan/hellovulkantexture/texture_frag.spv
new file mode 100644
index 0000000000..7521ef6eef
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture_frag.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkantexture/texture_vert.spv b/examples/vulkan/hellovulkantexture/texture_vert.spv
new file mode 100644
index 0000000000..6292c0de31
--- /dev/null
+++ b/examples/vulkan/hellovulkantexture/texture_vert.spv
Binary files differ
diff --git a/examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro
new file mode 100644
index 0000000000..db016da3ac
--- /dev/null
+++ b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.pro
@@ -0,0 +1,12 @@
+HEADERS += \
+ ../shared/trianglerenderer.h
+
+SOURCES += \
+ main.cpp \
+ ../shared/trianglerenderer.cpp
+
+RESOURCES += hellovulkantriangle.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkantriangle
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc
new file mode 100644
index 0000000000..489fc7295a
--- /dev/null
+++ b/examples/vulkan/hellovulkantriangle/hellovulkantriangle.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color_vert.spv">../shared/color_vert.spv</file>
+ <file alias="color_frag.spv">../shared/color_frag.spv</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkantriangle/main.cpp b/examples/vulkan/hellovulkantriangle/main.cpp
new file mode 100644
index 0000000000..d3eef2e14a
--- /dev/null
+++ b/examples/vulkan/hellovulkantriangle/main.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QVulkanInstance>
+#include <QLoggingCategory>
+#include "../shared/trianglerenderer.h"
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+};
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new TriangleRenderer(this, true); // try MSAA, when available
+}
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+
+ w.resize(1024, 768);
+ w.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp
new file mode 100644
index 0000000000..81daa9bb96
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "hellovulkanwidget.h"
+#include <QVulkanFunctions>
+#include <QApplication>
+#include <QVBoxLayout>
+#include <QPlainTextEdit>
+#include <QPushButton>
+#include <QLCDNumber>
+#include <QFileDialog>
+#include <QMessageBox>
+#include <QTabWidget>
+
+MainWindow::MainWindow(VulkanWindow *w, QPlainTextEdit *logWidget)
+ : m_window(w)
+{
+ QWidget *wrapper = QWidget::createWindowContainer(w);
+
+ m_info = new QPlainTextEdit;
+ m_info->setReadOnly(true);
+
+ m_number = new QLCDNumber(3);
+ m_number->setSegmentStyle(QLCDNumber::Filled);
+
+ QPushButton *grabButton = new QPushButton(tr("&Grab"));
+ grabButton->setFocusPolicy(Qt::NoFocus);
+
+ connect(grabButton, &QPushButton::clicked, this, &MainWindow::onGrabRequested);
+
+ QPushButton *quitButton = new QPushButton(tr("&Quit"));
+ quitButton->setFocusPolicy(Qt::NoFocus);
+
+ connect(quitButton, &QPushButton::clicked, qApp, &QCoreApplication::quit);
+
+ QVBoxLayout *layout = new QVBoxLayout;
+ m_infoTab = new QTabWidget(this);
+ m_infoTab->addTab(m_info, tr("Vulkan Info"));
+ m_infoTab->addTab(logWidget, tr("Debug Log"));
+ layout->addWidget(m_infoTab, 2);
+ layout->addWidget(m_number, 1);
+ layout->addWidget(wrapper, 5);
+ layout->addWidget(grabButton, 1);
+ layout->addWidget(quitButton, 1);
+ setLayout(layout);
+}
+
+void MainWindow::onVulkanInfoReceived(const QString &text)
+{
+ m_info->setPlainText(text);
+}
+
+void MainWindow::onFrameQueued(int colorValue)
+{
+ m_number->display(colorValue);
+}
+
+void MainWindow::onGrabRequested()
+{
+ if (!m_window->supportsGrab()) {
+ QMessageBox::warning(this, tr("Cannot grab"), tr("This swapchain does not support readbacks."));
+ return;
+ }
+
+ QImage img = m_window->grab();
+
+ // Our startNextFrame() implementation is synchronous so img is ready to be
+ // used right here.
+
+ QFileDialog fd(this);
+ fd.setAcceptMode(QFileDialog::AcceptSave);
+ fd.setDefaultSuffix("png");
+ fd.selectFile("test.png");
+ if (fd.exec() == QDialog::Accepted)
+ img.save(fd.selectedFiles().first());
+}
+
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new VulkanRenderer(this);
+}
+
+VulkanRenderer::VulkanRenderer(VulkanWindow *w)
+ : TriangleRenderer(w)
+{
+}
+
+void VulkanRenderer::initResources()
+{
+ TriangleRenderer::initResources();
+
+ QVulkanInstance *inst = m_window->vulkanInstance();
+ m_devFuncs = inst->deviceFunctions(m_window->device());
+
+ QString info;
+ info += QString().sprintf("Number of physical devices: %d\n", m_window->availablePhysicalDevices().count());
+
+ QVulkanFunctions *f = inst->functions();
+ VkPhysicalDeviceProperties props;
+ f->vkGetPhysicalDeviceProperties(m_window->physicalDevice(), &props);
+ info += QString().sprintf("Active physical device name: '%s' version %d.%d.%d\nAPI version %d.%d.%d\n",
+ props.deviceName,
+ VK_VERSION_MAJOR(props.driverVersion), VK_VERSION_MINOR(props.driverVersion),
+ VK_VERSION_PATCH(props.driverVersion),
+ VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion),
+ VK_VERSION_PATCH(props.apiVersion));
+
+ info += QStringLiteral("Supported instance layers:\n");
+ for (const QVulkanLayer &layer : inst->supportedLayers())
+ info += QString().sprintf(" %s v%u\n", layer.name.constData(), layer.version);
+ info += QStringLiteral("Enabled instance layers:\n");
+ for (const QByteArray &layer : inst->layers())
+ info += QString().sprintf(" %s\n", layer.constData());
+
+ info += QStringLiteral("Supported instance extensions:\n");
+ for (const QVulkanExtension &ext : inst->supportedExtensions())
+ info += QString().sprintf(" %s v%u\n", ext.name.constData(), ext.version);
+ info += QStringLiteral("Enabled instance extensions:\n");
+ for (const QByteArray &ext : inst->extensions())
+ info += QString().sprintf(" %s\n", ext.constData());
+
+ info += QString().sprintf("Color format: %u\nDepth-stencil format: %u\n",
+ m_window->colorFormat(), m_window->depthStencilFormat());
+
+ info += QStringLiteral("Supported sample counts:");
+ const QVector<int> sampleCounts = m_window->supportedSampleCounts();
+ for (int count : sampleCounts)
+ info += QLatin1Char(' ') + QString::number(count);
+ info += QLatin1Char('\n');
+
+ emit static_cast<VulkanWindow *>(m_window)->vulkanInfoReceived(info);
+}
+
+void VulkanRenderer::startNextFrame()
+{
+ TriangleRenderer::startNextFrame();
+ emit static_cast<VulkanWindow *>(m_window)->frameQueued(int(m_rotation) % 360);
+}
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h
new file mode 100644
index 0000000000..e70d331ae8
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../shared/trianglerenderer.h"
+#include <QWidget>
+
+class VulkanWindow;
+
+QT_BEGIN_NAMESPACE
+class QTabWidget;
+class QPlainTextEdit;
+class QLCDNumber;
+QT_END_NAMESPACE
+
+class MainWindow : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit MainWindow(VulkanWindow *w, QPlainTextEdit *logWidget);
+
+public slots:
+ void onVulkanInfoReceived(const QString &text);
+ void onFrameQueued(int colorValue);
+ void onGrabRequested();
+
+private:
+ VulkanWindow *m_window;
+ QTabWidget *m_infoTab;
+ QPlainTextEdit *m_info;
+ QLCDNumber *m_number;
+};
+
+class VulkanRenderer : public TriangleRenderer
+{
+public:
+ VulkanRenderer(VulkanWindow *w);
+
+ void initResources() override;
+ void startNextFrame() override;
+};
+
+class VulkanWindow : public QVulkanWindow
+{
+ Q_OBJECT
+
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+
+signals:
+ void vulkanInfoReceived(const QString &text);
+ void frameQueued(int colorValue);
+};
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro
new file mode 100644
index 0000000000..7b87d7f210
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.pro
@@ -0,0 +1,16 @@
+QT += widgets
+
+HEADERS += \
+ hellovulkanwidget.h \
+ ../shared/trianglerenderer.h
+
+SOURCES += \
+ hellovulkanwidget.cpp \
+ main.cpp \
+ ../shared/trianglerenderer.cpp
+
+RESOURCES += hellovulkanwidget.qrc
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkanwidget
+INSTALLS += target
diff --git a/examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc
new file mode 100644
index 0000000000..489fc7295a
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/hellovulkanwidget.qrc
@@ -0,0 +1,6 @@
+<!DOCTYPE RCC><RCC version="1.0">
+<qresource>
+ <file alias="color_vert.spv">../shared/color_vert.spv</file>
+ <file alias="color_frag.spv">../shared/color_frag.spv</file>
+</qresource>
+</RCC>
diff --git a/examples/vulkan/hellovulkanwidget/main.cpp b/examples/vulkan/hellovulkanwidget/main.cpp
new file mode 100644
index 0000000000..5ddaf90224
--- /dev/null
+++ b/examples/vulkan/hellovulkanwidget/main.cpp
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QApplication>
+#include <QPlainTextEdit>
+#include <QVulkanInstance>
+#include <QLibraryInfo>
+#include <QLoggingCategory>
+#include <QPointer>
+#include "hellovulkanwidget.h"
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+static QPointer<QPlainTextEdit> messageLogWidget;
+static QtMessageHandler oldMessageHandler = nullptr;
+
+static void messageHandler(QtMsgType msgType, const QMessageLogContext &logContext, const QString &text)
+{
+ if (!messageLogWidget.isNull())
+ messageLogWidget->appendPlainText(text);
+ if (oldMessageHandler)
+ oldMessageHandler(msgType, logContext, text);
+}
+
+int main(int argc, char *argv[])
+{
+ QApplication app(argc, argv);
+
+ messageLogWidget = new QPlainTextEdit(QLatin1String(QLibraryInfo::build()) + QLatin1Char('\n'));
+ messageLogWidget->setReadOnly(true);
+
+ oldMessageHandler = qInstallMessageHandler(messageHandler);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow *vulkanWindow = new VulkanWindow;
+ vulkanWindow->setVulkanInstance(&inst);
+
+ MainWindow mainWindow(vulkanWindow, messageLogWidget.data());
+ QObject::connect(vulkanWindow, &VulkanWindow::vulkanInfoReceived, &mainWindow, &MainWindow::onVulkanInfoReceived);
+ QObject::connect(vulkanWindow, &VulkanWindow::frameQueued, &mainWindow, &MainWindow::onFrameQueued);
+
+ mainWindow.resize(1024, 768);
+ mainWindow.show();
+
+ return app.exec();
+}
diff --git a/examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp
new file mode 100644
index 0000000000..0a7d1d4174
--- /dev/null
+++ b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.cpp
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "hellovulkanwindow.h"
+#include <QVulkanFunctions>
+
+//! [0]
+QVulkanWindowRenderer *VulkanWindow::createRenderer()
+{
+ return new VulkanRenderer(this);
+}
+
+VulkanRenderer::VulkanRenderer(QVulkanWindow *w)
+ : m_window(w)
+{
+}
+//! [0]
+
+//! [1]
+void VulkanRenderer::initResources()
+{
+ qDebug("initResources");
+
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(m_window->device());
+}
+//! [1]
+
+void VulkanRenderer::initSwapChainResources()
+{
+ qDebug("initSwapChainResources");
+}
+
+void VulkanRenderer::releaseSwapChainResources()
+{
+ qDebug("releaseSwapChainResources");
+}
+
+void VulkanRenderer::releaseResources()
+{
+ qDebug("releaseResources");
+}
+
+//! [2]
+void VulkanRenderer::startNextFrame()
+{
+ m_green += 0.005f;
+ if (m_green > 1.0f)
+ m_green = 0.0f;
+
+ VkClearColorValue clearColor = { 0.0f, m_green, 0.0f, 1.0f };
+ VkClearDepthStencilValue clearDS = { 1.0f, 0 };
+ VkClearValue clearValues[2];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ const QSize sz = m_window->swapChainImageSize();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ // Do nothing else. We will just clear to green, changing the component on
+ // every invocation. This also helps verifying the rate to which the thread
+ // is throttled to. (The elapsed time between startNextFrame calls should
+ // typically be around 16 ms. Note that rendering is 2 frames ahead of what
+ // is displayed.)
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+
+ m_window->frameReady();
+ m_window->requestUpdate(); // render continuously, throttled by the presentation rate
+}
+//! [2]
diff --git a/examples/vulkan/hellovulkanwindow/hellovulkanwindow.h b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.h
new file mode 100644
index 0000000000..5f52e402ca
--- /dev/null
+++ b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QVulkanWindow>
+
+//! [0]
+class VulkanRenderer : public QVulkanWindowRenderer
+{
+public:
+ VulkanRenderer(QVulkanWindow *w);
+
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+private:
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+ float m_green = 0;
+};
+
+class VulkanWindow : public QVulkanWindow
+{
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+};
+//! [0]
diff --git a/examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro
new file mode 100644
index 0000000000..8f7d9494e2
--- /dev/null
+++ b/examples/vulkan/hellovulkanwindow/hellovulkanwindow.pro
@@ -0,0 +1,6 @@
+HEADERS += hellovulkanwindow.h
+SOURCES += hellovulkanwindow.cpp main.cpp
+
+# install
+target.path = $$[QT_INSTALL_EXAMPLES]/vulkan/hellovulkanwindow
+INSTALLS += target
diff --git a/src/corelib/doc/snippets/signalmapper/filereader.cpp b/examples/vulkan/hellovulkanwindow/main.cpp
index 674f73d671..313c28f9e0 100644
--- a/src/corelib/doc/snippets/signalmapper/filereader.cpp
+++ b/examples/vulkan/hellovulkanwindow/main.cpp
@@ -1,9 +1,9 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the config.tests of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:BSD$
** Commercial License Usage
@@ -48,70 +48,46 @@
**
****************************************************************************/
-#include <QtGui>
-#include "filereader.h"
+#include <QGuiApplication>
+#include <QVulkanInstance>
+#include <QLoggingCategory>
+#include "hellovulkanwindow.h"
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
-FileReader::FileReader(QWidget *parent)
- : QWidget(parent)
+int main(int argc, char *argv[])
{
- textEdit = new QTextEdit;
+ QGuiApplication app(argc, argv);
- taxFileButton = new QPushButton("Tax File");
- accountFileButton = new QPushButton("Accounts File");
- reportFileButton = new QPushButton("Report File");
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
//! [0]
- signalMapper = new QSignalMapper(this);
- signalMapper->setMapping(taxFileButton, QString("taxfile.txt"));
- signalMapper->setMapping(accountFileButton, QString("accountsfile.txt"));
- signalMapper->setMapping(reportFileButton, QString("reportfile.txt"));
-
- connect(taxFileButton, &QPushButton::clicked,
- signalMapper, &QSignalMapper::map);
- connect(accountFileButton, &QPushButton::clicked,
- signalMapper, &QSignalMapper::map);
- connect(reportFileButton, &QPushButton::clicked,
- signalMapper, &QSignalMapper::map);
+ QVulkanInstance inst;
+
+#ifndef Q_OS_ANDROID
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+#else
+ inst.setLayers(QByteArrayList()
+ << "VK_LAYER_GOOGLE_threading"
+ << "VK_LAYER_LUNARG_parameter_validation"
+ << "VK_LAYER_LUNARG_object_tracker"
+ << "VK_LAYER_LUNARG_core_validation"
+ << "VK_LAYER_LUNARG_image"
+ << "VK_LAYER_LUNARG_swapchain"
+ << "VK_LAYER_GOOGLE_unique_objects");
+#endif
+
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
//! [0]
//! [1]
- connect(signalMapper, SIGNAL(mapped(QString)),
- this, SLOT(readFile(QString)));
-//! [1]
-
-/*
-//! [2]
- //slower due to signature normalization at runtime
-
- connect(signalMapper, SIGNAL(mapped(QString)),
- this, SLOT(readFile(QString)));
-//! [2]
-*/
- QHBoxLayout *buttonLayout = new QHBoxLayout;
- buttonLayout->addWidget(taxFileButton);
- buttonLayout->addWidget(accountFileButton);
- buttonLayout->addWidget(reportFileButton);
-
- QVBoxLayout *mainLayout = new QVBoxLayout;
- mainLayout->addWidget(textEdit);
- mainLayout->addLayout(buttonLayout);
-
- setLayout(mainLayout);
-}
-
-void FileReader::readFile(const QString &filename)
-{
- QFile file(filename);
-
- if (!file.open(QIODevice::ReadOnly)) {
- QMessageBox::information(this, tr("Unable to open file"),
- file.errorString());
- return;
- }
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+ w.resize(1024, 768);
+ w.show();
+//! [1]
- QTextStream in(&file);
- textEdit->setPlainText(in.readAll());
+ return app.exec();
}
-
diff --git a/examples/vulkan/shared/block.buf b/examples/vulkan/shared/block.buf
new file mode 100644
index 0000000000..28ec2620bd
--- /dev/null
+++ b/examples/vulkan/shared/block.buf
Binary files differ
diff --git a/examples/vulkan/shared/block.txt b/examples/vulkan/shared/block.txt
new file mode 100644
index 0000000000..a6b66b83cc
--- /dev/null
+++ b/examples/vulkan/shared/block.txt
@@ -0,0 +1,100 @@
+# Blender v2.78 (sub 0) OBJ File: ''
+# www.blender.org
+mtllib block.mtl
+o Cube_Cube.001
+v 0.450000 -0.500000 -0.450000
+v 0.450000 -0.500000 0.450000
+v -0.450000 -0.500000 0.450000
+v -0.450000 -0.500000 -0.450000
+v -0.500000 0.450000 0.450000
+v -0.500000 0.450000 -0.450000
+v -0.500000 -0.450000 -0.450000
+v -0.500000 -0.450000 0.450000
+v -0.450000 0.500000 -0.450000
+v -0.450000 0.500000 0.450000
+v 0.450000 0.500000 0.450000
+v 0.450000 0.500000 -0.450000
+v -0.450000 0.450000 -0.500000
+v 0.450000 0.450000 -0.500000
+v 0.450000 -0.450000 -0.500000
+v -0.450000 -0.450000 -0.500000
+v 0.450000 0.450000 0.500000
+v -0.450000 0.450000 0.500000
+v -0.450000 -0.450000 0.500000
+v 0.450000 -0.450000 0.500000
+v 0.500000 -0.450000 -0.450000
+v 0.500000 0.450000 -0.450000
+v 0.500000 -0.450000 0.450000
+v 0.500000 0.450000 0.450000
+vn 0.0000 -1.0000 -0.0000
+vn -1.0000 0.0000 0.0000
+vn 0.0000 1.0000 0.0000
+vn 0.0000 0.0000 -1.0000
+vn 0.0000 -0.0000 1.0000
+vn 0.5774 -0.5773 -0.5774
+vn 0.5774 0.5774 -0.5774
+vn 0.5774 -0.5774 0.5774
+vn 0.5774 0.5773 0.5774
+vn -0.5774 -0.5773 -0.5774
+vn -0.5773 0.5774 -0.5774
+vn -0.5774 -0.5774 0.5774
+vn -0.5774 0.5773 0.5774
+vn 0.7071 0.0000 -0.7071
+vn 0.7071 0.7071 0.0000
+vn 0.7071 -0.0000 0.7071
+vn 0.7071 -0.7071 -0.0000
+vn 0.0000 0.7071 0.7071
+vn -0.7071 -0.0000 0.7071
+vn 0.0000 -0.7071 0.7071
+vn -0.7071 0.7071 0.0000
+vn -0.7071 0.0000 -0.7071
+vn -0.7071 -0.7071 -0.0000
+vn 0.0000 0.7071 -0.7071
+vn 0.0000 -0.7071 -0.7071
+vn 1.0000 0.0000 0.0000
+usemtl None
+s 1
+f 2//1 4//1 1//1
+f 6//2 8//2 5//2
+f 10//3 12//3 9//3
+f 14//4 16//4 13//4
+f 18//5 20//5 17//5
+f 15//6 21//6 1//6
+f 14//7 12//7 22//7
+f 20//8 2//8 23//8
+f 11//9 17//9 24//9
+f 16//10 4//10 7//10
+f 9//11 13//11 6//11
+f 8//12 3//12 19//12
+f 10//13 5//13 18//13
+f 14//14 21//14 15//14
+f 11//15 22//15 12//15
+f 20//16 24//16 17//16
+f 1//17 23//17 2//17
+f 10//18 17//18 11//18
+f 8//19 18//19 5//19
+f 2//20 19//20 3//20
+f 9//21 5//21 10//21
+f 16//22 6//22 13//22
+f 3//23 7//23 4//23
+f 12//24 13//24 9//24
+f 4//25 15//25 1//25
+f 24//26 21//26 22//26
+f 2//1 3//1 4//1
+f 6//2 7//2 8//2
+f 10//3 11//3 12//3
+f 14//4 15//4 16//4
+f 18//5 19//5 20//5
+f 14//14 22//14 21//14
+f 11//15 24//15 22//15
+f 20//16 23//16 24//16
+f 1//17 21//17 23//17
+f 10//18 18//18 17//18
+f 8//19 19//19 18//19
+f 2//20 20//20 19//20
+f 9//21 6//21 5//21
+f 16//22 7//22 6//22
+f 3//23 8//23 7//23
+f 12//24 14//24 13//24
+f 4//25 16//25 15//25
+f 24//26 23//26 21//26
diff --git a/examples/vulkan/shared/color.frag b/examples/vulkan/shared/color.frag
new file mode 100644
index 0000000000..375587662f
--- /dev/null
+++ b/examples/vulkan/shared/color.frag
@@ -0,0 +1,10 @@
+#version 440
+
+layout(location = 0) in vec3 v_color;
+
+layout(location = 0) out vec4 fragColor;
+
+void main()
+{
+ fragColor = vec4(v_color, 1.0);
+}
diff --git a/examples/vulkan/shared/color.vert b/examples/vulkan/shared/color.vert
new file mode 100644
index 0000000000..02492c0e65
--- /dev/null
+++ b/examples/vulkan/shared/color.vert
@@ -0,0 +1,18 @@
+#version 440
+
+layout(location = 0) in vec4 position;
+layout(location = 1) in vec3 color;
+
+layout(location = 0) out vec3 v_color;
+
+layout(std140, binding = 0) uniform buf {
+ mat4 mvp;
+} ubuf;
+
+out gl_PerVertex { vec4 gl_Position; };
+
+void main()
+{
+ v_color = color;
+ gl_Position = ubuf.mvp * position;
+}
diff --git a/examples/vulkan/shared/color_frag.spv b/examples/vulkan/shared/color_frag.spv
new file mode 100644
index 0000000000..30e33b76ca
--- /dev/null
+++ b/examples/vulkan/shared/color_frag.spv
Binary files differ
diff --git a/examples/vulkan/shared/color_vert.spv b/examples/vulkan/shared/color_vert.spv
new file mode 100644
index 0000000000..a1f42e3119
--- /dev/null
+++ b/examples/vulkan/shared/color_vert.spv
Binary files differ
diff --git a/examples/vulkan/shared/objconvert.js b/examples/vulkan/shared/objconvert.js
new file mode 100644
index 0000000000..9b49e3cdac
--- /dev/null
+++ b/examples/vulkan/shared/objconvert.js
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+var fs = require('fs');
+
+var metadata = {
+ vertexCount: 0,
+ aabb: [[null, null], [null, null], [null, null]],
+ emitVertex: function(v) {
+ ++metadata.vertexCount;
+ var aabb = metadata.aabb;
+ if (aabb[0][0] === null || v[0] < aabb[0][0]) // min x
+ aabb[0][0] = v[0];
+ if (aabb[0][1] === null || v[0] > aabb[0][1]) // max x
+ aabb[0][1] = v[0];
+ if (aabb[1][0] === null || v[1] < aabb[1][0]) // min y
+ aabb[1][0] = v[1];
+ if (aabb[1][1] === null || v[1] > aabb[1][1]) // max y
+ aabb[1][1] = v[1];
+ if (aabb[2][0] === null || v[2] < aabb[2][0]) // min z
+ aabb[2][0] = v[2];
+ if (aabb[2][1] === null || v[2] > aabb[2][1]) // max z
+ aabb[2][1] = v[2];
+ },
+ getBuffer: function() {
+ var aabb = metadata.aabb;
+ console.log(metadata.vertexCount + " vertices");
+ console.log("AABB: " + aabb[0][0] + ".." + aabb[0][1]
+ + ", " + aabb[1][0] + ".." + aabb[1][1]
+ + ", " + aabb[2][0] + ".." + aabb[2][1]);
+ var buf = new Buffer((2 + 6) * 4);
+ var format = 1, p = 0;
+ buf.writeUInt32LE(format, p++);
+ buf.writeUInt32LE(metadata.vertexCount, p++ * 4);
+ for (var i = 0; i < 3; ++i) {
+ buf.writeFloatLE(aabb[i][0], p++ * 4);
+ buf.writeFloatLE(aabb[i][1], p++ * 4);
+ }
+ return buf;
+ }
+};
+
+function makeVec(s, n) {
+ var v = [];
+ s.split(' ').forEach(function (coordStr) {
+ var coord = parseFloat(coordStr);
+ if (!isNaN(coord))
+ v.push(coord);
+ });
+ if (v.length != n) {
+ console.error("Wrong vector size, expected " + n + ", got " + v.length);
+ process.exit();
+ }
+ return v;
+}
+
+function parseObj(filename, callback) {
+ fs.readFile(filename, "ascii", function (err, data) {
+ if (err)
+ throw err;
+ var groupCount = 0;
+ var parsed = { 'vertices': [], 'normals': [], 'texcoords': [], 'links': [] };
+ var missingTexCount = 0, missingNormCount = 0;
+ data.split('\n').forEach(function (line) {
+ var s = line.trim();
+ if (!s.length || groupCount > 1)
+ return;
+ if (s[0] === '#')
+ return;
+ if (s[0] === 'g') {
+ ++groupCount;
+ } else if (s.substr(0, 2) === "v ") {
+ parsed.vertices.push(makeVec(s, 3));
+ } else if (s.substr(0, 3) === "vn ") {
+ parsed.normals.push(makeVec(s, 3));
+ } else if (s.substr(0, 3) === "vt ") {
+ parsed.texcoords.push(makeVec(s, 2));
+ } else if (s.substr(0, 2) === "f ") {
+ var refs = s.split(' ');
+ var vertCount = refs.length - 1;
+ if (vertCount != 3)
+ console.warn("Face " + parsed.links.length / 3 + " has " + vertCount + " vertices! (not triangulated?)");
+ for (var i = 1, ie = Math.min(4, refs.length); i < ie; ++i) {
+ var refComps = refs[i].split('/');
+ var vertIndex = parseInt(refComps[0]) - 1;
+ var texIndex = -1;
+ if (refComps.length >= 2 && refComps[1].length)
+ texIndex = parseInt(refComps[1]) - 1;
+ var normIndex = -1;
+ if (refComps.length >= 3 && refComps[2].length)
+ normIndex = parseInt(refComps[2]) - 1;
+ parsed.links.push([vertIndex, texIndex, normIndex]);
+ if (texIndex == -1)
+ ++missingTexCount;
+ if (normIndex == -1)
+ ++missingNormCount;
+ }
+ }
+ });
+ console.log(missingTexCount + " missing texture coordinates, " + missingNormCount + " missing normals");
+ callback(parsed);
+ });
+}
+
+function fillVert(src, index, dst, elemCount, isVertexCoord) {
+ var vertex = [];
+ if (index >= 0) {
+ for (var i = 0; i < elemCount; ++i) {
+ var elem = src[index][i];
+ if (isVertexCoord)
+ vertex.push(elem);
+ dst.buf.writeFloatLE(elem, dst.bufptr++ * 4);
+ }
+ if (vertex.length == 3)
+ metadata.emitVertex(vertex);
+ } else {
+ if (isVertexCoord) {
+ console.error("Missing vertex");
+ process.exit();
+ }
+ for (var i = 0; i < elemCount; ++i)
+ dst.buf.writeFloatLE(0, dst.bufptr++ * 4);
+ }
+ return vertex;
+}
+
+function normalize(v) {
+ var len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
+ if (len == 0.0 || len == 1.0)
+ return;
+ len = Math.sqrt(len);
+ return [ v[0] / len, v[1] / len, v[2] / len ];
+}
+
+function surfaceNormal(a, b, c) {
+ var u = [ b[0] - a[0], b[1] - a[1], b[2] - a[2] ];
+ var v = [ c[0] - a[0], c[1] - a[1], c[2] - a[2] ];
+ var result = [ u[1] * v[2] - u[2] * v[1],
+ u[2] * v[0] - u[0] * v[2],
+ u[0] * v[1] - u[1] * v[0] ];
+ return normalize(result);
+}
+
+function objDataToBuf(parsed) {
+ var floatCount = parsed.links.length * (3 + 2 + 3);
+ var buf = new Buffer(floatCount * 4);
+ var dst = { 'buf': buf, 'bufptr': 0 };
+ var tri = [];
+ var genNormals = false;
+ var genNormCount = 0;
+ for (var i = 0; i < parsed.links.length; ++i) {
+ var link = parsed.links[i];
+ var vertIndex = link[0], texIndex = link[1], normIndex = link[2];
+ tri.push(fillVert(parsed.vertices, vertIndex, dst, 3, true));
+ fillVert(parsed.texcoords, texIndex, dst, 2);
+ fillVert(parsed.normals, normIndex, dst, 3);
+ if (normIndex == -1)
+ genNormals = true;
+ if (tri.length == 3) {
+ if (genNormals) {
+ var norm = surfaceNormal(tri[0], tri[1], tri[2]);
+ for (var nvIdx = 0; nvIdx < 3; ++nvIdx) {
+ dst.buf.writeFloatLE(norm[0], (dst.bufptr - 3 - nvIdx * 8) * 4);
+ dst.buf.writeFloatLE(norm[1], (dst.bufptr - 2 - nvIdx * 8) * 4);
+ dst.buf.writeFloatLE(norm[2], (dst.bufptr - 1 - nvIdx * 8) * 4);
+ }
+ genNormCount += 3;
+ }
+ tri = [];
+ }
+ }
+ if (genNormCount)
+ console.log("Generated " + genNormCount + " normals");
+ return buf;
+}
+
+var inFilename = process.argv[2];
+var outFilename = process.argv[3];
+
+if (process.argv.length < 4) {
+ console.log("Usage: objconvert file.obj file.buf");
+ process.exit();
+}
+
+parseObj(inFilename, function (parsed) {
+ var buf = objDataToBuf(parsed);
+ var f = fs.createWriteStream(outFilename);
+ f.on("error", function (e) { console.error(e); });
+ f.write(metadata.getBuffer());
+ f.write(buf);
+ f.end();
+ console.log("Written to " + outFilename + ", format is:");
+ console.log(" uint32 version, uint32 vertex_count, float32 aabb[6], vertex_count * (float32 vertex[3], float32 texcoord[2], float32 normal[3])");
+});
diff --git a/examples/vulkan/shared/qt_logo.buf b/examples/vulkan/shared/qt_logo.buf
new file mode 100644
index 0000000000..316ec41aee
--- /dev/null
+++ b/examples/vulkan/shared/qt_logo.buf
Binary files differ
diff --git a/examples/vulkan/shared/qt_logo.txt b/examples/vulkan/shared/qt_logo.txt
new file mode 100644
index 0000000000..167b8a4caf
--- /dev/null
+++ b/examples/vulkan/shared/qt_logo.txt
@@ -0,0 +1,2912 @@
+# Blender v2.77 (sub 0) OBJ File: 'qt_logo.blend'
+# www.blender.org
+o qt_logo_qt_logo_mesh
+v 0.500000 0.030000 -0.271909
+v 0.500000 0.030000 -0.234087
+v 0.500000 0.030000 0.229669
+v 0.361282 0.030000 0.368353
+v -0.369121 0.030000 0.368353
+v -0.403885 0.030000 0.368353
+v -0.500000 0.030000 0.368353
+v -0.500000 0.030000 0.272263
+v -0.500000 0.030000 0.234440
+v -0.500000 0.030000 -0.229316
+v -0.361282 0.030000 -0.368000
+v 0.369121 0.030000 -0.368000
+v 0.403886 0.030000 -0.368000
+v 0.500000 0.030000 -0.368000
+v -0.014123 0.030000 0.177038
+v -0.008432 0.030000 0.172481
+v -0.003036 0.030000 0.167611
+v 0.002070 0.030000 0.162429
+v 0.006887 0.030000 0.156934
+v 0.011418 0.030000 0.151127
+v 0.015664 0.030000 0.145008
+v 0.019629 0.030000 0.138577
+v 0.023315 0.030000 0.131833
+v 0.026724 0.030000 0.124776
+v 0.029858 0.030000 0.117408
+v 0.032720 0.030000 0.109727
+v 0.035255 0.030000 0.101769
+v 0.037575 0.030000 0.093399
+v 0.039680 0.030000 0.084618
+v 0.041569 0.030000 0.075425
+v 0.043240 0.030000 0.065820
+v 0.044692 0.030000 0.055804
+v 0.045923 0.030000 0.045375
+v 0.046934 0.030000 0.034535
+v 0.047722 0.030000 0.023284
+v 0.048286 0.030000 0.011620
+v 0.048626 0.030000 -0.000455
+v 0.048739 0.030000 -0.012942
+v 0.048469 0.030000 -0.031775
+v 0.047658 0.030000 -0.049771
+v 0.046305 0.030000 -0.066929
+v 0.044409 0.030000 -0.083249
+v 0.041969 0.030000 -0.098732
+v 0.038983 0.030000 -0.113377
+v 0.035450 0.030000 -0.127184
+v 0.031369 0.030000 -0.140154
+v 0.026739 0.030000 -0.152286
+v 0.021559 0.030000 -0.163580
+v 0.015828 0.030000 -0.174037
+v 0.009543 0.030000 -0.183656
+v 0.002656 0.030000 -0.192551
+v -0.005054 0.030000 -0.200667
+v -0.013585 0.030000 -0.208004
+v -0.022937 0.030000 -0.214563
+v -0.033107 0.030000 -0.220347
+v -0.044095 0.030000 -0.225355
+v -0.055900 0.030000 -0.229590
+v -0.068520 0.030000 -0.233052
+v -0.081954 0.030000 -0.235742
+v -0.096201 0.030000 -0.237663
+v -0.111260 0.030000 -0.238814
+v -0.127130 0.030000 -0.239198
+v -0.143000 0.030000 -0.238808
+v -0.158061 0.030000 -0.237638
+v -0.172312 0.030000 -0.235689
+v -0.185753 0.030000 -0.232963
+v -0.198385 0.030000 -0.229461
+v -0.210208 0.030000 -0.225185
+v -0.221221 0.030000 -0.220134
+v -0.231425 0.030000 -0.214311
+v -0.240819 0.030000 -0.207716
+v -0.249404 0.030000 -0.200351
+v -0.257179 0.030000 -0.192217
+v -0.264144 0.030000 -0.183315
+v -0.270435 0.030000 -0.173618
+v -0.276186 0.030000 -0.163098
+v -0.281394 0.030000 -0.151754
+v -0.286059 0.030000 -0.139586
+v -0.290179 0.030000 -0.126595
+v -0.293754 0.030000 -0.112781
+v -0.296782 0.030000 -0.098143
+v -0.299263 0.030000 -0.082682
+v -0.301194 0.030000 -0.066397
+v -0.302575 0.030000 -0.049288
+v -0.303404 0.030000 -0.031357
+v -0.303681 0.030000 -0.012601
+v -0.303411 0.030000 0.006061
+v -0.302602 0.030000 0.023884
+v -0.301253 0.030000 0.040864
+v -0.299364 0.030000 0.056999
+v -0.296935 0.030000 0.072288
+v -0.293967 0.030000 0.086726
+v -0.290460 0.030000 0.100313
+v -0.286412 0.030000 0.113046
+v -0.281825 0.030000 0.124922
+v -0.276698 0.030000 0.135939
+v -0.271032 0.030000 0.146095
+v -0.264826 0.030000 0.155387
+v -0.257932 0.030000 0.163877
+v -0.250200 0.030000 0.171629
+v -0.241634 0.030000 0.178643
+v -0.232233 0.030000 0.184918
+v -0.221998 0.030000 0.190455
+v -0.210932 0.030000 0.195254
+v -0.199035 0.030000 0.199315
+v -0.186309 0.030000 0.202637
+v -0.172754 0.030000 0.205221
+v -0.158371 0.030000 0.207067
+v -0.143163 0.030000 0.208174
+v -0.127130 0.030000 0.208543
+v -0.122805 0.030000 0.208515
+v -0.118691 0.030000 0.208431
+v -0.114786 0.030000 0.208293
+v -0.111086 0.030000 0.208101
+v -0.107590 0.030000 0.207858
+v -0.104294 0.030000 0.207563
+v -0.101198 0.030000 0.207219
+v -0.098298 0.030000 0.206827
+v -0.095593 0.030000 0.206387
+v -0.093079 0.030000 0.205901
+v -0.090754 0.030000 0.205370
+v -0.088616 0.030000 0.204795
+v -0.032379 0.030000 0.297137
+v 0.032720 0.030000 0.266811
+v 0.027981 0.030000 0.259139
+v 0.022692 0.030000 0.250576
+v 0.017036 0.030000 0.241420
+v 0.011197 0.030000 0.231966
+v 0.005358 0.030000 0.222513
+v -0.000298 0.030000 0.213356
+v -0.005587 0.030000 0.204794
+v -0.010326 0.030000 0.197122
+v -0.014331 0.030000 0.190638
+v -0.017419 0.030000 0.185639
+v -0.019406 0.030000 0.182422
+v -0.020109 0.030000 0.181283
+v 0.291411 0.030000 0.137327
+v 0.286764 0.030000 0.137511
+v 0.281577 0.030000 0.137715
+v 0.276031 0.030000 0.137934
+v 0.270305 0.030000 0.138160
+v 0.264578 0.030000 0.138386
+v 0.259032 0.030000 0.138605
+v 0.253845 0.030000 0.138810
+v 0.249198 0.030000 0.138993
+v 0.245271 0.030000 0.139148
+v 0.242243 0.030000 0.139267
+v 0.240294 0.030000 0.139344
+v 0.239605 0.030000 0.139372
+v 0.235884 0.030000 0.139286
+v 0.232394 0.030000 0.139029
+v 0.229135 0.030000 0.138600
+v 0.226110 0.030000 0.137996
+v 0.223322 0.030000 0.137217
+v 0.220774 0.030000 0.136262
+v 0.218466 0.030000 0.135130
+v 0.216403 0.030000 0.133819
+v 0.214585 0.030000 0.132328
+v 0.213017 0.030000 0.130656
+v 0.211699 0.030000 0.128802
+v 0.210634 0.030000 0.126764
+v 0.209732 0.030000 0.124535
+v 0.208903 0.030000 0.121937
+v 0.208147 0.030000 0.118969
+v 0.207465 0.030000 0.115633
+v 0.206860 0.030000 0.111927
+v 0.206331 0.030000 0.107853
+v 0.205880 0.030000 0.103409
+v 0.205509 0.030000 0.098596
+v 0.205218 0.030000 0.093413
+v 0.205009 0.030000 0.087862
+v 0.204882 0.030000 0.081942
+v 0.204840 0.030000 0.075652
+v 0.204840 0.030000 -0.063713
+v 0.292093 0.030000 -0.063713
+v 0.292093 0.030000 -0.122662
+v 0.204840 0.030000 -0.122662
+v 0.204840 0.030000 -0.214664
+v 0.136333 0.030000 -0.214664
+v 0.136333 0.030000 -0.122662
+v 0.087935 0.030000 -0.122662
+v 0.087935 0.030000 -0.064054
+v 0.136333 0.030000 -0.064054
+v 0.136333 0.030000 -0.050850
+v 0.136333 0.030000 -0.036113
+v 0.136333 0.030000 -0.020353
+v 0.136333 0.030000 -0.004083
+v 0.136333 0.030000 0.012188
+v 0.136333 0.030000 0.027947
+v 0.136333 0.030000 0.042685
+v 0.136333 0.030000 0.055889
+v 0.136333 0.030000 0.067048
+v 0.136333 0.030000 0.075652
+v 0.136333 0.030000 0.081189
+v 0.136333 0.030000 0.083148
+v 0.136475 0.030000 0.094258
+v 0.136899 0.030000 0.104757
+v 0.137605 0.030000 0.114646
+v 0.138592 0.030000 0.123924
+v 0.139858 0.030000 0.132592
+v 0.141403 0.030000 0.140649
+v 0.143224 0.030000 0.148096
+v 0.145321 0.030000 0.154932
+v 0.147692 0.030000 0.161158
+v 0.150337 0.030000 0.166773
+v 0.153254 0.030000 0.171778
+v 0.156442 0.030000 0.176172
+v 0.159999 0.030000 0.180091
+v 0.164025 0.030000 0.183669
+v 0.168520 0.030000 0.186906
+v 0.173483 0.030000 0.189802
+v 0.178915 0.030000 0.192358
+v 0.184816 0.030000 0.194573
+v 0.191185 0.030000 0.196447
+v 0.198023 0.030000 0.197980
+v 0.205330 0.030000 0.199173
+v 0.213105 0.030000 0.200024
+v 0.221349 0.030000 0.200536
+v 0.230061 0.030000 0.200706
+v 0.233945 0.030000 0.200649
+v 0.238099 0.030000 0.200479
+v 0.242523 0.030000 0.200195
+v 0.247217 0.030000 0.199797
+v 0.252180 0.030000 0.199286
+v 0.257413 0.030000 0.198662
+v 0.262916 0.030000 0.197923
+v 0.268689 0.030000 0.197071
+v 0.274732 0.030000 0.196106
+v 0.281044 0.030000 0.195027
+v 0.287626 0.030000 0.193834
+v 0.294479 0.030000 0.192528
+v -0.042504 0.030000 -0.131451
+v -0.039308 0.030000 -0.123910
+v -0.036421 0.030000 -0.115714
+v -0.033843 0.030000 -0.106862
+v -0.031573 0.030000 -0.097352
+v -0.029610 0.030000 -0.087182
+v -0.027952 0.030000 -0.076353
+v -0.026597 0.030000 -0.064862
+v -0.025546 0.030000 -0.052708
+v -0.024797 0.030000 -0.039891
+v -0.024348 0.030000 -0.026409
+v -0.024199 0.030000 -0.012261
+v -0.024348 0.030000 0.001795
+v -0.024794 0.030000 0.015166
+v -0.025536 0.030000 0.027852
+v -0.026572 0.030000 0.039848
+v -0.027902 0.030000 0.051154
+v -0.029525 0.030000 0.061767
+v -0.031438 0.030000 0.071683
+v -0.033641 0.030000 0.080902
+v -0.036133 0.030000 0.089420
+v -0.038913 0.030000 0.097236
+v -0.041979 0.030000 0.104346
+v -0.045331 0.030000 0.110749
+v -0.049179 0.030000 0.116548
+v -0.053569 0.030000 0.121850
+v -0.058501 0.030000 0.126652
+v -0.063975 0.030000 0.130954
+v -0.069995 0.030000 0.134754
+v -0.076559 0.030000 0.138051
+v -0.083671 0.030000 0.140844
+v -0.091330 0.030000 0.143132
+v -0.099539 0.030000 0.144914
+v -0.108298 0.030000 0.146188
+v -0.117608 0.030000 0.146953
+v -0.127471 0.030000 0.147209
+v -0.137341 0.030000 0.146947
+v -0.146670 0.030000 0.146161
+v -0.155456 0.030000 0.144855
+v -0.163700 0.030000 0.143031
+v -0.171399 0.030000 0.140692
+v -0.178553 0.030000 0.137838
+v -0.185160 0.030000 0.134474
+v -0.191219 0.030000 0.130601
+v -0.196729 0.030000 0.126221
+v -0.201689 0.030000 0.121337
+v -0.206097 0.030000 0.115952
+v -0.209952 0.030000 0.110067
+v -0.213382 0.030000 0.103587
+v -0.216513 0.030000 0.096412
+v -0.219346 0.030000 0.088547
+v -0.221881 0.030000 0.079993
+v -0.224118 0.030000 0.070753
+v -0.226057 0.030000 0.060830
+v -0.227697 0.030000 0.050224
+v -0.229039 0.030000 0.038940
+v -0.230083 0.030000 0.026978
+v -0.230828 0.030000 0.014343
+v -0.231276 0.030000 0.001035
+v -0.231425 0.030000 -0.012942
+v -0.231269 0.030000 -0.027005
+v -0.230801 0.030000 -0.040404
+v -0.230024 0.030000 -0.053140
+v -0.228938 0.030000 -0.065215
+v -0.227544 0.030000 -0.076633
+v -0.225844 0.030000 -0.087395
+v -0.223838 0.030000 -0.097504
+v -0.221528 0.030000 -0.106963
+v -0.218915 0.030000 -0.115773
+v -0.216000 0.030000 -0.123937
+v -0.212785 0.030000 -0.131458
+v -0.209271 0.030000 -0.138337
+v -0.205266 0.030000 -0.144620
+v -0.200750 0.030000 -0.150350
+v -0.195723 0.030000 -0.155529
+v -0.190184 0.030000 -0.160157
+v -0.184134 0.030000 -0.164237
+v -0.177573 0.030000 -0.167769
+v -0.170501 0.030000 -0.170754
+v -0.162917 0.030000 -0.173194
+v -0.154823 0.030000 -0.175090
+v -0.146217 0.030000 -0.176442
+v -0.137100 0.030000 -0.177253
+v -0.127471 0.030000 -0.177523
+v -0.117843 0.030000 -0.177253
+v -0.108727 0.030000 -0.176442
+v -0.100125 0.030000 -0.175090
+v -0.092037 0.030000 -0.173194
+v -0.084466 0.030000 -0.170754
+v -0.077411 0.030000 -0.167769
+v -0.070875 0.030000 -0.164237
+v -0.064859 0.030000 -0.160157
+v -0.059363 0.030000 -0.155529
+v -0.054389 0.030000 -0.150350
+v -0.049939 0.030000 -0.144620
+v -0.046012 0.030000 -0.138337
+v 0.500000 -0.030000 -0.271909
+v 0.500000 -0.030000 -0.234087
+v 0.500000 -0.030000 0.229669
+v 0.361282 -0.030000 0.368353
+v -0.369121 -0.030000 0.368353
+v -0.403885 -0.030000 0.368353
+v -0.500000 -0.030000 0.368353
+v -0.500000 -0.030000 0.272263
+v -0.500000 -0.030000 0.234440
+v -0.500000 -0.030000 -0.229316
+v -0.361282 -0.030000 -0.368000
+v 0.369121 -0.030000 -0.368000
+v 0.403886 -0.030000 -0.368000
+v 0.500000 -0.030000 -0.368000
+v -0.014123 -0.030000 0.177038
+v -0.008432 -0.030000 0.172481
+v -0.003036 -0.030000 0.167611
+v 0.002070 -0.030000 0.162429
+v 0.006887 -0.030000 0.156934
+v 0.011418 -0.030000 0.151127
+v 0.015664 -0.030000 0.145008
+v 0.019629 -0.030000 0.138577
+v 0.023315 -0.030000 0.131833
+v 0.026724 -0.030000 0.124776
+v 0.029858 -0.030000 0.117408
+v 0.032720 -0.030000 0.109727
+v 0.035255 -0.030000 0.101769
+v 0.037575 -0.030000 0.093399
+v 0.039680 -0.030000 0.084618
+v 0.041569 -0.030000 0.075425
+v 0.043240 -0.030000 0.065820
+v 0.044692 -0.030000 0.055804
+v 0.045923 -0.030000 0.045375
+v 0.046934 -0.030000 0.034535
+v 0.047722 -0.030000 0.023284
+v 0.048286 -0.030000 0.011620
+v 0.048626 -0.030000 -0.000455
+v 0.048739 -0.030000 -0.012942
+v 0.048469 -0.030000 -0.031775
+v 0.047658 -0.030000 -0.049771
+v 0.046305 -0.030000 -0.066929
+v 0.044409 -0.030000 -0.083249
+v 0.041969 -0.030000 -0.098732
+v 0.038983 -0.030000 -0.113377
+v 0.035450 -0.030000 -0.127184
+v 0.031369 -0.030000 -0.140154
+v 0.026739 -0.030000 -0.152286
+v 0.021559 -0.030000 -0.163580
+v 0.015828 -0.030000 -0.174037
+v 0.009543 -0.030000 -0.183656
+v 0.002656 -0.030000 -0.192551
+v -0.005054 -0.030000 -0.200667
+v -0.013585 -0.030000 -0.208004
+v -0.022937 -0.030000 -0.214563
+v -0.033107 -0.030000 -0.220347
+v -0.044095 -0.030000 -0.225355
+v -0.055900 -0.030000 -0.229590
+v -0.068520 -0.030000 -0.233052
+v -0.081954 -0.030000 -0.235742
+v -0.096201 -0.030000 -0.237663
+v -0.111260 -0.030000 -0.238814
+v -0.127130 -0.030000 -0.239198
+v -0.143000 -0.030000 -0.238808
+v -0.158061 -0.030000 -0.237638
+v -0.172312 -0.030000 -0.235689
+v -0.185753 -0.030000 -0.232963
+v -0.198385 -0.030000 -0.229461
+v -0.210208 -0.030000 -0.225185
+v -0.221221 -0.030000 -0.220134
+v -0.231425 -0.030000 -0.214311
+v -0.240819 -0.030000 -0.207716
+v -0.249404 -0.030000 -0.200351
+v -0.257179 -0.030000 -0.192217
+v -0.264144 -0.030000 -0.183315
+v -0.270435 -0.030000 -0.173618
+v -0.276186 -0.030000 -0.163098
+v -0.281394 -0.030000 -0.151754
+v -0.286059 -0.030000 -0.139586
+v -0.290179 -0.030000 -0.126595
+v -0.293754 -0.030000 -0.112781
+v -0.296782 -0.030000 -0.098143
+v -0.299263 -0.030000 -0.082682
+v -0.301194 -0.030000 -0.066397
+v -0.302575 -0.030000 -0.049288
+v -0.303404 -0.030000 -0.031357
+v -0.303681 -0.030000 -0.012601
+v -0.303411 -0.030000 0.006061
+v -0.302602 -0.030000 0.023884
+v -0.301253 -0.030000 0.040864
+v -0.299364 -0.030000 0.056999
+v -0.296935 -0.030000 0.072288
+v -0.293967 -0.030000 0.086726
+v -0.290460 -0.030000 0.100313
+v -0.286412 -0.030000 0.113046
+v -0.281825 -0.030000 0.124922
+v -0.276698 -0.030000 0.135939
+v -0.271032 -0.030000 0.146095
+v -0.264826 -0.030000 0.155387
+v -0.257932 -0.030000 0.163877
+v -0.250200 -0.030000 0.171629
+v -0.241634 -0.030000 0.178643
+v -0.232233 -0.030000 0.184918
+v -0.221998 -0.030000 0.190455
+v -0.210932 -0.030000 0.195254
+v -0.199035 -0.030000 0.199315
+v -0.186309 -0.030000 0.202637
+v -0.172754 -0.030000 0.205221
+v -0.158371 -0.030000 0.207067
+v -0.143163 -0.030000 0.208174
+v -0.127130 -0.030000 0.208543
+v -0.122805 -0.030000 0.208515
+v -0.118691 -0.030000 0.208431
+v -0.114786 -0.030000 0.208293
+v -0.111086 -0.030000 0.208101
+v -0.107590 -0.030000 0.207858
+v -0.104294 -0.030000 0.207563
+v -0.101198 -0.030000 0.207219
+v -0.098298 -0.030000 0.206827
+v -0.095593 -0.030000 0.206387
+v -0.093079 -0.030000 0.205901
+v -0.090754 -0.030000 0.205370
+v -0.088616 -0.030000 0.204795
+v -0.032379 -0.030000 0.297137
+v 0.032720 -0.030000 0.266811
+v 0.027981 -0.030000 0.259139
+v 0.022692 -0.030000 0.250576
+v 0.017036 -0.030000 0.241420
+v 0.011197 -0.030000 0.231966
+v 0.005358 -0.030000 0.222513
+v -0.000298 -0.030000 0.213356
+v -0.005587 -0.030000 0.204794
+v -0.010326 -0.030000 0.197122
+v -0.014331 -0.030000 0.190638
+v -0.017419 -0.030000 0.185639
+v -0.019406 -0.030000 0.182422
+v -0.020109 -0.030000 0.181283
+v 0.291411 -0.030000 0.137327
+v 0.286764 -0.030000 0.137511
+v 0.281577 -0.030000 0.137715
+v 0.276031 -0.030000 0.137934
+v 0.270305 -0.030000 0.138160
+v 0.264578 -0.030000 0.138386
+v 0.259032 -0.030000 0.138605
+v 0.253845 -0.030000 0.138810
+v 0.249198 -0.030000 0.138993
+v 0.245271 -0.030000 0.139148
+v 0.242243 -0.030000 0.139267
+v 0.240294 -0.030000 0.139344
+v 0.239605 -0.030000 0.139372
+v 0.235884 -0.030000 0.139286
+v 0.232394 -0.030000 0.139029
+v 0.229135 -0.030000 0.138600
+v 0.226110 -0.030000 0.137996
+v 0.223322 -0.030000 0.137217
+v 0.220774 -0.030000 0.136262
+v 0.218466 -0.030000 0.135130
+v 0.216403 -0.030000 0.133819
+v 0.214585 -0.030000 0.132328
+v 0.213017 -0.030000 0.130656
+v 0.211699 -0.030000 0.128802
+v 0.210634 -0.030000 0.126764
+v 0.209732 -0.030000 0.124535
+v 0.208903 -0.030000 0.121937
+v 0.208147 -0.030000 0.118969
+v 0.207465 -0.030000 0.115633
+v 0.206860 -0.030000 0.111927
+v 0.206331 -0.030000 0.107853
+v 0.205880 -0.030000 0.103409
+v 0.205509 -0.030000 0.098596
+v 0.205218 -0.030000 0.093413
+v 0.205009 -0.030000 0.087862
+v 0.204882 -0.030000 0.081942
+v 0.204840 -0.030000 0.075652
+v 0.204840 -0.030000 -0.063713
+v 0.292093 -0.030000 -0.063713
+v 0.292093 -0.030000 -0.122662
+v 0.204840 -0.030000 -0.122662
+v 0.204840 -0.030000 -0.214664
+v 0.136333 -0.030000 -0.214664
+v 0.136333 -0.030000 -0.122662
+v 0.087935 -0.030000 -0.122662
+v 0.087935 -0.030000 -0.064054
+v 0.136333 -0.030000 -0.064054
+v 0.136333 -0.030000 -0.050850
+v 0.136333 -0.030000 -0.036113
+v 0.136333 -0.030000 -0.020353
+v 0.136333 -0.030000 -0.004083
+v 0.136333 -0.030000 0.012188
+v 0.136333 -0.030000 0.027947
+v 0.136333 -0.030000 0.042685
+v 0.136333 -0.030000 0.055889
+v 0.136333 -0.030000 0.067048
+v 0.136333 -0.030000 0.075652
+v 0.136333 -0.030000 0.081189
+v 0.136333 -0.030000 0.083148
+v 0.136475 -0.030000 0.094258
+v 0.136899 -0.030000 0.104757
+v 0.137605 -0.030000 0.114646
+v 0.138592 -0.030000 0.123924
+v 0.139858 -0.030000 0.132592
+v 0.141403 -0.030000 0.140649
+v 0.143224 -0.030000 0.148096
+v 0.145321 -0.030000 0.154932
+v 0.147692 -0.030000 0.161158
+v 0.150337 -0.030000 0.166773
+v 0.153254 -0.030000 0.171778
+v 0.156442 -0.030000 0.176172
+v 0.159999 -0.030000 0.180091
+v 0.164025 -0.030000 0.183669
+v 0.168520 -0.030000 0.186906
+v 0.173483 -0.030000 0.189802
+v 0.178915 -0.030000 0.192358
+v 0.184816 -0.030000 0.194573
+v 0.191185 -0.030000 0.196447
+v 0.198023 -0.030000 0.197980
+v 0.205330 -0.030000 0.199173
+v 0.213105 -0.030000 0.200024
+v 0.221349 -0.030000 0.200536
+v 0.230061 -0.030000 0.200706
+v 0.233945 -0.030000 0.200649
+v 0.238099 -0.030000 0.200479
+v 0.242523 -0.030000 0.200195
+v 0.247217 -0.030000 0.199797
+v 0.252180 -0.030000 0.199286
+v 0.257413 -0.030000 0.198662
+v 0.262916 -0.030000 0.197923
+v 0.268689 -0.030000 0.197071
+v 0.274732 -0.030000 0.196106
+v 0.281044 -0.030000 0.195027
+v 0.287626 -0.030000 0.193834
+v 0.294479 -0.030000 0.192528
+v -0.042504 -0.030000 -0.131451
+v -0.039308 -0.030000 -0.123910
+v -0.036421 -0.030000 -0.115714
+v -0.033843 -0.030000 -0.106862
+v -0.031573 -0.030000 -0.097352
+v -0.029610 -0.030000 -0.087182
+v -0.027952 -0.030000 -0.076353
+v -0.026597 -0.030000 -0.064862
+v -0.025546 -0.030000 -0.052708
+v -0.024797 -0.030000 -0.039891
+v -0.024348 -0.030000 -0.026409
+v -0.024199 -0.030000 -0.012261
+v -0.024348 -0.030000 0.001795
+v -0.024794 -0.030000 0.015166
+v -0.025536 -0.030000 0.027852
+v -0.026572 -0.030000 0.039848
+v -0.027902 -0.030000 0.051154
+v -0.029525 -0.030000 0.061767
+v -0.031438 -0.030000 0.071683
+v -0.033641 -0.030000 0.080902
+v -0.036133 -0.030000 0.089420
+v -0.038913 -0.030000 0.097236
+v -0.041979 -0.030000 0.104346
+v -0.045331 -0.030000 0.110749
+v -0.049179 -0.030000 0.116548
+v -0.053569 -0.030000 0.121850
+v -0.058501 -0.030000 0.126652
+v -0.063975 -0.030000 0.130954
+v -0.069995 -0.030000 0.134754
+v -0.076559 -0.030000 0.138051
+v -0.083671 -0.030000 0.140844
+v -0.091330 -0.030000 0.143132
+v -0.099539 -0.030000 0.144914
+v -0.108298 -0.030000 0.146188
+v -0.117608 -0.030000 0.146953
+v -0.127471 -0.030000 0.147209
+v -0.137341 -0.030000 0.146947
+v -0.146670 -0.030000 0.146161
+v -0.155456 -0.030000 0.144855
+v -0.163700 -0.030000 0.143031
+v -0.171399 -0.030000 0.140692
+v -0.178553 -0.030000 0.137838
+v -0.185160 -0.030000 0.134474
+v -0.191219 -0.030000 0.130601
+v -0.196729 -0.030000 0.126221
+v -0.201689 -0.030000 0.121337
+v -0.206097 -0.030000 0.115952
+v -0.209952 -0.030000 0.110067
+v -0.213382 -0.030000 0.103587
+v -0.216513 -0.030000 0.096412
+v -0.219346 -0.030000 0.088547
+v -0.221881 -0.030000 0.079993
+v -0.224118 -0.030000 0.070753
+v -0.226057 -0.030000 0.060830
+v -0.227697 -0.030000 0.050224
+v -0.229039 -0.030000 0.038940
+v -0.230083 -0.030000 0.026978
+v -0.230828 -0.030000 0.014343
+v -0.231276 -0.030000 0.001035
+v -0.231425 -0.030000 -0.012942
+v -0.231269 -0.030000 -0.027005
+v -0.230801 -0.030000 -0.040404
+v -0.230024 -0.030000 -0.053140
+v -0.228938 -0.030000 -0.065215
+v -0.227544 -0.030000 -0.076633
+v -0.225844 -0.030000 -0.087395
+v -0.223838 -0.030000 -0.097504
+v -0.221528 -0.030000 -0.106963
+v -0.218915 -0.030000 -0.115773
+v -0.216000 -0.030000 -0.123937
+v -0.212785 -0.030000 -0.131458
+v -0.209271 -0.030000 -0.138337
+v -0.205266 -0.030000 -0.144620
+v -0.200750 -0.030000 -0.150350
+v -0.195723 -0.030000 -0.155529
+v -0.190184 -0.030000 -0.160157
+v -0.184134 -0.030000 -0.164237
+v -0.177573 -0.030000 -0.167769
+v -0.170501 -0.030000 -0.170754
+v -0.162917 -0.030000 -0.173194
+v -0.154823 -0.030000 -0.175090
+v -0.146217 -0.030000 -0.176442
+v -0.137100 -0.030000 -0.177253
+v -0.127471 -0.030000 -0.177523
+v -0.117843 -0.030000 -0.177253
+v -0.108727 -0.030000 -0.176442
+v -0.100125 -0.030000 -0.175090
+v -0.092037 -0.030000 -0.173194
+v -0.084466 -0.030000 -0.170754
+v -0.077411 -0.030000 -0.167769
+v -0.070875 -0.030000 -0.164237
+v -0.064859 -0.030000 -0.160157
+v -0.059363 -0.030000 -0.155529
+v -0.054389 -0.030000 -0.150350
+v -0.049939 -0.030000 -0.144620
+v -0.046012 -0.030000 -0.138337
+v 0.500000 -0.030000 -0.271909
+v 0.500000 0.030000 -0.271909
+v 0.500000 -0.030000 -0.234087
+v 0.500000 0.030000 -0.234087
+v 0.500000 -0.030000 0.229669
+v 0.500000 0.030000 0.229669
+v 0.361282 -0.030000 0.368353
+v 0.361282 0.030000 0.368353
+v -0.369121 -0.030000 0.368353
+v -0.369121 0.030000 0.368353
+v -0.403885 -0.030000 0.368353
+v -0.403885 0.030000 0.368353
+v -0.500000 -0.030000 0.368353
+v -0.500000 0.030000 0.368353
+v -0.500000 -0.030000 0.272263
+v -0.500000 0.030000 0.272263
+v -0.500000 -0.030000 0.234440
+v -0.500000 0.030000 0.234440
+v -0.500000 -0.030000 -0.229316
+v -0.500000 0.030000 -0.229316
+v -0.361282 -0.030000 -0.368000
+v -0.361282 0.030000 -0.368000
+v 0.369121 -0.030000 -0.368000
+v 0.369121 0.030000 -0.368000
+v 0.403886 -0.030000 -0.368000
+v 0.403886 0.030000 -0.368000
+v 0.500000 -0.030000 -0.368000
+v 0.500000 0.030000 -0.368000
+v -0.014123 -0.030000 0.177038
+v -0.014123 0.030000 0.177038
+v -0.008432 -0.030000 0.172481
+v -0.008432 0.030000 0.172481
+v -0.003036 -0.030000 0.167611
+v -0.003036 0.030000 0.167611
+v 0.002070 -0.030000 0.162429
+v 0.002070 0.030000 0.162429
+v 0.006887 -0.030000 0.156934
+v 0.006887 0.030000 0.156934
+v 0.011418 -0.030000 0.151127
+v 0.011418 0.030000 0.151127
+v 0.015664 -0.030000 0.145008
+v 0.015664 0.030000 0.145008
+v 0.019629 -0.030000 0.138577
+v 0.019629 0.030000 0.138577
+v 0.023315 -0.030000 0.131833
+v 0.023315 0.030000 0.131833
+v 0.026724 -0.030000 0.124776
+v 0.026724 0.030000 0.124776
+v 0.029858 -0.030000 0.117408
+v 0.029858 0.030000 0.117408
+v 0.032720 -0.030000 0.109727
+v 0.032720 0.030000 0.109727
+v 0.035255 -0.030000 0.101769
+v 0.035255 0.030000 0.101769
+v 0.037575 -0.030000 0.093399
+v 0.037575 0.030000 0.093399
+v 0.039680 -0.030000 0.084618
+v 0.039680 0.030000 0.084618
+v 0.041569 -0.030000 0.075425
+v 0.041569 0.030000 0.075425
+v 0.043240 -0.030000 0.065820
+v 0.043240 0.030000 0.065820
+v 0.044692 -0.030000 0.055804
+v 0.044692 0.030000 0.055804
+v 0.045923 -0.030000 0.045375
+v 0.045923 0.030000 0.045375
+v 0.046934 -0.030000 0.034535
+v 0.046934 0.030000 0.034535
+v 0.047722 -0.030000 0.023284
+v 0.047722 0.030000 0.023284
+v 0.048286 -0.030000 0.011620
+v 0.048286 0.030000 0.011620
+v 0.048626 -0.030000 -0.000455
+v 0.048626 0.030000 -0.000455
+v 0.048739 -0.030000 -0.012942
+v 0.048739 0.030000 -0.012942
+v 0.048469 -0.030000 -0.031775
+v 0.048469 0.030000 -0.031775
+v 0.047658 -0.030000 -0.049771
+v 0.047658 0.030000 -0.049771
+v 0.046305 -0.030000 -0.066929
+v 0.046305 0.030000 -0.066929
+v 0.044409 -0.030000 -0.083249
+v 0.044409 0.030000 -0.083249
+v 0.041969 -0.030000 -0.098732
+v 0.041969 0.030000 -0.098732
+v 0.038983 -0.030000 -0.113377
+v 0.038983 0.030000 -0.113377
+v 0.035450 -0.030000 -0.127184
+v 0.035450 0.030000 -0.127184
+v 0.031369 -0.030000 -0.140154
+v 0.031369 0.030000 -0.140154
+v 0.026739 -0.030000 -0.152286
+v 0.026739 0.030000 -0.152286
+v 0.021559 -0.030000 -0.163580
+v 0.021559 0.030000 -0.163580
+v 0.015828 -0.030000 -0.174037
+v 0.015828 0.030000 -0.174037
+v 0.009543 -0.030000 -0.183656
+v 0.009543 0.030000 -0.183656
+v 0.002656 -0.030000 -0.192551
+v 0.002656 0.030000 -0.192551
+v -0.005054 -0.030000 -0.200667
+v -0.005054 0.030000 -0.200667
+v -0.013585 -0.030000 -0.208004
+v -0.013585 0.030000 -0.208004
+v -0.022937 -0.030000 -0.214563
+v -0.022937 0.030000 -0.214563
+v -0.033107 -0.030000 -0.220347
+v -0.033107 0.030000 -0.220347
+v -0.044095 -0.030000 -0.225355
+v -0.044095 0.030000 -0.225355
+v -0.055900 -0.030000 -0.229590
+v -0.055900 0.030000 -0.229590
+v -0.068520 -0.030000 -0.233052
+v -0.068520 0.030000 -0.233052
+v -0.081954 -0.030000 -0.235742
+v -0.081954 0.030000 -0.235742
+v -0.096201 -0.030000 -0.237663
+v -0.096201 0.030000 -0.237663
+v -0.111260 -0.030000 -0.238814
+v -0.111260 0.030000 -0.238814
+v -0.127130 -0.030000 -0.239198
+v -0.127130 0.030000 -0.239198
+v -0.143000 -0.030000 -0.238808
+v -0.143000 0.030000 -0.238808
+v -0.158061 -0.030000 -0.237638
+v -0.158061 0.030000 -0.237638
+v -0.172312 -0.030000 -0.235689
+v -0.172312 0.030000 -0.235689
+v -0.185753 -0.030000 -0.232963
+v -0.185753 0.030000 -0.232963
+v -0.198385 -0.030000 -0.229461
+v -0.198385 0.030000 -0.229461
+v -0.210208 -0.030000 -0.225185
+v -0.210208 0.030000 -0.225185
+v -0.221221 -0.030000 -0.220134
+v -0.221221 0.030000 -0.220134
+v -0.231425 -0.030000 -0.214311
+v -0.231425 0.030000 -0.214311
+v -0.240819 -0.030000 -0.207716
+v -0.240819 0.030000 -0.207716
+v -0.249404 -0.030000 -0.200351
+v -0.249404 0.030000 -0.200351
+v -0.257179 -0.030000 -0.192217
+v -0.257179 0.030000 -0.192217
+v -0.264144 -0.030000 -0.183315
+v -0.264144 0.030000 -0.183315
+v -0.270435 -0.030000 -0.173618
+v -0.270435 0.030000 -0.173618
+v -0.276186 -0.030000 -0.163098
+v -0.276186 0.030000 -0.163098
+v -0.281394 -0.030000 -0.151754
+v -0.281394 0.030000 -0.151754
+v -0.286059 -0.030000 -0.139586
+v -0.286059 0.030000 -0.139586
+v -0.290179 -0.030000 -0.126595
+v -0.290179 0.030000 -0.126595
+v -0.293754 -0.030000 -0.112781
+v -0.293754 0.030000 -0.112781
+v -0.296782 -0.030000 -0.098143
+v -0.296782 0.030000 -0.098143
+v -0.299263 -0.030000 -0.082682
+v -0.299263 0.030000 -0.082682
+v -0.301194 -0.030000 -0.066397
+v -0.301194 0.030000 -0.066397
+v -0.302575 -0.030000 -0.049288
+v -0.302575 0.030000 -0.049288
+v -0.303404 -0.030000 -0.031357
+v -0.303404 0.030000 -0.031357
+v -0.303681 -0.030000 -0.012601
+v -0.303681 0.030000 -0.012601
+v -0.303411 -0.030000 0.006061
+v -0.303411 0.030000 0.006061
+v -0.302602 -0.030000 0.023884
+v -0.302602 0.030000 0.023884
+v -0.301253 -0.030000 0.040864
+v -0.301253 0.030000 0.040864
+v -0.299364 -0.030000 0.056999
+v -0.299364 0.030000 0.056999
+v -0.296935 -0.030000 0.072288
+v -0.296935 0.030000 0.072288
+v -0.293967 -0.030000 0.086726
+v -0.293967 0.030000 0.086726
+v -0.290460 -0.030000 0.100313
+v -0.290460 0.030000 0.100313
+v -0.286412 -0.030000 0.113046
+v -0.286412 0.030000 0.113046
+v -0.281825 -0.030000 0.124922
+v -0.281825 0.030000 0.124922
+v -0.276698 -0.030000 0.135939
+v -0.276698 0.030000 0.135939
+v -0.271032 -0.030000 0.146095
+v -0.271032 0.030000 0.146095
+v -0.264826 -0.030000 0.155387
+v -0.264826 0.030000 0.155387
+v -0.257932 -0.030000 0.163877
+v -0.257932 0.030000 0.163877
+v -0.250200 -0.030000 0.171629
+v -0.250200 0.030000 0.171629
+v -0.241634 -0.030000 0.178643
+v -0.241634 0.030000 0.178643
+v -0.232233 -0.030000 0.184918
+v -0.232233 0.030000 0.184918
+v -0.221998 -0.030000 0.190455
+v -0.221998 0.030000 0.190455
+v -0.210932 -0.030000 0.195254
+v -0.210932 0.030000 0.195254
+v -0.199035 -0.030000 0.199315
+v -0.199035 0.030000 0.199315
+v -0.186309 -0.030000 0.202637
+v -0.186309 0.030000 0.202637
+v -0.172754 -0.030000 0.205221
+v -0.172754 0.030000 0.205221
+v -0.158371 -0.030000 0.207067
+v -0.158371 0.030000 0.207067
+v -0.143163 -0.030000 0.208174
+v -0.143163 0.030000 0.208174
+v -0.127130 -0.030000 0.208543
+v -0.127130 0.030000 0.208543
+v -0.122805 -0.030000 0.208515
+v -0.122805 0.030000 0.208515
+v -0.118691 -0.030000 0.208431
+v -0.118691 0.030000 0.208431
+v -0.114786 -0.030000 0.208293
+v -0.114786 0.030000 0.208293
+v -0.111086 -0.030000 0.208101
+v -0.111086 0.030000 0.208101
+v -0.107590 -0.030000 0.207858
+v -0.107590 0.030000 0.207858
+v -0.104294 -0.030000 0.207563
+v -0.104294 0.030000 0.207563
+v -0.101198 -0.030000 0.207219
+v -0.101198 0.030000 0.207219
+v -0.098298 -0.030000 0.206827
+v -0.098298 0.030000 0.206827
+v -0.095593 -0.030000 0.206387
+v -0.095593 0.030000 0.206387
+v -0.093079 -0.030000 0.205901
+v -0.093079 0.030000 0.205901
+v -0.090754 -0.030000 0.205370
+v -0.090754 0.030000 0.205370
+v -0.088616 -0.030000 0.204795
+v -0.088616 0.030000 0.204795
+v -0.032379 -0.030000 0.297137
+v -0.032379 0.030000 0.297137
+v 0.032720 -0.030000 0.266811
+v 0.032720 0.030000 0.266811
+v 0.027981 -0.030000 0.259139
+v 0.027981 0.030000 0.259139
+v 0.022692 -0.030000 0.250576
+v 0.022692 0.030000 0.250576
+v 0.017036 -0.030000 0.241420
+v 0.017036 0.030000 0.241420
+v 0.011197 -0.030000 0.231966
+v 0.011197 0.030000 0.231966
+v 0.005358 -0.030000 0.222513
+v 0.005358 0.030000 0.222513
+v -0.000298 -0.030000 0.213356
+v -0.000298 0.030000 0.213356
+v -0.005587 -0.030000 0.204794
+v -0.005587 0.030000 0.204794
+v -0.010326 -0.030000 0.197122
+v -0.010326 0.030000 0.197122
+v -0.014331 -0.030000 0.190638
+v -0.014331 0.030000 0.190638
+v -0.017419 -0.030000 0.185639
+v -0.017419 0.030000 0.185639
+v -0.019406 -0.030000 0.182422
+v -0.019406 0.030000 0.182422
+v -0.020109 -0.030000 0.181283
+v -0.020109 0.030000 0.181283
+v 0.291411 -0.030000 0.137327
+v 0.291411 0.030000 0.137327
+v 0.286764 -0.030000 0.137511
+v 0.286764 0.030000 0.137511
+v 0.281577 -0.030000 0.137715
+v 0.281577 0.030000 0.137715
+v 0.276031 -0.030000 0.137934
+v 0.276031 0.030000 0.137934
+v 0.270305 -0.030000 0.138160
+v 0.270305 0.030000 0.138160
+v 0.264578 -0.030000 0.138386
+v 0.264578 0.030000 0.138386
+v 0.259032 -0.030000 0.138605
+v 0.259032 0.030000 0.138605
+v 0.253845 -0.030000 0.138810
+v 0.253845 0.030000 0.138810
+v 0.249198 -0.030000 0.138993
+v 0.249198 0.030000 0.138993
+v 0.245271 -0.030000 0.139148
+v 0.245271 0.030000 0.139148
+v 0.242243 -0.030000 0.139267
+v 0.242243 0.030000 0.139267
+v 0.240294 -0.030000 0.139344
+v 0.240294 0.030000 0.139344
+v 0.239605 -0.030000 0.139372
+v 0.239605 0.030000 0.139372
+v 0.235884 -0.030000 0.139286
+v 0.235884 0.030000 0.139286
+v 0.232394 -0.030000 0.139029
+v 0.232394 0.030000 0.139029
+v 0.229135 -0.030000 0.138600
+v 0.229135 0.030000 0.138600
+v 0.226110 -0.030000 0.137996
+v 0.226110 0.030000 0.137996
+v 0.223322 -0.030000 0.137217
+v 0.223322 0.030000 0.137217
+v 0.220774 -0.030000 0.136262
+v 0.220774 0.030000 0.136262
+v 0.218466 -0.030000 0.135130
+v 0.218466 0.030000 0.135130
+v 0.216403 -0.030000 0.133819
+v 0.216403 0.030000 0.133819
+v 0.214585 -0.030000 0.132328
+v 0.214585 0.030000 0.132328
+v 0.213017 -0.030000 0.130656
+v 0.213017 0.030000 0.130656
+v 0.211699 -0.030000 0.128802
+v 0.211699 0.030000 0.128802
+v 0.210634 -0.030000 0.126764
+v 0.210634 0.030000 0.126764
+v 0.209732 -0.030000 0.124535
+v 0.209732 0.030000 0.124535
+v 0.208903 -0.030000 0.121937
+v 0.208903 0.030000 0.121937
+v 0.208147 -0.030000 0.118969
+v 0.208147 0.030000 0.118969
+v 0.207465 -0.030000 0.115633
+v 0.207465 0.030000 0.115633
+v 0.206860 -0.030000 0.111927
+v 0.206860 0.030000 0.111927
+v 0.206331 -0.030000 0.107853
+v 0.206331 0.030000 0.107853
+v 0.205880 -0.030000 0.103409
+v 0.205880 0.030000 0.103409
+v 0.205509 -0.030000 0.098596
+v 0.205509 0.030000 0.098596
+v 0.205218 -0.030000 0.093413
+v 0.205218 0.030000 0.093413
+v 0.205009 -0.030000 0.087862
+v 0.205009 0.030000 0.087862
+v 0.204882 -0.030000 0.081942
+v 0.204882 0.030000 0.081942
+v 0.204840 -0.030000 0.075652
+v 0.204840 0.030000 0.075652
+v 0.204840 -0.030000 -0.063713
+v 0.204840 0.030000 -0.063713
+v 0.292093 -0.030000 -0.063713
+v 0.292093 0.030000 -0.063713
+v 0.292093 -0.030000 -0.122662
+v 0.292093 0.030000 -0.122662
+v 0.204840 -0.030000 -0.122662
+v 0.204840 0.030000 -0.122662
+v 0.204840 -0.030000 -0.214664
+v 0.204840 0.030000 -0.214664
+v 0.136333 -0.030000 -0.214664
+v 0.136333 0.030000 -0.214664
+v 0.136333 -0.030000 -0.122662
+v 0.136333 0.030000 -0.122662
+v 0.087935 -0.030000 -0.122662
+v 0.087935 0.030000 -0.122662
+v 0.087935 -0.030000 -0.064054
+v 0.087935 0.030000 -0.064054
+v 0.136333 -0.030000 -0.064054
+v 0.136333 0.030000 -0.064054
+v 0.136333 -0.030000 -0.050850
+v 0.136333 0.030000 -0.050850
+v 0.136333 -0.030000 -0.036113
+v 0.136333 0.030000 -0.036113
+v 0.136333 -0.030000 -0.020353
+v 0.136333 0.030000 -0.020353
+v 0.136333 -0.030000 -0.004083
+v 0.136333 0.030000 -0.004083
+v 0.136333 -0.030000 0.012188
+v 0.136333 0.030000 0.012188
+v 0.136333 -0.030000 0.027947
+v 0.136333 0.030000 0.027947
+v 0.136333 -0.030000 0.042685
+v 0.136333 0.030000 0.042685
+v 0.136333 -0.030000 0.055889
+v 0.136333 0.030000 0.055889
+v 0.136333 -0.030000 0.067048
+v 0.136333 0.030000 0.067048
+v 0.136333 -0.030000 0.075652
+v 0.136333 0.030000 0.075652
+v 0.136333 -0.030000 0.081189
+v 0.136333 0.030000 0.081189
+v 0.136333 -0.030000 0.083148
+v 0.136333 0.030000 0.083148
+v 0.136475 -0.030000 0.094258
+v 0.136475 0.030000 0.094258
+v 0.136899 -0.030000 0.104757
+v 0.136899 0.030000 0.104757
+v 0.137605 -0.030000 0.114646
+v 0.137605 0.030000 0.114646
+v 0.138592 -0.030000 0.123924
+v 0.138592 0.030000 0.123924
+v 0.139858 -0.030000 0.132592
+v 0.139858 0.030000 0.132592
+v 0.141403 -0.030000 0.140649
+v 0.141403 0.030000 0.140649
+v 0.143224 -0.030000 0.148096
+v 0.143224 0.030000 0.148096
+v 0.145321 -0.030000 0.154932
+v 0.145321 0.030000 0.154932
+v 0.147692 -0.030000 0.161158
+v 0.147692 0.030000 0.161158
+v 0.150337 -0.030000 0.166773
+v 0.150337 0.030000 0.166773
+v 0.153254 -0.030000 0.171778
+v 0.153254 0.030000 0.171778
+v 0.156442 -0.030000 0.176172
+v 0.156442 0.030000 0.176172
+v 0.159999 -0.030000 0.180091
+v 0.159999 0.030000 0.180091
+v 0.164025 -0.030000 0.183669
+v 0.164025 0.030000 0.183669
+v 0.168520 -0.030000 0.186906
+v 0.168520 0.030000 0.186906
+v 0.173483 -0.030000 0.189802
+v 0.173483 0.030000 0.189802
+v 0.178915 -0.030000 0.192358
+v 0.178915 0.030000 0.192358
+v 0.184816 -0.030000 0.194573
+v 0.184816 0.030000 0.194573
+v 0.191185 -0.030000 0.196447
+v 0.191185 0.030000 0.196447
+v 0.198023 -0.030000 0.197980
+v 0.198023 0.030000 0.197980
+v 0.205330 -0.030000 0.199173
+v 0.205330 0.030000 0.199173
+v 0.213105 -0.030000 0.200024
+v 0.213105 0.030000 0.200024
+v 0.221349 -0.030000 0.200536
+v 0.221349 0.030000 0.200536
+v 0.230061 -0.030000 0.200706
+v 0.230061 0.030000 0.200706
+v 0.233945 -0.030000 0.200649
+v 0.233945 0.030000 0.200649
+v 0.238099 -0.030000 0.200479
+v 0.238099 0.030000 0.200479
+v 0.242523 -0.030000 0.200195
+v 0.242523 0.030000 0.200195
+v 0.247217 -0.030000 0.199797
+v 0.247217 0.030000 0.199797
+v 0.252180 -0.030000 0.199286
+v 0.252180 0.030000 0.199286
+v 0.257413 -0.030000 0.198662
+v 0.257413 0.030000 0.198662
+v 0.262916 -0.030000 0.197923
+v 0.262916 0.030000 0.197923
+v 0.268689 -0.030000 0.197071
+v 0.268689 0.030000 0.197071
+v 0.274732 -0.030000 0.196106
+v 0.274732 0.030000 0.196106
+v 0.281044 -0.030000 0.195027
+v 0.281044 0.030000 0.195027
+v 0.287626 -0.030000 0.193834
+v 0.287626 0.030000 0.193834
+v 0.294479 -0.030000 0.192528
+v 0.294479 0.030000 0.192528
+v -0.042504 -0.030000 -0.131451
+v -0.042504 0.030000 -0.131451
+v -0.039308 -0.030000 -0.123910
+v -0.039308 0.030000 -0.123910
+v -0.036421 -0.030000 -0.115714
+v -0.036421 0.030000 -0.115714
+v -0.033843 -0.030000 -0.106862
+v -0.033843 0.030000 -0.106862
+v -0.031573 -0.030000 -0.097352
+v -0.031573 0.030000 -0.097352
+v -0.029610 -0.030000 -0.087182
+v -0.029610 0.030000 -0.087182
+v -0.027952 -0.030000 -0.076353
+v -0.027952 0.030000 -0.076353
+v -0.026597 -0.030000 -0.064862
+v -0.026597 0.030000 -0.064862
+v -0.025546 -0.030000 -0.052708
+v -0.025546 0.030000 -0.052708
+v -0.024797 -0.030000 -0.039891
+v -0.024797 0.030000 -0.039891
+v -0.024348 -0.030000 -0.026409
+v -0.024348 0.030000 -0.026409
+v -0.024199 -0.030000 -0.012261
+v -0.024199 0.030000 -0.012261
+v -0.024348 -0.030000 0.001795
+v -0.024348 0.030000 0.001795
+v -0.024794 -0.030000 0.015166
+v -0.024794 0.030000 0.015166
+v -0.025536 -0.030000 0.027852
+v -0.025536 0.030000 0.027852
+v -0.026572 -0.030000 0.039848
+v -0.026572 0.030000 0.039848
+v -0.027902 -0.030000 0.051154
+v -0.027902 0.030000 0.051154
+v -0.029525 -0.030000 0.061767
+v -0.029525 0.030000 0.061767
+v -0.031438 -0.030000 0.071683
+v -0.031438 0.030000 0.071683
+v -0.033641 -0.030000 0.080902
+v -0.033641 0.030000 0.080902
+v -0.036133 -0.030000 0.089420
+v -0.036133 0.030000 0.089420
+v -0.038913 -0.030000 0.097236
+v -0.038913 0.030000 0.097236
+v -0.041979 -0.030000 0.104346
+v -0.041979 0.030000 0.104346
+v -0.045331 -0.030000 0.110749
+v -0.045331 0.030000 0.110749
+v -0.049179 -0.030000 0.116548
+v -0.049179 0.030000 0.116548
+v -0.053569 -0.030000 0.121850
+v -0.053569 0.030000 0.121850
+v -0.058501 -0.030000 0.126652
+v -0.058501 0.030000 0.126652
+v -0.063975 -0.030000 0.130954
+v -0.063975 0.030000 0.130954
+v -0.069995 -0.030000 0.134754
+v -0.069995 0.030000 0.134754
+v -0.076559 -0.030000 0.138051
+v -0.076559 0.030000 0.138051
+v -0.083671 -0.030000 0.140844
+v -0.083671 0.030000 0.140844
+v -0.091330 -0.030000 0.143132
+v -0.091330 0.030000 0.143132
+v -0.099539 -0.030000 0.144914
+v -0.099539 0.030000 0.144914
+v -0.108298 -0.030000 0.146188
+v -0.108298 0.030000 0.146188
+v -0.117608 -0.030000 0.146953
+v -0.117608 0.030000 0.146953
+v -0.127471 -0.030000 0.147209
+v -0.127471 0.030000 0.147209
+v -0.137341 -0.030000 0.146947
+v -0.137341 0.030000 0.146947
+v -0.146670 -0.030000 0.146161
+v -0.146670 0.030000 0.146161
+v -0.155456 -0.030000 0.144855
+v -0.155456 0.030000 0.144855
+v -0.163700 -0.030000 0.143031
+v -0.163700 0.030000 0.143031
+v -0.171399 -0.030000 0.140692
+v -0.171399 0.030000 0.140692
+v -0.178553 -0.030000 0.137838
+v -0.178553 0.030000 0.137838
+v -0.185160 -0.030000 0.134474
+v -0.185160 0.030000 0.134474
+v -0.191219 -0.030000 0.130601
+v -0.191219 0.030000 0.130601
+v -0.196729 -0.030000 0.126221
+v -0.196729 0.030000 0.126221
+v -0.201689 -0.030000 0.121337
+v -0.201689 0.030000 0.121337
+v -0.206097 -0.030000 0.115952
+v -0.206097 0.030000 0.115952
+v -0.209952 -0.030000 0.110067
+v -0.209952 0.030000 0.110067
+v -0.213382 -0.030000 0.103587
+v -0.213382 0.030000 0.103587
+v -0.216513 -0.030000 0.096412
+v -0.216513 0.030000 0.096412
+v -0.219346 -0.030000 0.088547
+v -0.219346 0.030000 0.088547
+v -0.221881 -0.030000 0.079993
+v -0.221881 0.030000 0.079993
+v -0.224118 -0.030000 0.070753
+v -0.224118 0.030000 0.070753
+v -0.226057 -0.030000 0.060830
+v -0.226057 0.030000 0.060830
+v -0.227697 -0.030000 0.050224
+v -0.227697 0.030000 0.050224
+v -0.229039 -0.030000 0.038940
+v -0.229039 0.030000 0.038940
+v -0.230083 -0.030000 0.026978
+v -0.230083 0.030000 0.026978
+v -0.230828 -0.030000 0.014343
+v -0.230828 0.030000 0.014343
+v -0.231276 -0.030000 0.001035
+v -0.231276 0.030000 0.001035
+v -0.231425 -0.030000 -0.012942
+v -0.231425 0.030000 -0.012942
+v -0.231269 -0.030000 -0.027005
+v -0.231269 0.030000 -0.027005
+v -0.230801 -0.030000 -0.040404
+v -0.230801 0.030000 -0.040404
+v -0.230024 -0.030000 -0.053140
+v -0.230024 0.030000 -0.053140
+v -0.228938 -0.030000 -0.065215
+v -0.228938 0.030000 -0.065215
+v -0.227544 -0.030000 -0.076633
+v -0.227544 0.030000 -0.076633
+v -0.225844 -0.030000 -0.087395
+v -0.225844 0.030000 -0.087395
+v -0.223838 -0.030000 -0.097504
+v -0.223838 0.030000 -0.097504
+v -0.221528 -0.030000 -0.106963
+v -0.221528 0.030000 -0.106963
+v -0.218915 -0.030000 -0.115773
+v -0.218915 0.030000 -0.115773
+v -0.216000 -0.030000 -0.123937
+v -0.216000 0.030000 -0.123937
+v -0.212785 -0.030000 -0.131458
+v -0.212785 0.030000 -0.131458
+v -0.209271 -0.030000 -0.138337
+v -0.209271 0.030000 -0.138337
+v -0.205266 -0.030000 -0.144620
+v -0.205266 0.030000 -0.144620
+v -0.200750 -0.030000 -0.150350
+v -0.200750 0.030000 -0.150350
+v -0.195723 -0.030000 -0.155529
+v -0.195723 0.030000 -0.155529
+v -0.190184 -0.030000 -0.160157
+v -0.190184 0.030000 -0.160157
+v -0.184134 -0.030000 -0.164237
+v -0.184134 0.030000 -0.164237
+v -0.177573 -0.030000 -0.167769
+v -0.177573 0.030000 -0.167769
+v -0.170501 -0.030000 -0.170754
+v -0.170501 0.030000 -0.170754
+v -0.162917 -0.030000 -0.173194
+v -0.162917 0.030000 -0.173194
+v -0.154823 -0.030000 -0.175090
+v -0.154823 0.030000 -0.175090
+v -0.146217 -0.030000 -0.176442
+v -0.146217 0.030000 -0.176442
+v -0.137100 -0.030000 -0.177253
+v -0.137100 0.030000 -0.177253
+v -0.127471 -0.030000 -0.177523
+v -0.127471 0.030000 -0.177523
+v -0.117843 -0.030000 -0.177253
+v -0.117843 0.030000 -0.177253
+v -0.108727 -0.030000 -0.176442
+v -0.108727 0.030000 -0.176442
+v -0.100125 -0.030000 -0.175090
+v -0.100125 0.030000 -0.175090
+v -0.092037 -0.030000 -0.173194
+v -0.092037 0.030000 -0.173194
+v -0.084466 -0.030000 -0.170754
+v -0.084466 0.030000 -0.170754
+v -0.077411 -0.030000 -0.167769
+v -0.077411 0.030000 -0.167769
+v -0.070875 -0.030000 -0.164237
+v -0.070875 0.030000 -0.164237
+v -0.064859 -0.030000 -0.160157
+v -0.064859 0.030000 -0.160157
+v -0.059363 -0.030000 -0.155529
+v -0.059363 0.030000 -0.155529
+v -0.054389 -0.030000 -0.150350
+v -0.054389 0.030000 -0.150350
+v -0.049939 -0.030000 -0.144620
+v -0.049939 0.030000 -0.144620
+v -0.046012 -0.030000 -0.138337
+v -0.046012 0.030000 -0.138337
+vn 0.0000 1.0000 0.0000
+vn 0.0000 0.0000 1.0000
+vn 0.0000 0.0000 -1.0000
+vn 0.0000 -1.0000 0.0000
+vn 0.0000 -1.0000 -0.0001
+vn 0.0000 -1.0000 0.0001
+vn 1.0000 0.0000 0.0000
+vn 0.9238 0.0000 0.3827
+vn 0.3826 0.0000 0.9239
+vn -0.7071 0.0000 0.7071
+vn -1.0000 0.0000 0.0000
+vn -0.9238 0.0000 -0.3827
+vn -0.3826 0.0000 -0.9239
+vn 0.7071 0.0000 -0.7071
+vn -0.6478 0.0000 -0.7618
+vn -0.6020 0.0000 -0.7985
+vn -0.6914 0.0000 -0.7224
+vn -0.7324 0.0000 -0.6808
+vn -0.7705 0.0000 -0.6374
+vn -0.8053 0.0000 -0.5929
+vn -0.8367 0.0000 -0.5477
+vn -0.8647 0.0000 -0.5023
+vn -0.8367 0.0000 -0.5476
+vn -0.8892 0.0000 -0.4574
+vn -0.9106 0.0000 -0.4133
+vn -0.9289 0.0000 -0.3704
+vn -0.9452 0.0000 -0.3264
+vn -0.9584 0.0000 -0.2854
+vn -0.9682 0.0000 -0.2502
+vn -0.9761 0.0000 -0.2172
+vn -0.9825 0.0000 -0.1863
+vn -0.9875 0.0000 -0.1574
+vn -0.9915 0.0000 -0.1304
+vn -0.9944 0.0000 -0.1050
+vn -0.9967 0.0000 -0.0813
+vn -0.9982 0.0000 -0.0591
+vn -0.9993 0.0000 -0.0382
+vn -0.9998 0.0000 -0.0186
+vn -1.0000 0.0000 0.0026
+vn -0.9995 0.0000 0.0297
+vn -0.9981 0.0000 0.0618
+vn -0.9953 0.0000 0.0970
+vn -0.9908 0.0000 0.1356
+vn -0.9840 0.0000 0.1778
+vn -0.9746 0.0000 0.2239
+vn -0.9617 0.0000 0.2741
+vn -0.9445 0.0000 0.3285
+vn -0.9221 0.0000 0.3869
+vn -0.8935 0.0000 0.4490
+vn -0.8577 0.0000 0.5142
+vn -0.8146 0.0000 0.5800
+vn -0.7588 0.0000 0.6513
+vn -0.6894 0.0000 0.7244
+vn -0.6139 0.0000 0.7894
+vn -0.5349 0.0000 0.8449
+vn -0.4550 0.0000 0.8905
+vn -0.3765 0.0000 0.9264
+vn -0.3013 0.0000 0.9535
+vn -0.2306 0.0000 0.9730
+vn -0.1650 0.0000 0.9863
+vn -0.1050 0.0000 0.9945
+vn -0.0502 0.0000 0.9987
+vn 0.0002 0.0000 1.0000
+vn 0.0510 0.0000 0.9987
+vn 0.1065 0.0000 0.9943
+vn 0.1672 0.0000 0.9859
+vn 0.2331 0.0000 0.9724
+vn 0.3039 0.0000 0.9527
+vn 0.3788 0.0000 0.9254
+vn 0.4567 0.0000 0.8896
+vn 0.5357 0.0000 0.8444
+vn 0.6135 0.0000 0.7896
+vn 0.6878 0.0000 0.7259
+vn 0.7561 0.0000 0.6544
+vn 0.8140 0.0000 0.5808
+vn 0.8588 0.0000 0.5123
+vn 0.8937 0.0000 0.4487
+vn 0.9217 0.0000 0.3878
+vn 0.9438 0.0000 0.3303
+vn 0.9610 0.0000 0.2765
+vn 0.9740 0.0000 0.2266
+vn 0.9836 0.0000 0.1805
+vn 0.9904 0.0000 0.1381
+vn 0.9951 0.0000 0.0991
+vn 0.9980 0.0000 0.0633
+vn 0.9995 0.0000 0.0305
+vn 1.0000 0.0000 0.0001
+vn 0.9995 0.0000 -0.0299
+vn 0.9980 0.0000 -0.0623
+vn 0.9952 0.0000 -0.0978
+vn 0.9906 0.0000 -0.1366
+vn 0.9838 0.0000 -0.1791
+vn 0.9742 0.0000 -0.2257
+vn 0.9610 0.0000 -0.2766
+vn 0.9434 0.0000 -0.3318
+vn 0.9203 0.0000 -0.3913
+vn 0.8905 0.0000 -0.4548
+vn 0.8531 0.0000 -0.5217
+vn 0.8048 0.0000 -0.5935
+vn 0.7431 0.0000 -0.6691
+vn 0.6716 0.0000 -0.7409
+vn 0.5950 0.0000 -0.8037
+vn 0.5161 0.0000 -0.8565
+vn 0.4372 0.0000 -0.8993
+vn 0.3607 0.0000 -0.9326
+vn 0.2880 0.0000 -0.9576
+vn 0.2200 0.0000 -0.9755
+vn 0.1573 0.0000 -0.9875
+vn 0.1000 0.0000 -0.9950
+vn 0.0478 0.0000 -0.9988
+vn 0.0082 0.0000 -0.9999
+vn -0.0134 0.0000 -0.9999
+vn -0.0279 0.0000 -0.9996
+vn -0.0435 0.0000 -0.9990
+vn -0.0606 0.0000 -0.9981
+vn -0.0792 0.0000 -0.9968
+vn -0.0997 0.0000 -0.9950
+vn -0.1223 0.0000 -0.9925
+vn -0.1473 0.0000 -0.9891
+vn -0.1752 0.0000 -0.9845
+vn -0.2063 0.0000 -0.9785
+vn -0.1751 0.0000 -0.9845
+vn -0.2412 0.0000 -0.9705
+vn 0.3714 0.0000 -0.9284
+vn 0.2897 0.0000 -0.9571
+vn -0.9580 0.0000 -0.2867
+vn -0.8508 0.0000 0.5255
+vn -0.9800 0.0000 -0.1990
+vn 0.0394 0.0000 0.9992
+vn -0.6727 0.0000 0.7399
+vn 0.0395 0.0000 0.9992
+vn 0.0083 0.0000 0.9999
+vn -0.0482 0.0000 0.9988
+vn 0.0082 0.0000 0.9999
+vn -0.1021 0.0000 0.9948
+vn -0.1633 0.0000 0.9866
+vn -0.2325 0.0000 0.9726
+vn -0.3102 0.0000 0.9507
+vn -0.3962 0.0000 0.9181
+vn -0.4892 0.0000 0.8722
+vn -0.5863 0.0000 0.8101
+vn -0.6832 0.0000 0.7302
+vn -0.7739 0.0000 0.6333
+vn -0.8527 0.0000 0.5224
+vn -0.9077 0.0000 0.4195
+vn -0.9405 0.0000 0.3398
+vn -0.9612 0.0000 0.2756
+vn -0.9747 0.0000 0.2235
+vn -0.9835 0.0000 0.1807
+vn -0.9894 0.0000 0.1450
+vn -0.9934 0.0000 0.1148
+vn -0.9960 0.0000 0.0889
+vn -0.9978 0.0000 0.0665
+vn -0.9989 0.0000 0.0468
+vn -0.9995 0.0000 0.0295
+vn -0.9999 0.0000 0.0140
+vn -1.0000 0.0000 0.0034
+vn -0.7071 0.0000 -0.7071
+vn 0.7071 0.0000 0.7071
+vn 1.0000 0.0000 -0.0064
+vn 0.9996 0.0000 -0.0266
+vn 0.9984 0.0000 -0.0558
+vn 0.9961 0.0000 -0.0885
+vn 0.9921 0.0000 -0.1252
+vn 0.9861 0.0000 -0.1664
+vn 0.9771 0.0000 -0.2129
+vn 0.9641 0.0000 -0.2655
+vn 0.9458 0.0000 -0.3248
+vn 0.8852 0.0000 -0.4653
+vn 0.8377 0.0000 -0.5461
+vn 0.7761 0.0000 -0.6306
+vn 0.7033 0.0000 -0.7108
+vn 0.6251 0.0000 -0.7805
+vn 0.5448 0.0000 -0.8385
+vn 0.4653 0.0000 -0.8851
+vn 0.3889 0.0000 -0.9213
+vn 0.3170 0.0000 -0.9484
+vn 0.2506 0.0000 -0.9680
+vn 0.3171 0.0000 -0.9484
+vn 0.1900 0.0000 -0.9817
+vn 0.1350 0.0000 -0.9908
+vn 0.0854 0.0000 -0.9963
+vn 0.0407 0.0000 -0.9991
+vn 0.0024 0.0000 -1.0000
+vn -0.0278 0.0000 -0.9996
+vn -0.0525 0.0000 -0.9986
+vn -0.0742 0.0000 -0.9972
+vn -0.0934 0.0000 -0.9956
+vn -0.1105 0.0000 -0.9939
+vn -0.1257 0.0000 -0.9920
+vn -0.1395 0.0000 -0.9902
+vn -0.1519 0.0000 -0.9884
+vn -0.1631 0.0000 -0.9866
+vn -0.1734 0.0000 -0.9848
+vn -0.1827 0.0000 -0.9832
+vn -0.7879 0.0000 -0.6158
+vn 0.9324 0.0000 -0.3614
+vn 0.9064 0.0000 -0.4223
+vn 0.9520 0.0000 -0.3060
+vn 0.9667 0.0000 -0.2559
+vn 0.9775 0.0000 -0.2109
+vn 0.9854 0.0000 -0.1705
+vn 0.9909 0.0000 -0.1342
+vn 0.9948 0.0000 -0.1016
+vn 0.9974 0.0000 -0.0723
+vn 0.9989 0.0000 -0.0458
+vn 0.9998 0.0000 -0.0219
+vn 0.9998 0.0000 0.0219
+vn 0.9989 0.0000 0.0458
+vn 0.9974 0.0000 0.0722
+vn 0.9948 0.0000 0.1014
+vn 0.9910 0.0000 0.1340
+vn 0.9854 0.0000 0.1703
+vn 0.9775 0.0000 0.2110
+vn 0.9665 0.0000 0.2567
+vn 0.9514 0.0000 0.3081
+vn 0.9307 0.0000 0.3657
+vn 0.9027 0.0000 0.4301
+vn 0.8607 0.0000 0.5090
+vn 0.8028 0.0000 0.5962
+vn 0.7350 0.0000 0.6781
+vn 0.6587 0.0000 0.7524
+vn 0.5766 0.0000 0.8170
+vn 0.4919 0.0000 0.8706
+vn 0.4076 0.0000 0.9131
+vn 0.3262 0.0000 0.9453
+vn 0.2493 0.0000 0.9684
+vn 0.1781 0.0000 0.9840
+vn 0.1130 0.0000 0.9936
+vn 0.0539 0.0000 0.9985
+vn -0.0003 0.0000 1.0000
+vn -0.0552 0.0000 0.9984
+vn -0.1155 0.0000 0.9933
+vn -0.1816 0.0000 0.9834
+vn -0.2536 0.0000 0.9673
+vn -0.1816 0.0000 0.9833
+vn -0.3309 0.0000 0.9436
+vn -0.4125 0.0000 0.9109
+vn -0.4968 0.0000 0.8679
+vn -0.5812 0.0000 0.8137
+vn -0.6629 0.0000 0.7487
+vn -0.7388 0.0000 0.6739
+vn -0.8063 0.0000 0.5915
+vn -0.8611 0.0000 0.5084
+vn -0.9008 0.0000 0.4342
+vn -0.9291 0.0000 0.3696
+vn -0.9502 0.0000 0.3116
+vn -0.9656 0.0000 0.2598
+vn -0.9769 0.0000 0.2135
+vn -0.9850 0.0000 0.1723
+vn -0.9908 0.0000 0.1355
+vn -0.9947 0.0000 0.1025
+vn -0.9973 0.0000 0.0729
+vn -0.9989 0.0000 0.0462
+vn -0.9997 0.0000 0.0221
+vn -1.0000 0.0000 -0.0002
+vn -0.9997 0.0000 -0.0229
+vn -0.9988 0.0000 -0.0479
+vn -0.9972 0.0000 -0.0753
+vn -0.9944 0.0000 -0.1054
+vn -0.9903 0.0000 -0.1386
+vn -0.9845 0.0000 -0.1754
+vn -0.9764 0.0000 -0.2159
+vn -0.9654 0.0000 -0.2608
+vn -0.9506 0.0000 -0.3104
+vn -0.9311 0.0000 -0.3648
+vn -0.9055 0.0000 -0.4243
+vn -0.8679 0.0000 -0.4968
+vn -0.8153 0.0000 -0.5790
+vn -0.7525 0.0000 -0.6586
+vn -0.6803 0.0000 -0.7329
+vn -0.6010 0.0000 -0.7992
+vn -0.5172 0.0000 -0.8559
+vn -0.4319 0.0000 -0.9019
+vn -0.3479 0.0000 -0.9375
+vn -0.2673 0.0000 -0.9636
+vn -0.1917 0.0000 -0.9814
+vn -0.1220 0.0000 -0.9925
+vn -0.0583 0.0000 -0.9983
+vn 0.0583 0.0000 -0.9983
+vn 0.1220 0.0000 -0.9925
+vn 0.1919 0.0000 -0.9814
+vn 0.2677 0.0000 -0.9635
+vn 0.3486 0.0000 -0.9373
+vn 0.4330 0.0000 -0.9014
+vn 0.5190 0.0000 -0.8548
+vn 0.6035 0.0000 -0.7973
+vn 0.6836 0.0000 -0.7298
+vn 0.7565 0.0000 -0.6539
+vn 0.8199 0.0000 -0.5724
+vn 0.8704 0.0000 -0.4924
+s off
+f 10//1 12//1 11//1
+f 10//1 13//1 12//1
+f 10//1 14//1 13//1
+f 10//1 1//1 14//1
+f 10//1 63//1 1//1
+f 63//1 62//1 1//1
+f 62//1 2//1 1//1
+f 61//1 2//1 62//1
+f 60//1 2//1 61//1
+f 10//1 64//1 63//1
+f 59//1 2//1 60//1
+f 10//1 65//1 64//1
+f 58//1 2//1 59//1
+f 10//1 66//1 65//1
+f 58//1 178//1 2//1
+f 178//1 176//1 2//1
+f 176//1 3//1 2//1
+f 57//1 178//1 58//1
+f 10//1 67//1 66//1
+f 56//1 178//1 57//1
+f 10//1 68//1 67//1
+f 9//1 75//1 10//1
+f 75//1 74//1 10//1
+f 74//1 73//1 10//1
+f 73//1 72//1 10//1
+f 72//1 71//1 10//1
+f 71//1 70//1 10//1
+f 70//1 69//1 10//1
+f 69//1 68//1 10//1
+f 55//1 178//1 56//1
+f 54//1 179//1 55//1
+f 179//1 178//1 55//1
+f 54//1 180//1 179//1
+f 177//1 176//1 178//1
+f 53//1 180//1 54//1
+f 52//1 180//1 53//1
+f 51//1 180//1 52//1
+f 50//1 180//1 51//1
+f 49//1 180//1 50//1
+f 314//1 316//1 315//1
+f 313//1 316//1 314//1
+f 313//1 317//1 316//1
+f 313//1 318//1 317//1
+f 312//1 318//1 313//1
+f 312//1 319//1 318//1
+f 311//1 319//1 312//1
+f 48//1 180//1 49//1
+f 9//1 76//1 75//1
+f 311//1 320//1 319//1
+f 310//1 320//1 311//1
+f 310//1 321//1 320//1
+f 309//1 321//1 310//1
+f 309//1 322//1 321//1
+f 308//1 322//1 309//1
+f 308//1 323//1 322//1
+f 307//1 323//1 308//1
+f 47//1 180//1 48//1
+f 9//1 77//1 76//1
+f 307//1 324//1 323//1
+f 306//1 324//1 307//1
+f 306//1 325//1 324//1
+f 305//1 325//1 306//1
+f 46//1 180//1 47//1
+f 9//1 78//1 77//1
+f 305//1 326//1 325//1
+f 304//1 326//1 305//1
+f 304//1 327//1 326//1
+f 303//1 327//1 304//1
+f 45//1 180//1 46//1
+f 9//1 79//1 78//1
+f 302//1 327//1 303//1
+f 302//1 232//1 327//1
+f 301//1 232//1 302//1
+f 301//1 233//1 232//1
+f 44//1 181//1 45//1
+f 181//1 180//1 45//1
+f 9//1 80//1 79//1
+f 300//1 233//1 301//1
+f 300//1 234//1 233//1
+f 44//1 182//1 181//1
+f 175//1 3//1 176//1
+f 299//1 234//1 300//1
+f 299//1 235//1 234//1
+f 43//1 182//1 44//1
+f 9//1 81//1 80//1
+f 298//1 235//1 299//1
+f 298//1 236//1 235//1
+f 42//1 182//1 43//1
+f 9//1 82//1 81//1
+f 297//1 236//1 298//1
+f 297//1 237//1 236//1
+f 296//1 237//1 297//1
+f 296//1 238//1 237//1
+f 41//1 182//1 42//1
+f 9//1 83//1 82//1
+f 295//1 238//1 296//1
+f 295//1 239//1 238//1
+f 40//1 182//1 41//1
+f 9//1 84//1 83//1
+f 294//1 239//1 295//1
+f 294//1 240//1 239//1
+f 40//1 183//1 182//1
+f 40//1 184//1 183//1
+f 173//1 175//1 174//1
+f 173//1 3//1 175//1
+f 293//1 240//1 294//1
+f 293//1 241//1 240//1
+f 40//1 185//1 184//1
+f 39//1 185//1 40//1
+f 9//1 85//1 84//1
+f 292//1 241//1 293//1
+f 292//1 242//1 241//1
+f 39//1 186//1 185//1
+f 38//1 186//1 39//1
+f 9//1 86//1 85//1
+f 291//1 242//1 292//1
+f 291//1 243//1 242//1
+f 38//1 187//1 186//1
+f 290//1 243//1 291//1
+f 37//1 187//1 38//1
+f 9//1 87//1 86//1
+f 290//1 244//1 243//1
+f 37//1 188//1 187//1
+f 36//1 188//1 37//1
+f 289//1 244//1 290//1
+f 289//1 245//1 244//1
+f 9//1 88//1 87//1
+f 35//1 188//1 36//1
+f 35//1 189//1 188//1
+f 288//1 245//1 289//1
+f 288//1 246//1 245//1
+f 34//1 189//1 35//1
+f 9//1 89//1 88//1
+f 287//1 246//1 288//1
+f 287//1 247//1 246//1
+f 34//1 190//1 189//1
+f 33//1 190//1 34//1
+f 286//1 247//1 287//1
+f 286//1 248//1 247//1
+f 9//1 90//1 89//1
+f 33//1 191//1 190//1
+f 32//1 191//1 33//1
+f 285//1 248//1 286//1
+f 285//1 249//1 248//1
+f 31//1 191//1 32//1
+f 31//1 192//1 191//1
+f 9//1 91//1 90//1
+f 284//1 249//1 285//1
+f 284//1 250//1 249//1
+f 30//1 192//1 31//1
+f 30//1 193//1 192//1
+f 283//1 250//1 284//1
+f 283//1 251//1 250//1
+f 9//1 92//1 91//1
+f 29//1 193//1 30//1
+f 29//1 194//1 193//1
+f 172//1 3//1 173//1
+f 282//1 251//1 283//1
+f 282//1 252//1 251//1
+f 29//1 195//1 194//1
+f 171//1 3//1 172//1
+f 29//1 196//1 195//1
+f 28//1 196//1 29//1
+f 9//1 93//1 92//1
+f 170//1 3//1 171//1
+f 281//1 252//1 282//1
+f 281//1 253//1 252//1
+f 27//1 196//1 28//1
+f 169//1 3//1 170//1
+f 27//1 197//1 196//1
+f 280//1 253//1 281//1
+f 280//1 254//1 253//1
+f 168//1 137//1 169//1
+f 137//1 3//1 169//1
+f 9//1 94//1 93//1
+f 26//1 197//1 27//1
+f 167//1 137//1 168//1
+f 279//1 254//1 280//1
+f 279//1 255//1 254//1
+f 26//1 198//1 197//1
+f 166//1 137//1 167//1
+f 25//1 198//1 26//1
+f 278//1 255//1 279//1
+f 278//1 256//1 255//1
+f 165//1 137//1 166//1
+f 9//1 95//1 94//1
+f 25//1 199//1 198//1
+f 164//1 137//1 165//1
+f 277//1 256//1 278//1
+f 277//1 257//1 256//1
+f 24//1 199//1 25//1
+f 163//1 137//1 164//1
+f 276//1 257//1 277//1
+f 276//1 258//1 257//1
+f 162//1 137//1 163//1
+f 24//1 200//1 199//1
+f 161//1 137//1 162//1
+f 23//1 200//1 24//1
+f 9//1 96//1 95//1
+f 275//1 258//1 276//1
+f 275//1 259//1 258//1
+f 160//1 137//1 161//1
+f 159//1 137//1 160//1
+f 274//1 259//1 275//1
+f 158//1 137//1 159//1
+f 274//1 260//1 259//1
+f 22//1 200//1 23//1
+f 157//1 137//1 158//1
+f 22//1 201//1 200//1
+f 156//1 137//1 157//1
+f 273//1 260//1 274//1
+f 273//1 261//1 260//1
+f 155//1 137//1 156//1
+f 9//1 97//1 96//1
+f 154//1 137//1 155//1
+f 153//1 137//1 154//1
+f 153//1 138//1 137//1
+f 231//1 3//1 137//1
+f 153//1 139//1 138//1
+f 153//1 140//1 139//1
+f 272//1 261//1 273//1
+f 153//1 141//1 140//1
+f 152//1 141//1 153//1
+f 272//1 262//1 261//1
+f 152//1 142//1 141//1
+f 152//1 143//1 142//1
+f 21//1 201//1 22//1
+f 151//1 143//1 152//1
+f 151//1 144//1 143//1
+f 151//1 145//1 144//1
+f 151//1 146//1 145//1
+f 150//1 146//1 151//1
+f 150//1 147//1 146//1
+f 150//1 148//1 147//1
+f 149//1 148//1 150//1
+f 21//1 202//1 201//1
+f 271//1 262//1 272//1
+f 271//1 263//1 262//1
+f 270//1 263//1 271//1
+f 270//1 264//1 263//1
+f 269//1 264//1 270//1
+f 269//1 265//1 264//1
+f 20//1 202//1 21//1
+f 9//1 98//1 97//1
+f 268//1 265//1 269//1
+f 268//1 266//1 265//1
+f 267//1 266//1 268//1
+f 20//1 203//1 202//1
+f 19//1 203//1 20//1
+f 19//1 204//1 203//1
+f 9//1 99//1 98//1
+f 18//1 204//1 19//1
+f 18//1 205//1 204//1
+f 17//1 205//1 18//1
+f 9//1 100//1 99//1
+f 17//1 206//1 205//1
+f 16//1 206//1 17//1
+f 9//1 101//1 100//1
+f 16//1 207//1 206//1
+f 15//1 207//1 16//1
+f 15//1 208//1 207//1
+f 136//1 208//1 15//1
+f 9//1 102//1 101//1
+f 136//1 209//1 208//1
+f 135//1 209//1 136//1
+f 134//1 209//1 135//1
+f 134//1 210//1 209//1
+f 9//1 103//1 102//1
+f 133//1 210//1 134//1
+f 133//1 211//1 210//1
+f 133//1 212//1 211//1
+f 9//1 104//1 103//1
+f 132//1 212//1 133//1
+f 132//1 213//1 212//1
+f 230//1 3//1 231//1
+f 229//1 3//1 230//1
+f 132//1 214//1 213//1
+f 228//1 3//1 229//1
+f 9//1 105//1 104//1
+f 227//1 3//1 228//1
+f 132//1 215//1 214//1
+f 226//1 3//1 227//1
+f 131//1 215//1 132//1
+f 225//1 3//1 226//1
+f 131//1 216//1 215//1
+f 224//1 3//1 225//1
+f 131//1 217//1 216//1
+f 223//1 3//1 224//1
+f 9//1 106//1 105//1
+f 222//1 3//1 223//1
+f 131//1 218//1 217//1
+f 221//1 3//1 222//1
+f 220//1 3//1 221//1
+f 131//1 219//1 218//1
+f 219//1 3//1 220//1
+f 131//1 3//1 219//1
+f 9//1 107//1 106//1
+f 130//1 3//1 131//1
+f 121//1 123//1 122//1
+f 9//1 108//1 107//1
+f 120//1 123//1 121//1
+f 119//1 123//1 120//1
+f 118//1 123//1 119//1
+f 117//1 123//1 118//1
+f 9//1 109//1 108//1
+f 116//1 123//1 117//1
+f 115//1 123//1 116//1
+f 114//1 123//1 115//1
+f 113//1 123//1 114//1
+f 9//1 110//1 109//1
+f 112//1 123//1 113//1
+f 111//1 123//1 112//1
+f 110//1 123//1 111//1
+f 9//1 123//1 110//1
+f 129//1 3//1 130//1
+f 128//1 3//1 129//1
+f 128//1 4//1 3//1
+f 127//1 4//1 128//1
+f 8//1 123//1 9//1
+f 126//1 4//1 127//1
+f 125//1 4//1 126//1
+f 124//1 4//1 125//1
+f 123//1 4//1 124//1
+f 7//1 123//1 8//1
+f 7//1 4//1 123//1
+f 6//2 4//2 7//2
+f 5//3 4//3 6//3
+f 339//4 337//4 338//4
+f 340//4 337//4 339//4
+f 341//4 337//4 340//4
+f 328//4 337//4 341//4
+f 390//4 337//4 328//4
+f 389//4 390//4 328//4
+f 329//4 389//4 328//4
+f 329//4 388//4 389//4
+f 329//4 387//4 388//4
+f 391//4 337//4 390//4
+f 329//4 386//4 387//4
+f 392//4 337//4 391//4
+f 329//4 385//4 386//4
+f 393//4 337//4 392//4
+f 505//4 385//4 329//4
+f 503//4 505//4 329//4
+f 330//4 503//4 329//4
+f 505//4 384//4 385//4
+f 394//4 337//4 393//4
+f 505//4 383//4 384//4
+f 395//4 337//4 394//4
+f 402//4 336//4 337//4
+f 401//4 402//4 337//4
+f 400//4 401//4 337//4
+f 399//4 400//4 337//4
+f 398//4 399//4 337//4
+f 397//4 398//4 337//4
+f 396//4 397//4 337//4
+f 395//4 396//4 337//4
+f 505//4 382//4 383//4
+f 506//4 381//4 382//4
+f 505//4 506//4 382//4
+f 507//4 381//4 506//4
+f 503//4 504//4 505//4
+f 507//4 380//4 381//4
+f 507//4 379//4 380//4
+f 507//4 378//4 379//4
+f 507//4 377//4 378//4
+f 507//4 376//4 377//4
+f 643//4 641//4 642//4
+f 643//4 640//4 641//4
+f 644//4 640//4 643//4
+f 645//4 640//4 644//4
+f 645//4 639//4 640//4
+f 646//4 639//4 645//4
+f 646//4 638//4 639//4
+f 507//4 375//4 376//4
+f 403//4 336//4 402//4
+f 647//4 638//4 646//4
+f 647//4 637//4 638//4
+f 648//4 637//4 647//4
+f 648//4 636//4 637//4
+f 649//4 636//4 648//4
+f 649//4 635//4 636//4
+f 650//4 635//4 649//4
+f 650//4 634//4 635//4
+f 507//4 374//4 375//4
+f 404//4 336//4 403//4
+f 651//4 634//4 650//4
+f 651//4 633//4 634//4
+f 652//4 633//4 651//4
+f 652//4 632//4 633//4
+f 507//4 373//4 374//4
+f 405//4 336//4 404//4
+f 653//4 632//4 652//4
+f 653//4 631//4 632//4
+f 654//4 631//4 653//4
+f 654//4 630//4 631//4
+f 507//4 372//4 373//4
+f 406//4 336//4 405//4
+f 654//4 629//4 630//4
+f 559//4 629//4 654//4
+f 559//4 628//4 629//4
+f 560//4 628//4 559//4
+f 508//4 371//4 372//4
+f 507//4 508//4 372//4
+f 407//4 336//4 406//4
+f 560//4 627//4 628//4
+f 561//4 627//4 560//4
+f 509//4 371//4 508//4
+f 330//4 502//4 503//4
+f 561//4 626//4 627//4
+f 562//4 626//4 561//4
+f 509//4 370//4 371//4
+f 408//4 336//4 407//4
+f 562//4 625//4 626//4
+f 563//4 625//4 562//4
+f 509//4 369//4 370//4
+f 409//4 336//4 408//4
+f 563//4 624//4 625//4
+f 564//4 624//4 563//4
+f 564//4 623//4 624//4
+f 565//4 623//4 564//4
+f 509//4 368//4 369//4
+f 410//4 336//4 409//4
+f 565//4 622//4 623//4
+f 566//4 622//4 565//4
+f 509//4 367//4 368//4
+f 411//4 336//4 410//4
+f 566//4 621//4 622//4
+f 567//4 621//4 566//4
+f 510//4 367//4 509//4
+f 511//4 367//4 510//4
+f 502//4 500//4 501//4
+f 330//4 500//4 502//4
+f 567//4 620//4 621//4
+f 568//4 620//4 567//4
+f 512//4 367//4 511//4
+f 512//4 366//4 367//4
+f 412//4 336//4 411//4
+f 568//4 619//4 620//4
+f 569//4 619//4 568//4
+f 513//4 366//4 512//4
+f 513//4 365//4 366//4
+f 413//4 336//4 412//4
+f 569//4 618//4 619//4
+f 570//4 618//4 569//4
+f 514//4 365//4 513//4
+f 570//4 617//4 618//4
+f 514//4 364//4 365//4
+f 414//4 336//4 413//4
+f 571//4 617//4 570//4
+f 515//4 364//4 514//4
+f 515//4 363//4 364//4
+f 571//4 616//4 617//4
+f 572//4 616//4 571//4
+f 415//4 336//4 414//4
+f 515//4 362//4 363//4
+f 516//4 362//4 515//4
+f 572//4 615//4 616//4
+f 573//4 615//4 572//4
+f 516//4 361//4 362//4
+f 416//4 336//4 415//4
+f 573//4 614//4 615//4
+f 574//4 614//4 573//4
+f 517//4 361//4 516//4
+f 517//4 360//4 361//4
+f 574//4 613//4 614//4
+f 575//4 613//4 574//4
+f 417//4 336//4 416//4
+f 518//4 360//4 517//4
+f 518//4 359//4 360//4
+f 575//4 612//4 613//4
+f 576//4 612//4 575//4
+f 518//4 358//4 359//4
+f 519//4 358//4 518//4
+f 418//4 336//4 417//4
+f 576//4 611//4 612//4
+f 577//4 611//4 576//4
+f 519//4 357//4 358//4
+f 520//4 357//4 519//4
+f 577//4 610//4 611//4
+f 578//4 610//4 577//4
+f 419//4 336//4 418//4
+f 520//4 356//4 357//4
+f 521//4 356//4 520//4
+f 330//4 499//4 500//4
+f 578//4 609//4 610//4
+f 579//4 609//4 578//4
+f 522//4 356//4 521//4
+f 330//4 498//4 499//4
+f 523//4 356//4 522//4
+f 523//4 355//4 356//4
+f 420//4 336//4 419//4
+f 330//4 497//4 498//4
+f 579//4 608//4 609//4
+f 580//4 608//4 579//4
+f 523//4 354//4 355//4
+f 330//4 496//4 497//4
+f 524//4 354//4 523//4
+f 580//4 607//4 608//4
+f 581//4 607//4 580//4
+f 464//4 495//4 496//4
+f 330//4 464//4 496//4
+f 421//4 336//4 420//4
+f 524//4 353//4 354//4
+f 464//4 494//4 495//4
+f 581//4 606//4 607//4
+f 582//4 606//4 581//4
+f 525//4 353//4 524//4
+f 464//4 493//4 494//4
+f 525//4 352//4 353//4
+f 582//4 605//4 606//4
+f 583//4 605//4 582//4
+f 464//4 492//4 493//4
+f 422//4 336//4 421//4
+f 526//4 352//4 525//4
+f 464//4 491//4 492//4
+f 583//4 604//4 605//4
+f 584//4 604//4 583//4
+f 526//4 351//4 352//4
+f 464//4 490//4 491//4
+f 584//4 603//4 604//4
+f 585//4 603//4 584//4
+f 464//4 489//4 490//4
+f 527//4 351//4 526//4
+f 464//4 488//4 489//4
+f 527//4 350//4 351//4
+f 423//4 336//4 422//4
+f 585//4 602//4 603//4
+f 586//4 602//4 585//4
+f 464//4 487//4 488//4
+f 464//4 486//4 487//4
+f 586//4 601//4 602//4
+f 464//4 485//4 486//4
+f 587//4 601//4 586//4
+f 527//4 349//4 350//4
+f 464//4 484//4 485//4
+f 528//4 349//4 527//4
+f 464//4 483//4 484//4
+f 587//4 600//4 601//4
+f 588//4 600//4 587//4
+f 464//4 482//4 483//4
+f 424//4 336//4 423//4
+f 464//4 481//4 482//4
+f 464//4 480//4 481//4
+f 465//4 480//4 464//4
+f 330//4 558//4 464//4
+f 466//4 480//4 465//4
+f 467//4 480//4 466//4
+f 588//4 599//4 600//4
+f 468//4 480//4 467//4
+f 468//4 479//4 480//4
+f 589//4 599//4 588//4
+f 469//4 479//4 468//4
+f 470//4 479//4 469//4
+f 528//4 348//4 349//4
+f 470//4 478//4 479//4
+f 471//4 478//4 470//4
+f 472//4 478//4 471//4
+f 473//4 478//4 472//4
+f 473//4 477//4 478//4
+f 474//4 477//4 473//4
+f 475//5 477//5 474//5
+f 475//6 476//6 477//6
+f 529//4 348//4 528//4
+f 589//4 598//4 599//4
+f 590//4 598//4 589//4
+f 590//4 597//4 598//4
+f 591//4 597//4 590//4
+f 591//4 596//4 597//4
+f 592//4 596//4 591//4
+f 529//4 347//4 348//4
+f 425//4 336//4 424//4
+f 592//4 595//4 596//4
+f 593//4 595//4 592//4
+f 593//4 594//4 595//4
+f 530//4 347//4 529//4
+f 530//4 346//4 347//4
+f 531//4 346//4 530//4
+f 426//4 336//4 425//4
+f 531//4 345//4 346//4
+f 532//4 345//4 531//4
+f 532//4 344//4 345//4
+f 427//4 336//4 426//4
+f 533//4 344//4 532//4
+f 533//4 343//4 344//4
+f 428//4 336//4 427//4
+f 534//4 343//4 533//4
+f 534//4 342//4 343//4
+f 535//4 342//4 534//4
+f 535//4 463//4 342//4
+f 429//4 336//4 428//4
+f 536//4 463//4 535//4
+f 536//4 462//4 463//4
+f 536//4 461//4 462//4
+f 537//4 461//4 536//4
+f 430//4 336//4 429//4
+f 537//4 460//4 461//4
+f 538//4 460//4 537//4
+f 539//4 460//4 538//4
+f 431//4 336//4 430//4
+f 539//4 459//4 460//4
+f 540//4 459//4 539//4
+f 330//4 557//4 558//4
+f 330//4 556//4 557//4
+f 541//4 459//4 540//4
+f 330//4 555//4 556//4
+f 432//4 336//4 431//4
+f 330//4 554//4 555//4
+f 542//4 459//4 541//4
+f 330//4 553//4 554//4
+f 542//4 458//4 459//4
+f 330//4 552//4 553//4
+f 543//4 458//4 542//4
+f 330//4 551//4 552//4
+f 544//4 458//4 543//4
+f 330//4 550//4 551//4
+f 433//4 336//4 432//4
+f 330//4 549//4 550//4
+f 545//4 458//4 544//4
+f 330//4 548//4 549//4
+f 330//4 547//4 548//4
+f 546//4 458//4 545//4
+f 330//4 546//4 547//4
+f 330//4 458//4 546//4
+f 434//4 336//4 433//4
+f 330//4 457//4 458//4
+f 450//4 448//4 449//4
+f 435//4 336//4 434//4
+f 450//4 447//4 448//4
+f 450//4 446//4 447//4
+f 450//4 445//4 446//4
+f 450//4 444//4 445//4
+f 436//4 336//4 435//4
+f 450//4 443//4 444//4
+f 450//4 442//4 443//4
+f 450//4 441//4 442//4
+f 450//4 440//4 441//4
+f 437//4 336//4 436//4
+f 450//4 439//4 440//4
+f 450//4 438//4 439//4
+f 450//4 437//4 438//4
+f 450//4 336//4 437//4
+f 330//4 456//4 457//4
+f 330//4 455//4 456//4
+f 331//4 455//4 330//4
+f 331//4 454//4 455//4
+f 450//4 335//4 336//4
+f 331//4 453//4 454//4
+f 331//4 452//4 453//4
+f 331//4 451//4 452//4
+f 331//4 450//4 451//4
+f 450//4 334//4 335//4
+f 331//4 334//4 450//4
+f 331//2 333//2 334//2
+f 331//3 332//3 333//3
+s 1
+f 658//7 655//7 656//7
+f 660//8 657//7 658//7
+f 662//9 659//8 660//8
+f 664//2 661//9 662//9
+f 666//2 663//2 664//2
+f 668//10 665//2 666//2
+f 670//11 667//10 668//10
+f 672//11 669//11 670//11
+f 674//12 671//11 672//11
+f 676//13 673//12 674//12
+f 678//3 675//13 676//13
+f 680//3 677//3 678//3
+f 682//14 679//3 680//3
+f 656//7 681//14 682//14
+f 686//15 683//16 684//16
+f 688//17 685//15 686//15
+f 690//18 687//17 688//17
+f 692//19 689//18 690//18
+f 694//20 691//19 692//19
+f 696//21 693//20 694//20
+f 698//22 695//23 696//21
+f 700//24 697//22 698//22
+f 702//25 699//24 700//24
+f 704//26 701//25 702//25
+f 706//27 703//26 704//26
+f 708//28 705//27 706//27
+f 710//29 707//28 708//28
+f 712//30 709//29 710//29
+f 714//31 711//30 712//30
+f 716//32 713//31 714//31
+f 718//33 715//32 716//32
+f 720//34 717//33 718//33
+f 722//35 719//34 720//34
+f 724//36 721//35 722//35
+f 726//37 723//36 724//36
+f 728//38 725//37 726//37
+f 730//39 727//38 728//38
+f 732//40 729//39 730//39
+f 734//41 731//40 732//40
+f 736//42 733//41 734//41
+f 738//43 735//42 736//42
+f 740//44 737//43 738//43
+f 742//45 739//44 740//44
+f 744//46 741//45 742//45
+f 746//47 743//46 744//46
+f 748//48 745//47 746//47
+f 750//49 747//48 748//48
+f 752//50 749//49 750//49
+f 754//51 751//50 752//50
+f 756//52 753//51 754//51
+f 758//53 755//52 756//52
+f 760//54 757//53 758//53
+f 762//55 759//54 760//54
+f 764//56 761//55 762//55
+f 766//57 763//56 764//56
+f 768//58 765//57 766//57
+f 770//59 767//58 768//58
+f 772//60 769//59 770//59
+f 774//61 771//60 772//60
+f 776//62 773//61 774//61
+f 778//63 775//62 776//62
+f 780//64 777//63 778//63
+f 782//65 779//64 780//64
+f 784//66 781//65 782//65
+f 786//67 783//66 784//66
+f 788//68 785//67 786//67
+f 790//69 787//68 788//68
+f 792//70 789//69 790//69
+f 794//71 791//70 792//70
+f 796//72 793//71 794//71
+f 798//73 795//72 796//72
+f 800//74 797//73 798//73
+f 802//75 799//74 800//74
+f 804//76 801//75 802//75
+f 806//77 803//76 804//76
+f 808//78 805//77 806//77
+f 810//79 807//78 808//78
+f 812//80 809//79 810//79
+f 814//81 811//80 812//80
+f 816//82 813//81 814//81
+f 818//83 815//82 816//82
+f 820//84 817//83 818//83
+f 822//85 819//84 820//84
+f 824//86 821//85 822//85
+f 826//87 823//86 824//86
+f 828//88 825//87 826//87
+f 830//89 827//88 828//88
+f 832//90 829//89 830//89
+f 834//91 831//90 832//90
+f 836//92 833//91 834//91
+f 838//93 835//92 836//92
+f 840//94 837//93 838//93
+f 842//95 839//94 840//94
+f 844//96 841//95 842//95
+f 846//97 843//96 844//96
+f 848//98 845//97 846//97
+f 850//99 847//98 848//98
+f 852//100 849//99 850//99
+f 854//101 851//100 852//100
+f 856//102 853//101 854//101
+f 858//103 855//102 856//102
+f 860//104 857//103 858//103
+f 862//105 859//104 860//104
+f 864//106 861//105 862//105
+f 866//107 863//106 864//106
+f 868//108 865//107 866//107
+f 870//109 867//108 868//108
+f 872//110 869//109 870//109
+f 874//111 871//110 872//110
+f 876//112 873//111 874//111
+f 878//113 875//112 876//112
+f 880//114 877//113 878//113
+f 882//115 879//114 880//114
+f 884//116 881//115 882//115
+f 886//117 883//116 884//116
+f 888//118 885//117 886//117
+f 890//119 887//118 888//118
+f 892//120 889//119 890//119
+f 894//121 891//122 892//120
+f 896//123 893//121 894//121
+f 898//124 895//123 896//123
+f 900//125 897//124 898//124
+f 902//126 899//125 900//125
+f 904//127 901//126 902//126
+f 906//127 903//127 904//127
+f 908//127 905//127 906//127
+f 910//127 907//127 908//127
+f 912//127 909//127 910//127
+f 914//127 911//127 912//127
+f 916//127 913//127 914//127
+f 918//127 915//127 916//127
+f 920//127 917//127 918//127
+f 922//127 919//127 920//127
+f 924//127 921//127 922//127
+f 926//128 923//127 924//127
+f 684//16 925//128 926//128
+f 930//129 927//130 928//130
+f 932//129 929//129 930//129
+f 934//129 931//129 932//129
+f 936//129 933//129 934//129
+f 938//129 935//129 936//129
+f 940//129 937//129 938//129
+f 942//129 939//129 940//129
+f 944//129 941//129 942//129
+f 946//129 943//129 944//129
+f 948//129 945//129 946//129
+f 950//131 947//129 948//129
+f 952//132 949//129 950//131
+f 954//133 951//134 952//132
+f 956//135 953//133 954//133
+f 958//136 955//135 956//135
+f 960//137 957//136 958//136
+f 962//138 959//137 960//137
+f 964//139 961//138 962//138
+f 966//140 963//139 964//139
+f 968//141 965//140 966//140
+f 970//142 967//141 968//141
+f 972//143 969//142 970//142
+f 974//144 971//143 972//143
+f 976//145 973//144 974//144
+f 978//146 975//145 976//145
+f 980//147 977//146 978//146
+f 982//148 979//147 980//147
+f 984//149 981//148 982//148
+f 986//150 983//149 984//149
+f 988//151 985//150 986//150
+f 990//152 987//151 988//151
+f 992//153 989//152 990//152
+f 994//154 991//153 992//153
+f 996//155 993//154 994//154
+f 998//156 995//155 996//155
+f 1000//157 997//156 998//156
+f 1002//158 999//157 1000//157
+f 1004//158 1001//158 1002//158
+f 1006//10 1003//158 1004//158
+f 1008//10 1005//10 1006//10
+f 1010//10 1007//10 1008//10
+f 1012//159 1009//10 1010//10
+f 1014//159 1011//159 1012//159
+f 1016//159 1013//159 1014//159
+f 1018//14 1015//159 1016//159
+f 1020//14 1017//14 1018//14
+f 1022//7 1019//14 1020//14
+f 1024//7 1021//7 1022//7
+f 1026//7 1023//7 1024//7
+f 1028//7 1025//7 1026//7
+f 1030//7 1027//7 1028//7
+f 1032//7 1029//7 1030//7
+f 1034//7 1031//7 1032//7
+f 1036//7 1033//7 1034//7
+f 1038//7 1035//7 1036//7
+f 1040//7 1037//7 1038//7
+f 1042//7 1039//7 1040//7
+f 1044//160 1041//7 1042//7
+f 1046//161 1043//160 1044//160
+f 1048//162 1045//161 1046//161
+f 1050//163 1047//162 1048//162
+f 1052//164 1049//163 1050//163
+f 1054//165 1051//164 1052//164
+f 1056//166 1053//165 1054//165
+f 1058//167 1055//166 1056//166
+f 1060//168 1057//167 1058//167
+f 1062//96 1059//168 1060//168
+f 1064//169 1061//96 1062//96
+f 1066//170 1063//169 1064//169
+f 1068//171 1065//170 1066//170
+f 1070//172 1067//171 1068//171
+f 1072//173 1069//172 1070//172
+f 1074//174 1071//173 1072//173
+f 1076//175 1073//174 1074//174
+f 1078//176 1075//175 1076//175
+f 1080//177 1077//176 1078//176
+f 1082//178 1079//179 1080//177
+f 1084//180 1081//178 1082//178
+f 1086//181 1083//180 1084//180
+f 1088//182 1085//181 1086//181
+f 1090//183 1087//182 1088//182
+f 1092//184 1089//183 1090//183
+f 1094//185 1091//184 1092//184
+f 1096//186 1093//185 1094//185
+f 1098//187 1095//186 1096//186
+f 1100//188 1097//187 1098//187
+f 1102//189 1099//188 1100//188
+f 1104//190 1101//189 1102//189
+f 1106//191 1103//190 1104//190
+f 1108//192 1105//191 1106//191
+f 1110//193 1107//192 1108//192
+f 1112//194 1109//193 1110//193
+f 1114//195 1111//194 1112//194
+f 1116//196 1113//195 1114//195
+f 928//130 1115//196 1116//196
+f 1120//197 1117//198 1118//198
+f 1122//199 1119//197 1120//197
+f 1124//200 1121//199 1122//199
+f 1126//201 1123//200 1124//200
+f 1128//202 1125//201 1126//201
+f 1130//203 1127//202 1128//202
+f 1132//204 1129//203 1130//203
+f 1134//205 1131//204 1132//204
+f 1136//206 1133//205 1134//205
+f 1138//207 1135//206 1136//206
+f 1140//7 1137//207 1138//207
+f 1142//208 1139//7 1140//7
+f 1144//209 1141//208 1142//208
+f 1146//210 1143//209 1144//209
+f 1148//211 1145//210 1146//210
+f 1150//212 1147//211 1148//211
+f 1152//213 1149//212 1150//212
+f 1154//214 1151//213 1152//213
+f 1156//215 1153//214 1154//214
+f 1158//216 1155//215 1156//215
+f 1160//217 1157//216 1158//216
+f 1162//218 1159//217 1160//217
+f 1164//219 1161//218 1162//218
+f 1166//220 1163//219 1164//219
+f 1168//221 1165//220 1166//220
+f 1170//222 1167//221 1168//221
+f 1172//223 1169//222 1170//222
+f 1174//224 1171//223 1172//223
+f 1176//225 1173//224 1174//224
+f 1178//226 1175//225 1176//225
+f 1180//227 1177//226 1178//226
+f 1182//228 1179//227 1180//227
+f 1184//229 1181//228 1182//228
+f 1186//230 1183//229 1184//229
+f 1188//231 1185//230 1186//230
+f 1190//232 1187//231 1188//231
+f 1192//233 1189//232 1190//232
+f 1194//234 1191//233 1192//233
+f 1196//235 1193//236 1194//234
+f 1198//237 1195//235 1196//235
+f 1200//238 1197//237 1198//237
+f 1202//239 1199//238 1200//238
+f 1204//240 1201//239 1202//239
+f 1206//241 1203//240 1204//240
+f 1208//242 1205//241 1206//241
+f 1210//243 1207//242 1208//242
+f 1212//244 1209//243 1210//243
+f 1214//245 1211//244 1212//244
+f 1216//246 1213//245 1214//245
+f 1218//247 1215//246 1216//246
+f 1220//248 1217//247 1218//247
+f 1222//249 1219//248 1220//248
+f 1224//250 1221//249 1222//249
+f 1226//251 1223//250 1224//250
+f 1228//252 1225//251 1226//251
+f 1230//253 1227//252 1228//252
+f 1232//254 1229//253 1230//253
+f 1234//255 1231//254 1232//254
+f 1236//256 1233//255 1234//255
+f 1238//257 1235//256 1236//256
+f 1240//258 1237//257 1238//257
+f 1242//259 1239//258 1240//258
+f 1244//260 1241//259 1242//259
+f 1246//261 1243//260 1244//260
+f 1248//262 1245//261 1246//261
+f 1250//263 1247//262 1248//262
+f 1252//264 1249//263 1250//263
+f 1254//265 1251//264 1252//264
+f 1256//266 1253//265 1254//265
+f 1258//267 1255//266 1256//266
+f 1260//268 1257//267 1258//267
+f 1262//269 1259//268 1260//268
+f 1264//270 1261//269 1262//269
+f 1266//271 1263//270 1264//270
+f 1268//272 1265//271 1266//271
+f 1270//273 1267//272 1268//272
+f 1272//274 1269//273 1270//273
+f 1274//275 1271//274 1272//274
+f 1276//276 1273//275 1274//275
+f 1278//277 1275//276 1276//276
+f 1280//278 1277//277 1278//277
+f 1282//279 1279//278 1280//278
+f 1284//3 1281//279 1282//279
+f 1286//280 1283//3 1284//3
+f 1288//281 1285//280 1286//280
+f 1290//282 1287//281 1288//281
+f 1292//283 1289//282 1290//282
+f 1294//284 1291//283 1292//283
+f 1296//285 1293//284 1294//284
+f 1298//286 1295//285 1296//285
+f 1300//287 1297//286 1298//286
+f 1302//288 1299//287 1300//287
+f 1304//289 1301//288 1302//288
+f 1306//290 1303//289 1304//289
+f 1308//291 1305//290 1306//290
+f 1118//198 1307//291 1308//291
+f 658//7 657//7 655//7
+f 660//8 659//8 657//7
+f 662//9 661//9 659//8
+f 664//2 663//2 661//9
+f 666//2 665//2 663//2
+f 668//10 667//10 665//2
+f 670//11 669//11 667//10
+f 672//11 671//11 669//11
+f 674//12 673//12 671//11
+f 676//13 675//13 673//12
+f 678//3 677//3 675//13
+f 680//3 679//3 677//3
+f 682//14 681//14 679//3
+f 656//7 655//7 681//14
+f 686//15 685//15 683//16
+f 688//17 687//17 685//15
+f 690//18 689//18 687//17
+f 692//19 691//19 689//18
+f 694//20 693//20 691//19
+f 696//21 695//23 693//20
+f 698//22 697//22 695//23
+f 700//24 699//24 697//22
+f 702//25 701//25 699//24
+f 704//26 703//26 701//25
+f 706//27 705//27 703//26
+f 708//28 707//28 705//27
+f 710//29 709//29 707//28
+f 712//30 711//30 709//29
+f 714//31 713//31 711//30
+f 716//32 715//32 713//31
+f 718//33 717//33 715//32
+f 720//34 719//34 717//33
+f 722//35 721//35 719//34
+f 724//36 723//36 721//35
+f 726//37 725//37 723//36
+f 728//38 727//38 725//37
+f 730//39 729//39 727//38
+f 732//40 731//40 729//39
+f 734//41 733//41 731//40
+f 736//42 735//42 733//41
+f 738//43 737//43 735//42
+f 740//44 739//44 737//43
+f 742//45 741//45 739//44
+f 744//46 743//46 741//45
+f 746//47 745//47 743//46
+f 748//48 747//48 745//47
+f 750//49 749//49 747//48
+f 752//50 751//50 749//49
+f 754//51 753//51 751//50
+f 756//52 755//52 753//51
+f 758//53 757//53 755//52
+f 760//54 759//54 757//53
+f 762//55 761//55 759//54
+f 764//56 763//56 761//55
+f 766//57 765//57 763//56
+f 768//58 767//58 765//57
+f 770//59 769//59 767//58
+f 772//60 771//60 769//59
+f 774//61 773//61 771//60
+f 776//62 775//62 773//61
+f 778//63 777//63 775//62
+f 780//64 779//64 777//63
+f 782//65 781//65 779//64
+f 784//66 783//66 781//65
+f 786//67 785//67 783//66
+f 788//68 787//68 785//67
+f 790//69 789//69 787//68
+f 792//70 791//70 789//69
+f 794//71 793//71 791//70
+f 796//72 795//72 793//71
+f 798//73 797//73 795//72
+f 800//74 799//74 797//73
+f 802//75 801//75 799//74
+f 804//76 803//76 801//75
+f 806//77 805//77 803//76
+f 808//78 807//78 805//77
+f 810//79 809//79 807//78
+f 812//80 811//80 809//79
+f 814//81 813//81 811//80
+f 816//82 815//82 813//81
+f 818//83 817//83 815//82
+f 820//84 819//84 817//83
+f 822//85 821//85 819//84
+f 824//86 823//86 821//85
+f 826//87 825//87 823//86
+f 828//88 827//88 825//87
+f 830//89 829//89 827//88
+f 832//90 831//90 829//89
+f 834//91 833//91 831//90
+f 836//92 835//92 833//91
+f 838//93 837//93 835//92
+f 840//94 839//94 837//93
+f 842//95 841//95 839//94
+f 844//96 843//96 841//95
+f 846//97 845//97 843//96
+f 848//98 847//98 845//97
+f 850//99 849//99 847//98
+f 852//100 851//100 849//99
+f 854//101 853//101 851//100
+f 856//102 855//102 853//101
+f 858//103 857//103 855//102
+f 860//104 859//104 857//103
+f 862//105 861//105 859//104
+f 864//106 863//106 861//105
+f 866//107 865//107 863//106
+f 868//108 867//108 865//107
+f 870//109 869//109 867//108
+f 872//110 871//110 869//109
+f 874//111 873//111 871//110
+f 876//112 875//112 873//111
+f 878//113 877//113 875//112
+f 880//114 879//114 877//113
+f 882//115 881//115 879//114
+f 884//116 883//116 881//115
+f 886//117 885//117 883//116
+f 888//118 887//118 885//117
+f 890//119 889//119 887//118
+f 892//120 891//122 889//119
+f 894//121 893//121 891//122
+f 896//123 895//123 893//121
+f 898//124 897//124 895//123
+f 900//125 899//125 897//124
+f 902//126 901//126 899//125
+f 904//127 903//127 901//126
+f 906//127 905//127 903//127
+f 908//127 907//127 905//127
+f 910//127 909//127 907//127
+f 912//127 911//127 909//127
+f 914//127 913//127 911//127
+f 916//127 915//127 913//127
+f 918//127 917//127 915//127
+f 920//127 919//127 917//127
+f 922//127 921//127 919//127
+f 924//127 923//127 921//127
+f 926//128 925//128 923//127
+f 684//16 683//16 925//128
+f 930//129 929//129 927//130
+f 932//129 931//129 929//129
+f 934//129 933//129 931//129
+f 936//129 935//129 933//129
+f 938//129 937//129 935//129
+f 940//129 939//129 937//129
+f 942//129 941//129 939//129
+f 944//129 943//129 941//129
+f 946//129 945//129 943//129
+f 948//129 947//129 945//129
+f 950//131 949//129 947//129
+f 952//132 951//134 949//129
+f 954//133 953//133 951//134
+f 956//135 955//135 953//133
+f 958//136 957//136 955//135
+f 960//137 959//137 957//136
+f 962//138 961//138 959//137
+f 964//139 963//139 961//138
+f 966//140 965//140 963//139
+f 968//141 967//141 965//140
+f 970//142 969//142 967//141
+f 972//143 971//143 969//142
+f 974//144 973//144 971//143
+f 976//145 975//145 973//144
+f 978//146 977//146 975//145
+f 980//147 979//147 977//146
+f 982//148 981//148 979//147
+f 984//149 983//149 981//148
+f 986//150 985//150 983//149
+f 988//151 987//151 985//150
+f 990//152 989//152 987//151
+f 992//153 991//153 989//152
+f 994//154 993//154 991//153
+f 996//155 995//155 993//154
+f 998//156 997//156 995//155
+f 1000//157 999//157 997//156
+f 1002//158 1001//158 999//157
+f 1004//158 1003//158 1001//158
+f 1006//10 1005//10 1003//158
+f 1008//10 1007//10 1005//10
+f 1010//10 1009//10 1007//10
+f 1012//159 1011//159 1009//10
+f 1014//159 1013//159 1011//159
+f 1016//159 1015//159 1013//159
+f 1018//14 1017//14 1015//159
+f 1020//14 1019//14 1017//14
+f 1022//7 1021//7 1019//14
+f 1024//7 1023//7 1021//7
+f 1026//7 1025//7 1023//7
+f 1028//7 1027//7 1025//7
+f 1030//7 1029//7 1027//7
+f 1032//7 1031//7 1029//7
+f 1034//7 1033//7 1031//7
+f 1036//7 1035//7 1033//7
+f 1038//7 1037//7 1035//7
+f 1040//7 1039//7 1037//7
+f 1042//7 1041//7 1039//7
+f 1044//160 1043//160 1041//7
+f 1046//161 1045//161 1043//160
+f 1048//162 1047//162 1045//161
+f 1050//163 1049//163 1047//162
+f 1052//164 1051//164 1049//163
+f 1054//165 1053//165 1051//164
+f 1056//166 1055//166 1053//165
+f 1058//167 1057//167 1055//166
+f 1060//168 1059//168 1057//167
+f 1062//96 1061//96 1059//168
+f 1064//169 1063//169 1061//96
+f 1066//170 1065//170 1063//169
+f 1068//171 1067//171 1065//170
+f 1070//172 1069//172 1067//171
+f 1072//173 1071//173 1069//172
+f 1074//174 1073//174 1071//173
+f 1076//175 1075//175 1073//174
+f 1078//176 1077//176 1075//175
+f 1080//177 1079//179 1077//176
+f 1082//178 1081//178 1079//179
+f 1084//180 1083//180 1081//178
+f 1086//181 1085//181 1083//180
+f 1088//182 1087//182 1085//181
+f 1090//183 1089//183 1087//182
+f 1092//184 1091//184 1089//183
+f 1094//185 1093//185 1091//184
+f 1096//186 1095//186 1093//185
+f 1098//187 1097//187 1095//186
+f 1100//188 1099//188 1097//187
+f 1102//189 1101//189 1099//188
+f 1104//190 1103//190 1101//189
+f 1106//191 1105//191 1103//190
+f 1108//192 1107//192 1105//191
+f 1110//193 1109//193 1107//192
+f 1112//194 1111//194 1109//193
+f 1114//195 1113//195 1111//194
+f 1116//196 1115//196 1113//195
+f 928//130 927//130 1115//196
+f 1120//197 1119//197 1117//198
+f 1122//199 1121//199 1119//197
+f 1124//200 1123//200 1121//199
+f 1126//201 1125//201 1123//200
+f 1128//202 1127//202 1125//201
+f 1130//203 1129//203 1127//202
+f 1132//204 1131//204 1129//203
+f 1134//205 1133//205 1131//204
+f 1136//206 1135//206 1133//205
+f 1138//207 1137//207 1135//206
+f 1140//7 1139//7 1137//207
+f 1142//208 1141//208 1139//7
+f 1144//209 1143//209 1141//208
+f 1146//210 1145//210 1143//209
+f 1148//211 1147//211 1145//210
+f 1150//212 1149//212 1147//211
+f 1152//213 1151//213 1149//212
+f 1154//214 1153//214 1151//213
+f 1156//215 1155//215 1153//214
+f 1158//216 1157//216 1155//215
+f 1160//217 1159//217 1157//216
+f 1162//218 1161//218 1159//217
+f 1164//219 1163//219 1161//218
+f 1166//220 1165//220 1163//219
+f 1168//221 1167//221 1165//220
+f 1170//222 1169//222 1167//221
+f 1172//223 1171//223 1169//222
+f 1174//224 1173//224 1171//223
+f 1176//225 1175//225 1173//224
+f 1178//226 1177//226 1175//225
+f 1180//227 1179//227 1177//226
+f 1182//228 1181//228 1179//227
+f 1184//229 1183//229 1181//228
+f 1186//230 1185//230 1183//229
+f 1188//231 1187//231 1185//230
+f 1190//232 1189//232 1187//231
+f 1192//233 1191//233 1189//232
+f 1194//234 1193//236 1191//233
+f 1196//235 1195//235 1193//236
+f 1198//237 1197//237 1195//235
+f 1200//238 1199//238 1197//237
+f 1202//239 1201//239 1199//238
+f 1204//240 1203//240 1201//239
+f 1206//241 1205//241 1203//240
+f 1208//242 1207//242 1205//241
+f 1210//243 1209//243 1207//242
+f 1212//244 1211//244 1209//243
+f 1214//245 1213//245 1211//244
+f 1216//246 1215//246 1213//245
+f 1218//247 1217//247 1215//246
+f 1220//248 1219//248 1217//247
+f 1222//249 1221//249 1219//248
+f 1224//250 1223//250 1221//249
+f 1226//251 1225//251 1223//250
+f 1228//252 1227//252 1225//251
+f 1230//253 1229//253 1227//252
+f 1232//254 1231//254 1229//253
+f 1234//255 1233//255 1231//254
+f 1236//256 1235//256 1233//255
+f 1238//257 1237//257 1235//256
+f 1240//258 1239//258 1237//257
+f 1242//259 1241//259 1239//258
+f 1244//260 1243//260 1241//259
+f 1246//261 1245//261 1243//260
+f 1248//262 1247//262 1245//261
+f 1250//263 1249//263 1247//262
+f 1252//264 1251//264 1249//263
+f 1254//265 1253//265 1251//264
+f 1256//266 1255//266 1253//265
+f 1258//267 1257//267 1255//266
+f 1260//268 1259//268 1257//267
+f 1262//269 1261//269 1259//268
+f 1264//270 1263//270 1261//269
+f 1266//271 1265//271 1263//270
+f 1268//272 1267//272 1265//271
+f 1270//273 1269//273 1267//272
+f 1272//274 1271//274 1269//273
+f 1274//275 1273//275 1271//274
+f 1276//276 1275//276 1273//275
+f 1278//277 1277//277 1275//276
+f 1280//278 1279//278 1277//277
+f 1282//279 1281//279 1279//278
+f 1284//3 1283//3 1281//279
+f 1286//280 1285//280 1283//3
+f 1288//281 1287//281 1285//280
+f 1290//282 1289//282 1287//281
+f 1292//283 1291//283 1289//282
+f 1294//284 1293//284 1291//283
+f 1296//285 1295//285 1293//284
+f 1298//286 1297//286 1295//285
+f 1300//287 1299//287 1297//286
+f 1302//288 1301//288 1299//287
+f 1304//289 1303//289 1301//288
+f 1306//290 1305//290 1303//289
+f 1308//291 1307//291 1305//290
+f 1118//198 1117//198 1307//291
diff --git a/examples/vulkan/shared/trianglerenderer.cpp b/examples/vulkan/shared/trianglerenderer.cpp
new file mode 100644
index 0000000000..f346f90c89
--- /dev/null
+++ b/examples/vulkan/shared/trianglerenderer.cpp
@@ -0,0 +1,513 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "trianglerenderer.h"
+#include <QVulkanFunctions>
+#include <QFile>
+
+// Note that the vertex data and the projection matrix assume OpenGL. With
+// Vulkan Y is negated in clip space and the near/far plane is at 0/1 instead
+// of -1/1. These will be corrected for by an extra transformation when
+// calculating the modelview-projection matrix.
+static float vertexData[] = {
+ 0.0f, 0.5f, 1.0f, 0.0f, 0.0f,
+ -0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
+ 0.5f, -0.5f, 0.0f, 0.0f, 1.0f
+};
+
+static const int UNIFORM_DATA_SIZE = 16 * sizeof(float);
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+TriangleRenderer::TriangleRenderer(QVulkanWindow *w, bool msaa)
+ : m_window(w)
+{
+ if (msaa) {
+ const QVector<int> counts = w->supportedSampleCounts();
+ qDebug() << "Supported sample counts:" << counts;
+ for (int s = 16; s >= 4; s /= 2) {
+ if (counts.contains(s)) {
+ qDebug("Requesting sample count %d", s);
+ m_window->setSampleCount(s);
+ break;
+ }
+ }
+ }
+}
+
+VkShaderModule TriangleRenderer::createShader(const QString &name)
+{
+ QFile file(name);
+ if (!file.open(QIODevice::ReadOnly)) {
+ qWarning("Failed to read shader %s", qPrintable(name));
+ return VK_NULL_HANDLE;
+ }
+ QByteArray blob = file.readAll();
+ file.close();
+
+ VkShaderModuleCreateInfo shaderInfo;
+ memset(&shaderInfo, 0, sizeof(shaderInfo));
+ shaderInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
+ shaderInfo.codeSize = blob.size();
+ shaderInfo.pCode = reinterpret_cast<const uint32_t *>(blob.constData());
+ VkShaderModule shaderModule;
+ VkResult err = m_devFuncs->vkCreateShaderModule(m_window->device(), &shaderInfo, nullptr, &shaderModule);
+ if (err != VK_SUCCESS) {
+ qWarning("Failed to create shader module: %d", err);
+ return VK_NULL_HANDLE;
+ }
+
+ return shaderModule;
+}
+
+void TriangleRenderer::initResources()
+{
+ qDebug("initResources");
+
+ VkDevice dev = m_window->device();
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(dev);
+
+ // Prepare the vertex and uniform data. The vertex data will never
+ // change so one buffer is sufficient regardless of the value of
+ // QVulkanWindow::CONCURRENT_FRAME_COUNT. Uniform data is changing per
+ // frame however so active frames have to have a dedicated copy.
+
+ // Use just one memory allocation and one buffer. We will then specify the
+ // appropriate offsets for uniform buffers in the VkDescriptorBufferInfo.
+ // Have to watch out for
+ // VkPhysicalDeviceLimits::minUniformBufferOffsetAlignment, though.
+
+ // The uniform buffer is not strictly required in this example, we could
+ // have used push constants as well since our single matrix (64 bytes) fits
+ // into the spec mandated minimum limit of 128 bytes. However, once that
+ // limit is not sufficient, the per-frame buffers, as shown below, will
+ // become necessary.
+
+ const int concurrentFrameCount = m_window->concurrentFrameCount();
+ const VkPhysicalDeviceLimits *pdevLimits = &m_window->physicalDeviceProperties()->limits;
+ const VkDeviceSize uniAlign = pdevLimits->minUniformBufferOffsetAlignment;
+ qDebug("uniform buffer offset alignment is %u", (uint) uniAlign);
+ VkBufferCreateInfo bufInfo;
+ memset(&bufInfo, 0, sizeof(bufInfo));
+ bufInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
+ // Our internal layout is vertex, uniform, uniform, ... with each uniform buffer start offset aligned to uniAlign.
+ const VkDeviceSize vertexAllocSize = aligned(sizeof(vertexData), uniAlign);
+ const VkDeviceSize uniformAllocSize = aligned(UNIFORM_DATA_SIZE, uniAlign);
+ bufInfo.size = vertexAllocSize + concurrentFrameCount * uniformAllocSize;
+ bufInfo.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
+
+ VkResult err = m_devFuncs->vkCreateBuffer(dev, &bufInfo, nullptr, &m_buf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create buffer: %d", err);
+
+ VkMemoryRequirements memReq;
+ m_devFuncs->vkGetBufferMemoryRequirements(dev, m_buf, &memReq);
+
+ VkMemoryAllocateInfo memAllocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ m_window->hostVisibleMemoryIndex()
+ };
+
+ err = m_devFuncs->vkAllocateMemory(dev, &memAllocInfo, nullptr, &m_bufMem);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate memory: %d", err);
+
+ err = m_devFuncs->vkBindBufferMemory(dev, m_buf, m_bufMem, 0);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to bind buffer memory: %d", err);
+
+ quint8 *p;
+ err = m_devFuncs->vkMapMemory(dev, m_bufMem, 0, memReq.size, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ memcpy(p, vertexData, sizeof(vertexData));
+ QMatrix4x4 ident;
+ memset(m_uniformBufInfo, 0, sizeof(m_uniformBufInfo));
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ const VkDeviceSize offset = vertexAllocSize + i * uniformAllocSize;
+ memcpy(p + offset, ident.constData(), 16 * sizeof(float));
+ m_uniformBufInfo[i].buffer = m_buf;
+ m_uniformBufInfo[i].offset = offset;
+ m_uniformBufInfo[i].range = uniformAllocSize;
+ }
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ VkVertexInputBindingDescription vertexBindingDesc = {
+ 0, // binding
+ 5 * sizeof(float),
+ VK_VERTEX_INPUT_RATE_VERTEX
+ };
+ VkVertexInputAttributeDescription vertexAttrDesc[] = {
+ { // position
+ 0, // location
+ 0, // binding
+ VK_FORMAT_R32G32_SFLOAT,
+ 0
+ },
+ { // color
+ 1,
+ 0,
+ VK_FORMAT_R32G32B32_SFLOAT,
+ 2 * sizeof(float)
+ }
+ };
+
+ VkPipelineVertexInputStateCreateInfo vertexInputInfo;
+ vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
+ vertexInputInfo.pNext = nullptr;
+ vertexInputInfo.flags = 0;
+ vertexInputInfo.vertexBindingDescriptionCount = 1;
+ vertexInputInfo.pVertexBindingDescriptions = &vertexBindingDesc;
+ vertexInputInfo.vertexAttributeDescriptionCount = 2;
+ vertexInputInfo.pVertexAttributeDescriptions = vertexAttrDesc;
+
+ // Set up descriptor set and its layout.
+ VkDescriptorPoolSize descPoolSizes = { VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, uint32_t(concurrentFrameCount) };
+ VkDescriptorPoolCreateInfo descPoolInfo;
+ memset(&descPoolInfo, 0, sizeof(descPoolInfo));
+ descPoolInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
+ descPoolInfo.maxSets = concurrentFrameCount;
+ descPoolInfo.poolSizeCount = 1;
+ descPoolInfo.pPoolSizes = &descPoolSizes;
+ err = m_devFuncs->vkCreateDescriptorPool(dev, &descPoolInfo, nullptr, &m_descPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor pool: %d", err);
+
+ VkDescriptorSetLayoutBinding layoutBinding = {
+ 0, // binding
+ VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
+ 1,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ nullptr
+ };
+ VkDescriptorSetLayoutCreateInfo descLayoutInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ nullptr,
+ 0,
+ 1,
+ &layoutBinding
+ };
+ err = m_devFuncs->vkCreateDescriptorSetLayout(dev, &descLayoutInfo, nullptr, &m_descSetLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create descriptor set layout: %d", err);
+
+ for (int i = 0; i < concurrentFrameCount; ++i) {
+ VkDescriptorSetAllocateInfo descSetAllocInfo = {
+ VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ nullptr,
+ m_descPool,
+ 1,
+ &m_descSetLayout
+ };
+ err = m_devFuncs->vkAllocateDescriptorSets(dev, &descSetAllocInfo, &m_descSet[i]);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate descriptor set: %d", err);
+
+ VkWriteDescriptorSet descWrite;
+ memset(&descWrite, 0, sizeof(descWrite));
+ descWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
+ descWrite.dstSet = m_descSet[i];
+ descWrite.descriptorCount = 1;
+ descWrite.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
+ descWrite.pBufferInfo = &m_uniformBufInfo[i];
+ m_devFuncs->vkUpdateDescriptorSets(dev, 1, &descWrite, 0, nullptr);
+ }
+
+ // Pipeline cache
+ VkPipelineCacheCreateInfo pipelineCacheInfo;
+ memset(&pipelineCacheInfo, 0, sizeof(pipelineCacheInfo));
+ pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
+ err = m_devFuncs->vkCreatePipelineCache(dev, &pipelineCacheInfo, nullptr, &m_pipelineCache);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline cache: %d", err);
+
+ // Pipeline layout
+ VkPipelineLayoutCreateInfo pipelineLayoutInfo;
+ memset(&pipelineLayoutInfo, 0, sizeof(pipelineLayoutInfo));
+ pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
+ pipelineLayoutInfo.setLayoutCount = 1;
+ pipelineLayoutInfo.pSetLayouts = &m_descSetLayout;
+ err = m_devFuncs->vkCreatePipelineLayout(dev, &pipelineLayoutInfo, nullptr, &m_pipelineLayout);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create pipeline layout: %d", err);
+
+ // Shaders
+ VkShaderModule vertShaderModule = createShader(QStringLiteral(":/color_vert.spv"));
+ VkShaderModule fragShaderModule = createShader(QStringLiteral(":/color_frag.spv"));
+
+ // Graphics pipeline
+ VkGraphicsPipelineCreateInfo pipelineInfo;
+ memset(&pipelineInfo, 0, sizeof(pipelineInfo));
+ pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+
+ VkPipelineShaderStageCreateInfo shaderStages[2] = {
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_VERTEX_BIT,
+ vertShaderModule,
+ "main",
+ nullptr
+ },
+ {
+ VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ nullptr,
+ 0,
+ VK_SHADER_STAGE_FRAGMENT_BIT,
+ fragShaderModule,
+ "main",
+ nullptr
+ }
+ };
+ pipelineInfo.stageCount = 2;
+ pipelineInfo.pStages = shaderStages;
+
+ pipelineInfo.pVertexInputState = &vertexInputInfo;
+
+ VkPipelineInputAssemblyStateCreateInfo ia;
+ memset(&ia, 0, sizeof(ia));
+ ia.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ ia.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
+ pipelineInfo.pInputAssemblyState = &ia;
+
+ // The viewport and scissor will be set dynamically via vkCmdSetViewport/Scissor.
+ // This way the pipeline does not need to be touched when resizing the window.
+ VkPipelineViewportStateCreateInfo vp;
+ memset(&vp, 0, sizeof(vp));
+ vp.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ vp.viewportCount = 1;
+ vp.scissorCount = 1;
+ pipelineInfo.pViewportState = &vp;
+
+ VkPipelineRasterizationStateCreateInfo rs;
+ memset(&rs, 0, sizeof(rs));
+ rs.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ rs.polygonMode = VK_POLYGON_MODE_FILL;
+ rs.cullMode = VK_CULL_MODE_NONE; // we want the back face as well
+ rs.frontFace = VK_FRONT_FACE_CLOCKWISE;
+ rs.lineWidth = 1.0f;
+ pipelineInfo.pRasterizationState = &rs;
+
+ VkPipelineMultisampleStateCreateInfo ms;
+ memset(&ms, 0, sizeof(ms));
+ ms.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ // Enable multisampling.
+ ms.rasterizationSamples = m_window->sampleCountFlagBits();
+ pipelineInfo.pMultisampleState = &ms;
+
+ VkPipelineDepthStencilStateCreateInfo ds;
+ memset(&ds, 0, sizeof(ds));
+ ds.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
+ ds.depthTestEnable = VK_TRUE;
+ ds.depthWriteEnable = VK_TRUE;
+ ds.depthCompareOp = VK_COMPARE_OP_LESS_OR_EQUAL;
+ pipelineInfo.pDepthStencilState = &ds;
+
+ VkPipelineColorBlendStateCreateInfo cb;
+ memset(&cb, 0, sizeof(cb));
+ cb.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
+ // no blend, write out all of rgba
+ VkPipelineColorBlendAttachmentState att;
+ memset(&att, 0, sizeof(att));
+ att.colorWriteMask = 0xF;
+ cb.attachmentCount = 1;
+ cb.pAttachments = &att;
+ pipelineInfo.pColorBlendState = &cb;
+
+ VkDynamicState dynEnable[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR };
+ VkPipelineDynamicStateCreateInfo dyn;
+ memset(&dyn, 0, sizeof(dyn));
+ dyn.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ dyn.dynamicStateCount = sizeof(dynEnable) / sizeof(VkDynamicState);
+ dyn.pDynamicStates = dynEnable;
+ pipelineInfo.pDynamicState = &dyn;
+
+ pipelineInfo.layout = m_pipelineLayout;
+ pipelineInfo.renderPass = m_window->defaultRenderPass();
+
+ err = m_devFuncs->vkCreateGraphicsPipelines(dev, m_pipelineCache, 1, &pipelineInfo, nullptr, &m_pipeline);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create graphics pipeline: %d", err);
+
+ if (vertShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, vertShaderModule, nullptr);
+ if (fragShaderModule)
+ m_devFuncs->vkDestroyShaderModule(dev, fragShaderModule, nullptr);
+}
+
+void TriangleRenderer::initSwapChainResources()
+{
+ qDebug("initSwapChainResources");
+
+ // Projection matrix
+ m_proj = m_window->clipCorrectionMatrix(); // adjust for Vulkan-OpenGL clip space differences
+ const QSize sz = m_window->swapChainImageSize();
+ m_proj.perspective(45.0f, sz.width() / (float) sz.height(), 0.01f, 100.0f);
+ m_proj.translate(0, 0, -4);
+}
+
+void TriangleRenderer::releaseSwapChainResources()
+{
+ qDebug("releaseSwapChainResources");
+}
+
+void TriangleRenderer::releaseResources()
+{
+ qDebug("releaseResources");
+
+ VkDevice dev = m_window->device();
+
+ if (m_pipeline) {
+ m_devFuncs->vkDestroyPipeline(dev, m_pipeline, nullptr);
+ m_pipeline = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineLayout) {
+ m_devFuncs->vkDestroyPipelineLayout(dev, m_pipelineLayout, nullptr);
+ m_pipelineLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_pipelineCache) {
+ m_devFuncs->vkDestroyPipelineCache(dev, m_pipelineCache, nullptr);
+ m_pipelineCache = VK_NULL_HANDLE;
+ }
+
+ if (m_descSetLayout) {
+ m_devFuncs->vkDestroyDescriptorSetLayout(dev, m_descSetLayout, nullptr);
+ m_descSetLayout = VK_NULL_HANDLE;
+ }
+
+ if (m_descPool) {
+ m_devFuncs->vkDestroyDescriptorPool(dev, m_descPool, nullptr);
+ m_descPool = VK_NULL_HANDLE;
+ }
+
+ if (m_buf) {
+ m_devFuncs->vkDestroyBuffer(dev, m_buf, nullptr);
+ m_buf = VK_NULL_HANDLE;
+ }
+
+ if (m_bufMem) {
+ m_devFuncs->vkFreeMemory(dev, m_bufMem, nullptr);
+ m_bufMem = VK_NULL_HANDLE;
+ }
+}
+
+void TriangleRenderer::startNextFrame()
+{
+ VkDevice dev = m_window->device();
+ VkCommandBuffer cb = m_window->currentCommandBuffer();
+ const QSize sz = m_window->swapChainImageSize();
+
+ VkClearColorValue clearColor = { 0, 0, 0, 1 };
+ VkClearDepthStencilValue clearDS = { 1, 0 };
+ VkClearValue clearValues[3];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearValues[2].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = m_window->sampleCountFlagBits() > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ quint8 *p;
+ VkResult err = m_devFuncs->vkMapMemory(dev, m_bufMem, m_uniformBufInfo[m_window->currentFrame()].offset,
+ UNIFORM_DATA_SIZE, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS)
+ qFatal("Failed to map memory: %d", err);
+ QMatrix4x4 m = m_proj;
+ m.rotate(m_rotation, 0, 1, 0);
+ memcpy(p, m.constData(), 16 * sizeof(float));
+ m_devFuncs->vkUnmapMemory(dev, m_bufMem);
+
+ // Not exactly a real animation system, just advance on every frame for now.
+ m_rotation += 1.0f;
+
+ m_devFuncs->vkCmdBindPipeline(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline);
+ m_devFuncs->vkCmdBindDescriptorSets(cb, VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipelineLayout, 0, 1,
+ &m_descSet[m_window->currentFrame()], 0, nullptr);
+ VkDeviceSize vbOffset = 0;
+ m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset);
+
+ VkViewport viewport;
+ viewport.x = viewport.y = 0;
+ viewport.width = sz.width();
+ viewport.height = sz.height();
+ viewport.minDepth = 0;
+ viewport.maxDepth = 1;
+ m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
+
+ VkRect2D scissor;
+ scissor.offset.x = scissor.offset.y = 0;
+ scissor.extent.width = viewport.width;
+ scissor.extent.height = viewport.height;
+ m_devFuncs->vkCmdSetScissor(cb, 0, 1, &scissor);
+
+ m_devFuncs->vkCmdDraw(cb, 3, 1, 0, 0);
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+
+ m_window->frameReady();
+ m_window->requestUpdate(); // render continuously, throttled by the presentation rate
+}
diff --git a/examples/vulkan/shared/trianglerenderer.h b/examples/vulkan/shared/trianglerenderer.h
new file mode 100644
index 0000000000..9a33291a95
--- /dev/null
+++ b/examples/vulkan/shared/trianglerenderer.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:BSD$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** BSD License Usage
+** Alternatively, you may use this file under the terms of the BSD license
+** as follows:
+**
+** "Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+** * Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+** * Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in
+** the documentation and/or other materials provided with the
+** distribution.
+** * Neither the name of The Qt Company Ltd nor the names of its
+** contributors may be used to endorse or promote products derived
+** from this software without specific prior written permission.
+**
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QVulkanWindow>
+
+class TriangleRenderer : public QVulkanWindowRenderer
+{
+public:
+ TriangleRenderer(QVulkanWindow *w, bool msaa = false);
+
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+protected:
+ VkShaderModule createShader(const QString &name);
+
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+
+ VkDeviceMemory m_bufMem = VK_NULL_HANDLE;
+ VkBuffer m_buf = VK_NULL_HANDLE;
+ VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkDescriptorPool m_descPool = VK_NULL_HANDLE;
+ VkDescriptorSetLayout m_descSetLayout = VK_NULL_HANDLE;
+ VkDescriptorSet m_descSet[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+
+ VkPipelineCache m_pipelineCache = VK_NULL_HANDLE;
+ VkPipelineLayout m_pipelineLayout = VK_NULL_HANDLE;
+ VkPipeline m_pipeline = VK_NULL_HANDLE;
+
+ QMatrix4x4 m_proj;
+ float m_rotation = 0.0f;
+};
diff --git a/examples/vulkan/vulkan.pro b/examples/vulkan/vulkan.pro
new file mode 100644
index 0000000000..920762cb9e
--- /dev/null
+++ b/examples/vulkan/vulkan.pro
@@ -0,0 +1,10 @@
+TEMPLATE = subdirs
+
+SUBDIRS = hellovulkanwindow \
+ hellovulkantriangle \
+ hellovulkantexture
+
+qtHaveModule(widgets) {
+ SUBDIRS += hellovulkanwidget
+ qtHaveModule(concurrent): SUBDIRS += hellovulkancubes
+}
diff --git a/examples/widgets/animation/stickman/stickman.cpp b/examples/widgets/animation/stickman/stickman.cpp
index 7a4629c4d2..b7a2d87ada 100644
--- a/examples/widgets/animation/stickman/stickman.cpp
+++ b/examples/widgets/animation/stickman/stickman.cpp
@@ -53,13 +53,7 @@
#include <QPainter>
#include <QTimer>
-
-#define _USE_MATH_DEFINES
-#include <math.h>
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
+#include <qmath.h>
static const qreal Coords[NodeCount * 2] = {
0.0, -150.0, // head, #0
@@ -300,7 +294,7 @@ void StickMan::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidge
QPointF dist = node2->pos() - node1->pos();
qreal sinAngle = dist.x() / sqrt(pow(dist.x(), 2) + pow(dist.y(), 2));
- qreal angle = asin(sinAngle) * 180.0 / M_PI;
+ qreal angle = qRadiansToDegrees(asin(sinAngle));
QPointF headPos = node1->pos();
painter->translate(headPos);
diff --git a/examples/widgets/doc/src/painterpaths.qdoc b/examples/widgets/doc/src/painterpaths.qdoc
index 2cc5ff410a..bd821ac1bf 100644
--- a/examples/widgets/doc/src/painterpaths.qdoc
+++ b/examples/widgets/doc/src/painterpaths.qdoc
@@ -98,14 +98,9 @@
\section1 Window Class Implementation
- In the implementation of the \c Window class we first declare the
- constant \c Pi with six significant figures:
-
- \snippet painting/painterpaths/window.cpp 0
-
- In the constructor, we then define the various painter paths and
- create corresponding \c RenderArea widgets which will render the
- graphical shapes:
+ In the \c Window constructor, we define the various painter paths
+ and create corresponding \c RenderArea widgets which will render
+ the graphical shapes:
\snippet painting/painterpaths/window.cpp 1
diff --git a/examples/widgets/doc/src/tablet.qdoc b/examples/widgets/doc/src/tablet.qdoc
index 88fdefa68f..2b11020c07 100644
--- a/examples/widgets/doc/src/tablet.qdoc
+++ b/examples/widgets/doc/src/tablet.qdoc
@@ -206,8 +206,7 @@
\snippet widgets/tablet/tabletcanvas.cpp 0
- In the constructor we initialize our class variables. We need
- to draw the background of our pixmap, as the default is gray.
+ In the constructor we initialize most of our class variables.
Here is the implementation of \c saveImage():
@@ -247,7 +246,15 @@
\snippet widgets/tablet/tabletcanvas.cpp 4
- We simply draw the pixmap to the top left of the widget.
+ The first time Qt calls paintEvent(), m_pixmap is default-constructed, so
+ QPixmap::isNull() returns \c true. Now that we know which screen we will be
+ rendering to, we can create a pixmap with the appropriate resolution.
+ The size of the pixmap with which we fill the window depends on the screen
+ resolution, as the example does not support zoom; and it may be that one
+ screen is \l {High DPI Displays}{high DPI} while another is not. We need to
+ draw the background too, as the default is gray.
+
+ After that, we simply draw the pixmap to the top left of the widget.
Here is the implementation of \c paintPixmap():
diff --git a/examples/widgets/effects/blurpicker/blurpicker.cpp b/examples/widgets/effects/blurpicker/blurpicker.cpp
index 43823bed30..a00af2144a 100644
--- a/examples/widgets/effects/blurpicker/blurpicker.cpp
+++ b/examples/widgets/effects/blurpicker/blurpicker.cpp
@@ -52,13 +52,9 @@
#include <QtWidgets>
#include <QtCore/qmath.h>
-
+#include <qmath.h>
#include "blureffect.h"
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
BlurPicker::BlurPicker(QWidget *parent): QGraphicsView(parent), m_index(0.0), m_animation(this, "index")
{
setBackgroundBrush(QPixmap(":/images/background.jpg"));
@@ -84,9 +80,10 @@ void BlurPicker::setIndex(qreal index)
m_index = index;
qreal baseline = 0;
+ const qreal iconAngle = 2 * M_PI / m_icons.count();
for (int i = 0; i < m_icons.count(); ++i) {
QGraphicsItem *icon = m_icons[i];
- qreal a = ((i + m_index) * 2 * M_PI) / m_icons.count();
+ qreal a = (i + m_index) * iconAngle;
qreal xs = 170 * qSin(a);
qreal ys = 100 * qCos(a);
QPointF pos(xs, ys);
diff --git a/examples/widgets/effects/lighting/lighting.cpp b/examples/widgets/effects/lighting/lighting.cpp
index 68350f32b7..1ba7dd9ce7 100644
--- a/examples/widgets/effects/lighting/lighting.cpp
+++ b/examples/widgets/effects/lighting/lighting.cpp
@@ -49,14 +49,9 @@
****************************************************************************/
#include "lighting.h"
-
#include <QtWidgets>
#include <QtCore/qmath.h>
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-
Lighting::Lighting(QWidget *parent): QGraphicsView(parent), angle(0.0)
{
setScene(&m_scene);
@@ -120,7 +115,7 @@ void Lighting::setupScene()
void Lighting::animate()
{
- angle += (M_PI / 30);
+ angle += qDegreesToRadians(qreal(6));
qreal xs = 200 * qSin(angle) - 40 + 25;
qreal ys = 200 * qCos(angle) - 40 + 25;
m_lightSource->setPos(xs, ys);
diff --git a/examples/widgets/graphicsview/boxes/glbuffers.cpp b/examples/widgets/graphicsview/boxes/glbuffers.cpp
index 1481292e76..851cd17796 100644
--- a/examples/widgets/graphicsview/boxes/glbuffers.cpp
+++ b/examples/widgets/graphicsview/boxes/glbuffers.cpp
@@ -50,11 +50,11 @@
#include "glbuffers.h"
#include <QtGui/qmatrix4x4.h>
-
+#include <QtCore/qmath.h>
void qgluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
- const GLdouble ymax = zNear * tan(fovy * M_PI / 360.0);
+ const GLdouble ymax = zNear * tan(qDegreesToRadians(fovy) / 2.0);
const GLdouble ymin = -ymax;
const GLdouble xmin = ymin * aspect;
const GLdouble xmax = ymax * aspect;
diff --git a/examples/widgets/graphicsview/boxes/scene.cpp b/examples/widgets/graphicsview/boxes/scene.cpp
index 9ac429c667..31b9553c75 100644
--- a/examples/widgets/graphicsview/boxes/scene.cpp
+++ b/examples/widgets/graphicsview/boxes/scene.cpp
@@ -52,7 +52,7 @@
#include "scene.h"
#include <QtGui/qmatrix4x4.h>
#include <QtGui/qvector3d.h>
-#include <cmath>
+#include <qmath.h>
#include "3rdparty/fbm.h"
@@ -868,11 +868,12 @@ void Scene::renderCubemaps()
QVector3D center;
+ const float eachAngle = 2 * M_PI / m_cubemaps.size();
for (int i = m_frame % N; i < m_cubemaps.size(); i += N) {
if (0 == m_cubemaps[i])
continue;
- float angle = 2.0f * PI * i / m_cubemaps.size();
+ float angle = i * eachAngle;
center = m_trackBalls[1].rotation().rotatedVector(QVector3D(std::cos(angle), std::sin(angle), 0.0f));
diff --git a/examples/widgets/graphicsview/boxes/scene.h b/examples/widgets/graphicsview/boxes/scene.h
index a2ba1d0b5a..ccb6f368cd 100644
--- a/examples/widgets/graphicsview/boxes/scene.h
+++ b/examples/widgets/graphicsview/boxes/scene.h
@@ -63,8 +63,6 @@
#include "glbuffers.h"
#include "qtbox.h"
-#define PI 3.14159265358979
-
QT_BEGIN_NAMESPACE
class QMatrix4x4;
QT_END_NAMESPACE
diff --git a/examples/widgets/graphicsview/boxes/trackball.cpp b/examples/widgets/graphicsview/boxes/trackball.cpp
index 15f3af77d1..794ce7ac37 100644
--- a/examples/widgets/graphicsview/boxes/trackball.cpp
+++ b/examples/widgets/graphicsview/boxes/trackball.cpp
@@ -50,6 +50,7 @@
#include "trackball.h"
#include "scene.h"
+#include <qmath.h>
#include <cmath>
//============================================================================//
@@ -101,10 +102,11 @@ void TrackBall::move(const QPointF& p, const QQuaternion &transformation)
case Plane:
{
QLineF delta(m_lastPos, p);
- m_angularVelocity = 180*delta.length() / (PI*msecs);
+ const float angleDelta = qRadiansToDegrees(float(delta.length()));
+ m_angularVelocity = angleDelta / msecs;
m_axis = QVector3D(-delta.dy(), delta.dx(), 0.0f).normalized();
m_axis = transformation.rotatedVector(m_axis);
- m_rotation = QQuaternion::fromAxisAndAngle(m_axis, 180 / PI * delta.length()) * m_rotation;
+ m_rotation = QQuaternion::fromAxisAndAngle(m_axis, angleDelta) * m_rotation;
}
break;
case Sphere:
@@ -124,7 +126,7 @@ void TrackBall::move(const QPointF& p, const QQuaternion &transformation)
currentPos3D.normalize();
m_axis = QVector3D::crossProduct(lastPos3D, currentPos3D);
- float angle = 180 / PI * std::asin(std::sqrt(QVector3D::dotProduct(m_axis, m_axis)));
+ float angle = qRadiansToDegrees(std::asin(m_axis.length()));
m_angularVelocity = angle / msecs;
m_axis.normalize();
diff --git a/examples/widgets/graphicsview/collidingmice/mouse.cpp b/examples/widgets/graphicsview/collidingmice/mouse.cpp
index b94c650c18..298e4aae64 100644
--- a/examples/widgets/graphicsview/collidingmice/mouse.cpp
+++ b/examples/widgets/graphicsview/collidingmice/mouse.cpp
@@ -53,11 +53,10 @@
#include <QGraphicsScene>
#include <QPainter>
#include <QStyleOption>
+#include <qmath.h>
-#include <math.h>
-
-static const double Pi = 3.14159265358979323846264338327950288419717;
-static double TwoPi = 2.0 * Pi;
+const qreal Pi = M_PI;
+const qreal TwoPi = 2 * M_PI;
static qreal normalizeAngle(qreal angle)
{
@@ -140,9 +139,7 @@ void Mouse::advance(int step)
//! [5]
QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0));
if (lineToCenter.length() > 150) {
- qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length());
- if (lineToCenter.dy() < 0)
- angleToCenter = TwoPi - angleToCenter;
+ qreal angleToCenter = std::atan2(lineToCenter.dy(), lineToCenter.dx());
angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2);
if (angleToCenter < Pi && angleToCenter > Pi / 4) {
@@ -171,9 +168,7 @@ void Mouse::advance(int step)
continue;
QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0));
- qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length());
- if (lineToMouse.dy() < 0)
- angleToMouse = TwoPi - angleToMouse;
+ qreal angleToMouse = std::atan2(lineToMouse.dy(), lineToMouse.dx());
angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2);
if (angleToMouse >= 0 && angleToMouse < Pi / 2) {
diff --git a/examples/widgets/graphicsview/diagramscene/arrow.cpp b/examples/widgets/graphicsview/diagramscene/arrow.cpp
index 012b9ea2ed..88160d9399 100644
--- a/examples/widgets/graphicsview/diagramscene/arrow.cpp
+++ b/examples/widgets/graphicsview/diagramscene/arrow.cpp
@@ -51,13 +51,10 @@
#include "arrow.h"
-#include <math.h>
-
+#include <qmath.h>
#include <QPen>
#include <QPainter>
-const qreal Pi = 3.14;
-
//! [0]
Arrow::Arrow(DiagramItem *startItem, DiagramItem *endItem, QGraphicsItem *parent)
: QGraphicsLineItem(parent)
@@ -132,14 +129,12 @@ void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *,
setLine(QLineF(intersectPoint, myStartItem->pos()));
//! [5] //! [6]
- double angle = ::acos(line().dx() / line().length());
- if (line().dy() >= 0)
- angle = (Pi * 2) - angle;
+ double angle = std::atan2(-line().dy(), line().dx());
- QPointF arrowP1 = line().p1() + QPointF(sin(angle + Pi / 3) * arrowSize,
- cos(angle + Pi / 3) * arrowSize);
- QPointF arrowP2 = line().p1() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
- cos(angle + Pi - Pi / 3) * arrowSize);
+ QPointF arrowP1 = line().p1() + QPointF(sin(angle + M_PI / 3) * arrowSize,
+ cos(angle + M_PI / 3) * arrowSize);
+ QPointF arrowP2 = line().p1() + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
+ cos(angle + M_PI - M_PI / 3) * arrowSize);
arrowHead.clear();
arrowHead << line().p1() << arrowP1 << arrowP2;
diff --git a/examples/widgets/graphicsview/elasticnodes/edge.cpp b/examples/widgets/graphicsview/elasticnodes/edge.cpp
index e794e803cf..aec12b4225 100644
--- a/examples/widgets/graphicsview/elasticnodes/edge.cpp
+++ b/examples/widgets/graphicsview/elasticnodes/edge.cpp
@@ -51,13 +51,9 @@
#include "edge.h"
#include "node.h"
-#include <math.h>
-
+#include <qmath.h>
#include <QPainter>
-static const double Pi = 3.14159265358979323846264338327950288419717;
-static double TwoPi = 2.0 * Pi;
-
//! [0]
Edge::Edge(Node *sourceNode, Node *destNode)
: arrowSize(10)
@@ -139,18 +135,16 @@ void Edge::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
//! [6]
// Draw the arrows
- double angle = ::acos(line.dx() / line.length());
- if (line.dy() >= 0)
- angle = TwoPi - angle;
-
- QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + Pi / 3) * arrowSize,
- cos(angle + Pi / 3) * arrowSize);
- QPointF sourceArrowP2 = sourcePoint + QPointF(sin(angle + Pi - Pi / 3) * arrowSize,
- cos(angle + Pi - Pi / 3) * arrowSize);
- QPointF destArrowP1 = destPoint + QPointF(sin(angle - Pi / 3) * arrowSize,
- cos(angle - Pi / 3) * arrowSize);
- QPointF destArrowP2 = destPoint + QPointF(sin(angle - Pi + Pi / 3) * arrowSize,
- cos(angle - Pi + Pi / 3) * arrowSize);
+ double angle = std::atan2(-line.dy(), line.dx());
+
+ QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + M_PI / 3) * arrowSize,
+ cos(angle + M_PI / 3) * arrowSize);
+ QPointF sourceArrowP2 = sourcePoint + QPointF(sin(angle + M_PI - M_PI / 3) * arrowSize,
+ cos(angle + M_PI - M_PI / 3) * arrowSize);
+ QPointF destArrowP1 = destPoint + QPointF(sin(angle - M_PI / 3) * arrowSize,
+ cos(angle - M_PI / 3) * arrowSize);
+ QPointF destArrowP2 = destPoint + QPointF(sin(angle - M_PI + M_PI / 3) * arrowSize,
+ cos(angle - M_PI + M_PI / 3) * arrowSize);
painter->setBrush(Qt::black);
painter->drawPolygon(QPolygonF() << line.p1() << sourceArrowP1 << sourceArrowP2);
diff --git a/examples/widgets/itemviews/chart/pieview.cpp b/examples/widgets/itemviews/chart/pieview.cpp
index fb439fae67..3f85e397ee 100644
--- a/examples/widgets/itemviews/chart/pieview.cpp
+++ b/examples/widgets/itemviews/chart/pieview.cpp
@@ -49,12 +49,8 @@
****************************************************************************/
#include <QtWidgets>
+#include <qmath.h>
#include <cmath>
-
-#ifndef M_PI
-#define M_PI 3.1415927
-#endif
-
#include "pieview.h"
PieView::PieView(QWidget *parent)
@@ -125,9 +121,9 @@ QModelIndex PieView::indexAt(const QPoint &point) const
return QModelIndex();
// Determine the angle of the point.
- double angle = (180 / M_PI) * std::acos(cx / d);
- if (cy < 0)
- angle = 360 - angle;
+ double angle = qRadiansToDegrees(std::atan2(cy, cx));
+ if (angle < 0)
+ angle = 360 + angle;
// Find the relevant slice of the pie.
double startAngle = 0.0;
diff --git a/examples/widgets/itemviews/storageview/storagemodel.cpp b/examples/widgets/itemviews/storageview/storagemodel.cpp
index b7c594f8f7..1395c9f208 100644
--- a/examples/widgets/itemviews/storageview/storagemodel.cpp
+++ b/examples/widgets/itemviews/storageview/storagemodel.cpp
@@ -52,25 +52,10 @@
#include "storagemodel.h"
#include <QDir>
+#include <QLocale>
#include <qmath.h>
#include <cmath>
-static QString sizeToString(qint64 size)
-{
- static const char *const strings[] = { "b", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" };
-
- if (size <= 0)
- return StorageModel::tr("0 b");
-
- double power = std::log((double)size)/std::log(1024.0);
- int intPower = (int)power;
- intPower = intPower >= 8 ? 8 - 1 : intPower;
-
- double normSize = size / std::pow(1024.0, intPower);
- //: this should expand to "1.23 GB"
- return StorageModel::tr("%1 %2").arg(normSize, 0, 'f', intPower > 0 ? 2 : 0).arg(strings[intPower]);
-}
-
StorageModel::StorageModel(QObject *parent) :
QAbstractTableModel(parent),
m_volumes(QStorageInfo::mountedVolumes())
@@ -106,11 +91,11 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
case ColumnFileSystemName:
return volume.fileSystemType();
case ColumnTotal:
- return sizeToString(volume.bytesTotal());
+ return QLocale().formattedDataSize(volume.bytesTotal());
case ColumnFree:
- return sizeToString(volume.bytesFree());
+ return QLocale().formattedDataSize(volume.bytesFree());
case ColumnAvailable:
- return sizeToString(volume.bytesAvailable());
+ return QLocale().formattedDataSize(volume.bytesAvailable());
case ColumnIsReady:
return volume.isReady();
case ColumnIsReadOnly:
@@ -121,6 +106,7 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
break;
}
} else if (role == Qt::ToolTipRole) {
+ QLocale locale;
const QStorageInfo &volume = m_volumes.at(index.row());
return tr("Root path : %1\n"
"Name: %2\n"
@@ -140,9 +126,9 @@ QVariant StorageModel::data(const QModelIndex &index, int role) const
arg(volume.displayName()).
arg(QString::fromUtf8(volume.device())).
arg(QString::fromUtf8(volume.fileSystemType())).
- arg(sizeToString(volume.bytesTotal())).
- arg(sizeToString(volume.bytesFree())).
- arg(sizeToString(volume.bytesAvailable())).
+ arg(locale.formattedDataSize(volume.bytesTotal())).
+ arg(locale.formattedDataSize(volume.bytesFree())).
+ arg(locale.formattedDataSize(volume.bytesAvailable())).
arg(volume.isReady() ? tr("true") : tr("false")).
arg(volume.isReadOnly() ? tr("true") : tr("false")).
arg(volume.isValid() ? tr("true") : tr("false")).
diff --git a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
index 10e3dd045a..afceddfca1 100644
--- a/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
+++ b/examples/widgets/mainwindows/mainwindow/mainwindow.cpp
@@ -63,7 +63,6 @@
#include <QFileDialog>
#include <QDialogButtonBox>
#include <QMessageBox>
-#include <QSignalMapper>
#include <QApplication>
#include <QPainter>
#include <QMouseEvent>
diff --git a/examples/widgets/painting/composition/composition.cpp b/examples/widgets/painting/composition/composition.cpp
index d5d674fd83..0b57d3c7d3 100644
--- a/examples/widgets/painting/composition/composition.cpp
+++ b/examples/widgets/painting/composition/composition.cpp
@@ -464,7 +464,7 @@ void CompositionRenderer::paint(QPainter *painter)
drawBase(p);
}
- memcpy(m_buffer.bits(), m_base_buffer.bits(), m_buffer.byteCount());
+ memcpy(m_buffer.bits(), m_base_buffer.bits(), m_buffer.sizeInBytes());
{
QPainter p(&m_buffer);
diff --git a/examples/widgets/painting/painterpaths/window.cpp b/examples/widgets/painting/painterpaths/window.cpp
index 7122411a6c..a987937b39 100644
--- a/examples/widgets/painting/painterpaths/window.cpp
+++ b/examples/widgets/painting/painterpaths/window.cpp
@@ -53,11 +53,7 @@
#include <QtWidgets>
-#include <cmath>
-
-//! [0]
-const float Pi = 3.14159f;
-//! [0]
+#include <qmath.h>
//! [1]
Window::Window()
@@ -133,8 +129,8 @@ Window::Window()
QPainterPath starPath;
starPath.moveTo(90, 50);
for (int i = 1; i < 5; ++i) {
- starPath.lineTo(50 + 40 * std::cos(0.8 * i * Pi),
- 50 + 40 * std::sin(0.8 * i * Pi));
+ starPath.lineTo(50 + 40 * std::cos(0.8 * i * M_PI),
+ 50 + 40 * std::sin(0.8 * i * M_PI));
}
starPath.closeSubpath();
//! [9]
diff --git a/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp b/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp
index c929ff6922..740d007d44 100644
--- a/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp
+++ b/examples/widgets/tools/plugandpaint/plugins/basictools/basictoolsplugin.cpp
@@ -50,13 +50,11 @@
#include <QtWidgets>
-#include <cmath>
+#include <qmath.h>
#include <stdlib.h>
#include "basictoolsplugin.h"
-const float Pi = 3.14159f;
-
//! [0]
QStringList BasicToolsPlugin::brushes() const
{
@@ -149,8 +147,8 @@ QPainterPath BasicToolsPlugin::generateShape(const QString &shape,
} else if (shape == tr("Star")) {
path.moveTo(90, 50);
for (int i = 1; i < 5; ++i) {
- path.lineTo(50 + 40 * std::cos(0.8 * i * Pi),
- 50 + 40 * std::sin(0.8 * i * Pi));
+ path.lineTo(50 + 40 * std::cos(0.8 * i * M_PI),
+ 50 + 40 * std::sin(0.8 * i * M_PI));
}
path.closeSubpath();
} else if (shape == tr("Text...")) {
diff --git a/examples/widgets/widgets/tablet/tabletcanvas.cpp b/examples/widgets/widgets/tablet/tabletcanvas.cpp
index 90b3222970..4b11568dfe 100644
--- a/examples/widgets/widgets/tablet/tabletcanvas.cpp
+++ b/examples/widgets/widgets/tablet/tabletcanvas.cpp
@@ -65,21 +65,9 @@ TabletCanvas::TabletCanvas()
, m_deviceDown(false)
{
resize(500, 500);
- initPixmap();
setAutoFillBackground(true);
setAttribute(Qt::WA_TabletTracking);
}
-
-void TabletCanvas::initPixmap()
-{
- QPixmap newPixmap = QPixmap(width(), height());
- newPixmap.fill(Qt::white);
- QPainter painter(&newPixmap);
- if (!m_pixmap.isNull())
- painter.drawPixmap(0, 0, m_pixmap);
- painter.end();
- m_pixmap = newPixmap;
-}
//! [0]
//! [1]
@@ -105,23 +93,26 @@ bool TabletCanvas::loadImage(const QString &file)
//! [3]
void TabletCanvas::tabletEvent(QTabletEvent *event)
{
-
switch (event->type()) {
case QEvent::TabletPress:
if (!m_deviceDown) {
m_deviceDown = true;
lastPoint.pos = event->posF();
+ lastPoint.pressure = event->pressure();
lastPoint.rotation = event->rotation();
}
break;
case QEvent::TabletMove:
+#ifndef Q_OS_IOS
if (event->device() == QTabletEvent::RotationStylus)
updateCursor(event);
+#endif
if (m_deviceDown) {
updateBrush(event);
QPainter painter(&m_pixmap);
paintPixmap(painter, event);
lastPoint.pos = event->posF();
+ lastPoint.pressure = event->pressure();
lastPoint.rotation = event->rotation();
}
break;
@@ -138,8 +129,23 @@ void TabletCanvas::tabletEvent(QTabletEvent *event)
//! [3]
//! [4]
+void TabletCanvas::initPixmap()
+{
+ qreal dpr = devicePixelRatioF();
+ QPixmap newPixmap = QPixmap(width() * dpr, height() * dpr);
+ newPixmap.setDevicePixelRatio(dpr);
+ newPixmap.fill(Qt::white);
+ QPainter painter(&newPixmap);
+ if (!m_pixmap.isNull())
+ painter.drawPixmap(0, 0, m_pixmap);
+ painter.end();
+ m_pixmap = newPixmap;
+}
+
void TabletCanvas::paintEvent(QPaintEvent *)
{
+ if (m_pixmap.isNull())
+ initPixmap();
QPainter painter(this);
painter.drawPixmap(0, 0, m_pixmap);
}
@@ -171,13 +177,14 @@ void TabletCanvas::paintPixmap(QPainter &painter, QTabletEvent *event)
painter.setPen(Qt::NoPen);
painter.setBrush(m_brush);
QPolygonF poly;
- qreal halfWidth = m_pen.widthF();
- QPointF brushAdjust(qSin(qDegreesToRadians(lastPoint.rotation)) * halfWidth,
- qCos(qDegreesToRadians(lastPoint.rotation)) * halfWidth);
+ qreal halfWidth = pressureToWidth(lastPoint.pressure);
+ QPointF brushAdjust(qSin(qDegreesToRadians(-lastPoint.rotation)) * halfWidth,
+ qCos(qDegreesToRadians(-lastPoint.rotation)) * halfWidth);
poly << lastPoint.pos + brushAdjust;
poly << lastPoint.pos - brushAdjust;
- brushAdjust = QPointF(qSin(qDegreesToRadians(event->rotation())) * halfWidth,
- qCos(qDegreesToRadians(event->rotation())) * halfWidth);
+ halfWidth = m_pen.widthF();
+ brushAdjust = QPointF(qSin(qDegreesToRadians(-event->rotation())) * halfWidth,
+ qCos(qDegreesToRadians(-event->rotation())) * halfWidth);
poly << event->posF() - brushAdjust;
poly << event->posF() + brushAdjust;
painter.drawConvexPolygon(poly);
@@ -215,6 +222,11 @@ void TabletCanvas::paintPixmap(QPainter &painter, QTabletEvent *event)
}
//! [5]
+qreal TabletCanvas::pressureToWidth(qreal pressure)
+{
+ return pressure * 10 + 1;
+}
+
//! [7]
void TabletCanvas::updateBrush(const QTabletEvent *event)
{
@@ -260,7 +272,7 @@ void TabletCanvas::updateBrush(const QTabletEvent *event)
//! [9] //! [10]
switch (m_lineWidthValuator) {
case PressureValuator:
- m_pen.setWidthF(event->pressure() * 10 + 1);
+ m_pen.setWidthF(pressureToWidth(event->pressure()));
break;
case TiltValuator:
m_pen.setWidthF(maximum(abs(vValue - 127), abs(hValue - 127)) / 12);
@@ -305,7 +317,7 @@ void TabletCanvas::updateCursor(const QTabletEvent *event)
QPainter painter(&img);
QTransform transform = painter.transform();
transform.translate(16, 16);
- transform.rotate(-event->rotation());
+ transform.rotate(event->rotation());
painter.setTransform(transform);
painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
painter.drawImage(-24, -24, origImg);
diff --git a/examples/widgets/widgets/tablet/tabletcanvas.h b/examples/widgets/widgets/tablet/tabletcanvas.h
index 1784e05916..a1b31c65bf 100644
--- a/examples/widgets/widgets/tablet/tabletcanvas.h
+++ b/examples/widgets/widgets/tablet/tabletcanvas.h
@@ -103,6 +103,7 @@ private:
void initPixmap();
void paintPixmap(QPainter &painter, QTabletEvent *event);
Qt::BrushStyle brushPattern(qreal value);
+ qreal pressureToWidth(qreal pressure);
void updateBrush(const QTabletEvent *event);
void updateCursor(const QTabletEvent *event);
@@ -117,6 +118,7 @@ private:
struct Point {
QPointF pos;
+ qreal pressure;
qreal rotation;
} lastPoint;
};
diff --git a/examples/xml/dombookmarks/mainwindow.cpp b/examples/xml/dombookmarks/mainwindow.cpp
index e0f208d336..fade2dfc96 100644
--- a/examples/xml/dombookmarks/mainwindow.cpp
+++ b/examples/xml/dombookmarks/mainwindow.cpp
@@ -58,13 +58,13 @@ MainWindow::MainWindow()
xbelTree = new XbelTree;
setCentralWidget(xbelTree);
- createActions();
createMenus();
statusBar()->showMessage(tr("Ready"));
setWindowTitle(tr("DOM Bookmarks"));
- resize(480, 320);
+ const QSize availableSize = QApplication::desktop()->availableGeometry(this).size();
+ resize(availableSize.width() / 2, availableSize.height() / 3);
}
void MainWindow::open()
@@ -80,8 +80,8 @@ void MainWindow::open()
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot read file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -102,8 +102,8 @@ void MainWindow::saveAs()
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot write file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -119,37 +119,21 @@ void MainWindow::about()
"documents."));
}
-void MainWindow::createActions()
+void MainWindow::createMenus()
{
- openAct = new QAction(tr("&Open..."), this);
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open);
openAct->setShortcuts(QKeySequence::Open);
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
- saveAsAct = new QAction(tr("&Save As..."), this);
+ QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
- connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
- exitAct = new QAction(tr("E&xit"), this);
+ QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
-
- aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
-
- aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
-}
-
-void MainWindow::createMenus()
-{
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(openAct);
- fileMenu->addAction(saveAsAct);
- fileMenu->addAction(exitAct);
menuBar()->addSeparator();
- helpMenu = menuBar()->addMenu(tr("&Help"));
- helpMenu->addAction(aboutAct);
- helpMenu->addAction(aboutQtAct);
+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
}
diff --git a/examples/xml/dombookmarks/mainwindow.h b/examples/xml/dombookmarks/mainwindow.h
index 6d490caf64..0a8c7bdd82 100644
--- a/examples/xml/dombookmarks/mainwindow.h
+++ b/examples/xml/dombookmarks/mainwindow.h
@@ -68,18 +68,9 @@ public slots:
void about();
private:
- void createActions();
void createMenus();
XbelTree *xbelTree;
-
- QMenu *fileMenu;
- QMenu *helpMenu;
- QAction *openAct;
- QAction *saveAsAct;
- QAction *exitAct;
- QAction *aboutAct;
- QAction *aboutQtAct;
};
#endif
diff --git a/examples/xml/dombookmarks/xbeltree.cpp b/examples/xml/dombookmarks/xbeltree.cpp
index 82afc48bd9..f7ff1de638 100644
--- a/examples/xml/dombookmarks/xbeltree.cpp
+++ b/examples/xml/dombookmarks/xbeltree.cpp
@@ -52,6 +52,18 @@
#include "xbeltree.h"
+enum { DomElementRole = Qt::UserRole + 1 };
+
+Q_DECLARE_METATYPE(QDomElement)
+
+static inline QString titleElement() { return QStringLiteral("title"); }
+static inline QString folderElement() { return QStringLiteral("folder"); }
+static inline QString bookmarkElement() { return QStringLiteral("bookmark"); }
+
+static inline QString versionAttribute() { return QStringLiteral("version"); }
+static inline QString hrefAttribute() { return QStringLiteral("href"); }
+static inline QString foldedAttribute() { return QStringLiteral("folded"); }
+
XbelTree::XbelTree(QWidget *parent)
: QTreeWidget(parent)
{
@@ -68,6 +80,24 @@ XbelTree::XbelTree(QWidget *parent)
bookmarkIcon.addPixmap(style()->standardPixmap(QStyle::SP_FileIcon));
}
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+void XbelTree::contextMenuEvent(QContextMenuEvent *event)
+{
+ const QTreeWidgetItem *item = itemAt(event->pos());
+ if (!item)
+ return;
+ const QString url = item->text(1);
+ QMenu contextMenu;
+ QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard"));
+ QAction *openAction = contextMenu.addAction(tr("Open"));
+ QAction *action = contextMenu.exec(event->globalPos());
+ if (action == copyAction)
+ QGuiApplication::clipboard()->setText(url);
+ else if (action == openAction)
+ QDesktopServices::openUrl(QUrl(url));
+}
+#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD
+
bool XbelTree::read(QIODevice *device)
{
QString errorStr;
@@ -89,8 +119,8 @@ bool XbelTree::read(QIODevice *device)
QMessageBox::information(window(), tr("DOM Bookmarks"),
tr("The file is not an XBEL file."));
return false;
- } else if (root.hasAttribute("version")
- && root.attribute("version") != "1.0") {
+ } else if (root.hasAttribute(versionAttribute())
+ && root.attribute(versionAttribute()) != QLatin1String("1.0")) {
QMessageBox::information(window(), tr("DOM Bookmarks"),
tr("The file is not an XBEL version 1.0 "
"file."));
@@ -99,22 +129,20 @@ bool XbelTree::read(QIODevice *device)
clear();
- disconnect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
- this, SLOT(updateDomElement(QTreeWidgetItem*,int)));
+ disconnect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement);
- QDomElement child = root.firstChildElement("folder");
+ QDomElement child = root.firstChildElement(folderElement());
while (!child.isNull()) {
parseFolderElement(child);
- child = child.nextSiblingElement("folder");
+ child = child.nextSiblingElement(folderElement());
}
- connect(this, SIGNAL(itemChanged(QTreeWidgetItem*,int)),
- this, SLOT(updateDomElement(QTreeWidgetItem*,int)));
+ connect(this, &QTreeWidget::itemChanged, this, &XbelTree::updateDomElement);
return true;
}
-bool XbelTree::write(QIODevice *device)
+bool XbelTree::write(QIODevice *device) const
{
const int IndentSize = 4;
@@ -123,21 +151,21 @@ bool XbelTree::write(QIODevice *device)
return true;
}
-void XbelTree::updateDomElement(QTreeWidgetItem *item, int column)
+void XbelTree::updateDomElement(const QTreeWidgetItem *item, int column)
{
- QDomElement element = domElementForItem.value(item);
+ QDomElement element = item->data(0, DomElementRole).value<QDomElement>();
if (!element.isNull()) {
if (column == 0) {
- QDomElement oldTitleElement = element.firstChildElement("title");
- QDomElement newTitleElement = domDocument.createElement("title");
+ QDomElement oldTitleElement = element.firstChildElement(titleElement());
+ QDomElement newTitleElement = domDocument.createElement(titleElement());
QDomText newTitleText = domDocument.createTextNode(item->text(0));
newTitleElement.appendChild(newTitleText);
element.replaceChild(newTitleElement, oldTitleElement);
} else {
- if (element.tagName() == "bookmark")
- element.setAttribute("href", item->text(1));
+ if (element.tagName() == bookmarkElement())
+ element.setAttribute(hrefAttribute(), item->text(1));
}
}
}
@@ -147,7 +175,7 @@ void XbelTree::parseFolderElement(const QDomElement &element,
{
QTreeWidgetItem *item = createItem(element, parentItem);
- QString title = element.firstChildElement("title").text();
+ QString title = element.firstChildElement(titleElement()).text();
if (title.isEmpty())
title = QObject::tr("Folder");
@@ -155,25 +183,25 @@ void XbelTree::parseFolderElement(const QDomElement &element,
item->setIcon(0, folderIcon);
item->setText(0, title);
- bool folded = (element.attribute("folded") != "no");
+ bool folded = (element.attribute(foldedAttribute()) != QLatin1String("no"));
setItemExpanded(item, !folded);
QDomElement child = element.firstChildElement();
while (!child.isNull()) {
- if (child.tagName() == "folder") {
+ if (child.tagName() == folderElement()) {
parseFolderElement(child, item);
- } else if (child.tagName() == "bookmark") {
+ } else if (child.tagName() == bookmarkElement()) {
QTreeWidgetItem *childItem = createItem(child, item);
- QString title = child.firstChildElement("title").text();
+ QString title = child.firstChildElement(titleElement()).text();
if (title.isEmpty())
title = QObject::tr("Folder");
childItem->setFlags(item->flags() | Qt::ItemIsEditable);
childItem->setIcon(0, bookmarkIcon);
childItem->setText(0, title);
- childItem->setText(1, child.attribute("href"));
- } else if (child.tagName() == "separator") {
+ childItem->setText(1, child.attribute(hrefAttribute()));
+ } else if (child.tagName() == QLatin1String("separator")) {
QTreeWidgetItem *childItem = createItem(child, item);
childItem->setFlags(item->flags() & ~(Qt::ItemIsSelectable | Qt::ItemIsEditable));
childItem->setText(0, QString(30, 0xB7));
@@ -191,6 +219,6 @@ QTreeWidgetItem *XbelTree::createItem(const QDomElement &element,
} else {
item = new QTreeWidgetItem(this);
}
- domElementForItem.insert(item, element);
+ item->setData(0, DomElementRole, QVariant::fromValue(element));
return item;
}
diff --git a/examples/xml/dombookmarks/xbeltree.h b/examples/xml/dombookmarks/xbeltree.h
index bf4b55ea74..f6c7ef8bfe 100644
--- a/examples/xml/dombookmarks/xbeltree.h
+++ b/examples/xml/dombookmarks/xbeltree.h
@@ -52,7 +52,6 @@
#define XBELTREE_H
#include <QDomDocument>
-#include <QHash>
#include <QIcon>
#include <QTreeWidget>
@@ -64,10 +63,15 @@ public:
XbelTree(QWidget *parent = 0);
bool read(QIODevice *device);
- bool write(QIODevice *device);
+ bool write(QIODevice *device) const;
+
+protected:
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ void contextMenuEvent(QContextMenuEvent *event) Q_DECL_OVERRIDE;
+#endif
private slots:
- void updateDomElement(QTreeWidgetItem *item, int column);
+ void updateDomElement(const QTreeWidgetItem *item, int column);
private:
void parseFolderElement(const QDomElement &element,
@@ -76,7 +80,6 @@ private:
QTreeWidgetItem *parentItem = 0);
QDomDocument domDocument;
- QHash<QTreeWidgetItem *, QDomElement> domElementForItem;
QIcon folderIcon;
QIcon bookmarkIcon;
};
diff --git a/examples/xml/saxbookmarks/mainwindow.cpp b/examples/xml/saxbookmarks/mainwindow.cpp
index 2ce2b9a508..0583cd82cf 100644
--- a/examples/xml/saxbookmarks/mainwindow.cpp
+++ b/examples/xml/saxbookmarks/mainwindow.cpp
@@ -62,17 +62,40 @@ MainWindow::MainWindow()
treeWidget = new QTreeWidget;
treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch);
treeWidget->setHeaderLabels(labels);
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(treeWidget, &QWidget::customContextMenuRequested,
+ this, &MainWindow::onCustomContextMenuRequested);
+#endif
setCentralWidget(treeWidget);
- createActions();
createMenus();
statusBar()->showMessage(tr("Ready"));
setWindowTitle(tr("SAX Bookmarks"));
- resize(480, 320);
+ const QSize availableSize = QApplication::desktop()->availableGeometry(this).size();
+ resize(availableSize.width() / 2, availableSize.height() / 3);
}
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+void MainWindow::onCustomContextMenuRequested(const QPoint &pos)
+{
+ const QTreeWidgetItem *item = treeWidget->itemAt(pos);
+ if (!item)
+ return;
+ const QString url = item->text(1);
+ QMenu contextMenu;
+ QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard"));
+ QAction *openAction = contextMenu.addAction(tr("Open"));
+ QAction *action = contextMenu.exec(treeWidget->viewport()->mapToGlobal(pos));
+ if (action == copyAction)
+ QGuiApplication::clipboard()->setText(url);
+ else if (action == openAction)
+ QDesktopServices::openUrl(QUrl(url));
+}
+#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD
+
void MainWindow::open()
{
QString fileName =
@@ -93,8 +116,8 @@ void MainWindow::open()
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot read file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -116,8 +139,8 @@ void MainWindow::saveAs()
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("SAX Bookmarks"),
tr("Cannot write file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -134,37 +157,21 @@ void MainWindow::about()
"hand."));
}
-void MainWindow::createActions()
+void MainWindow::createMenus()
{
- openAct = new QAction(tr("&Open..."), this);
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open);
openAct->setShortcuts(QKeySequence::Open);
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
- saveAsAct = new QAction(tr("&Save As..."), this);
+ QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
- connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
- exitAct = new QAction(tr("E&xit"), this);
+ QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
-
- aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
-
- aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
-}
-
-void MainWindow::createMenus()
-{
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(openAct);
- fileMenu->addAction(saveAsAct);
- fileMenu->addAction(exitAct);
menuBar()->addSeparator();
- helpMenu = menuBar()->addMenu(tr("&Help"));
- helpMenu->addAction(aboutAct);
- helpMenu->addAction(aboutQtAct);
+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
}
diff --git a/examples/xml/saxbookmarks/mainwindow.h b/examples/xml/saxbookmarks/mainwindow.h
index 828a0ed14e..20a11bb202 100644
--- a/examples/xml/saxbookmarks/mainwindow.h
+++ b/examples/xml/saxbookmarks/mainwindow.h
@@ -68,20 +68,13 @@ public slots:
void open();
void saveAs();
void about();
-
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ void onCustomContextMenuRequested(const QPoint &pos);
+#endif
private:
- void createActions();
void createMenus();
QTreeWidget *treeWidget;
-
- QMenu *fileMenu;
- QMenu *helpMenu;
- QAction *openAct;
- QAction *saveAsAct;
- QAction *exitAct;
- QAction *aboutAct;
- QAction *aboutQtAct;
};
#endif
diff --git a/examples/xml/saxbookmarks/xbelgenerator.cpp b/examples/xml/saxbookmarks/xbelgenerator.cpp
index 30ce1428e6..ee6f113f9c 100644
--- a/examples/xml/saxbookmarks/xbelgenerator.cpp
+++ b/examples/xml/saxbookmarks/xbelgenerator.cpp
@@ -52,7 +52,7 @@
#include "xbelgenerator.h"
-XbelGenerator::XbelGenerator(QTreeWidget *treeWidget)
+XbelGenerator::XbelGenerator(const QTreeWidget *treeWidget)
: treeWidget(treeWidget)
{
}
@@ -81,25 +81,25 @@ QString XbelGenerator::indent(int depth)
QString XbelGenerator::escapedText(const QString &str)
{
QString result = str;
- result.replace("&", "&amp;");
- result.replace("<", "&lt;");
- result.replace(">", "&gt;");
+ result.replace('&', "&amp;");
+ result.replace('<', "&lt;");
+ result.replace('>', "&gt;");
return result;
}
QString XbelGenerator::escapedAttribute(const QString &str)
{
QString result = escapedText(str);
- result.replace("\"", "&quot;");
+ result.replace(QLatin1Char('"'), "&quot;");
result.prepend(QLatin1Char('"'));
result.append(QLatin1Char('"'));
return result;
}
-void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth)
+void XbelGenerator::generateItem(const QTreeWidgetItem *item, int depth)
{
QString tagName = item->data(0, Qt::UserRole).toString();
- if (tagName == "folder") {
+ if (tagName == QLatin1String("folder")) {
bool folded = !treeWidget->isItemExpanded(item);
out << indent(depth) << "<folder folded=\"" << (folded ? "yes" : "no")
<< "\">\n"
@@ -110,7 +110,7 @@ void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth)
generateItem(item->child(i), depth + 1);
out << indent(depth) << "</folder>\n";
- } else if (tagName == "bookmark") {
+ } else if (tagName == QLatin1String("bookmark")) {
out << indent(depth) << "<bookmark";
if (!item->text(1).isEmpty())
out << " href=" << escapedAttribute(item->text(1));
@@ -118,7 +118,7 @@ void XbelGenerator::generateItem(QTreeWidgetItem *item, int depth)
<< indent(depth + 1) << "<title>" << escapedText(item->text(0))
<< "</title>\n"
<< indent(depth) << "</bookmark>\n";
- } else if (tagName == "separator") {
+ } else if (tagName == QLatin1String("separator")) {
out << indent(depth) << "<separator/>\n";
}
}
diff --git a/examples/xml/saxbookmarks/xbelgenerator.h b/examples/xml/saxbookmarks/xbelgenerator.h
index 44069599e2..abfabfd75c 100644
--- a/examples/xml/saxbookmarks/xbelgenerator.h
+++ b/examples/xml/saxbookmarks/xbelgenerator.h
@@ -61,7 +61,7 @@ QT_END_NAMESPACE
class XbelGenerator
{
public:
- XbelGenerator(QTreeWidget *treeWidget);
+ explicit XbelGenerator(const QTreeWidget *treeWidget);
bool write(QIODevice *device);
@@ -69,9 +69,9 @@ private:
static QString indent(int indentLevel);
static QString escapedText(const QString &str);
static QString escapedAttribute(const QString &str);
- void generateItem(QTreeWidgetItem *item, int depth);
+ void generateItem(const QTreeWidgetItem *item, int depth);
- QTreeWidget *treeWidget;
+ const QTreeWidget *treeWidget;
QTextStream out;
};
diff --git a/examples/xml/saxbookmarks/xbelhandler.cpp b/examples/xml/saxbookmarks/xbelhandler.cpp
index 03b16c81f1..7e2a9db3c2 100644
--- a/examples/xml/saxbookmarks/xbelhandler.cpp
+++ b/examples/xml/saxbookmarks/xbelhandler.cpp
@@ -52,6 +52,10 @@
#include "xbelhandler.h"
+static inline QString versionAttribute() { return QStringLiteral("version"); }
+static inline QString hrefAttribute() { return QStringLiteral("href"); }
+static inline QString foldedAttribute() { return QStringLiteral("folded"); }
+
XbelHandler::XbelHandler(QTreeWidget *treeWidget)
: treeWidget(treeWidget)
{
@@ -72,32 +76,32 @@ bool XbelHandler::startElement(const QString & /* namespaceURI */,
const QString &qName,
const QXmlAttributes &attributes)
{
- if (!metXbelTag && qName != "xbel") {
+ if (!metXbelTag && qName != QLatin1String("xbel")) {
errorStr = QObject::tr("The file is not an XBEL file.");
return false;
}
- if (qName == "xbel") {
- QString version = attributes.value("version");
- if (!version.isEmpty() && version != "1.0") {
+ if (qName == QLatin1String("xbel")) {
+ QString version = attributes.value(versionAttribute());
+ if (!version.isEmpty() && version != QLatin1String("1.0")) {
errorStr = QObject::tr("The file is not an XBEL version 1.0 file.");
return false;
}
metXbelTag = true;
- } else if (qName == "folder") {
+ } else if (qName == QLatin1String("folder")) {
item = createChildItem(qName);
item->setFlags(item->flags() | Qt::ItemIsEditable);
item->setIcon(0, folderIcon);
item->setText(0, QObject::tr("Folder"));
- bool folded = (attributes.value("folded") != "no");
+ bool folded = (attributes.value(foldedAttribute()) != QLatin1String("no"));
treeWidget->setItemExpanded(item, !folded);
- } else if (qName == "bookmark") {
+ } else if (qName == QLatin1String("bookmark")) {
item = createChildItem(qName);
item->setFlags(item->flags() | Qt::ItemIsEditable);
item->setIcon(0, bookmarkIcon);
item->setText(0, QObject::tr("Unknown title"));
- item->setText(1, attributes.value("href"));
- } else if (qName == "separator") {
+ item->setText(1, attributes.value(hrefAttribute()));
+ } else if (qName == QLatin1String("separator")) {
item = createChildItem(qName);
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
item->setText(0, QString(30, 0xB7));
@@ -111,11 +115,11 @@ bool XbelHandler::endElement(const QString & /* namespaceURI */,
const QString & /* localName */,
const QString &qName)
{
- if (qName == "title") {
+ if (qName == QLatin1String("title")) {
if (item)
item->setText(0, currentText);
- } else if (qName == "folder" || qName == "bookmark"
- || qName == "separator") {
+ } else if (qName == QLatin1String("folder") || qName == QLatin1String("bookmark")
+ || qName == QLatin1String("separator")) {
item = item->parent();
}
return true;
diff --git a/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc b/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc
index 0720e3eadd..ad093c2098 100644
--- a/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc
+++ b/examples/xml/streambookmarks/doc/src/qxmlstreambookmarks.qdoc
@@ -167,7 +167,7 @@
add them to the \c fileMenu and \c helpMenu. The connections are as shown
below:
- \snippet streambookmarks/mainwindow.cpp 4
+ \snippet streambookmarks/mainwindow.cpp 5
The \c createMenus() function creates the \c fileMenu and \c helpMenu
and adds the QAction objects to them in order to create the menu shown
diff --git a/examples/xml/streambookmarks/mainwindow.cpp b/examples/xml/streambookmarks/mainwindow.cpp
index 7c0fd8720d..c9a18fa3c4 100644
--- a/examples/xml/streambookmarks/mainwindow.cpp
+++ b/examples/xml/streambookmarks/mainwindow.cpp
@@ -63,18 +63,41 @@ MainWindow::MainWindow()
treeWidget = new QTreeWidget;
treeWidget->header()->setSectionResizeMode(QHeaderView::Stretch);
treeWidget->setHeaderLabels(labels);
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
+ connect(treeWidget, &QWidget::customContextMenuRequested,
+ this, &MainWindow::onCustomContextMenuRequested);
+#endif
setCentralWidget(treeWidget);
- createActions();
createMenus();
statusBar()->showMessage(tr("Ready"));
setWindowTitle(tr("QXmlStream Bookmarks"));
- resize(480, 320);
+ const QSize availableSize = QApplication::desktop()->availableGeometry(this).size();
+ resize(availableSize.width() / 2, availableSize.height() / 3);
}
//! [0]
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+void MainWindow::onCustomContextMenuRequested(const QPoint &pos)
+{
+ const QTreeWidgetItem *item = treeWidget->itemAt(pos);
+ if (!item)
+ return;
+ const QString url = item->text(1);
+ QMenu contextMenu;
+ QAction *copyAction = contextMenu.addAction(tr("Copy Link to Clipboard"));
+ QAction *openAction = contextMenu.addAction(tr("Open"));
+ QAction *action = contextMenu.exec(treeWidget->viewport()->mapToGlobal(pos));
+ if (action == copyAction)
+ QGuiApplication::clipboard()->setText(url);
+ else if (action == openAction)
+ QDesktopServices::openUrl(QUrl(url));
+}
+#endif // !QT_NO_CONTEXTMENU && !QT_NO_CLIPBOARD
+
//! [1]
void MainWindow::open()
{
@@ -92,8 +115,8 @@ void MainWindow::open()
if (!file.open(QFile::ReadOnly | QFile::Text)) {
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
tr("Cannot read file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -101,8 +124,8 @@ void MainWindow::open()
if (!reader.read(&file)) {
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
tr("Parse error in file %1:\n\n%2")
- .arg(fileName)
- .arg(reader.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ reader.errorString()));
} else {
statusBar()->showMessage(tr("File loaded"), 2000);
}
@@ -124,8 +147,8 @@ void MainWindow::saveAs()
if (!file.open(QFile::WriteOnly | QFile::Text)) {
QMessageBox::warning(this, tr("QXmlStream Bookmarks"),
tr("Cannot write file %1:\n%2.")
- .arg(fileName)
- .arg(file.errorString()));
+ .arg(QDir::toNativeSeparators(fileName),
+ file.errorString()));
return;
}
@@ -144,41 +167,23 @@ void MainWindow::about()
}
//! [3]
-//! [4]
-void MainWindow::createActions()
+//! [5]
+void MainWindow::createMenus()
{
- openAct = new QAction(tr("&Open..."), this);
+ QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
+ QAction *openAct = fileMenu->addAction(tr("&Open..."), this, &MainWindow::open);
openAct->setShortcuts(QKeySequence::Open);
- connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
- saveAsAct = new QAction(tr("&Save As..."), this);
+ QAction *saveAsAct = fileMenu->addAction(tr("&Save As..."), this, &MainWindow::saveAs);
saveAsAct->setShortcuts(QKeySequence::SaveAs);
- connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
- exitAct = new QAction(tr("E&xit"), this);
+ QAction *exitAct = fileMenu->addAction(tr("E&xit"), this, &QWidget::close);
exitAct->setShortcuts(QKeySequence::Quit);
- connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
-
- aboutAct = new QAction(tr("&About"), this);
- connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
-
- aboutQtAct = new QAction(tr("About &Qt"), this);
- connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
-}
-//! [4]
-
-//! [5]
-void MainWindow::createMenus()
-{
- fileMenu = menuBar()->addMenu(tr("&File"));
- fileMenu->addAction(openAct);
- fileMenu->addAction(saveAsAct);
- fileMenu->addAction(exitAct);
menuBar()->addSeparator();
- helpMenu = menuBar()->addMenu(tr("&Help"));
- helpMenu->addAction(aboutAct);
- helpMenu->addAction(aboutQtAct);
+ QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
+ helpMenu->addAction(tr("&About"), this, &MainWindow::about);
+ helpMenu->addAction(tr("About &Qt"), qApp, &QCoreApplication::quit);
}
//! [5]
diff --git a/examples/xml/streambookmarks/mainwindow.h b/examples/xml/streambookmarks/mainwindow.h
index 2b6feeb26f..fbdc1e0c62 100644
--- a/examples/xml/streambookmarks/mainwindow.h
+++ b/examples/xml/streambookmarks/mainwindow.h
@@ -69,20 +69,13 @@ public slots:
void open();
void saveAs();
void about();
-
+#if !defined(QT_NO_CONTEXTMENU) && !defined(QT_NO_CLIPBOARD)
+ void onCustomContextMenuRequested(const QPoint &pos);
+#endif
private:
- void createActions();
void createMenus();
QTreeWidget *treeWidget;
-
- QMenu *fileMenu;
- QMenu *helpMenu;
- QAction *openAct;
- QAction *saveAsAct;
- QAction *exitAct;
- QAction *aboutAct;
- QAction *aboutQtAct;
};
//! [0]
diff --git a/examples/xml/streambookmarks/xbelreader.cpp b/examples/xml/streambookmarks/xbelreader.cpp
index 53d6b94ba0..099985d91e 100644
--- a/examples/xml/streambookmarks/xbelreader.cpp
+++ b/examples/xml/streambookmarks/xbelreader.cpp
@@ -72,10 +72,12 @@ bool XbelReader::read(QIODevice *device)
xml.setDevice(device);
if (xml.readNextStartElement()) {
- if (xml.name() == "xbel" && xml.attributes().value("version") == "1.0")
+ if (xml.name() == QLatin1String("xbel")
+ && xml.attributes().value(versionAttribute()) == QLatin1String("1.0")) {
readXBEL();
- else
+ } else {
xml.raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));
+ }
}
return !xml.error();
@@ -95,14 +97,14 @@ QString XbelReader::errorString() const
//! [3]
void XbelReader::readXBEL()
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "xbel");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("xbel"));
while (xml.readNextStartElement()) {
- if (xml.name() == "folder")
+ if (xml.name() == QLatin1String("folder"))
readFolder(0);
- else if (xml.name() == "bookmark")
+ else if (xml.name() == QLatin1String("bookmark"))
readBookmark(0);
- else if (xml.name() == "separator")
+ else if (xml.name() == QLatin1String("separator"))
readSeparator(0);
else
xml.skipCurrentElement();
@@ -113,7 +115,7 @@ void XbelReader::readXBEL()
//! [4]
void XbelReader::readTitle(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "title");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("title"));
QString title = xml.readElementText();
item->setText(0, title);
@@ -123,7 +125,7 @@ void XbelReader::readTitle(QTreeWidgetItem *item)
//! [5]
void XbelReader::readSeparator(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "separator");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("separator"));
QTreeWidgetItem *separator = createChildItem(item);
separator->setFlags(item->flags() & ~Qt::ItemIsSelectable);
@@ -134,20 +136,20 @@ void XbelReader::readSeparator(QTreeWidgetItem *item)
void XbelReader::readFolder(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "folder");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("folder"));
QTreeWidgetItem *folder = createChildItem(item);
- bool folded = (xml.attributes().value("folded") != "no");
+ bool folded = (xml.attributes().value(foldedAttribute()) != QLatin1String("no"));
treeWidget->setItemExpanded(folder, !folded);
while (xml.readNextStartElement()) {
- if (xml.name() == "title")
+ if (xml.name() == QLatin1String("title"))
readTitle(folder);
- else if (xml.name() == "folder")
+ else if (xml.name() == QLatin1String("folder"))
readFolder(folder);
- else if (xml.name() == "bookmark")
+ else if (xml.name() == QLatin1String("bookmark"))
readBookmark(folder);
- else if (xml.name() == "separator")
+ else if (xml.name() == QLatin1String("separator"))
readSeparator(folder);
else
xml.skipCurrentElement();
@@ -156,16 +158,16 @@ void XbelReader::readFolder(QTreeWidgetItem *item)
void XbelReader::readBookmark(QTreeWidgetItem *item)
{
- Q_ASSERT(xml.isStartElement() && xml.name() == "bookmark");
+ Q_ASSERT(xml.isStartElement() && xml.name() == QLatin1String("bookmark"));
QTreeWidgetItem *bookmark = createChildItem(item);
bookmark->setFlags(bookmark->flags() | Qt::ItemIsEditable);
bookmark->setIcon(0, bookmarkIcon);
bookmark->setText(0, QObject::tr("Unknown title"));
- bookmark->setText(1, xml.attributes().value("href").toString());
+ bookmark->setText(1, xml.attributes().value(hrefAttribute()).toString());
while (xml.readNextStartElement()) {
- if (xml.name() == "title")
+ if (xml.name() == QLatin1String("title"))
readTitle(bookmark);
else
xml.skipCurrentElement();
diff --git a/examples/xml/streambookmarks/xbelreader.h b/examples/xml/streambookmarks/xbelreader.h
index 3175441ddd..fd486a430f 100644
--- a/examples/xml/streambookmarks/xbelreader.h
+++ b/examples/xml/streambookmarks/xbelreader.h
@@ -71,6 +71,10 @@ public:
QString errorString() const;
+ static inline QString versionAttribute() { return QStringLiteral("version"); }
+ static inline QString hrefAttribute() { return QStringLiteral("href"); }
+ static inline QString foldedAttribute() { return QStringLiteral("folded"); }
+
private:
//! [2]
void readXBEL();
diff --git a/examples/xml/streambookmarks/xbelwriter.cpp b/examples/xml/streambookmarks/xbelwriter.cpp
index fdf2e1095e..2959680678 100644
--- a/examples/xml/streambookmarks/xbelwriter.cpp
+++ b/examples/xml/streambookmarks/xbelwriter.cpp
@@ -51,9 +51,14 @@
#include <QtWidgets>
#include "xbelwriter.h"
+#include "xbelreader.h"
+
+static inline QString yesValue() { return QStringLiteral("yes"); }
+static inline QString noValue() { return QStringLiteral("no"); }
+static inline QString titleElement() { return QStringLiteral("title"); }
//! [0]
-XbelWriter::XbelWriter(QTreeWidget *treeWidget)
+XbelWriter::XbelWriter(const QTreeWidget *treeWidget)
: treeWidget(treeWidget)
{
xml.setAutoFormatting(true);
@@ -66,9 +71,9 @@ bool XbelWriter::writeFile(QIODevice *device)
xml.setDevice(device);
xml.writeStartDocument();
- xml.writeDTD("<!DOCTYPE xbel>");
- xml.writeStartElement("xbel");
- xml.writeAttribute("version", "1.0");
+ xml.writeDTD(QStringLiteral("<!DOCTYPE xbel>"));
+ xml.writeStartElement(QStringLiteral("xbel"));
+ xml.writeAttribute(XbelReader::versionAttribute(), QStringLiteral("1.0"));
for (int i = 0; i < treeWidget->topLevelItemCount(); ++i)
writeItem(treeWidget->topLevelItem(i));
@@ -78,24 +83,24 @@ bool XbelWriter::writeFile(QIODevice *device)
//! [1]
//! [2]
-void XbelWriter::writeItem(QTreeWidgetItem *item)
+void XbelWriter::writeItem(const QTreeWidgetItem *item)
{
QString tagName = item->data(0, Qt::UserRole).toString();
- if (tagName == "folder") {
+ if (tagName == QLatin1String("folder")) {
bool folded = !treeWidget->isItemExpanded(item);
xml.writeStartElement(tagName);
- xml.writeAttribute("folded", folded ? "yes" : "no");
- xml.writeTextElement("title", item->text(0));
+ xml.writeAttribute(XbelReader::foldedAttribute(), folded ? yesValue() : noValue());
+ xml.writeTextElement(titleElement(), item->text(0));
for (int i = 0; i < item->childCount(); ++i)
writeItem(item->child(i));
xml.writeEndElement();
- } else if (tagName == "bookmark") {
+ } else if (tagName == QLatin1String("bookmark")) {
xml.writeStartElement(tagName);
if (!item->text(1).isEmpty())
- xml.writeAttribute("href", item->text(1));
- xml.writeTextElement("title", item->text(0));
+ xml.writeAttribute(XbelReader::hrefAttribute(), item->text(1));
+ xml.writeTextElement(titleElement(), item->text(0));
xml.writeEndElement();
- } else if (tagName == "separator") {
+ } else if (tagName == QLatin1String("separator")) {
xml.writeEmptyElement(tagName);
}
}
diff --git a/examples/xml/streambookmarks/xbelwriter.h b/examples/xml/streambookmarks/xbelwriter.h
index b15bf60e31..465d8f0dc4 100644
--- a/examples/xml/streambookmarks/xbelwriter.h
+++ b/examples/xml/streambookmarks/xbelwriter.h
@@ -62,13 +62,13 @@ QT_END_NAMESPACE
class XbelWriter
{
public:
- XbelWriter(QTreeWidget *treeWidget);
+ explicit XbelWriter(const QTreeWidget *treeWidget);
bool writeFile(QIODevice *device);
private:
- void writeItem(QTreeWidgetItem *item);
+ void writeItem(const QTreeWidgetItem *item);
QXmlStreamWriter xml;
- QTreeWidget *treeWidget;
+ const QTreeWidget *treeWidget;
};
//! [0]
diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf
index 6a2fa4f506..234f71d495 100644
--- a/mkspecs/common/gcc-base.conf
+++ b/mkspecs/common/gcc-base.conf
@@ -87,6 +87,7 @@ QMAKE_CFLAGS_SSSE3 += -mssse3
QMAKE_CFLAGS_SSE4_1 += -msse4.1
QMAKE_CFLAGS_SSE4_2 += -msse4.2
QMAKE_CFLAGS_F16C += -mf16c
+QMAKE_CFLAGS_RDRND += -mrdrnd
QMAKE_CFLAGS_AVX += -mavx
QMAKE_CFLAGS_AVX2 += -mavx2
QMAKE_CFLAGS_AVX512F += -mavx512f
@@ -98,6 +99,8 @@ QMAKE_CFLAGS_AVX512BW += -mavx512bw
QMAKE_CFLAGS_AVX512VL += -mavx512vl
QMAKE_CFLAGS_AVX512IFMA += -mavx512ifma
QMAKE_CFLAGS_AVX512VBMI += -mavx512vbmi
+QMAKE_CFLAGS_AESNI += -maes
+QMAKE_CFLAGS_SHANI += -msha
QMAKE_CFLAGS_NEON += -mfpu=neon
QMAKE_CFLAGS_MIPS_DSP += -mdsp
QMAKE_CFLAGS_MIPS_DSPR2 += -mdspr2
diff --git a/mkspecs/common/linux.conf b/mkspecs/common/linux.conf
index 13916a5646..5e2b5b59eb 100644
--- a/mkspecs/common/linux.conf
+++ b/mkspecs/common/linux.conf
@@ -35,6 +35,7 @@ QMAKE_LIBS_OPENGL = -lGL
QMAKE_LIBS_OPENGL_ES2 = -lGLESv2
QMAKE_LIBS_OPENVG = -lOpenVG
QMAKE_LIBS_THREAD = -lpthread
+QMAKE_LIBS_VULKAN =
QMAKE_INCDIR_WAYLAND =
QMAKE_LIBS_WAYLAND_CLIENT = -lwayland-client
diff --git a/mkspecs/common/msvc-desktop.conf b/mkspecs/common/msvc-desktop.conf
index f538acfcd9..bb10113fe7 100644
--- a/mkspecs/common/msvc-desktop.conf
+++ b/mkspecs/common/msvc-desktop.conf
@@ -47,6 +47,8 @@ QMAKE_CFLAGS_SSE3 = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_SSSE3 = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_SSE4_1 = $$QMAKE_CFLAGS_SSE2
QMAKE_CFLAGS_SSE4_2 = $$QMAKE_CFLAGS_SSE2
+QMAKE_CFLAGS_AESNI = $$QMAKE_CFLAGS_SSE2
+QMAKE_CFLAGS_SHANI = $$QMAKE_CFLAGS_SSE2
QMAKE_CXX = $$QMAKE_CC
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
@@ -107,3 +109,4 @@ VCSOLUTION_EXTENSION = .sln
VCPROJ_KEYWORD = Qt4VSv1.0
include(angle.conf)
+include(windows-vulkan.conf)
diff --git a/mkspecs/common/msvc-version.conf b/mkspecs/common/msvc-version.conf
index d8ec089f55..c2e22f455a 100644
--- a/mkspecs/common/msvc-version.conf
+++ b/mkspecs/common/msvc-version.conf
@@ -50,6 +50,7 @@ greaterThan(QMAKE_MSC_VER, 1799) {
QMAKE_CXXFLAGS += -FS -Zc:rvalueCast -Zc:inline
QMAKE_CFLAGS_F16C = -arch:AVX
+ QMAKE_CFLAGS_RDRND =
equals(QMAKE_MSC_VER, 1800) {
QMAKE_CFLAGS_RELEASE += -Zc:strictStrings
diff --git a/mkspecs/common/qcc-base.conf b/mkspecs/common/qcc-base.conf
index b48e84ee1d..24ee29b6b8 100644
--- a/mkspecs/common/qcc-base.conf
+++ b/mkspecs/common/qcc-base.conf
@@ -33,6 +33,8 @@ QMAKE_CFLAGS_SSE4_1 += -msse4.1
QMAKE_CFLAGS_SSE4_2 += -msse4.2
QMAKE_CFLAGS_AVX += -mavx
QMAKE_CFLAGS_AVX2 += -mavx2
+QMAKE_CFLAGS_AESNI += -maes
+QMAKE_CFLAGS_SHANI += -msha
QMAKE_CFLAGS_STACK_PROTECTOR_STRONG = -fstack-protector-strong
diff --git a/mkspecs/common/windows-vulkan.conf b/mkspecs/common/windows-vulkan.conf
new file mode 100644
index 0000000000..5f930c7910
--- /dev/null
+++ b/mkspecs/common/windows-vulkan.conf
@@ -0,0 +1,5 @@
+# Pick up the VULKAN_SDK env var set by the LunarG SDK so that the Vulkan
+# headers are found out-of-the-box on typical Windows setups.
+
+QMAKE_INCDIR_VULKAN = $$(VULKAN_SDK)\\include
+QMAKE_LIBS_VULKAN =
diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf
index 8e0aba7371..c440d53867 100644
--- a/mkspecs/common/winrt_winphone/qmake.conf
+++ b/mkspecs/common/winrt_winphone/qmake.conf
@@ -34,6 +34,8 @@ QMAKE_CFLAGS_SSE4_1 = -arch:SSE2
QMAKE_CFLAGS_SSE4_2 = -arch:SSE2
QMAKE_CFLAGS_AVX = -arch:AVX
QMAKE_CFLAGS_AVX2 = -arch:AVX
+QMAKE_CFLAGS_AESNI = -arch:SSE2
+QMAKE_CFLAGS_SHANI = -arch:SSE2
QMAKE_CXX = $$QMAKE_CC
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
diff --git a/mkspecs/devices/linux-rasp-pi-g++/qmake.conf b/mkspecs/devices/linux-rasp-pi-g++/qmake.conf
index 5497b0ce1b..b72091373d 100644
--- a/mkspecs/devices/linux-rasp-pi-g++/qmake.conf
+++ b/mkspecs/devices/linux-rasp-pi-g++/qmake.conf
@@ -1,5 +1,6 @@
-#
-# qmake configuration for Broadcom's Raspberry PI
+# qmake configuration for:
+# - Raspberry PI
+# - Raspberry PI Zero
# http://wiki.qt.io/RaspberryPi
include(../common/linux_device_pre.conf)
diff --git a/mkspecs/devices/linux-tinkerboard-g++/qmake.conf b/mkspecs/devices/linux-tinkerboard-g++/qmake.conf
new file mode 100644
index 0000000000..15874847de
--- /dev/null
+++ b/mkspecs/devices/linux-tinkerboard-g++/qmake.conf
@@ -0,0 +1,20 @@
+#
+# qmake configuration for the Asus Tinkerboard (Rockchip RK3288, Cortex-A17, Mali-T764)
+#
+# This configuration targets eglfs via DRM/KMS and Wayland.
+
+include(../common/linux_device_pre.conf)
+
+QMAKE_LIBS_EGL += -lEGL
+QMAKE_LIBS_OPENGL_ES2 += -lGLESv2 -lEGL
+QMAKE_LIBS_OPENVG += -lOpenVG -lEGL
+
+DISTRO_OPTS += hard-float
+COMPILER_FLAGS += -mtune=cortex-a17 -march=armv7-a -mfpu=neon-vfpv4
+
+# Preferred eglfs backend
+EGLFS_DEVICE_INTEGRATION = eglfs_kms
+
+include(../common/linux_arm_device_post.conf)
+
+load(qt_config)
diff --git a/mkspecs/devices/linux-tinkerboard-g++/qplatformdefs.h b/mkspecs/devices/linux-tinkerboard-g++/qplatformdefs.h
new file mode 100644
index 0000000000..e927f75015
--- /dev/null
+++ b/mkspecs/devices/linux-tinkerboard-g++/qplatformdefs.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../../linux-g++/qplatformdefs.h"
diff --git a/mkspecs/features/ctest_testcase_common.prf b/mkspecs/features/ctest_testcase_common.prf
index cdc5cca1d7..4c7e03f0f7 100644
--- a/mkspecs/features/ctest_testcase_common.prf
+++ b/mkspecs/features/ctest_testcase_common.prf
@@ -27,22 +27,8 @@ isEmpty(CTEST_VERSION) {
}
CMAKE_VERSION = $$last(CMAKE_VERSION)
-CMAKE_VERSION_MAJOR = $$section(CMAKE_VERSION, ., 0, 0)
-CMAKE_VERSION_MINOR = $$section(CMAKE_VERSION, ., 1, 1)
-CMAKE_VERSION_PATCH = $$section(CMAKE_VERSION, ., 2, 2)
-# CMake can report versions like 2.8.11-rc1, so strip off the rc part.
-CMAKE_VERSION_PATCH ~= s,-.*,,
-
-VERSION_OK =
-greaterThan(CMAKE_VERSION_MAJOR, 2) {
- VERSION_OK = 1
-} else:greaterThan(CMAKE_VERSION_MAJOR, 1):greaterThan(CMAKE_VERSION_MINOR, 8) {
- VERSION_OK = 1
-} else:greaterThan(CMAKE_VERSION_MAJOR, 1):greaterThan(CMAKE_VERSION_MINOR, 7):greaterThan(CMAKE_VERSION_PATCH, 2) {
- VERSION_OK = 1
-}
-isEmpty(VERSION_OK) {
+!versionAtLeast(CMAKE_VERSION, 2.8.3) {
message("cmake $$CMAKE_VERSION is too old for this test.")
return()
}
diff --git a/mkspecs/features/qmltestcase.prf b/mkspecs/features/qmltestcase.prf
index 335ba90009..4dfec50be8 100644
--- a/mkspecs/features/qmltestcase.prf
+++ b/mkspecs/features/qmltestcase.prf
@@ -1,13 +1,19 @@
-CONFIG += testcase
-
-QT += qml qmltest
-
-mac: CONFIG -= app_bundle
+!isEmpty(SOURCES) {
+ QT += qml qmltest
+ load(testcase)
+ CONFIG -= app_bundle
+ DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$_PRO_FILE_PWD_\\\"\"
+} else {
+ # Allow a project to run tests without a CPP stub
+ TEMPLATE = aux
+ QMAKE_EXTRA_TARGETS += check
+ qtPrepareTool(QMAKE_QMLTESTRUNNER, qmltestrunner)
+ check.commands = $$QMAKE_QMLTESTRUNNER
+}
# If the .pro file specified an IMPORTPATH, then add that to
# the command-line when the test is run.
!isEmpty(IMPORTPATH) {
- load(testcase)
for(import, IMPORTPATH): check.commands += -import \"$$import\"
}
-DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$_PRO_FILE_PWD_\\\"\"
+
diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf
index e66c24b027..65574d2635 100644
--- a/mkspecs/features/qt_common.prf
+++ b/mkspecs/features/qt_common.prf
@@ -55,9 +55,8 @@ host_build:cross_compile: return()
# -Wdate-time: warn if we use __DATE__ or __TIME__ (we want to be able to reproduce the exact same binary)
# -Wvla: use of variable-length arrays (an extension to C++)
clang {
- # Clang 3.5 introduced -Wdate-time
- # The conditional assumes we aren't compiling against Clang 2.x anymore
- greaterThan(QT_CLANG_MAJOR_VERSION, 3)|greaterThan(QT_CLANG_MINOR_VERSION, 4): \
+ clang_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
+ versionAtLeast(clang_ver, 3.5): \
QMAKE_CXXFLAGS_WARN_ON += -Wdate-time
} else: gcc:!intel_icc {
QMAKE_CXXFLAGS_WARN_ON += -Wvla
diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf
index 36f632e8ca..8a8c17f01b 100644
--- a/mkspecs/features/qt_module.prf
+++ b/mkspecs/features/qt_module.prf
@@ -195,7 +195,7 @@ sse2:!contains(QT_CPU_FEATURES.$$QT_ARCH, sse2):!host_build:!if(static:qtConfig(
clang {
apple_clang_ver = $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}
reg_clang_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
- !lessThan(apple_clang_ver, "5.1")|!lessThan(reg_clang_ver, "3.4"): \
+ versionAtLeast(apple_clang_ver, 5.1)|versionAtLeast(reg_clang_ver, 3.4): \
CONFIG += compiler_supports_fpmath
} else: gcc {
CONFIG += compiler_supports_fpmath
diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf
index 8837410b8d..6cc72bb5e3 100644
--- a/mkspecs/features/qt_module_headers.prf
+++ b/mkspecs/features/qt_module_headers.prf
@@ -121,18 +121,19 @@ exists($$OUT_PWD/qt$${MODULE}-config.h) {
for (injection, SYNCQT.INJECTIONS) {
injects = $$split(injection, :)
dst_hdr = $$absolute_path($$member(injects, 0), $$MODULE_INC_OUTDIR)
- fwd_hdr = $$member(injects, 1)
+ ofwd_hdr = $$member(injects, 1)
+ fwd_hdr = $$replace(ofwd_hdr, ^\\^, )
MAIN_FWD = $$MODULE_INC_OUTDIR/$$fwd_hdr
MAIN_FWD_CONT = '$${LITERAL_HASH}include "$$relative_path($$dst_hdr, $$dirname(MAIN_FWD))"'
write_file($$MAIN_FWD, MAIN_FWD_CONT)|error()
- touch($$MAIN_FWD, $$dst_hdr)
+ equals(fwd_hdr, ofwd_hdr): touch($$MAIN_FWD, $$dst_hdr)
!git_build: QMAKE_DISTCLEAN += $$MAIN_FWD
injects = $$member(injects, 2, -1)
for (inject, injects) {
CLASS_FWD = $$MODULE_INC_OUTDIR/$$inject
CLASS_FWD_CONT = '$${LITERAL_HASH}include "$$fwd_hdr"'
write_file($$CLASS_FWD, CLASS_FWD_CONT)|error()
- touch($$CLASS_FWD, $$dst_hdr)
+ touch($$CLASS_FWD, $$MAIN_FWD)
!git_build: QMAKE_DISTCLEAN += $$CLASS_FWD
}
}
@@ -213,20 +214,15 @@ headersclean:!internal_module {
!contains(QT_ARCH, arm):!contains(QT_ARCH, mips): \
hcleanFLAGS += -Wcast-align
- greaterThan(QT_CLANG_MAJOR_VERSION, 3) {
- hcleanFLAGS += -Wdouble-promotion
- } greaterThan(QT_CLANG_MAJOR_VERSION, 2):greaterThan(QT_CLANG_MINOR_VERSION, 7) {
- hcleanFLAGS += -Wdouble-promotion
- }
+ clang_ver = $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}
+ versionAtLeast(clang_ver, 3.8): hcleanFLAGS += -Wdouble-promotion
!clang {
# options accepted only by GCC
- greaterThan(QT_GCC_MAJOR_VERSION, 4) {
- hcleanFLAGS += -Wdouble-promotion
- } greaterThan(QT_GCC_MAJOR_VERSION, 3):greaterThan(QT_GCC_MINOR_VERSION, 4) {
- hcleanFLAGS += -Wdouble-promotion
- }
+ gcc_ver = $${QT_GCC_MAJOR_VERSION}.$${QT_GCC_MINOR_VERSION}
+ versionAtLeast(gcc_ver, 4.5): hcleanFLAGS += -Wdouble-promotion
+
c++11 {
# only enabled for actual c++11 builds due to
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=52806
@@ -252,12 +248,17 @@ headersclean:!internal_module {
}
hcleanCOMMAND = $$QMAKE_CXX -c $(CXXFLAGS) $$hcleanFLAGS $(INCPATH) $$hcleanDEFS -xc++ ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
- } else: win32-msvc2013 {
+ } else: msvc:!intel_icl {
# 4180: qualifier applied to function type has no meaning; ignored
# 4458: declaration of 'identifier' hides class member
# -Za enables strict standards behavior, but we can't add it because
# <windows.h> and <GL.h> violate the standards.
hcleanFLAGS = -WX -W3 -wd4180 -wd4458
+
+ # MSVC 2015 (compiler version 19.0):
+ # 4577: 'noexcept' used with no exception handling mode specified; termination on exception is not guaranteed. Specify /EHsc
+ greaterThan(QMAKE_MSC_VER, 18): hcleanFLAGS += -wd4577
+
hcleanCOMMAND = $$QMAKE_CXX -c $(CXXFLAGS) $$hcleanFLAGS $(INCPATH) $$hcleanDEFS -FI${QMAKE_FILE_IN} -Fo${QMAKE_FILE_OUT} \
$$[QT_INSTALL_DATA/src]/mkspecs/features/data/dummy.cpp
}
diff --git a/mkspecs/features/simd.prf b/mkspecs/features/simd.prf
index 953fc52c65..8471ce7e7c 100644
--- a/mkspecs/features/simd.prf
+++ b/mkspecs/features/simd.prf
@@ -93,6 +93,8 @@ addSimdCompiler(sse3)
addSimdCompiler(ssse3)
addSimdCompiler(sse4_1)
addSimdCompiler(sse4_2)
+addSimdCompiler(aesni)
+addSimdCompiler(shani)
addSimdCompiler(avx)
addSimdCompiler(avx2)
addSimdCompiler(avx512f)
@@ -105,6 +107,7 @@ addSimdCompiler(avx512vl)
addSimdCompiler(avx512ifma)
addSimdCompiler(avx512vbmi)
addSimdCompiler(f16c)
+addSimdCompiler(rdrnd)
addSimdCompiler(neon)
addSimdCompiler(mips_dsp)
addSimdCompiler(mips_dspr2)
diff --git a/mkspecs/features/uic.prf b/mkspecs/features/uic.prf
index ca8283920a..134d3b4acb 100644
--- a/mkspecs/features/uic.prf
+++ b/mkspecs/features/uic.prf
@@ -3,8 +3,10 @@ qtPrepareTool(QMAKE_UIC, uic, _DEP)
isEmpty(UI_DIR):UI_DIR = .
isEmpty(QMAKE_MOD_UIC):QMAKE_MOD_UIC = ui_
+contains(TEMPLATE, .*lib):dll: QMAKE_UIC_FLAGS += -no-stringliteral
+
uic.depends += $$QMAKE_UIC_EXE
-uic.commands = $$QMAKE_UIC ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
+uic.commands = $$QMAKE_UIC $$QMAKE_UIC_FLAGS ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
uic.depend_command = $$QMAKE_UIC_DEP -d ${QMAKE_FILE_IN}
uic.output = $$UI_DIR/$${QMAKE_MOD_UIC}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_H)}
uic.input = FORMS
diff --git a/mkspecs/features/uikit/bitcode.prf b/mkspecs/features/uikit/bitcode.prf
index df298171c0..f1fd33981a 100644
--- a/mkspecs/features/uikit/bitcode.prf
+++ b/mkspecs/features/uikit/bitcode.prf
@@ -1,4 +1,4 @@
-lessThan(QMAKE_XCODE_VERSION, "7.0") {
+!versionAtLeast(QMAKE_XCODE_VERSION, 7.0) {
warning("You need to update Xcode to version 7 or newer to support bitcode")
} else: !macx-xcode {
# Simulator builds and all debug builds SHOULD use -fembed-bitcode-marker,
diff --git a/mkspecs/features/uikit/default_post.prf b/mkspecs/features/uikit/default_post.prf
index f7245e48b1..c1b6f38a6c 100644
--- a/mkspecs/features/uikit/default_post.prf
+++ b/mkspecs/features/uikit/default_post.prf
@@ -39,7 +39,7 @@ macx-xcode {
qmake_launch_images.files = $$qmake_copy_image.output
QMAKE_BUNDLE_DATA += qmake_launch_images
- lessThan(QMAKE_XCODE_VERSION, "6.0") {
+ !versionAtLeast(QMAKE_XCODE_VERSION, 6.0) {
warning("You need to update Xcode to version 6 or newer to fully support iPhone6/6+")
} else {
# Set up default LaunchScreen to support iPhone6/6+
diff --git a/mkspecs/features/uikit/default_pre.prf b/mkspecs/features/uikit/default_pre.prf
index 00e29a5c8b..6a44a67bca 100644
--- a/mkspecs/features/uikit/default_pre.prf
+++ b/mkspecs/features/uikit/default_pre.prf
@@ -21,8 +21,8 @@ unset(sim_and_dev)
load(default_pre)
# Check for supported Xcode versions
-lessThan(QMAKE_XCODE_VERSION, "4.3"): \
+!versionAtLeast(QMAKE_XCODE_VERSION, 4.3): \
error("This mkspec requires Xcode 4.3 or later")
-ios:shared:lessThan(QMAKE_IOS_DEPLOYMENT_TARGET, "8.0"): \
+ios:shared:!versionAtLeast(QMAKE_IOS_DEPLOYMENT_TARGET, 8.0): \
QMAKE_IOS_DEPLOYMENT_TARGET = 8.0
diff --git a/mkspecs/features/uikit/watchos_coretext.prf b/mkspecs/features/uikit/watchos_coretext.prf
new file mode 100644
index 0000000000..30e5af2e7e
--- /dev/null
+++ b/mkspecs/features/uikit/watchos_coretext.prf
@@ -0,0 +1,15 @@
+# CoreText is documented to be available on watchOS, but the headers aren't present
+# in the watchOS Simulator SDK like they are supposed to be. Work around the problem
+# by adding the device SDK's headers to the search path as a fallback.
+# rdar://25314492, rdar://27844864
+simulator_system_frameworks = $$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks
+watchos:simulator:!exists($$simulator_system_frameworks/CoreText.framework/Headers/CoreText.h) {
+ device_system_frameworks = $$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks
+ for (arch, QMAKE_APPLE_SIMULATOR_ARCHS) {
+ QMAKE_CXXFLAGS += \
+ -Xarch_$${arch} \
+ -F$$simulator_system_frameworks \
+ -Xarch_$${arch} \
+ -F$$device_system_frameworks
+ }
+}
diff --git a/mkspecs/features/unix/separate_debug_info.prf b/mkspecs/features/unix/separate_debug_info.prf
index ebb37bdfc7..0b34b17c27 100644
--- a/mkspecs/features/unix/separate_debug_info.prf
+++ b/mkspecs/features/unix/separate_debug_info.prf
@@ -56,6 +56,13 @@ have_target:!static:if(darwin|!isEmpty(QMAKE_OBJCOPY)) {
debug_info_plist.input = $$QMAKESPEC/Info.plist.dSYM.in
debug_info_plist.output = $${debug_info_target}.$$debug_info_suffix/Contents/Info.plist
QMAKE_SUBSTITUTES += debug_info_plist
+
+ !isEmpty(QMAKE_DSYM_DEBUG_SCRIPT) {
+ debug_script.input = $$QMAKE_DSYM_DEBUG_SCRIPT
+ debug_script.output = $${debug_info_target}.$$debug_info_suffix/Contents/Resources/Python/$${TARGET}.py
+ debug_script.CONFIG = verbatim
+ QMAKE_SUBSTITUTES += debug_script
+ }
}
contains(INSTALLS, target):isEmpty(target.files):isEmpty(target.commands):isEmpty(target.extra) {
@@ -64,6 +71,11 @@ have_target:!static:if(darwin|!isEmpty(QMAKE_OBJCOPY)) {
debug_info_plist_target.files = $${debug_info_target}.$$debug_info_suffix/Contents/Info.plist
debug_info_plist_target.path += $${target.path}/$${debug_info_target_rel}.$$debug_info_suffix/Contents
INSTALLS += debug_info_plist_target
+
+ debug_script_target.CONFIG += no_check_exist
+ debug_script_target.files = $${debug_info_target}.$$debug_info_suffix/Contents/Resources/Python/$${TARGET}.py
+ debug_script_target.path += $${target.path}/$${debug_info_target_rel}.$$debug_info_suffix/Contents/Resources/Python
+ INSTALLS += debug_script_target
}
debug_info_target.CONFIG += no_check_exist
diff --git a/mkspecs/linux-icc-k1om/qmake.conf b/mkspecs/linux-icc-k1om/qmake.conf
new file mode 100644
index 0000000000..86cd921e89
--- /dev/null
+++ b/mkspecs/linux-icc-k1om/qmake.conf
@@ -0,0 +1,21 @@
+#
+# qmake configuration for linux-icc-k1om
+#
+# Written for Intel C++ Compiler
+#
+# This mkspec is intended for use on x100 Co-processors
+#
+
+# Use the linux-icc as the base for our configuration
+include(../linux-icc/qmake.conf)
+
+QMAKE_CC = icc -mmic
+QMAKE_CFLAGS_WARN_ON += -wd10364,1786
+
+QMAKE_CXX = icpc -mmic
+QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
+
+QMAKE_LFLAGS += -mmic
+QMAKE_LFLAGS_APP =
+QMAKE_AR = xiar crs
+
diff --git a/mkspecs/linux-icc-k1om/qplatformdefs.h b/mkspecs/linux-icc-k1om/qplatformdefs.h
new file mode 100644
index 0000000000..33a3bf0e1c
--- /dev/null
+++ b/mkspecs/linux-icc-k1om/qplatformdefs.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../linux-icc/qplatformdefs.h"
diff --git a/mkspecs/linux-icc/qmake.conf b/mkspecs/linux-icc/qmake.conf
index 4fc2251665..1d94f0c931 100644
--- a/mkspecs/linux-icc/qmake.conf
+++ b/mkspecs/linux-icc/qmake.conf
@@ -45,7 +45,10 @@ QMAKE_CFLAGS_AVX512PF += -xMIC-AVX512
QMAKE_CFLAGS_AVX512DQ += -xCORE-AVX512
QMAKE_CFLAGS_AVX512BW += -xCORE-AVX512
QMAKE_CFLAGS_AVX512VL += -xCORE-AVX512
+QMAKE_CFLAGS_AESNI += -maes
QMAKE_CFLAGS_F16C += $$QMAKE_CFLAGS_AVX2
+QMAKE_CFLAGS_RDRND += -mrdrnd
+QMAKE_CFLAGS_SHANI += -msha
QMAKE_CXX = icpc
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
diff --git a/mkspecs/macx-icc/qmake.conf b/mkspecs/macx-icc/qmake.conf
index e999aa36a4..80cffbf9dc 100644
--- a/mkspecs/macx-icc/qmake.conf
+++ b/mkspecs/macx-icc/qmake.conf
@@ -43,7 +43,10 @@ QMAKE_CFLAGS_AVX512PF += -xMIC-AVX512
QMAKE_CFLAGS_AVX512DQ += -xCORE-AVX512
QMAKE_CFLAGS_AVX512BW += -xCORE-AVX512
QMAKE_CFLAGS_AVX512VL += -xCORE-AVX512
+QMAKE_CFLAGS_AESNI += -maes
QMAKE_CFLAGS_F16C += $$QMAKE_CFLAGS_AVX2
+QMAKE_CFLAGS_RDRND += -mrdrnd
+QMAKE_CFLAGS_SHANI += -msha
QMAKE_CXX = icpc
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf
index 29151ef8b9..105391f6f4 100644
--- a/mkspecs/win32-g++/qmake.conf
+++ b/mkspecs/win32-g++/qmake.conf
@@ -28,6 +28,8 @@ QMAKE_YACCFLAGS = -d
QMAKE_CFLAGS += -fno-keep-inline-dllexport
QMAKE_CFLAGS_WARN_ON += -Wextra
QMAKE_CFLAGS_SSE2 += -mstackrealign
+QMAKE_CFLAGS_AESNI = -maes
+QMAKE_CFLAGS_SHANI = -msha
QMAKE_CXX = $${CROSS_COMPILE}g++
QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
@@ -78,6 +80,7 @@ QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
QMAKE_NM = $${CROSS_COMPILE}nm -P
include(../common/angle.conf)
+include(../common/windows-vulkan.conf)
include(../common/gcc-base.conf)
load(qt_config)
diff --git a/mkspecs/win32-icc-k1om/qmake.conf b/mkspecs/win32-icc-k1om/qmake.conf
new file mode 100644
index 0000000000..498b47cf2d
--- /dev/null
+++ b/mkspecs/win32-icc-k1om/qmake.conf
@@ -0,0 +1,15 @@
+#
+# qmake configuration for win32-icc-k1om
+#
+# Written for Intel C++
+#
+# Use the win32-icc as the base for our configuration
+include(../win32-icc/qmake.conf)
+
+# rework k1om
+
+QMAKE_CC = icl /Qmic
+QMAKE_CXX = icl /Qmic
+QMAKE_LINK = xild
+QMAKE_LINK_SHLIB = xild
+QMAKE_LFLAGS = -limf -lsvml -lirng -lintlc
diff --git a/mkspecs/win32-icc-k1om/qplatformdefs.h b/mkspecs/win32-icc-k1om/qplatformdefs.h
new file mode 100644
index 0000000000..8a3afa7630
--- /dev/null
+++ b/mkspecs/win32-icc-k1om/qplatformdefs.h
@@ -0,0 +1,40 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the qmake spec of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "../win32-msvc/qplatformdefs.h"
diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf
index ee95f8a866..863fd77ea9 100644
--- a/mkspecs/win32-icc/qmake.conf
+++ b/mkspecs/win32-icc/qmake.conf
@@ -34,6 +34,8 @@ QMAKE_CFLAGS_AVX512DQ += -QxCORE-AVX512
QMAKE_CFLAGS_AVX512BW += -QxCORE-AVX512
QMAKE_CFLAGS_AVX512VL += -QxCORE-AVX512
QMAKE_CFLAGS_F16C = $$QMAKE_CFLAGS_AVX2
+QMAKE_CFLAGS_AESNI = -QxSSE2
+QMAKE_CFLAGS_SHANI = -QxSSE4.2
QMAKE_CXX = $$QMAKE_CC
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS /Zc:forScope
@@ -58,5 +60,6 @@ QMAKE_LIB = xilib /NOLOGO
DSP_EXTENSION = .dsp
include(../common/angle.conf)
+include(../common/windows-vulkan.conf)
load(qt_config)
diff --git a/qmake/Makefile.unix b/qmake/Makefile.unix
index ed1668d54e..1da4b3727f 100644
--- a/qmake/Makefile.unix
+++ b/qmake/Makefile.unix
@@ -2,107 +2,144 @@ QMKSRC = $(SOURCE_PATH)/qmake
QMKLIBSRC = $(QMKSRC)/library
QMKGENSRC = $(QMKSRC)/generators
-#qmake code
-OBJS=project.o option.o property.o main.o ioutils.o proitems.o \
- qmakevfs.o qmakeglobals.o qmakeparser.o qmakeevaluator.o qmakebuiltins.o \
- makefile.o unixmake2.o unixmake.o \
- mingw_make.o winmakefile.o projectgenerator.o \
- meta.o makefiledeps.o metamakefile.o xmloutput.o pbuilder_pbx.o \
- msvc_vcproj.o msvc_vcxproj.o msvc_nmake.o msvc_objectmodel.o msbuild_objectmodel.o
-
-#qt code
-QOBJS=qtextcodec.o qutfcodec.o qstring.o qstring_compat.o qstringbuilder.o qtextstream.o qiodevice.o \
- qringbuffer.o qdebug.o qmalloc.o qglobal.o \
- qarraydata.o qbytearray.o qbytearraymatcher.o qdatastream.o qbuffer.o qlist.o qfiledevice.o qfile.o \
- qfilesystementry.o qfilesystemengine.o qfsfileengine.o qfsfileengine_iterator.o qregexp.o \
- qbitarray.o qdir.o qdiriterator.o quuid.o qhash.o qfileinfo.o qdatetime.o qstringlist.o \
- qabstractfileengine.o qtemporaryfile.o qmap.o qmetatype.o qsettings.o qsystemerror.o \
- qvariant.o qvsnprintf.o qlocale.o qlocale_tools.o qlinkedlist.o qnumeric.o \
- qcryptographichash.o qxmlstream.o qxmlutils.o qlogging.o qoperatingsystemversion.o \
- qjson.o qjsondocument.o qjsonparser.o qjsonarray.o qjsonobject.o qjsonvalue.o \
- $(QTOBJS) $(QTOBJS2)
-
-
-#all sources, used for the depend target
+#qmake code (please keep in order matching DEPEND_SRC)
+OBJS = \
+ main.o meta.o option.o project.o property.o \
+ ioutils.o proitems.o qmakebuiltins.o qmakeevaluator.o \
+ qmakeglobals.o qmakeparser.o qmakevfs.o \
+ pbuilder_pbx.o \
+ makefile.o makefiledeps.o metamakefile.o projectgenerator.o \
+ unixmake2.o unixmake.o \
+ mingw_make.o msbuild_objectmodel.o \
+ msvc_nmake.o msvc_objectmodel.o msvc_vcproj.o msvc_vcxproj.o \
+ winmakefile.o \
+ xmloutput.o
+
+#qt code (please keep in order matching DEPEND_SRC)
+QOBJS = \
+ qtextcodec.o qutfcodec.o \
+ qglobal.o qlogging.o qmalloc.o qnumeric.o qoperatingsystemversion.o qrandom.o \
+ qabstractfileengine.o qbuffer.o qdatastream.o qdebug.o \
+ qdir.o qdiriterator.o \
+ qfile.o qfiledevice.o qfileinfo.o qfilesystemengine.o \
+ qfilesystementry.o qfsfileengine.o qfsfileengine_iterator.o \
+ qiodevice.o qsettings.o qtemporaryfile.o qtextstream.o \
+ qjsonarray.o qjson.o qjsondocument.o qjsonobject.o qjsonparser.o qjsonvalue.o \
+ qmetatype.o qsystemerror.o qvariant.o \
+ quuid.o \
+ qarraydata.o qbitarray.o qbytearray.o qbytearraymatcher.o \
+ qcryptographichash.o qdatetime.o qhash.o qlinkedlist.o qlist.o \
+ qlocale.o qlocale_tools.o qmap.o qregexp.o qringbuffer.o \
+ qstringbuilder.o qstring_compat.o qstring.o qstringlist.o qversionnumber.o \
+ qvsnprintf.o qxmlstream.o qxmlutils.o \
+ $(QTOBJS) $(QTOBJS2)
+# QTOBJS and QTOBJS2 are populated by Makefile.unix.* as for QTSRC (see below).
+# Note: qlibraryinfo.o omitted deliberately - see below.
+# Note: qcore_mac_objc.o is in SOURCES (see qmake.pri) but not QOBJS.
+
+#all sources, used for the depend target (please keep alphabetic in each block)
DEPEND_SRC = \
- $(QMKSRC)/main.cpp $(QMKSRC)/project.cpp $(QMKSRC)/option.cpp $(QMKSRC)/property.cpp \
+ $(QMKSRC)/main.cpp \
$(QMKSRC)/meta.cpp \
- $(QMKLIBSRC)/ioutils.cpp $(QMKLIBSRC)/proitems.cpp $(QMKLIBSRC)/qmakeglobals.cpp \
- $(QMKLIBSRC)/qmakeparser.cpp $(QMKLIBSRC)/qmakeevaluator.cpp $(QMKLIBSRC)/qmakebuiltins.cpp \
- $(QMKGENSRC)/makefiledeps.cpp $(QMKGENSRC)/metamakefile.cpp \
- $(QMKGENSRC)/projectgenerator.cpp $(QMKGENSRC)/makefile.cpp \
- $(QMKGENSRC)/unix/unixmake.cpp $(QMKGENSRC)/unix/unixmake2.cpp \
+ $(QMKSRC)/option.cpp \
+ $(QMKSRC)/project.cpp \
+ $(QMKSRC)/property.cpp \
+ $(QMKLIBSRC)/ioutils.cpp \
+ $(QMKLIBSRC)/proitems.cpp \
+ $(QMKLIBSRC)/qmakebuiltins.cpp \
+ $(QMKLIBSRC)/qmakeevaluator.cpp \
+ $(QMKLIBSRC)/qmakeglobals.cpp \
+ $(QMKLIBSRC)/qmakeparser.cpp \
+ $(QMKLIBSRC)/qmakevfs.cpp \
$(QMKGENSRC)/mac/pbuilder_pbx.cpp \
- $(QMKGENSRC)/win32/registry.cpp \
+ $(QMKGENSRC)/makefile.cpp \
+ $(QMKGENSRC)/makefiledeps.cpp \
+ $(QMKGENSRC)/metamakefile.cpp \
+ $(QMKGENSRC)/projectgenerator.cpp \
+ $(QMKGENSRC)/unix/unixmake2.cpp \
+ $(QMKGENSRC)/unix/unixmake.cpp \
+ $(QMKGENSRC)/win32/mingw_make.cpp \
+ $(QMKGENSRC)/win32/msbuild_objectmodel.cpp \
+ $(QMKGENSRC)/win32/msvc_nmake.cpp \
+ $(QMKGENSRC)/win32/msvc_objectmodel.cpp \
+ $(QMKGENSRC)/win32/msvc_vcproj.cpp \
+ $(QMKGENSRC)/win32/msvc_vcxproj.cpp \
$(QMKGENSRC)/win32/winmakefile.cpp \
- $(QMKGENSRC)/win32/mingw_make.cpp $(QMKGENSRC)/win32/msvc_nmake.cpp \
- $(QMKGENSRC)/mac/xmloutput.cpp \
- $(QMKGENSRC)/win32/msvc_vcproj.cpp $(QMKGENSRC)/win32/msvc_vcxproj.cpp \
- $(QMKGENSRC)/win32/msvc_objectmodel.cpp $(QMKGENSRC)/win32/msbuild_objectmodel.cpp \
- $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qstring.cpp $(SOURCE_PATH)/src/corelib/io/qfile.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \
- $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \
- $(SOURCE_PATH)/src/corelib/io/qdebug.cpp \
+ $(QMKGENSRC)/xmloutput.cpp \
+ $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp \
+ $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qglobal.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qlogging.cpp \
$(SOURCE_PATH)/src/corelib/global/qmalloc.cpp \
- $(SOURCE_PATH)/src/corelib/global/qglobal.cpp $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\
- $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \
- $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp \
+ $(SOURCE_PATH)/src/corelib/global/qrandom.cpp \
$(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qdebug.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qdir.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfile.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp \
$(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp $(SOURCE_PATH)/src/corelib/tools/qlist.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qsettings.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp \
+ $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjson.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp \
+ $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp \
+ $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm \
+ $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp \
+ $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \
+ $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp \
+ $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp \
$(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp \
- $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp \
- $(SOURCE_PATH)/src/corelib/io/qdir.cpp $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp \
- $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp $(SOURCE_PATH)/src/corelib/tools/qmap.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp\
+ $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qhash.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qlist.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlocale.cpp \
$(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qhash.cpp $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp \
- $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm \
- $(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm \
- $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp \
- $(SOURCE_PATH)/src/corelib/io/qsettings.cpp $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp \
- $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp \
- $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qmap.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qstring.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp \
+ $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp \
$(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp \
$(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp \
- $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp \
- $(SOURCE_PATH)/src/corelib/global/qlogging.cpp \
- $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjson.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp \
- $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp \
$(QTSRCS) $(QTSRCS2)
+# QTSRCS and QTSRCS2 come from Makefile.unix.* (concatenated with this
+# by configure); QTSRCS2 may include *.mm entries on macOS.
+# See below for special handling of qlibraryinfo.cpp
CPPFLAGS = -g $(EXTRA_CPPFLAGS) \
- -I$(QMKSRC) -I$(QMKLIBSRC) -I$(QMKSRC)/generators -I$(QMKSRC)/generators/unix -I$(QMKSRC)/generators/win32 \
- -I$(QMKSRC)/generators/mac \
+ -I$(QMKSRC) -I$(QMKLIBSRC) -I$(QMKGENSRC) \
+ -I$(QMKGENSRC)/unix -I$(QMKGENSRC)/win32 -I$(QMKGENSRC)/mac \
-I$(INC_PATH) -I$(INC_PATH)/QtCore \
-I$(INC_PATH)/QtCore/$(QT_VERSION) -I$(INC_PATH)/QtCore/$(QT_VERSION)/QtCore \
-I$(BUILD_PATH)/src/corelib/global \
-I$(QMAKESPEC) \
-DQT_VERSION_STR=\"$(QT_VERSION)\" -DQT_VERSION_MAJOR=$(QT_MAJOR_VERSION) -DQT_VERSION_MINOR=$(QT_MINOR_VERSION) -DQT_VERSION_PATCH=$(QT_PATCH_VERSION) \
- -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \
- -DQT_NO_FOREACH
+ -DQT_BUILD_QMAKE -DQT_BOOTSTRAPPED -DPROEVALUATOR_FULL \
+ -DQT_NO_FOREACH
CXXFLAGS = $(EXTRA_CXXFLAGS) $(CONFIG_CXXFLAGS) $(CPPFLAGS)
LFLAGS = $(EXTRA_LFLAGS) $(CONFIG_LFLAGS)
@@ -220,222 +257,231 @@ projectgenerator.o: $(QMKSRC)/generators/projectgenerator.cpp
qtextstream.o: $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qtextstream.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qvariant.o: $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qvariant.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qsettings.o: $(SOURCE_PATH)/src/corelib/io/qsettings.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qsystemerror.o: $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qsystemerror.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlibraryinfo.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) -DQT_BUILD_QMAKE_BOOTSTRAP $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) -DQT_BUILD_QMAKE_BOOTSTRAP $<
qlibraryinfo_final.o: $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp $(BUILD_PATH)/src/corelib/global/qconfig.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlibraryinfo.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qnumeric.o: $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qnumeric.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
+
+qrandom.o: $(SOURCE_PATH)/src/corelib/global/qrandom.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qsettings_mac.o: $(SOURCE_PATH)/src/corelib/io/qsettings_mac.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings_mac.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qsettings_win.o: $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qsettings_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qiodevice.o: $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qiodevice.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qringbuffer.o: $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qringbuffer.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qdebug.o: $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdebug.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qmalloc.o: $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qmalloc.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qglobal.o: $(SOURCE_PATH)/src/corelib/global/qglobal.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qglobal.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qarraydata.o: $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qarraydata.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qbytearray.o: $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearray.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qvsnprintf.o: $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qvsnprintf.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qbytearraymatcher.o: $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbytearraymatcher.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qmetatype.o: $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qmetatype.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qcore_mac.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_mac.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
+
+qcore_unix.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_unix.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qoperatingsystemversion.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qoperatingsystemversion_win.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qoperatingsystemversion_darwin.o: $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_darwin.mm
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qoperatingsystemversion_darwin.mm
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qcore_mac_objc.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_mac_objc.mm
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qcore_foundation.o: $(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/kernel/qcore_foundation.mm
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qutfcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qutfcodec.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qtextcodec.o: $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/codecs/qtextcodec.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qstring.o: $(SOURCE_PATH)/src/corelib/tools/qstring.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstring.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qstring_compat.o: $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstring_compat.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qstringbuilder.o: $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringbuilder.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlocale.o: $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlocale_tools.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_tools.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlocale_unix.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_unix.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlocale_win.o: $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlocale_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
+
+qversionnumber.o: $(SOURCE_PATH)/src/corelib/tools/qversionnumber.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qdatastream.o: $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdatastream.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qbuffer.o: $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qbuffer.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlist.o: $(SOURCE_PATH)/src/corelib/tools/qlist.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlist.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfile.o: $(SOURCE_PATH)/src/corelib/io/qfile.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfile.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfiledevice.o: $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfiledevice.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystementry.o: $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystementry.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystemengine.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystemengine_unix.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystemengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemengine_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystemiterator_unix.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfilesystemiterator_win.o: $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfsfileengine.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfsfileengine_iterator.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_iterator.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfsfileengine_unix.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfsfileengine_win.o: $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfsfileengine_win.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qabstractfileengine.o: $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qabstractfileengine.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qtemporaryfile.o: $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qtemporaryfile.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qregexp.o: $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qregexp.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qbitarray.o: $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qbitarray.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qdir.o: $(SOURCE_PATH)/src/corelib/io/qdir.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdir.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qdiriterator.o: $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qdiriterator.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
quuid.o: $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/quuid.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qfileinfo.o: $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/io/qfileinfo.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qdatetime.o: $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qdatetime.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qstringlist.o: $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qstringlist.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qmap.o: $(SOURCE_PATH)/src/corelib/tools/qmap.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qmap.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qhash.o: $(SOURCE_PATH)/src/corelib/tools/qhash.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qhash.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlinkedlist.o: $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qlinkedlist.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
-qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp
+qcryptographichash.o: $(SOURCE_PATH)/src/corelib/tools/qcryptographichash.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qxmlstream.o: $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlstream.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qxmlutils.o: $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/xml/qxmlutils.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qlogging.o: $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/global/qlogging.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qsystemlibrary.o: $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/plugin/qsystemlibrary.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjson.o: $(SOURCE_PATH)/src/corelib/json/qjson.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjson.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjsondocument.o: $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsondocument.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjsonparser.o: $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonparser.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjsonarray.o: $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonarray.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjsonobject.o: $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonobject.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
qjsonvalue.o: $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp
- $(CXX) -c -o $@ $(CXXFLAGS) $(SOURCE_PATH)/src/corelib/json/qjsonvalue.cpp
+ $(CXX) -c -o $@ $(CXXFLAGS) $<
# DO NOT DELETE THIS LINE -- make depend depends on it
diff --git a/qmake/Makefile.unix.unix b/qmake/Makefile.unix.unix
index 63eba4f5a5..e8c1cd1017 100644
--- a/qmake/Makefile.unix.unix
+++ b/qmake/Makefile.unix.unix
@@ -1,10 +1,12 @@
EXEEXT =
QTOBJS = \
+ qcore_unix.o \
qfilesystemengine_unix.o \
qfilesystemiterator_unix.o \
qfsfileengine_unix.o \
qlocale_unix.o
QTSRCS = \
+ $(SOURCE_PATH)/src/corelib/kernel/qcore_unix.cpp \
$(SOURCE_PATH)/src/corelib/io/qfilesystemengine_unix.cpp \
$(SOURCE_PATH)/src/corelib/io/qfilesystemiterator_unix.cpp \
$(SOURCE_PATH)/src/corelib/io/qfsfileengine_unix.cpp \
diff --git a/qmake/Makefile.unix.win32 b/qmake/Makefile.unix.win32
index c747eedcd0..bfcad35357 100644
--- a/qmake/Makefile.unix.win32
+++ b/qmake/Makefile.unix.win32
@@ -1,6 +1,6 @@
EXEEXT = .exe
EXTRA_CXXFLAGS = -DUNICODE
-EXTRA_LFLAGS = -static -s -lole32 -luuid -ladvapi32 -lkernel32
+EXTRA_LFLAGS = -static -s -lole32 -luuid -ladvapi32 -lkernel32 -lnetapi32
QTOBJS = \
qfilesystemengine_win.o \
qfilesystemiterator_win.o \
diff --git a/qmake/Makefile.win32 b/qmake/Makefile.win32
index 7639d09ffd..28bf96939b 100644
--- a/qmake/Makefile.win32
+++ b/qmake/Makefile.win32
@@ -46,7 +46,7 @@ CXXFLAGS_BARE = $(CFLAGS_BARE)
CXXFLAGS = $(CFLAGS)
LFLAGS =
-LIBS = ole32.lib advapi32.lib shell32.lib
+LIBS = ole32.lib advapi32.lib shell32.lib netapi32.lib
ADDCLEAN = qmake.pdb qmake.ilk
#qmake code
@@ -93,6 +93,7 @@ QTOBJS= \
qlocale.obj \
qlocale_tools.obj \
qlocale_win.obj \
+ qversionnumber.obj \
qmalloc.obj \
qmap.obj \
qoperatingsystemversion.obj \
@@ -108,6 +109,7 @@ QTOBJS= \
qtextstream.obj \
qdatastream.obj \
quuid.obj \
+ qrandom.obj \
qsettings.obj \
qvariant.obj \
qsettings_win.obj \
diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc
index 216cc30af1..c9759fa517 100644
--- a/qmake/doc/src/qmake-manual.qdoc
+++ b/qmake/doc/src/qmake-manual.qdoc
@@ -2266,6 +2266,14 @@
For more information, see \l {Expressing Supported iOS Versions}.
+ \section1 QMAKE_UIC_FLAGS
+
+ This variable is used to customize the list of options passed to the
+ \l{uic}{User Interface Compiler} in each of the build rules where it is
+ used. For example, \c{-no-stringliteral} can be passed to use QLatin1String
+ instead of QStringLiteral in generated code (which is the default for
+ dynamic libraries).
+
\section1 QMAKE_WATCHOS_DEPLOYMENT_TARGET
\note This variable is used on the watchOS platform only.
@@ -3557,6 +3565,20 @@
\snippet code/doc_src_qmake-manual.pro 169
+ \section2 versionAtLeast(variablename, versionNumber)
+
+ Tests that the version number from \c variablename is greater than or equal
+ to \c versionNumber. The version number is considered to be a sequence of
+ non-negative decimal numbers delimited by '.'; any non-numerical tail of
+ the string will be ignored. Comparison is performed segment-wise from left
+ to right; if one version is a prefix of the other, it is considered smaller.
+
+ \section2 versionAtMost(variablename, versionNumber)
+
+ Tests that the version number from \c variablename is less than or equal to
+ \c versionNumber. Works as
+ \l{versionAtLeast(variablename, versionNumber)}{versionAtLeast()}.
+
\section2 warning(string)
Always succeeds, and displays \c string as a warning message to the user.
diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp
index 74989e4e7e..300792c5af 100644
--- a/qmake/generators/win32/msvc_objectmodel.cpp
+++ b/qmake/generators/win32/msvc_objectmodel.cpp
@@ -320,7 +320,7 @@ triState operator!(const triState &rhs)
QStringList VCToolBase::fixCommandLine(const QString &input)
{
// The splitting regexp is a bit bizarre for backwards compat reasons (why else ...).
- return input.split(QRegExp(QLatin1String("\n\t|\r\\\\h|\r\n")));
+ return input.split(QRegExp(QLatin1String("(\n\t|\r\\\\h|\r\n)\\s*")));
}
static QString vcCommandSeparator()
diff --git a/qmake/generators/win32/msvc_vcproj.cpp b/qmake/generators/win32/msvc_vcproj.cpp
index f261574482..24d1657552 100644
--- a/qmake/generators/win32/msvc_vcproj.cpp
+++ b/qmake/generators/win32/msvc_vcproj.cpp
@@ -223,7 +223,7 @@ QUuid VcprojGenerator::getProjectUUID(const QString &filename)
bool validUUID = true;
// Read GUID from variable-space
- QUuid uuid = project->first("GUID").toQString();
+ auto uuid = QUuid::fromString(project->first("GUID").toQStringView());
// If none, create one based on the MD5 of absolute project path
if(uuid.isNull() || !filename.isEmpty()) {
diff --git a/qmake/library/proitems.h b/qmake/library/proitems.h
index c81e205699..40fc23ed19 100644
--- a/qmake/library/proitems.h
+++ b/qmake/library/proitems.h
@@ -139,6 +139,7 @@ public:
static uint hash(const QChar *p, int n);
ALWAYS_INLINE QStringRef toQStringRef() const { return QStringRef(&m_string, m_offset, m_length); }
+ ALWAYS_INLINE QStringView toQStringView() const { return QStringView(m_string).mid(m_offset, m_length); }
ALWAYS_INLINE ProKey &toKey() { return *(ProKey *)this; }
ALWAYS_INLINE const ProKey &toKey() const { return *(const ProKey *)this; }
diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp
index 2bb6f2e12d..85de50ef0c 100644
--- a/qmake/library/qmakebuiltins.cpp
+++ b/qmake/library/qmakebuiltins.cpp
@@ -51,6 +51,7 @@
#ifdef PROEVALUATOR_THREAD_SAFE
# include <qthreadpool.h>
#endif
+#include <qversionnumber.h>
#include <algorithm>
@@ -97,6 +98,7 @@ enum ExpandFunc {
enum TestFunc {
T_INVALID = 0, T_REQUIRES, T_GREATERTHAN, T_LESSTHAN, T_EQUALS,
+ T_VERSION_AT_LEAST, T_VERSION_AT_MOST,
T_EXISTS, T_EXPORT, T_CLEAR, T_UNSET, T_EVAL, T_CONFIG, T_SYSTEM,
T_DEFINED, T_DISCARD_FROM, T_CONTAINS, T_INFILE,
T_COUNT, T_ISEMPTY, T_PARSE_JSON, T_INCLUDE, T_LOAD, T_DEBUG, T_LOG, T_MESSAGE, T_WARNING, T_ERROR, T_IF,
@@ -170,6 +172,8 @@ void QMakeEvaluator::initFunctionStatics()
{ "lessThan", T_LESSTHAN },
{ "equals", T_EQUALS },
{ "isEqual", T_EQUALS },
+ { "versionAtLeast", T_VERSION_AT_LEAST },
+ { "versionAtMost", T_VERSION_AT_MOST },
{ "exists", T_EXISTS },
{ "export", T_EXPORT },
{ "clear", T_CLEAR },
@@ -569,7 +573,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
}
} else {
if (args.count() != 1) {
- evalError(fL1S("%1(var) requires one argument.").arg(func.toQString(m_tmp1)));
+ evalError(fL1S("%1(var) requires one argument.").arg(func.toQStringView()));
} else {
var = args[0];
regexp = true;
@@ -603,7 +607,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
} else {
QString tmp = args.at(0).toQString(m_tmp1);
for (int i = 1; i < args.count(); ++i)
- tmp = tmp.arg(args.at(i).toQString(m_tmp2));
+ tmp = tmp.arg(args.at(i).toQStringView());
ret << (tmp.isSharedWith(m_tmp1) ? args.at(0) : ProString(tmp).setSource(args.at(0)));
}
break;
@@ -636,7 +640,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
leftalign = true;
} else {
evalError(fL1S("format_number(): invalid format option %1.")
- .arg(opt.toQString(m_tmp3)));
+ .arg(opt.toQStringView()));
goto formfail;
}
}
@@ -649,7 +653,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
qlonglong num = args.at(0).toLongLong(&ok, ibase);
if (!ok) {
evalError(fL1S("format_number(): malformed number %2 for base %1.")
- .arg(ibase).arg(args.at(0).toQString(m_tmp3)));
+ .arg(ibase).arg(args.at(0).toQStringView()));
break;
}
QString outstr;
@@ -691,7 +695,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
qlonglong num = arg.toLongLong(&ok);
if (!ok) {
evalError(fL1S("num_add(): malformed number %1.")
- .arg(arg.toQString(m_tmp3)));
+ .arg(arg.toQStringView()));
goto nafail;
}
sum += num;
@@ -778,7 +782,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
case E_FIRST:
case E_LAST:
if (args.count() != 1) {
- evalError(fL1S("%1(var) requires one argument.").arg(func.toQString(m_tmp1)));
+ evalError(fL1S("%1(var) requires one argument.").arg(func.toQStringView()));
} else {
const ProStringList &var = values(map(args.at(0)));
if (!var.isEmpty()) {
@@ -792,7 +796,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
case E_TAKE_FIRST:
case E_TAKE_LAST:
if (args.count() != 1) {
- evalError(fL1S("%1(var) requires one argument.").arg(func.toQString(m_tmp1)));
+ evalError(fL1S("%1(var) requires one argument.").arg(func.toQStringView()));
} else {
ProStringList &var = valuesRef(map(args.at(0)));
if (!var.isEmpty()) {
@@ -1120,7 +1124,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
case E_RESOLVE_DEPENDS:
if (args.count() < 1 || args.count() > 4) {
evalError(fL1S("%1(var, [prefix, [suffixes, [prio-suffix]]]) requires one to four arguments.")
- .arg(func.toQString(m_tmp1)));
+ .arg(func.toQStringView()));
} else {
QHash<ProKey, QSet<ProKey> > dependencies;
ProValueMap dependees;
@@ -1261,7 +1265,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinExpand(
}
break;
default:
- evalError(fL1S("Function '%1' is not implemented.").arg(func.toQString(m_tmp1)));
+ evalError(fL1S("Function '%1' is not implemented.").arg(func.toQStringView()));
break;
}
@@ -1291,7 +1295,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
return returnBool(findValues(var, &it));
}
evalError(fL1S("defined(function, type): unexpected type [%1].")
- .arg(args.at(1).toQString(m_tmp1)));
+ .arg(args.at(1).toQStringView()));
return ReturnFalse;
}
return returnBool(m_functionDefs.replaceFunctions.contains(var)
@@ -1432,12 +1436,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
}
if (args.count() == 1)
return returnBool(isActiveConfig(args.at(0).toQStringRef()));
- const QStringList &mutuals = args.at(1).toQString(m_tmp2).split(QLatin1Char('|'));
+ const auto mutuals = args.at(1).toQStringRef().split(QLatin1Char('|'));
const ProStringList &configs = values(statics.strCONFIG);
for (int i = configs.size() - 1; i >= 0; i--) {
for (int mut = 0; mut < mutuals.count(); mut++) {
- if (configs[i] == mutuals[mut].trimmed())
+ if (configs[i].toQStringRef() == mutuals[mut].trimmed())
return returnBool(configs[i] == args[0]);
}
}
@@ -1466,11 +1470,11 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
t ^= 1;
}
} else {
- const QStringList &mutuals = args.at(2).toQString(m_tmp3).split(QLatin1Char('|'));
+ const auto mutuals = args.at(2).toQStringRef().split(QLatin1Char('|'));
for (int i = l.size() - 1; i >= 0; i--) {
const ProString val = l[i];
for (int mut = 0; mut < mutuals.count(); mut++) {
- if (val == mutuals[mut].trimmed()) {
+ if (val.toQStringRef() == mutuals[mut].trimmed()) {
return returnBool((!regx.isEmpty()
&& regx.exactMatch(val.toQString(m_tmp2)))
|| val == qry);
@@ -1501,7 +1505,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
|| comp == QLatin1String("=") || comp == QLatin1String("==")) {
// fallthrough
} else {
- evalError(fL1S("Unexpected modifier to count(%2).").arg(comp.toQString(m_tmp1)));
+ evalError(fL1S("Unexpected modifier to count(%2).").arg(comp.toQStringView()));
return ReturnFalse;
}
}
@@ -1511,7 +1515,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
case T_LESSTHAN: {
if (args.count() != 2) {
evalError(fL1S("%1(variable, value) requires two arguments.")
- .arg(function.toQString(m_tmp1)));
+ .arg(function.toQStringView()));
return ReturnFalse;
}
const ProString &rhs = args.at(1);
@@ -1533,15 +1537,28 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
case T_EQUALS:
if (args.count() != 2) {
evalError(fL1S("%1(variable, value) requires two arguments.")
- .arg(function.toQString(m_tmp1)));
+ .arg(function.toQStringView()));
return ReturnFalse;
}
return returnBool(values(map(args.at(0))).join(statics.field_sep)
- == args.at(1).toQString(m_tmp1));
+ == args.at(1).toQStringView());
+ case T_VERSION_AT_LEAST:
+ case T_VERSION_AT_MOST: {
+ if (args.count() != 2) {
+ evalError(fL1S("%1(variable, versionNumber) requires two arguments.")
+ .arg(function.toQStringView()));
+ return ReturnFalse;
+ }
+ const QVersionNumber lvn = QVersionNumber::fromString(values(args.at(0).toKey()).join('.'));
+ const QVersionNumber rvn = QVersionNumber::fromString(args.at(1).toQStringView());
+ if (func_t == T_VERSION_AT_LEAST)
+ return returnBool(lvn >= rvn);
+ return returnBool(lvn <= rvn);
+ }
case T_CLEAR: {
if (args.count() != 1) {
evalError(fL1S("%1(variable) requires one argument.")
- .arg(function.toQString(m_tmp1)));
+ .arg(function.toQStringView()));
return ReturnFalse;
}
ProValueMap *hsh;
@@ -1558,7 +1575,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
case T_UNSET: {
if (args.count() != 1) {
evalError(fL1S("%1(variable) requires one argument.")
- .arg(function.toQString(m_tmp1)));
+ .arg(function.toQStringView()));
return ReturnFalse;
}
ProValueMap *hsh;
@@ -1665,7 +1682,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
case T_MESSAGE: {
if (args.count() != 1) {
evalError(fL1S("%1(message) requires one argument.")
- .arg(function.toQString(m_tmp1)));
+ .arg(function.toQStringView()));
return ReturnFalse;
}
const QString &msg = m_option->expandEnvVars(args.at(0).toQString(m_tmp2));
@@ -1846,7 +1863,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
srcvar = dstvar;
ProValueMap::Iterator srcvarIt;
if (!findValues(srcvar, &srcvarIt)) {
- evalError(fL1S("Variable %1 is not defined.").arg(srcvar.toQString(m_tmp1)));
+ evalError(fL1S("Variable %1 is not defined.").arg(srcvar.toQStringView()));
return ReturnFalse;
}
// The caches for the host and target may differ (e.g., when we are manipulating
@@ -1975,7 +1992,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional(
#endif
return ReturnTrue;
default:
- evalError(fL1S("Function '%1' is not implemented.").arg(function.toQString(m_tmp1)));
+ evalError(fL1S("Function '%1' is not implemented.").arg(function.toQStringView()));
return ReturnFalse;
}
}
diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp
index b0ed01e3aa..12e2827788 100644
--- a/qmake/library/qmakeevaluator.cpp
+++ b/qmake/library/qmakeevaluator.cpp
@@ -1582,7 +1582,7 @@ ProString QMakeEvaluator::propertyValue(const ProKey &name) const
return ProString(m_mkspecPaths.join(m_option->dirlist_sep));
ProString ret = m_option->propertyValue(name);
// if (ret.isNull())
-// evalError(fL1S("Querying unknown property %1").arg(name.toQString(m_mtmp)));
+// evalError(fL1S("Querying unknown property %1").arg(name.toQStringView()));
return ret;
}
@@ -1775,7 +1775,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditionalFunction(
}
skipExpression(tokPtr);
- evalError(fL1S("'%1' is not a recognized test function.").arg(func.toQString(m_tmp1)));
+ evalError(fL1S("'%1' is not a recognized test function.").arg(func.toQStringView()));
return ReturnFalse;
}
@@ -1801,7 +1801,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateExpandFunction(
}
skipExpression(tokPtr);
- evalError(fL1S("'%1' is not a recognized replace function.").arg(func.toQString(m_tmp1)));
+ evalError(fL1S("'%1' is not a recognized replace function.").arg(func.toQStringView()));
return ReturnFalse;
}
diff --git a/qmake/option.cpp b/qmake/option.cpp
index 4da2a1ae2c..9737f1f680 100644
--- a/qmake/option.cpp
+++ b/qmake/option.cpp
@@ -352,16 +352,19 @@ Option::init(int argc, char **argv)
}
}
}
- if (!globals->qmake_abslocation.isNull())
- globals->qmake_abslocation = QDir::cleanPath(globals->qmake_abslocation);
- else // This is rather unlikely to ever happen on a modern system ...
- globals->qmake_abslocation = QLibraryInfo::rawLocation(QLibraryInfo::HostBinariesPath,
- QLibraryInfo::EffectivePaths) +
+ if (Q_UNLIKELY(globals->qmake_abslocation.isNull())) {
+ // This is rather unlikely to ever happen on a modern system ...
+ globals->qmake_abslocation = QLibraryInfo::rawLocation(
+ QLibraryInfo::HostBinariesPath,
+ QLibraryInfo::EffectivePaths)
#ifdef Q_OS_WIN
- "/qmake.exe";
+ + "/qmake.exe";
#else
- "/qmake";
+ + "/qmake";
#endif
+ } else {
+ globals->qmake_abslocation = QDir::cleanPath(globals->qmake_abslocation);
+ }
} else {
Option::qmake_mode = Option::QMAKE_GENERATE_MAKEFILE;
}
diff --git a/qmake/project.cpp b/qmake/project.cpp
index 3a073b0954..e8509ad096 100644
--- a/qmake/project.cpp
+++ b/qmake/project.cpp
@@ -91,7 +91,7 @@ bool QMakeProject::test(const ProKey &func, const QList<ProStringList> &args)
return boolRet(evaluateBoolFunction(*it, args, func));
evalError(QStringLiteral("'%1' is not a recognized test function.")
- .arg(func.toQString(m_tmp1)));
+ .arg(func.toQStringView()));
return false;
}
@@ -116,7 +116,7 @@ QStringList QMakeProject::expand(const ProKey &func, const QList<ProStringList>
}
evalError(QStringLiteral("'%1' is not a recognized replace function.")
- .arg(func.toQString(m_tmp1)));
+ .arg(func.toQStringView()));
return QStringList();
}
diff --git a/qmake/qmake.pri b/qmake/qmake.pri
index c0f7250bcf..f6f6a47e95 100644
--- a/qmake/qmake.pri
+++ b/qmake/qmake.pri
@@ -68,6 +68,7 @@ bootstrap { #Qt code
qlibraryinfo.cpp \
qsystemerror.cpp \
qvariant.cpp \
+ qversionnumber.cpp \
qvsnprintf.cpp \
qxmlstream.cpp \
qxmlutils.cpp \
@@ -119,6 +120,7 @@ bootstrap { #Qt code
qtextstream.h \
quuid.h \
qvector.h \
+ qversionnumber.h \
qxmlstream.h \
qxmlutils.h \
qjson.h \
@@ -132,8 +134,7 @@ bootstrap { #Qt code
unix {
SOURCES += qfilesystemengine_unix.cpp qfilesystemiterator_unix.cpp qfsfileengine_unix.cpp
mac {
- SOURCES += qcore_mac.cpp qsettings_mac.cpp
- OBJECTIVE_SOURCES += qcore_mac_objc.mm qlocale_mac.mm
+ SOURCES += qcore_mac.cpp qsettings_mac.cpp qcore_mac_objc.mm qlocale_mac.mm
LIBS += -framework ApplicationServices -framework CoreServices -framework Foundation
} else {
SOURCES += qlocale_unix.cpp
@@ -141,8 +142,8 @@ bootstrap { #Qt code
} else:win32 {
SOURCES += qfilesystemengine_win.cpp qfsfileengine_win.cpp qfilesystemiterator_win.cpp qsettings_win.cpp \
qsystemlibrary.cpp qlocale_win.cpp registry.cpp
- win32-msvc*:LIBS += ole32.lib advapi32.lib
- mingw:LIBS += -lole32 -luuid -ladvapi32 -lkernel32
+ win32-msvc*:LIBS += ole32.lib advapi32.lib netapi32.lib
+ mingw:LIBS += -lole32 -luuid -ladvapi32 -lkernel32 -lnetapi32
}
qnx {
diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
index 3b7b11c8ee..e5746bf3eb 100644
--- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
+++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
@@ -168,21 +168,7 @@ contains(SHAPERS, coretext) {
# even in 10.8 where they were also made available stand-alone.
LIBS_PRIVATE += -framework ApplicationServices
- # CoreText is documented to be available on watchOS, but the headers aren't present
- # in the watchOS Simulator SDK like they are supposed to be. Work around the problem
- # by adding the device SDK's headers to the search path as a fallback.
- # rdar://25314492, rdar://27844864
- watchos:simulator {
- simulator_system_frameworks = $$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks
- device_system_frameworks = $$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks
- for (arch, QMAKE_APPLE_SIMULATOR_ARCHS) {
- QMAKE_CXXFLAGS += \
- -Xarch_$${arch} \
- -F$$simulator_system_frameworks \
- -Xarch_$${arch} \
- -F$$device_system_frameworks
- }
- }
+ CONFIG += watchos_coretext
}
contains(SHAPERS, fallback)|isEmpty(SHAPERS) {
diff --git a/src/3rdparty/iaccessible2/generated/x86/ia2_api_all.h b/src/3rdparty/iaccessible2/generated/x86/ia2_api_all.h
index eb3b57b8bd..9e4be75bb9 100644
--- a/src/3rdparty/iaccessible2/generated/x86/ia2_api_all.h
+++ b/src/3rdparty/iaccessible2/generated/x86/ia2_api_all.h
@@ -16,7 +16,9 @@
*/
/* @@MIDL_FILE_HEADING( ) */
-#pragma warning( disable: 4049 ) /* more than 64k source lines */
+#ifdef _MSC_VER
+# pragma warning( disable: 4049 ) /* more than 64k source lines */
+#endif
/* verify that the <rpcndr.h> version is high enough to compile this file*/
diff --git a/src/3rdparty/iaccessible2/generated/x86/ia2_api_all_i.c b/src/3rdparty/iaccessible2/generated/x86/ia2_api_all_i.c
index c50b3e9a4f..61bb5ee5f7 100644
--- a/src/3rdparty/iaccessible2/generated/x86/ia2_api_all_i.c
+++ b/src/3rdparty/iaccessible2/generated/x86/ia2_api_all_i.c
@@ -18,7 +18,9 @@
*/
/* @@MIDL_FILE_HEADING( ) */
-#pragma warning( disable: 4049 ) /* more than 64k source lines */
+#ifdef _MSC_VER
+# pragma warning( disable: 4049 ) /* more than 64k source lines */
+#endif
#ifdef __cplusplus
@@ -65,7 +67,7 @@ typedef IID CLSID;
#define MIDL_DEFINE_GUID(type,name,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) \
const type name = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
-#endif !_MIDL_USE_GUIDDEF_
+#endif // !_MIDL_USE_GUIDDEF_
MIDL_DEFINE_GUID(IID, IID_IAccessibleRelation,0x7CDF86EE,0xC3DA,0x496a,0xBD,0xA4,0x28,0x1B,0x33,0x6E,0x1F,0xDC);
diff --git a/src/3rdparty/icc/LICENSE.txt b/src/3rdparty/icc/LICENSE.txt
new file mode 100644
index 0000000000..e25b1d39f1
--- /dev/null
+++ b/src/3rdparty/icc/LICENSE.txt
@@ -0,0 +1,10 @@
+For the file sRGB2014.icc:
+
+Copyright International Color Consortium, 2015
+
+This profile is made available by the International Color Consortium, and may be copied,
+distributed, embedded, made, used, and sold without restriction. Altered versions of this
+profile shall have the original identification and copyright information removed and
+shall not be misrepresented as the original profile.
+
+(original source location: http://www.color.org/srgbprofiles.xalter)
diff --git a/src/3rdparty/icc/qt_attribution.json b/src/3rdparty/icc/qt_attribution.json
new file mode 100644
index 0000000000..7a1c813522
--- /dev/null
+++ b/src/3rdparty/icc/qt_attribution.json
@@ -0,0 +1,15 @@
+[
+ {
+ "Id": "icc-sRGB-color-profile",
+ "Name": "sRGB color profile icc file",
+ "QDocModule": "qtgui",
+ "QtUsage": "Used in Qt Gui (Embedded into PDF/A-1b files generated by QPrinter/QPdfWriter).",
+ "Files": "sRGB2014.icc",
+
+ "Description": "An ICC color profile for PDF/A-1b compatible PDF files.",
+ "LicenseId": "ICC License",
+ "License": "International Color Consortium License",
+ "LicenseFile": "LICENSE.txt",
+ "Copyright": "Copyright International Color Consortium, 2015"
+ }
+]
diff --git a/src/3rdparty/icc/sRGB2014.icc b/src/3rdparty/icc/sRGB2014.icc
new file mode 100644
index 0000000000..49afbfef10
--- /dev/null
+++ b/src/3rdparty/icc/sRGB2014.icc
Binary files differ
diff --git a/src/3rdparty/sqlite.pri b/src/3rdparty/sqlite.pri
index 79179daaf4..91083f84c4 100644
--- a/src/3rdparty/sqlite.pri
+++ b/src/3rdparty/sqlite.pri
@@ -1,5 +1,5 @@
CONFIG(release, debug|release):DEFINES *= NDEBUG
-DEFINES += SQLITE_OMIT_LOAD_EXTENSION SQLITE_OMIT_COMPLETE SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_FTS5 SQLITE_ENABLE_RTREE
+DEFINES += SQLITE_ENABLE_COLUMN_METADATA SQLITE_OMIT_LOAD_EXTENSION SQLITE_OMIT_COMPLETE SQLITE_ENABLE_FTS3 SQLITE_ENABLE_FTS3_PARENTHESIS SQLITE_ENABLE_FTS5 SQLITE_ENABLE_RTREE
!contains(CONFIG, largefile):DEFINES += SQLITE_DISABLE_LFS
qtConfig(posix_fallocate): DEFINES += HAVE_POSIX_FALLOCATE=1
winrt: DEFINES += SQLITE_OS_WINRT
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index 32d4abf43a..720a35902b 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -63,6 +63,9 @@ import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AlphaAnimation;
+import android.view.animation.Animation;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.KeyCharacterMap;
@@ -997,10 +1000,36 @@ public class QtActivityDelegate
public void hideSplashScreen()
{
+ hideSplashScreen(0);
+ }
+
+ public void hideSplashScreen(final int duration)
+ {
if (m_splashScreen == null)
return;
- m_layout.removeView(m_splashScreen);
- m_splashScreen = null;
+
+ if (duration <= 0) {
+ m_layout.removeView(m_splashScreen);
+ m_splashScreen = null;
+ return;
+ }
+
+ final Animation fadeOut = new AlphaAnimation(1, 0);
+ fadeOut.setInterpolator(new AccelerateInterpolator());
+ fadeOut.setDuration(duration);
+
+ fadeOut.setAnimationListener(new Animation.AnimationListener() {
+ @Override
+ public void onAnimationEnd(Animation animation) { hideSplashScreen(0); }
+
+ @Override
+ public void onAnimationRepeat(Animation animation) {}
+
+ @Override
+ public void onAnimationStart(Animation animation) {}
+ });
+
+ m_splashScreen.startAnimation(fadeOut);
}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index 902e2f68e7..f15c7f3a97 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -49,12 +49,14 @@ import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.ActivityInfo;
import android.net.Uri;
+import android.os.Build;
import android.os.Handler;
+import android.os.IBinder;
import android.os.Looper;
import android.content.ClipboardManager;
import android.content.ClipboardManager.OnPrimaryClipChangedListener;
-import android.os.Build;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyEvent;
@@ -188,7 +190,21 @@ public class QtNative
for (String libName : libraries) {
try {
- File f = new File(nativeLibraryDir+"lib"+libName+".so");
+ String libNameTemplate = "lib" + libName + ".so";
+ File f = new File(nativeLibraryDir + libNameTemplate);
+ if (!f.exists()) {
+ Log.i(QtTAG, "Can't find '" + f.getAbsolutePath());
+ try {
+ ActivityInfo info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(),
+ PackageManager.GET_META_DATA);
+ String systemLibraryDir = QtNativeLibrariesDir.systemLibrariesDir;
+ if (info.metaData.containsKey("android.app.system_libs_prefix"))
+ systemLibraryDir = info.metaData.getString("android.app.system_libs_prefix");
+ f = new File(systemLibraryDir + libNameTemplate);
+ } catch (Exception e) {
+
+ }
+ }
if (f.exists())
System.load(f.getAbsolutePath());
else
@@ -281,7 +297,20 @@ public class QtNative
String mainLibrary,
String nativeLibraryDir) throws Exception
{
- File f = new File(nativeLibraryDir + "lib" + mainLibrary + ".so");
+ String mainLibNameTemplate = "lib" + mainLibrary + ".so";
+ File f = new File(nativeLibraryDir + mainLibNameTemplate);
+ if (!f.exists()) {
+ try {
+ ActivityInfo info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(),
+ PackageManager.GET_META_DATA);
+ String systemLibraryDir = QtNativeLibrariesDir.systemLibrariesDir;
+ if (info.metaData.containsKey("android.app.system_libs_prefix"))
+ systemLibraryDir = info.metaData.getString("android.app.system_libs_prefix");
+ f = new File(systemLibraryDir + mainLibNameTemplate);
+ } catch (Exception e) {
+
+ }
+ }
if (!f.exists())
throw new Exception("Can't find main library '" + mainLibrary + "'");
@@ -786,13 +815,13 @@ public class QtNative
});
}
- private static void hideSplashScreen()
+ private static void hideSplashScreen(final int duration)
{
runAction(new Runnable() {
@Override
public void run() {
if (m_activityDelegate != null)
- m_activityDelegate.hideSplashScreen();
+ m_activityDelegate.hideSplashScreen(duration);
}
});
}
@@ -880,4 +909,9 @@ public class QtNative
private static native void setNativeActivity(Activity activity);
private static native void setNativeService(Service service);
+ // activity methods
+
+ // service methods
+ public static native IBinder onBind(Intent intent);
+ // service methods
}
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java b/src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java
index ff3bf19383..4a732f7f7f 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNativeLibrariesDir.java
@@ -45,6 +45,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.NameNotFoundException;
public class QtNativeLibrariesDir {
+ public static final String systemLibrariesDir = "/system/lib/";
public static String nativeLibrariesDir(Context context)
{
String m_nativeLibraryDir = null;
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java
index 035a65a84c..195ec376c9 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtServiceDelegate.java
@@ -53,6 +53,7 @@ import android.net.LocalSocket;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
+import android.os.IBinder;
import android.os.ResultReceiver;
import android.text.method.MetaKeyKeyListener;
import android.util.Base64;
@@ -187,4 +188,11 @@ public class QtServiceDelegate
{
QtNative.quitQtCoreApplication();
}
+
+ public IBinder onBind(Intent intent)
+ {
+ synchronized (this) {
+ return QtNative.onBind(intent);
+ }
+ }
}
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
index 69f351033d..99c4ecca07 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtLoader.java
@@ -84,6 +84,7 @@ public abstract class QtLoader {
public static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables";
public static final String APPLICATION_PARAMETERS_KEY = "application.parameters";
public static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
+ public static final String QT_LIBS_RESOURCE_ID_KEY = "android.app.qt_libs_resource_id";
public static final String BUNDLED_IN_LIB_RESOURCE_ID_KEY = "android.app.bundled_in_lib_resource_id";
public static final String BUNDLED_IN_ASSETS_RESOURCE_ID_KEY = "android.app.bundled_in_assets_resource_id";
public static final String MAIN_LIBRARY_KEY = "main.library";
@@ -92,6 +93,10 @@ public abstract class QtLoader {
public static final String EXTRACT_STYLE_KEY = "extract.android.style";
private static final String EXTRACT_STYLE_MINIMAL_KEY = "extract.android.style.option";
+ // These parameters matter in case of deploying application as system (embedded into firmware)
+ public static final String SYSTEM_LIB_PATH = "/system/lib/";
+ public String[] SYSTEM_APP_PATHS = {"/system/priv-app/", "/system/app/"};
+
/// Ministro server parameter keys
public static final String REQUIRED_MODULES_KEY = "required.modules";
public static final String APPLICATION_TITLE_KEY = "application.title";
@@ -106,7 +111,6 @@ public abstract class QtLoader {
public static final String REPOSITORY_KEY = "repository"; // use this key to overwrite the default ministro repsitory
public static final String ANDROID_THEMES_KEY = "android.themes"; // themes that your application uses
-
public String APPLICATION_PARAMETERS = null; // use this variable to pass any parameters to your application,
// the parameters must not contain any white spaces
// and must be separated with "\t"
@@ -210,11 +214,11 @@ public abstract class QtLoader {
// add all bundled Qt libs to loader params
ArrayList<String> libs = new ArrayList<String>();
- if ( m_contextInfo.metaData.containsKey("android.app.bundled_libs_resource_id") )
+ if (m_contextInfo.metaData.containsKey("android.app.bundled_libs_resource_id"))
libs.addAll(Arrays.asList(m_context.getResources().getStringArray(m_contextInfo.metaData.getInt("android.app.bundled_libs_resource_id"))));
String libName = null;
- if ( m_contextInfo.metaData.containsKey("android.app.lib_name") ) {
+ if (m_contextInfo.metaData.containsKey("android.app.lib_name")) {
libName = m_contextInfo.metaData.getString("android.app.lib_name");
loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function
}
@@ -408,13 +412,9 @@ public abstract class QtLoader {
}
}
- private void extractBundledPluginsAndImports(String pluginsPrefix)
+ private void extractBundledPluginsAndImports(String pluginsPrefix, String libsDir)
throws IOException
{
- ArrayList<String> libs = new ArrayList<String>();
-
- String libsDir = m_context.getApplicationInfo().nativeLibraryDir + "/";
-
long packageVersion = -1;
try {
PackageInfo packageInfo = m_context.getPackageManager().getPackageInfo(m_context.getPackageName(), 0);
@@ -530,6 +530,35 @@ public abstract class QtLoader {
&& m_contextInfo.metaData.getInt("android.app.use_local_qt_libs") == 1) {
ArrayList<String> libraryList = new ArrayList<String>();
+ boolean apkDeployFromSystem = false;
+ String apkPath = m_context.getApplicationInfo().publicSourceDir;
+ File apkFile = new File(apkPath);
+ if (apkFile.exists() && Arrays.asList(SYSTEM_APP_PATHS).contains(apkFile.getParentFile().getAbsolutePath() + "/"))
+ apkDeployFromSystem = true;
+
+ String libsDir = null;
+ if (apkDeployFromSystem) {
+ String systemLibsPrefix = SYSTEM_LIB_PATH;
+ if (m_contextInfo.metaData.containsKey("android.app.system_libs_prefix")) {
+ systemLibsPrefix = m_contextInfo.metaData.getString("android.app.system_libs_prefix");
+ } else {
+ Log.e(QtApplication.QtTAG, "It looks like app deployed as system app. "
+ + "It may be necessary to specify path to system lib directory using "
+ + "android.app.system_libs_prefix metadata variable in your AndroidManifest.xml");
+ Log.e(QtApplication.QtTAG, "Using " + SYSTEM_LIB_PATH + " as default path");
+ }
+ File systemLibraryDir = new File(systemLibsPrefix);
+ if (systemLibraryDir.exists() && systemLibraryDir.isDirectory() && systemLibraryDir.list().length > 0)
+ libsDir = systemLibsPrefix;
+ } else {
+ String nativeLibraryPrefix = m_context.getApplicationInfo().nativeLibraryDir + "/";
+ File nativeLibraryDir = new File(nativeLibraryPrefix);
+ if (nativeLibraryDir.exists() && nativeLibraryDir.isDirectory() && nativeLibraryDir.list().length > 0)
+ libsDir = nativeLibraryPrefix;
+ }
+
+ if (apkDeployFromSystem && libsDir == null)
+ throw new Exception("");
String localPrefix = "/data/local/tmp/qt/";
if (m_contextInfo.metaData.containsKey("android.app.libs_prefix"))
@@ -542,33 +571,30 @@ public abstract class QtLoader {
&& m_contextInfo.metaData.getInt("android.app.bundle_local_qt_libs") == 1) {
localPrefix = m_context.getApplicationInfo().dataDir + "/";
pluginsPrefix = localPrefix + "qt-reserved-files/";
+
+ if (libsDir == null)
+ throw new Exception("");
+
cleanOldCacheIfNecessary(localPrefix, pluginsPrefix);
- extractBundledPluginsAndImports(pluginsPrefix);
+ extractBundledPluginsAndImports(pluginsPrefix, libsDir);
+
bundlingQtLibs = true;
}
if (m_qtLibs != null) {
- for (int i=0;i<m_qtLibs.length;i++) {
- libraryList.add(localPrefix
- + "lib/lib"
- + m_qtLibs[i]
- + ".so");
- }
+ String libPrefix = apkDeployFromSystem ? libsDir + "lib" : localPrefix + "lib/lib";
+ for (int i = 0; i < m_qtLibs.length; i++)
+ libraryList.add(libPrefix + m_qtLibs[i] + ".so");
}
if (m_contextInfo.metaData.containsKey("android.app.load_local_libs")) {
String[] extraLibs = m_contextInfo.metaData.getString("android.app.load_local_libs").split(":");
for (String lib : extraLibs) {
- if (lib.length() > 0) {
- if (lib.startsWith("lib/"))
- libraryList.add(localPrefix + lib);
- else
- libraryList.add(pluginsPrefix + lib);
- }
- }
+ if (lib.length() > 0)
+ libraryList.add((lib.startsWith("lib/") ? localPrefix : pluginsPrefix) + lib);
+ }
}
-
String dexPaths = new String();
String pathSeparator = System.getProperty("path.separator", ":");
if (!bundlingQtLibs && m_contextInfo.metaData.containsKey("android.app.load_local_jars")) {
diff --git a/src/android/templates/AndroidManifest.xml b/src/android/templates/AndroidManifest.xml
index 066ec0a63c..62e9d0f11c 100644
--- a/src/android/templates/AndroidManifest.xml
+++ b/src/android/templates/AndroidManifest.xml
@@ -30,6 +30,8 @@
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
+ <!-- Used to specify custom system library path to run with local system libs -->
+ <!-- <meta-data android:name="android.app.system_libs_prefix" android:value="/system/lib/"/> -->
<!-- Messages maps -->
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index aed3532024..4f0cd914ca 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -43,6 +43,7 @@
#ifndef QT_NO_TEXTCODEC
+#include "qbytearraymatcher.h"
#include "qlist.h"
#include "qfile.h"
#include "qstringlist.h"
@@ -803,6 +804,7 @@ QTextEncoder* QTextCodec::makeEncoder(QTextCodec::ConversionFlags flags) const
The \a state of the convertor used is updated.
*/
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Converts \a str from Unicode to the encoding of this codec, and
returns the result in a QByteArray.
@@ -811,6 +813,19 @@ QByteArray QTextCodec::fromUnicode(const QString& str) const
{
return convertFromUnicode(str.constData(), str.length(), 0);
}
+#endif
+
+/*!
+ \overload
+ \since 5.10
+
+ Converts \a str from Unicode to the encoding of this codec, and
+ returns the result in a QByteArray.
+*/
+QByteArray QTextCodec::fromUnicode(QStringView str) const
+{
+ return convertFromUnicode(str.data(), str.length(), nullptr);
+}
/*!
\fn QString QTextCodec::toUnicode(const char *input, int size,
@@ -844,6 +859,7 @@ bool QTextCodec::canEncode(QChar ch) const
return (state.invalidChars == 0);
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\overload
@@ -856,7 +872,22 @@ bool QTextCodec::canEncode(const QString& s) const
convertFromUnicode(s.constData(), s.length(), &state);
return (state.invalidChars == 0);
}
+#endif
+
+/*!
+ \overload
+ \since 5.10
+ Returns \c true if the Unicode string \a s can be fully encoded
+ with this codec; otherwise returns \c false.
+*/
+bool QTextCodec::canEncode(QStringView s) const
+{
+ ConverterState state;
+ state.flags = ConvertInvalidToNull;
+ convertFromUnicode(s.data(), s.length(), &state);
+ return !state.invalidChars;
+}
/*!
\overload
@@ -921,6 +952,7 @@ bool QTextEncoder::hasFailure() const
return state.invalidChars != 0;
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Converts the Unicode string \a str into an encoded QByteArray.
*/
@@ -929,6 +961,17 @@ QByteArray QTextEncoder::fromUnicode(const QString& str)
QByteArray result = c->fromUnicode(str.constData(), str.length(), &state);
return result;
}
+#endif
+
+/*!
+ \overload
+ \since 5.10
+ Converts the Unicode string \a str into an encoded QByteArray.
+*/
+QByteArray QTextEncoder::fromUnicode(QStringView str)
+{
+ return c->fromUnicode(str.data(), str.length(), &state);
+}
/*!
\overload
@@ -1050,10 +1093,12 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCo
// determine charset
QTextCodec *c = QTextCodec::codecForUtfText(ba, 0);
if (!c) {
+ static Q_RELAXED_CONSTEXPR auto matcher = qMakeStaticByteArrayMatcher("meta ");
QByteArray header = ba.left(1024).toLower();
- int pos = header.indexOf("meta ");
+ int pos = matcher.indexIn(header);
if (pos != -1) {
- pos = header.indexOf("charset=", pos);
+ static Q_RELAXED_CONSTEXPR auto matcher = qMakeStaticByteArrayMatcher("charset=");
+ pos = matcher.indexIn(header, pos);
if (pos != -1) {
pos += qstrlen("charset=");
diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h
index 47b2fe6eed..5163d37238 100644
--- a/src/corelib/codecs/qtextcodec.h
+++ b/src/corelib/codecs/qtextcodec.h
@@ -79,11 +79,17 @@ public:
static QTextCodec *codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec);
bool canEncode(QChar) const;
+#if QT_STRINGVIEW_LEVEL < 2
bool canEncode(const QString&) const;
+#endif
+ bool canEncode(QStringView) const;
QString toUnicode(const QByteArray&) const;
QString toUnicode(const char* chars) const;
+#if QT_STRINGVIEW_LEVEL < 2
QByteArray fromUnicode(const QString& uc) const;
+#endif
+ QByteArray fromUnicode(QStringView uc) const;
enum ConversionFlag {
DefaultConversion,
ConvertInvalidToNull = 0x80000000,
@@ -133,9 +139,12 @@ class Q_CORE_EXPORT QTextEncoder {
Q_DISABLE_COPY(QTextEncoder)
public:
explicit QTextEncoder(const QTextCodec *codec) : c(codec), state() {}
- QTextEncoder(const QTextCodec *codec, QTextCodec::ConversionFlags flags);
+ explicit QTextEncoder(const QTextCodec *codec, QTextCodec::ConversionFlags flags);
~QTextEncoder();
+#if QT_STRINGVIEW_LEVEL < 2
QByteArray fromUnicode(const QString& str);
+#endif
+ QByteArray fromUnicode(QStringView str);
QByteArray fromUnicode(const QChar *uc, int len);
bool hasFailure() const;
private:
@@ -147,7 +156,7 @@ class Q_CORE_EXPORT QTextDecoder {
Q_DISABLE_COPY(QTextDecoder)
public:
explicit QTextDecoder(const QTextCodec *codec) : c(codec), state() {}
- QTextDecoder(const QTextCodec *codec, QTextCodec::ConversionFlags flags);
+ explicit QTextDecoder(const QTextCodec *codec, QTextCodec::ConversionFlags flags);
~QTextDecoder();
QString toUnicode(const char* chars, int len);
QString toUnicode(const QByteArray &ba);
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
index 91f7bb4fd6..c8fede2b8f 100644
--- a/src/corelib/configure.json
+++ b/src/corelib/configure.json
@@ -251,6 +251,11 @@
]
}
},
+ "cxx11_random": {
+ "label": "C++11 <random>",
+ "type": "compile",
+ "test": "unix/cxx11_random"
+ },
"eventfd": {
"label": "eventfd",
"type": "compile",
@@ -264,6 +269,26 @@
]
}
},
+ "futimens": {
+ "label": "futimens()",
+ "type": "compile",
+ "test": "unix/futimens"
+ },
+ "futimes": {
+ "label": "futimes()",
+ "type": "compile",
+ "test": "unix/futimes"
+ },
+ "getauxval": {
+ "label": "getauxval()",
+ "type": "compile",
+ "test": "unix/getauxval"
+ },
+ "getentropy": {
+ "label": "getentropy()",
+ "type": "compile",
+ "test": "unix/getentropy"
+ },
"posix-iconv": {
"label": "POSIX iconv",
"type": "compile",
@@ -349,6 +374,15 @@
]
}
},
+ "renameat2": {
+ "label": "renameat2()",
+ "type": "compile",
+ "test": {
+ "head": "#define _ATFILE_SOURCE 1",
+ "include": [ "fcntl.h", "stdio.h" ],
+ "main": "renameat2(AT_FDCWD, argv[1], AT_FDCWD, argv[2], RENAME_NOREPLACE | RENAME_WHITEOUT);"
+ }
+ },
"syslog": {
"label": "syslog",
"type": "compile",
@@ -395,11 +429,36 @@
"condition": "features.doubleconversion && libs.doubleconversion",
"output": [ "privateFeature" ]
},
+ "cxx11_random": {
+ "label": "C++11 <random>",
+ "condition": "tests.cxx11_random",
+ "output": [ "privateFeature" ]
+ },
"eventfd": {
"label": "eventfd",
"condition": "tests.eventfd",
"output": [ "feature" ]
},
+ "futimens": {
+ "label": "futimens()",
+ "condition": "!config.win32 && tests.futimens",
+ "output": [ "privateFeature" ]
+ },
+ "futimes": {
+ "label": "futimes()",
+ "condition": "!config.win32 && !features.futimens && tests.futimes",
+ "output": [ "privateFeature" ]
+ },
+ "getauxval": {
+ "label": "getauxval()",
+ "condition": "config.linux && tests.getauxval",
+ "output": [ "privateFeature" ]
+ },
+ "getentropy": {
+ "label": "getentropy()",
+ "condition": "config.unix && tests.getentropy",
+ "output": [ "privateFeature" ]
+ },
"glib": {
"label": "GLib",
"autoDetect": "!config.win32",
@@ -516,6 +575,11 @@
"condition": "features.statemachine",
"output": [ "publicFeature" ]
},
+ "renameat2": {
+ "label": "renameat2()",
+ "condition": "config.linux && tests.renameat2",
+ "output": [ "privateFeature" ]
+ },
"slog2": {
"label": "slog2",
"condition": "libs.slog2",
@@ -764,6 +828,11 @@ ensure that the IDEs they use either set QT_LOGGING_TO_CONSOLE to 1
or are able to read the logged output from journald, syslog or slog2."
},
{
+ "type": "warning",
+ "condition": "!config.win32 && !config.darwin && !config.bsd && !features.cxx11_random",
+ "message": "No high-quality PRNG available for QRandomGenerator fallback.\nIf the HW or OS RNG fails, Qt will abort execution."
+ },
+ {
"type": "error",
"condition": "input.doubleconversion == 'no' && !tests.xlocalescanprint",
"message": "Your C library does not provide sscanf_l or snprintf_l.
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 7d09070b81..376ef872ee 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -152,3 +152,5 @@ ctest_qt5_module_files.files += $$ctest_macros_file.output $$cmake_extras_mkspec
ctest_qt5_module_files.path = $$[QT_INSTALL_LIBS]/cmake/Qt5Core
INSTALLS += ctest_qt5_module_files cmake_qt5_umbrella_module_files
+
+QMAKE_DSYM_DEBUG_SCRIPT = $$PWD/debug_script.py
diff --git a/src/corelib/debug_script.py b/src/corelib/debug_script.py
new file mode 100644
index 0000000000..9111213ef7
--- /dev/null
+++ b/src/corelib/debug_script.py
@@ -0,0 +1,98 @@
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the QtCore module of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+import os
+import sys
+import imp
+
+from distutils.version import LooseVersion
+
+MODULE_NAME = 'qt'
+
+def import_bridge(path, debugger, session_dict, reload_module = False):
+ if not reload_module and MODULE_NAME in sys.modules:
+ del sys.modules[MODULE_NAME]
+
+ bridge = imp.load_source(MODULE_NAME, path)
+
+ if not hasattr(bridge, '__lldb_init_module'):
+ return None
+
+ # Make available for the current LLDB session, so that LLDB
+ # can find the functions when initializing the module.
+ session_dict[MODULE_NAME] = bridge
+
+ # Initialize the module now that it's available globally
+ bridge.__lldb_init_module(debugger, session_dict)
+
+ if not debugger.GetCategory('Qt'):
+ # Summary provider failed for some reason
+ del session_dict[MODULE_NAME]
+ return None
+
+ return bridge
+
+def report_success(bridge):
+ print "Using Qt summary providers from Creator %s in '%s'" \
+ % (bridge.CREATOR_VERSION, bridge.CREATOR_PATH)
+
+def __lldb_init_module(debugger, session_dict):
+ # Check if the module has already been imported globally. This ensures
+ # that the Qt Creator application search is only performed once per
+ # LLDB process invocation, while still reloading for each session.
+ if MODULE_NAME in sys.modules:
+ module = sys.modules[MODULE_NAME]
+ # Reload module for this sessions
+ bridge = import_bridge(module.__file__, debugger, session_dict,
+ reload_module = True)
+ if bridge:
+ report_success(bridge)
+ return
+
+ versions = {}
+ for install in os.popen(
+ 'mdfind kMDItemCFBundleIdentifier=org.qt-project.qtcreator'
+ '| while read p;'
+ 'do echo $p=$(mdls "$p" -name kMDItemVersion -raw);'
+ 'done'):
+ install = install.strip()
+ (p, v) = install.split('=')
+ versions[v] = p
+
+ for version in sorted(versions, key=LooseVersion, reverse=True):
+ path = versions[version]
+
+ bridge_path = path + '/Contents/Resources/debugger/lldbbridge.py'
+ bridge = import_bridge(bridge_path, debugger, session_dict)
+ if bridge:
+ bridge.CREATOR_VERSION = version
+ bridge.CREATOR_PATH = path
+ report_success(bridge)
+ return
+
+ print "Could not find Qt Creator installation, no Qt summary providers installed"
diff --git a/src/corelib/doc/snippets/code/doc_src_qpair.cpp b/src/corelib/doc/snippets/code/doc_src_qpair.cpp
index f94e3b0d37..e62f91830c 100644
--- a/src/corelib/doc/snippets/code/doc_src_qpair.cpp
+++ b/src/corelib/doc/snippets/code/doc_src_qpair.cpp
@@ -47,6 +47,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+#include <qmath.h>
//! [0]
QPair<QString, double> pair;
@@ -55,7 +56,7 @@ QPair<QString, double> pair;
//! [1]
pair.first = "pi";
-pair.second = 3.14159265358979323846;
+pair.second = M_PI;
//! [1]
//! [struct]
@@ -65,10 +66,10 @@ struct Variable {
};
Variable v;
v.name = "pi";
-v.value = 3.14159265358979323846;
+v.value = M_PI;
//! [struct]
//! [2]
QList<QPair<int, double> > list;
-list.append(qMakePair(66, 3.14159));
+list.append(qMakePair(66, M_PI));
//! [2]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qlocale.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qlocale.cpp
index 3794049f97..aed14c379f 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qlocale.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qlocale.cpp
@@ -103,3 +103,20 @@ d = german.toDouble( "1234.56", &ok ); // ok == false
d = german.toDouble( "1.234", &ok ); // ok == true, d == 1234.0
//! [3]
+
+//! [3-qstringview]
+bool ok;
+double d;
+
+QLocale c(QLocale::C);
+d = c.toDouble(u"1234.56", &ok); // ok == true, d == 1234.56
+d = c.toDouble(u"1,234.56", &ok); // ok == true, d == 1234.56
+d = c.toDouble(u"1234,56", &ok); // ok == false
+
+QLocale german(QLocale::German);
+d = german.toDouble(u"1234,56", &ok); // ok == true, d == 1234.56
+d = german.toDouble(u"1.234,56", &ok); // ok == true, d == 1234.56
+d = german.toDouble(u"1234.56", &ok); // ok == false
+
+d = german.toDouble(u"1.234", &ok); // ok == true, d == 1234.0
+//! [3-qstringview]
diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp
index 1fcb7b9945..7a2b4812ef 100644
--- a/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp
+++ b/src/corelib/doc/snippets/code/src_corelib_tools_qstringiterator.cpp
@@ -58,7 +58,7 @@ int main()
{
//! [0]
QString string(QStringLiteral("a string"));
-QStringIterator i(string);
+QStringIterator i(string); // implicitly converted to QStringView
//! [0]
//! [1]
@@ -71,8 +71,7 @@ while (i.hasNext())
{
//! [2]
-QString string(QStringLiteral("𝄞 is the G clef"));
-QStringIterator i(string);
+QStringIterator i(u"𝄞 is the G clef");
qDebug() << hex << i.next(); // will print 1d11e (U+1D11E, MUSICAL SYMBOL G CLEF)
qDebug() << hex << i.next(); // will print 20 (U+0020, SPACE)
qDebug() << hex << i.next(); // will print 69 (U+0069, LATIN SMALL LETTER I)
diff --git a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
index 39b03f5ff3..e91c41b305 100644
--- a/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
+++ b/src/corelib/doc/snippets/qsignalmapper/buttonwidget.cpp
@@ -49,6 +49,7 @@
****************************************************************************/
#include <QtGui>
+#include <QtWidgets>
#include "buttonwidget.h"
@@ -74,3 +75,18 @@ ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
setLayout(gridLayout);
}
//! [2]
+
+//! [3]
+ButtonWidget::ButtonWidget(const QStringList &texts, QWidget *parent)
+ : QWidget(parent)
+{
+ QGridLayout *gridLayout = new QGridLayout;
+ for (int i = 0; i < texts.size(); ++i) {
+ QString text = texts[i];
+ QPushButton *button = new QPushButton(text);
+ connect(button, &QPushButton::clicked, [=] { clicked(text); });
+ gridLayout->addWidget(button, i / 3, i % 3);
+ }
+ setLayout(gridLayout);
+}
+//! [3]
diff --git a/src/corelib/doc/snippets/qstring/main.cpp b/src/corelib/doc/snippets/qstring/main.cpp
index 41ee5a9cef..3a6f6483fb 100644
--- a/src/corelib/doc/snippets/qstring/main.cpp
+++ b/src/corelib/doc/snippets/qstring/main.cpp
@@ -262,6 +262,17 @@ void Widget::argFunction()
.arg(i).arg(total).arg(fileName);
//! [11]
+ {
+ //! [11]
+ int i; // current file's number
+ int total; // number of files to process
+ QStringView fileName; // current file's name
+
+ QString status = QString("Processing file %1 of %2: %3")
+ .arg(i).arg(total).arg(fileName);
+ //! [11]
+ }
+
//! [12] //! [13]
QString str;
//! [12]
@@ -321,6 +332,12 @@ void Widget::compareSensitiveFunction()
int y = QString::compare("auto", "Car", Qt::CaseSensitive); // y > 0
int z = QString::compare("auto", "Car", Qt::CaseInsensitive); // z < 0
//! [16]
+
+ //! [qCompareStrings-QSV-QSV]
+ int x = qCompareStrings(u"aUtO", u"AuTo", Qt::CaseInsensitive); // x == 0
+ int y = qCompareStrings(u"auto", u"Car", Qt::CaseSensitive); // y > 0
+ int z = qCompareStrings(u"auto", u"Car", Qt::CaseInsensitive); // z < 0
+ //! [qCompareStrings-QSV-QSV]
}
void Widget::containsFunction()
diff --git a/src/corelib/doc/snippets/qversionnumber/main.cpp b/src/corelib/doc/snippets/qversionnumber/main.cpp
index 0e9997b6dc..27b7b1a7ef 100644
--- a/src/corelib/doc/snippets/qversionnumber/main.cpp
+++ b/src/corelib/doc/snippets/qversionnumber/main.cpp
@@ -95,6 +95,14 @@ void QObject::parse()
// version is 5.4.0
// suffixIndex is 5
//! [3]
+
+ //! [3-latin1-1]
+ QLatin1String string("5.4.0-alpha");
+ int suffixIndex;
+ auto version = QVersionNumber::fromString(string, &suffixIndex);
+ // version is 5.4.0
+ // suffixIndex is 5
+ //! [3-latin1-1]
}
void Object::equivalent()
diff --git a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
index ed61511c62..6d3064d217 100644
--- a/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
+++ b/src/corelib/doc/src/objectmodel/signalsandslots.qdoc
@@ -395,24 +395,12 @@
signal, Qt provides the QObject::sender() function, which returns
a pointer to the object that sent the signal.
- The QSignalMapper class is provided for situations where many
- signals are connected to the same slot and the slot needs to
- handle each signal differently.
+ Lambda expressions are a convenient way to pass custom arguments to a slot:
- Suppose you have three push buttons that determine which file you
- will open: "Tax File", "Accounts File", or "Report File".
-
- In order to open the correct file, you use QSignalMapper::setMapping() to
- map all the QPushButton::clicked() signals to a QSignalMapper object. Then you connect
- the file's QPushButton::clicked() signal to the QSignalMapper::map() slot.
-
- \snippet signalmapper/filereader.cpp 0
-
- Then, you connect the \l{QSignalMapper::}{mapped()} signal to
- \c{readFile()} where a different file will be opened, depending on
- which push button is pressed.
-
- \snippet signalmapper/filereader.cpp 1
+ \code
+ connect(action, &QAction::triggered, engine,
+ [=]() { engine->processAction(action->text()); });
+ \endcode
\sa {Meta-Object System}, {Qt's Property System}
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri
index b76d1ef43c..78b37755a4 100644
--- a/src/corelib/global/global.pri
+++ b/src/corelib/global/global.pri
@@ -9,6 +9,7 @@ HEADERS += \
global/qprocessordetection.h \
global/qnamespace.h \
global/qendian.h \
+ global/qendian_p.h \
global/qnumeric_p.h \
global/qnumeric.h \
global/qfloat16_p.h \
@@ -21,6 +22,8 @@ HEADERS += \
global/qisenum.h \
global/qtypetraits.h \
global/qflags.h \
+ global/qrandom.h \
+ global/qrandom_p.h \
global/qhooks_p.h \
global/qversiontagging.h
@@ -33,6 +36,7 @@ SOURCES += \
global/qfloat16.cpp \
global/qoperatingsystemversion.cpp \
global/qlogging.cpp \
+ global/qrandom.cpp \
global/qhooks.cpp
VERSIONTAGGING_SOURCES = global/qversiontagging.cpp
@@ -55,6 +59,22 @@ if(linux*|hurd*):!cross_compile:!static:!*-armcc* {
DEFINES += ELF_INTERPRETER=\\\"$$system(LC_ALL=C readelf -l /bin/ls | perl -n -e \'$$prog\')\\\"
}
+linux:!static {
+ precompile_header {
+ # we'll get an error if we just use SOURCES +=
+ no_pch_assembler.commands = $$QMAKE_CC -c $(CFLAGS) $(INCPATH) ${QMAKE_FILE_IN} -o ${QMAKE_FILE_OUT}
+ no_pch_assembler.dependency_type = TYPE_C
+ no_pch_assembler.output = ${QMAKE_VAR_OBJECTS_DIR}${QMAKE_FILE_BASE}$${first(QMAKE_EXT_OBJ)}
+ no_pch_assembler.input = NO_PCH_ASM
+ no_pch_assembler.name = compiling[no_pch] ${QMAKE_FILE_IN}
+ silent: no_pch_assembler.commands = @echo compiling[no_pch] ${QMAKE_FILE_IN} && $$no_pch_assembler.commands
+ QMAKE_EXTRA_COMPILERS += no_pch_assembler
+ NO_PCH_ASM += global/minimum-linux.S
+ } else {
+ SOURCES += global/minimum-linux.S
+ }
+}
+
qtConfig(slog2): \
LIBS_PRIVATE += -lslog2
diff --git a/src/corelib/global/minimum-linux.S b/src/corelib/global/minimum-linux.S
new file mode 100644
index 0000000000..aa67be44ca
--- /dev/null
+++ b/src/corelib/global/minimum-linux.S
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qglobal_p.h"
+
+/* Copied from #include <elf.h>:
+ */
+#define ELF_NOTE_GNU "GNU"
+#define NT_GNU_ABI_TAG 1
+#define ELF_NOTE_OS_LINUX 0
+
+#ifdef __arm__
+# define progbits %progbits
+# define note %note
+#else
+# define progbits @progbits
+# define note @note
+#endif
+
+/* Add information for the ELF dynamic linker what the minimum Linux version
+ * required for Qt is.
+ *
+ * The .note.ABI-tag note section is defined at
+ * https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/noteabitag.html
+ */
+
+ .section ".note.GNU-stack", "", progbits
+ .section ".note.ABI-tag", "a", note
+ .align 4 /* we have 32-bit data */
+
+/* * For the format of the note section's contents, see Elf32_Nhdr / Elf64_Nhdr */
+ .long .Lnameend-.Lname /* n_namesz */
+ .long 16 /* n_descsz(16 bytes, normative) */
+ .long NT_GNU_ABI_TAG /* n_type */
+
+.Lname:
+ .asciz ELF_NOTE_GNU
+.Lnameend:
+
+/* Operating systems: */
+ .long ELF_NOTE_OS_LINUX
+
+/* Minimum Linux kernel version:
+ * We require the following features in Qt (unconditional, no fallback):
+ * Feature Added in version Macro
+ * - inotify_init1 before 2.6.12-rc12
+ * - futex(2) before 2.6.12-rc12
+ * - FUTEX_PRIVATE_FLAG 2.6.22
+ * - O_CLOEXEC 2.6.23
+ * - eventfd 2.6.23
+ * - pipe2 & dup3 2.6.27
+ * - accept4 2.6.28
+ * - renameat2 3.16 QT_CONFIG(renameat2)
+ * - getrandom 3.17 QT_CONFIG(getentropy)
+ */
+
+#if QT_CONFIG(getentropy)
+ .long 3
+ .long 17
+ .long 0
+#elif QT_CONFIG(renameat2)
+ .long 3
+ .long 16
+ .long 0
+#else
+ .long 2
+ .long 6
+ .long 28
+#endif
diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h
index 0b02ecc8ec..eb752354b1 100644
--- a/src/corelib/global/qconfig-bootstrapped.h
+++ b/src/corelib/global/qconfig-bootstrapped.h
@@ -75,13 +75,19 @@
#else
# define QT_FEATURE_alloca_malloc_h -1
#endif
+#define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE(<random>) ? 1 : -1)
+#define QT_FEATURE_getauxval (QT_HAS_INCLUDE(<sys/auxv.h>) ? 1 : -1)
+#define QT_FEATURE_getentropy -1
#define QT_FEATURE_iconv -1
#define QT_FEATURE_icu -1
#define QT_FEATURE_journald -1
+#define QT_FEATURE_futimens -1
+#define QT_FEATURE_futimes -1
#define QT_FEATURE_library -1
#define QT_NO_QOBJECT
#define QT_FEATURE_process -1
#define QT_NO_SYSTEMLOCALE
+#define QT_FEATURE_renameat2 -1
#define QT_FEATURE_slog2 -1
#define QT_FEATURE_syslog -1
#define QT_FEATURE_temporaryfile 1
diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h
index 4e9cd2e6e3..3337829de0 100644
--- a/src/corelib/global/qendian.h
+++ b/src/corelib/global/qendian.h
@@ -52,22 +52,6 @@ QT_BEGIN_NAMESPACE
/*
* ENDIAN FUNCTIONS
*/
-inline void qbswap_helper(const void *src, void *dest, int size)
-{
- for (int i = 0; i < size ; ++i)
- static_cast<uchar *>(dest)[i] = static_cast<const uchar *>(src)[size - 1 - i];
-}
-
-/*
- * qbswap(const T src, const void *dest);
- * Changes the byte order of \a src from big endian to little endian or vice versa
- * and stores the result in \a dest.
- * There is no alignment requirements for \a dest.
-*/
-template <typename T> inline void qbswap(const T src, void *dest)
-{
- qbswap_helper(&src, dest, sizeof(T));
-}
// Used to implement a type-safe and alignment-safe copy operation
// If you want to avoid the memcpy, you must write specializations for these functions
@@ -103,30 +87,11 @@ template <typename T> Q_ALWAYS_INLINE T qFromUnaligned(const void *src)
* This function can be used if you are not concerned about alignment issues,
* and it is therefore a bit more convenient and in most cases more efficient.
*/
-template <typename T> T qbswap(T source);
-
-// GCC 4.3 implemented all the intrinsics, but the 16-bit one only got implemented in 4.8;
-// Clang 2.6 implemented the 32- and 64-bit but waited until 3.2 to implement the 16-bit one
-#if (defined(Q_CC_GNU) && Q_CC_GNU >= 403) || QT_HAS_BUILTIN(__builtin_bswap32)
-template <> inline quint64 qbswap<quint64>(quint64 source)
-{
- return __builtin_bswap64(source);
-}
-template <> inline quint32 qbswap<quint32>(quint32 source)
-{
- return __builtin_bswap32(source);
-}
+template <typename T> Q_DECL_CONSTEXPR T qbswap(T source);
-template <> inline void qbswap<quint64>(quint64 source, void *dest)
-{
- qToUnaligned<quint64>(__builtin_bswap64(source), dest);
-}
-template <> inline void qbswap<quint32>(quint32 source, void *dest)
-{
- qToUnaligned<quint32>(__builtin_bswap32(source), dest);
-}
-#else
-template <> inline quint64 qbswap<quint64>(quint64 source)
+// These definitions are written so that they are recognized by most compilers
+// as bswap and replaced with single instruction builtins if available.
+template <> inline Q_DECL_CONSTEXPR quint64 qbswap<quint64>(quint64 source)
{
return 0
| ((source & Q_UINT64_C(0x00000000000000ff)) << 56)
@@ -139,7 +104,7 @@ template <> inline quint64 qbswap<quint64>(quint64 source)
| ((source & Q_UINT64_C(0xff00000000000000)) >> 56);
}
-template <> inline quint32 qbswap<quint32>(quint32 source)
+template <> inline Q_DECL_CONSTEXPR quint32 qbswap<quint32>(quint32 source)
{
return 0
| ((source & 0x000000ff) << 24)
@@ -147,65 +112,61 @@ template <> inline quint32 qbswap<quint32>(quint32 source)
| ((source & 0x00ff0000) >> 8)
| ((source & 0xff000000) >> 24);
}
-#endif // GCC & Clang intrinsics
-#if (defined(Q_CC_GNU) && Q_CC_GNU >= 408) || QT_HAS_BUILTIN(__builtin_bswap16)
-template <> inline quint16 qbswap<quint16>(quint16 source)
-{
- return __builtin_bswap16(source);
-}
-template <> inline void qbswap<quint16>(quint16 source, void *dest)
-{
- qToUnaligned<quint16>(__builtin_bswap16(source), dest);
-}
-#else
-template <> inline quint16 qbswap<quint16>(quint16 source)
+
+template <> inline Q_DECL_CONSTEXPR quint16 qbswap<quint16>(quint16 source)
{
return quint16( 0
| ((source & 0x00ff) << 8)
| ((source & 0xff00) >> 8) );
}
-#endif // GCC & Clang intrinsics
+
+template <> inline Q_DECL_CONSTEXPR quint8 qbswap<quint8>(quint8 source)
+{
+ return source;
+}
// signed specializations
-template <> inline qint64 qbswap<qint64>(qint64 source)
+template <> inline Q_DECL_CONSTEXPR qint64 qbswap<qint64>(qint64 source)
{
return qbswap<quint64>(quint64(source));
}
-template <> inline qint32 qbswap<qint32>(qint32 source)
+template <> inline Q_DECL_CONSTEXPR qint32 qbswap<qint32>(qint32 source)
{
return qbswap<quint32>(quint32(source));
}
-template <> inline qint16 qbswap<qint16>(qint16 source)
+template <> inline Q_DECL_CONSTEXPR qint16 qbswap<qint16>(qint16 source)
{
return qbswap<quint16>(quint16(source));
}
-template <> inline void qbswap<qint64>(qint64 source, void *dest)
+template <> inline Q_DECL_CONSTEXPR qint8 qbswap<qint8>(qint8 source)
{
- qbswap<quint64>(quint64(source), dest);
+ return source;
}
-template <> inline void qbswap<qint32>(qint32 source, void *dest)
+/*
+ * qbswap(const T src, const void *dest);
+ * Changes the byte order of \a src from big endian to little endian or vice versa
+ * and stores the result in \a dest.
+ * There is no alignment requirements for \a dest.
+*/
+template <typename T> inline void qbswap(const T src, void *dest)
{
- qbswap<quint32>(quint32(source), dest);
+ qToUnaligned<T>(qbswap<T>(src), dest);
}
-template <> inline void qbswap<qint16>(qint16 source, void *dest)
-{
- qbswap<quint16>(quint16(source), dest);
-}
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
-template <typename T> inline T qToBigEndian(T source)
+template <typename T> inline Q_DECL_CONSTEXPR T qToBigEndian(T source)
{ return source; }
-template <typename T> inline T qFromBigEndian(T source)
+template <typename T> inline Q_DECL_CONSTEXPR T qFromBigEndian(T source)
{ return source; }
-template <typename T> inline T qToLittleEndian(T source)
+template <typename T> inline Q_DECL_CONSTEXPR T qToLittleEndian(T source)
{ return qbswap<T>(source); }
-template <typename T> inline T qFromLittleEndian(T source)
+template <typename T> inline Q_DECL_CONSTEXPR T qFromLittleEndian(T source)
{ return qbswap<T>(source); }
template <typename T> inline void qToBigEndian(T src, void *dest)
{ qToUnaligned<T>(src, dest); }
@@ -213,13 +174,13 @@ template <typename T> inline void qToLittleEndian(T src, void *dest)
{ qbswap<T>(src, dest); }
#else // Q_LITTLE_ENDIAN
-template <typename T> inline T qToBigEndian(T source)
+template <typename T> inline Q_DECL_CONSTEXPR T qToBigEndian(T source)
{ return qbswap<T>(source); }
-template <typename T> inline T qFromBigEndian(T source)
+template <typename T> inline Q_DECL_CONSTEXPR T qFromBigEndian(T source)
{ return qbswap<T>(source); }
-template <typename T> inline T qToLittleEndian(T source)
+template <typename T> inline Q_DECL_CONSTEXPR T qToLittleEndian(T source)
{ return source; }
-template <typename T> inline T qFromLittleEndian(T source)
+template <typename T> inline Q_DECL_CONSTEXPR T qFromLittleEndian(T source)
{ return source; }
template <typename T> inline void qToBigEndian(T src, void *dest)
{ qbswap<T>(src, dest); }
@@ -228,15 +189,6 @@ template <typename T> inline void qToLittleEndian(T src, void *dest)
#endif // Q_BYTE_ORDER == Q_BIG_ENDIAN
-template <> inline quint8 qbswap<quint8>(quint8 source)
-{
- return source;
-}
-
-template <> inline qint8 qbswap<qint8>(qint8 source)
-{
- return source;
-}
/* T qFromLittleEndian(const void *src)
* This function will read a little-endian encoded value from \a src
@@ -267,6 +219,127 @@ template <> inline quint8 qFromBigEndian<quint8>(const void *src)
template <> inline qint8 qFromBigEndian<qint8>(const void *src)
{ return static_cast<const qint8 *>(src)[0]; }
+template<class S>
+class QSpecialInteger
+{
+ typedef typename S::StorageType T;
+ T val;
+public:
+ QSpecialInteger() = default;
+ explicit Q_DECL_CONSTEXPR QSpecialInteger(T i) : val(S::toSpecial(i)) {}
+
+ QSpecialInteger &operator =(T i) { val = S::toSpecial(i); return *this; }
+ operator T() const { return S::fromSpecial(val); }
+
+ bool operator ==(QSpecialInteger<S> i) const { return val == i.val; }
+ bool operator !=(QSpecialInteger<S> i) const { return val != i.val; }
+
+ QSpecialInteger &operator +=(T i)
+ { return (*this = S::fromSpecial(val) + i); }
+ QSpecialInteger &operator -=(T i)
+ { return (*this = S::fromSpecial(val) - i); }
+ QSpecialInteger &operator *=(T i)
+ { return (*this = S::fromSpecial(val) * i); }
+ QSpecialInteger &operator >>=(T i)
+ { return (*this = S::fromSpecial(val) >> i); }
+ QSpecialInteger &operator <<=(T i)
+ { return (*this = S::fromSpecial(val) << i); }
+ QSpecialInteger &operator /=(T i)
+ { return (*this = S::fromSpecial(val) / i); }
+ QSpecialInteger &operator %=(T i)
+ { return (*this = S::fromSpecial(val) % i); }
+ QSpecialInteger &operator |=(T i)
+ { return (*this = S::fromSpecial(val) | i); }
+ QSpecialInteger &operator &=(T i)
+ { return (*this = S::fromSpecial(val) & i); }
+ QSpecialInteger &operator ^=(T i)
+ { return (*this = S::fromSpecial(val) ^ i); }
+};
+
+template<typename T>
+class QLittleEndianStorageType {
+public:
+ typedef T StorageType;
+ static Q_DECL_CONSTEXPR T toSpecial(T source) { return qToLittleEndian(source); }
+ static Q_DECL_CONSTEXPR T fromSpecial(T source) { return qFromLittleEndian(source); }
+};
+
+template<typename T>
+class QBigEndianStorageType {
+public:
+ typedef T StorageType;
+ static Q_DECL_CONSTEXPR T toSpecial(T source) { return qToBigEndian(source); }
+ static Q_DECL_CONSTEXPR T fromSpecial(T source) { return qFromBigEndian(source); }
+};
+
+#ifdef Q_QDOC
+class QLEInteger {
+public:
+ explicit Q_DECL_CONSTEXPR QLEInteger(T i);
+ QLEInteger &operator =(T i);
+ operator T() const;
+ bool operator ==(QLEInteger i) const;
+ bool operator !=(QLEInteger i) const;
+ QLEInteger &operator +=(T i);
+ QLEInteger &operator -=(T i);
+ QLEInteger &operator *=(T i);
+ QLEInteger &operator >>=(T i);
+ QLEInteger &operator <<=(T i);
+ QLEInteger &operator /=(T i);
+ QLEInteger &operator %=(T i);
+ QLEInteger &operator |=(T i);
+ QLEInteger &operator &=(T i);
+ QLEInteger &operator ^=(T i);
+};
+
+class QBEInteger {
+public:
+ explicit Q_DECL_CONSTEXPR QBEInteger(T i);
+ QBEInteger &operator =(T i);
+ operator T() const;
+ bool operator ==(QBEInteger i) const;
+ bool operator !=(QBEInteger i) const;
+ QBEInteger &operator +=(T i);
+ QBEInteger &operator -=(T i);
+ QBEInteger &operator *=(T i);
+ QBEInteger &operator >>=(T i);
+ QBEInteger &operator <<=(T i);
+ QBEInteger &operator /=(T i);
+ QBEInteger &operator %=(T i);
+ QBEInteger &operator |=(T i);
+ QBEInteger &operator &=(T i);
+ QBEInteger &operator ^=(T i);
+};
+#else
+
+template<typename T>
+using QLEInteger = QSpecialInteger<QLittleEndianStorageType<T>>;
+
+template<typename T>
+using QBEInteger = QSpecialInteger<QBigEndianStorageType<T>>;
+#endif
+template <typename T>
+class QTypeInfo<QLEInteger<T> >
+ : public QTypeInfoMerger<QLEInteger<T>, T> {};
+
+template <typename T>
+class QTypeInfo<QBEInteger<T> >
+ : public QTypeInfoMerger<QBEInteger<T>, T> {};
+
+typedef QLEInteger<qint16> qint16_le;
+typedef QLEInteger<qint32> qint32_le;
+typedef QLEInteger<qint64> qint64_le;
+typedef QLEInteger<quint16> quint16_le;
+typedef QLEInteger<quint32> quint32_le;
+typedef QLEInteger<quint64> quint64_le;
+
+typedef QBEInteger<qint16> qint16_be;
+typedef QBEInteger<qint32> qint32_be;
+typedef QBEInteger<qint64> qint64_be;
+typedef QBEInteger<quint16> quint16_be;
+typedef QBEInteger<quint32> quint32_be;
+typedef QBEInteger<quint64> quint64_be;
+
QT_END_NAMESPACE
#endif // QENDIAN_H
diff --git a/src/corelib/global/qendian.qdoc b/src/corelib/global/qendian.qdoc
index 9ce9dbdb0e..2ccdea5979 100644
--- a/src/corelib/global/qendian.qdoc
+++ b/src/corelib/global/qendian.qdoc
@@ -183,3 +183,372 @@
unmodified.
*/
+/*!
+ \class QLEInteger
+ \inmodule QtCore
+ \brief The QLEInteger class provides platform-independent little-endian integers.
+ \since 5.10
+
+ The template parameter \c T must be a C++ integer type:
+ \list
+ \li 8-bit: char, signed char, unsigned char, qint8, quint8
+ \li 16-bit: short, unsigned short, qint16, quint16, char16_t
+ \li 32-bit: int, unsigned int, qint32, quint32, char32_t
+ \li 64-bit: long long, unsigned long long, qint64, quint64
+ \li platform-specific size: long, unsigned long
+ \li pointer size: qintptr, quintptr, qptrdiff
+ \endlist
+
+ \note Using this class may be slower than using native integers, so only use it when
+ an exact endian is needed.
+*/
+
+/*! \fn QLEInteger::QLEInteger(T value)
+
+ Constructs a QLEInteger with the given \a value.
+*/
+
+/*! \fn QLEInteger &QLEInteger::operator=(T value)
+
+ Assigns \a value to this QLEInteger and returns a reference to
+ this QLEInteger.
+*/
+
+/*!
+ \fn QLEInteger::operator T() const
+
+ Returns the value of this QLEInteger as a native integer.
+*/
+
+/*!
+ \fn bool QLEInteger::operator==(QLEInteger other) const
+
+ Returns \c true if the value of this QLEInteger is equal to the value of \a other.
+*/
+
+/*!
+ \fn bool QLEInteger::operator!=(QLEInteger other) const
+
+ Returns \c true if the value of this QLEInteger is not equal to the value of \a other.
+*/
+
+/*!
+ \fn QLEInteger &QLEInteger::operator+=(T i)
+
+ Adds \a i to this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QLEInteger &QLEInteger::operator-=(T i)
+
+ Subtracts \a i from this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QLEInteger &QLEInteger::operator*=(T i)
+
+ Multiplies \a i with this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QLEInteger &QLEInteger::operator/=(T i)
+
+ Divides this QLEInteger with \a i and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QLEInteger &QLEInteger::operator%=(T i)
+
+ Sets this QLEInteger to the remainder of a division by \a i and
+ returns a reference to this object.
+*/
+
+/*!
+ \fn QLEInteger &QLEInteger::operator>>=(T i)
+
+ Performs a left-shift by \a i on this QLEInteger and returns a
+ reference to this object.
+*/
+
+/*!
+ \fn QLEInteger &QLEInteger::operator<<=(T i)
+
+ Performs a right-shift by \a i on this QLEInteger and returns a
+ reference to this object.
+*/
+
+/*!
+ \fn QLEInteger &QLEInteger::operator|=(T i)
+
+ Performs a bitwise OR with \a i onto this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QLEInteger &QLEInteger::operator&=(T i)
+
+ Performs a bitwise AND with \a i onto this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QLEInteger &QLEInteger::operator^=(T i)
+
+ Performs a bitwise XOR with \a i onto this QLEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \class QBEInteger
+ \inmodule QtCore
+ \brief The QBEInteger class provides platform-independent big-endian integers.
+ \since 5.10
+
+ The template parameter \c T must be a C++ integer type:
+ \list
+ \li 8-bit: char, signed char, unsigned char, qint8, quint8
+ \li 16-bit: short, unsigned short, qint16, quint16, char16_t (C++11)
+ \li 32-bit: int, unsigned int, qint32, quint32, char32_t (C++11)
+ \li 64-bit: long long, unsigned long long, qint64, quint64
+ \li platform-specific size: long, unsigned long
+ \li pointer size: qintptr, quintptr, qptrdiff
+ \endlist
+
+ \note Using this class may be slower than using native integers, so only use it when
+ an exact endian is needed.
+*/
+
+/*! \fn QBEInteger::QBEInteger(T value)
+
+ Constructs a QBEInteger with the given \a value.
+*/
+
+/*! \fn QBEInteger &QBEInteger::operator=(T value)
+
+ Assigns \a value to this QBEInteger and returns a reference to
+ this QBEInteger.
+*/
+
+/*!
+ \fn QBEInteger::operator T() const
+
+ Returns the value of this QBEInteger as a native integer.
+*/
+
+/*!
+ \fn bool QBEInteger::operator==(QBEInteger other) const
+
+ Returns \c true if the value of this QBEInteger is equal to the value of \a other.
+*/
+
+/*!
+ \fn bool QBEInteger::operator!=(QBEInteger other) const
+
+ Returns \c true if the value of this QBEInteger is not equal to the value of \a other.
+*/
+
+/*!
+ \fn QBEInteger &QBEInteger::operator+=(T i)
+
+ Adds \a i to this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QBEInteger &QBEInteger::operator-=(T i)
+
+ Subtracts \a i from this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QBEInteger &QBEInteger::operator*=(T i)
+
+ Multiplies \a i with this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QBEInteger &QBEInteger::operator/=(T i)
+
+ Divides this QBEInteger with \a i and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QBEInteger &QBEInteger::operator%=(T i)
+
+ Sets this QBEInteger to the remainder of a division by \a i and
+ returns a reference to this object.
+*/
+
+/*!
+ \fn QBEInteger &QBEInteger::operator>>=(T i)
+
+ Performs a left-shift by \a i on this QBEInteger and returns a
+ reference to this object.
+*/
+
+/*!
+ \fn QBEInteger &QBEInteger::operator<<=(T i)
+
+ Performs a right-shift by \a i on this QBEInteger and returns a
+ reference to this object.
+*/
+
+/*!
+ \fn QBEInteger &QBEInteger::operator|=(T i)
+
+ Performs a bitwise OR with \a i onto this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QBEInteger &QBEInteger::operator&=(T i)
+
+ Performs a bitwise AND with \a i onto this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \fn QBEInteger &QBEInteger::operator^=(T i)
+
+ Performs a bitwise XOR with \a i onto this QBEInteger and returns a reference to
+ this object.
+*/
+
+/*!
+ \typedef quint16_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<quint16>. This type is guaranteed to be stored in memory as
+ a 16-bit little-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint16
+*/
+
+/*!
+ \typedef quint32_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<quint32>. This type is guaranteed to be stored in memory as
+ a 32-bit little-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint32
+*/
+
+/*!
+ \typedef quint64_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<quint64>. This type is guaranteed to be stored in memory as
+ a 64-bit little-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint64
+*/
+
+/*!
+ \typedef quint16_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<quint16>. This type is guaranteed to be stored in memory as
+ a 16-bit big-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint16
+*/
+
+/*!
+ \typedef quint32_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<quint32>. This type is guaranteed to be stored in memory as
+ a 32-bit big-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint32
+*/
+
+/*!
+ \typedef quint64_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<quint64>. This type is guaranteed to be stored in memory as
+ a 64-bit big-endian unsigned integer on all platforms supported by Qt.
+
+ \sa quint64
+*/
+
+/*!
+ \typedef qint16_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<qint16>. This type is guaranteed to be stored in memory as
+ a 16-bit little-endian signed integer on all platforms supported by Qt.
+
+ \sa qint16
+*/
+
+/*!
+ \typedef qint32_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<qint32>. This type is guaranteed to be stored in memory as
+ a 32-bit little-endian signed integer on all platforms supported by Qt.
+
+ \sa qint32
+*/
+
+/*!
+ \typedef qint64_le
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QLEInteger<qint64>. This type is guaranteed to be stored in memory as
+ a 64-bit little-endian signed integer on all platforms supported by Qt.
+
+ \sa qint64
+*/
+
+/*!
+ \typedef qint16_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<qint16>. This type is guaranteed to be stored in memory as
+ a 16-bit big-endian signed integer on all platforms supported by Qt.
+
+ \sa qint16
+*/
+
+/*!
+ \typedef qint32_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<qint32>. This type is guaranteed to be stored in memory as
+ a 32-bit big-endian signed integer on all platforms supported by Qt.
+
+ \sa qint32
+*/
+
+/*!
+ \typedef qint64_be
+ \relates <QtEndian>
+ \since 5.10
+
+ Typedef for QBEInteger<qint64>. This type is guaranteed to be stored in memory as
+ a 64-bit big-endian signed integer on all platforms supported by Qt.
+
+ \sa qint64
+*/
diff --git a/src/corelib/global/qendian_p.h b/src/corelib/global/qendian_p.h
new file mode 100644
index 0000000000..c830e65b54
--- /dev/null
+++ b/src/corelib/global/qendian_p.h
@@ -0,0 +1,142 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QENDIAN_P_H
+#define QENDIAN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qendian.h>
+
+QT_BEGIN_NAMESPACE
+
+// Note if using multiple of these bitfields in a union; the underlying storage type must
+// match. Since we always use an unsigned storage type, unsigned and signed versions may
+// be used together, but different bit-widths may not.
+template<class S, int pos, int width>
+class QSpecialIntegerBitfield
+{
+protected:
+ typedef typename S::StorageType T;
+ typedef typename std::make_unsigned<T>::type UT;
+
+ static Q_DECL_CONSTEXPR UT mask()
+ {
+ return ((UT(1) << width) - 1) << pos;
+ }
+public:
+ // FIXME: val is public until qtdeclarative is fixed to not access it directly.
+ UT val;
+
+ QSpecialIntegerBitfield &operator =(T t)
+ {
+ UT i = S::fromSpecial(val);
+ i &= ~mask();
+ i |= (UT(t) << pos) & mask();
+ val = S::toSpecial(i);
+ return *this;
+ }
+ operator T() const
+ {
+ if (std::is_signed<T>::value) {
+ UT i = S::fromSpecial(val);
+ i <<= (sizeof(T) * 8) - width - pos;
+ T t = T(i);
+ t >>= (sizeof(T) * 8) - width;
+ return t;
+ }
+ return (S::fromSpecial(val) & mask()) >> pos;
+ }
+
+ bool operator !() const { return !(val & S::toSpecial(mask())); }
+ bool operator ==(QSpecialIntegerBitfield<S, pos, width> i) const
+ { return ((val ^ i.val) & S::toSpecial(mask())) == 0; }
+ bool operator !=(QSpecialIntegerBitfield<S, pos, width> i) const
+ { return ((val ^ i.val) & S::toSpecial(mask())) != 0; }
+
+ QSpecialIntegerBitfield &operator +=(T i)
+ { return (*this = (T(*this) + i)); }
+ QSpecialIntegerBitfield &operator -=(T i)
+ { return (*this = (T(*this) - i)); }
+ QSpecialIntegerBitfield &operator *=(T i)
+ { return (*this = (T(*this) * i)); }
+ QSpecialIntegerBitfield &operator /=(T i)
+ { return (*this = (T(*this) / i)); }
+ QSpecialIntegerBitfield &operator %=(T i)
+ { return (*this = (T(*this) % i)); }
+ QSpecialIntegerBitfield &operator |=(T i)
+ { return (*this = (T(*this) | i)); }
+ QSpecialIntegerBitfield &operator &=(T i)
+ { return (*this = (T(*this) & i)); }
+ QSpecialIntegerBitfield &operator ^=(T i)
+ { return (*this = (T(*this) ^ i)); }
+ QSpecialIntegerBitfield &operator >>=(T i)
+ { return (*this = (T(*this) >> i)); }
+ QSpecialIntegerBitfield &operator <<=(T i)
+ { return (*this = (T(*this) << i)); }
+};
+
+template<typename T, int pos, int width>
+using QLEIntegerBitfield = QSpecialIntegerBitfield<QLittleEndianStorageType<T>, pos, width>;
+
+template<typename T, int pos, int width>
+using QBEIntegerBitfield = QSpecialIntegerBitfield<QBigEndianStorageType<T>, pos, width>;
+
+template<int pos, int width>
+using qint32_le_bitfield = QLEIntegerBitfield<int, pos, width>;
+template<int pos, int width>
+using quint32_le_bitfield = QLEIntegerBitfield<uint, pos, width>;
+template<int pos, int width>
+using qint32_be_bitfield = QBEIntegerBitfield<int, pos, width>;
+template<int pos, int width>
+using quint32_be_bitfield = QBEIntegerBitfield<uint, pos, width>;
+
+
+QT_END_NAMESPACE
+
+#endif // QENDIAN_P_H
diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp
index 1de1ae65fb..89edfc8787 100644
--- a/src/corelib/global/qfloat16.cpp
+++ b/src/corelib/global/qfloat16.cpp
@@ -41,7 +41,11 @@
QT_BEGIN_NAMESPACE
-/*! \headerfile <QFloat16>
+/*!
+ \headerfile <QFloat16>
+ \title 16-bit Floating Point Support
+ \ingroup funclists
+ \brief The <QFloat16> header file provides 16-bit floating point support.
This header file provides support for half-precision (16-bit) floating
point data with the class \c qfloat16. It is fully compliant with IEEE
@@ -59,24 +63,6 @@ QT_BEGIN_NAMESPACE
\since 5.9
*/
-Q_STATIC_ASSERT_X(sizeof(float) == sizeof(quint32),
- "qfloat16 assumes that floats are 32 bits wide");
-
-// There are a few corner cases regarding denormals where GHS compiler is relying
-// hardware behavior that is not IEC 559 compliant. Therefore the compiler
-// reports std::numeric_limits<float>::is_iec559 as false. This is all right
-// according to our needs.
-
-#if !defined(Q_CC_GHS)
-Q_STATIC_ASSERT_X(std::numeric_limits<float>::is_iec559,
- "Only works with IEEE 754 floating point");
-#endif
-
-Q_STATIC_ASSERT_X(std::numeric_limits<float>::has_infinity &&
- std::numeric_limits<float>::has_quiet_NaN &&
- std::numeric_limits<float>::has_signaling_NaN,
- "Only works with IEEE 754 floating point");
-
/*!
Returns true if the \c qfloat16 \a {f} is equivalent to infinity.
\relates <QFloat16>
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 4223d2a3e1..ab79637323 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -42,7 +42,6 @@
#include "qstring.h"
#include "qvector.h"
#include "qlist.h"
-#include "qthreadstorage.h"
#include "qdir.h"
#include "qdatetime.h"
#include "qoperatingsystemversion.h"
@@ -118,6 +117,38 @@ Q_CORE_EXPORT void *qMemSet(void *dest, int c, size_t n);
Q_STATIC_ASSERT_X(sizeof(int) == 4, "Qt assumes that int is 32 bits");
Q_STATIC_ASSERT_X(UCHAR_MAX == 255, "Qt assumes that char is 8 bits");
Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined incorrectly");
+Q_STATIC_ASSERT_X(sizeof(float) == 4, "Qt assumes that float is 32 bits");
+
+// While we'd like to check for __STDC_IEC_559__, as per ISO/IEC 9899:2011
+// Annex F (C11, normative for C++11), there are a few corner cases regarding
+// denormals where GHS compiler is relying hardware behavior that is not IEC
+// 559 compliant. So split the check in several subchecks.
+
+// On GHC the compiler reports std::numeric_limits<float>::is_iec559 as false.
+// This is all right according to our needs.
+#if !defined(Q_CC_GHS)
+Q_STATIC_ASSERT_X(std::numeric_limits<float>::is_iec559,
+ "Qt assumes IEEE 754 floating point");
+#endif
+
+// Technically, presence of NaN and infinities are implied from the above check,
+// but double checking our environment doesn't hurt...
+Q_STATIC_ASSERT_X(std::numeric_limits<float>::has_infinity &&
+ std::numeric_limits<float>::has_quiet_NaN &&
+ std::numeric_limits<float>::has_signaling_NaN,
+ "Qt assumes IEEE 754 floating point");
+
+// is_iec559 checks for ISO/IEC/IEEE 60559:2011 (aka IEEE 754-2008) compliance,
+// but that allows for a non-binary radix. We need to recheck that.
+// Note how __STDC_IEC_559__ would instead check for IEC 60559:1989, aka
+// ANSI/IEEE 754−1985, which specifically implies binary floating point numbers.
+Q_STATIC_ASSERT_X(std::numeric_limits<float>::radix == 2,
+ "Qt assumes binary IEEE 754 floating point");
+
+// not required by the definition of size_t, but we depend on this
+Q_STATIC_ASSERT_X(sizeof(size_t) == sizeof(void *), "size_t and a pointer don't have the same size");
+Q_STATIC_ASSERT(sizeof(size_t) == sizeof(qssize_t)); // implied by the definition
+Q_STATIC_ASSERT((std::is_same<qssize_t, qptrdiff>::value));
/*!
\class QFlag
@@ -780,6 +811,21 @@ Q_STATIC_ASSERT_X(QT_POINTER_SIZE == sizeof(void *), "QT_POINTER_SIZE defined in
*/
/*!
+ \typedef qssize_t
+ \relates <QtGlobal>
+ \since 5.10
+
+ Integral type providing Posix' \c ssize_t for all platforms.
+
+ This type is guaranteed to be the same size as a \c size_t on all
+ platforms supported by Qt.
+
+ Note that qssize_t is signed. Use \c size_t for unsigned values.
+
+ \sa qptrdiff
+*/
+
+/*!
\enum QtMsgType
\relates <QtGlobal>
@@ -3076,7 +3122,7 @@ void qt_assert_x(const char *where, const char *what, const char *file, int line
Deliberately not exported as part of the Qt API, but used in both
qsimplerichtext.cpp and qgfxraster_qws.cpp
*/
-Q_CORE_EXPORT unsigned int qt_int_sqrt(unsigned int n)
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION unsigned int qt_int_sqrt(unsigned int n)
{
// n must be in the range 0...UINT_MAX/2-1
if (n >= (UINT_MAX>>2)) {
@@ -3106,24 +3152,27 @@ void *qMemSet(void *dest, int c, size_t n) { return memset(dest, c, n); }
// add thread-safety for the Qt wrappers.
static QBasicMutex environmentMutex;
-// getenv is declared as deprecated in VS2005. This function
-// makes use of the new secure getenv function.
/*!
\relates <QtGlobal>
+ \threadsafe
- Returns the value of the environment variable with name \a
- varName. To get the variable string, use QByteArray::constData().
- To convert the data to a QString use QString::fromLocal8Bit().
+ Returns the value of the environment variable with name \a varName as a
+ QByteArray. If no variable by that name is found in the environment, this
+ function returns a default-constructed QByteArray.
- \note qgetenv() was introduced because getenv() from the standard
- C library was deprecated in VC2005 (and later versions). qgetenv()
- uses the new replacement function in VC, and calls the standard C
- library's implementation on all other platforms.
+ The Qt environment manipulation functions are thread-safe, but this
+ requires that the C library equivalent functions like getenv and putenv are
+ not directly called.
+
+ To convert the data to a QString use QString::fromLocal8Bit().
- \warning Don't use qgetenv on Windows if the content may contain
- non-US-ASCII characters, like file paths.
+ \note on desktop Windows, qgetenv() may produce data loss if the
+ original string contains Unicode characters not representable in the
+ ANSI encoding. Use qEnvironmentVariable() instead.
+ On Unix systems, this function is lossless.
- \sa qputenv(), qEnvironmentVariableIsSet(), qEnvironmentVariableIsEmpty()
+ \sa qputenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet(),
+ qEnvironmentVariableIsEmpty()
*/
QByteArray qgetenv(const char *varName)
{
@@ -3145,6 +3194,87 @@ QByteArray qgetenv(const char *varName)
#endif
}
+
+/*!
+ \relates <QtGlobal>
+ \since 5.10
+
+ Returns the value of the environment variable with name \a varName as a
+ QString. If no variable by that name is found in the environment, this
+ function returns \a defaultValue.
+
+ The Qt environment manipulation functions are thread-safe, but this
+ requires that the C library equivalent functions like getenv and putenv are
+ not directly called.
+
+ The following table describes how to choose between qgetenv() and
+ qEnvironmentVariable():
+ \table
+ \header \li Condition \li Recommendation
+ \row
+ \li Variable contains file paths or user text
+ \li qEnvironmentVariable()
+ \row
+ \li Windows-specific code
+ \li qEnvironmentVariable()
+ \row
+ \li Unix-specific code, destination variable is not QString and/or is
+ used to interface with non-Qt APIs
+ \li qgetenv()
+ \row
+ \li Destination variable is a QString
+ \li qEnvironmentVariable()
+ \row
+ \li Destination variable is a QByteArray or std::string
+ \li qgetenv()
+ \endtable
+
+ \note on Unix systems, this function may produce data loss if the original
+ string contains arbitrary binary data that cannot be decoded by the locale
+ codec. Use qgetenv() instead for that case. On Windows, this function is
+ lossless.
+
+ \note the variable name \a varName must contain only US-ASCII characters.
+
+ \sa qputenv(), qgetenv(), qEnvironmentVariableIsSet(), qEnvironmentVariableIsEmpty()
+*/
+QString qEnvironmentVariable(const char *varName, const QString &defaultValue)
+{
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+ QMutexLocker locker(&environmentMutex);
+ QVarLengthArray<wchar_t, 32> wname(int(strlen(varName)) + 1);
+ for (int i = 0; i < wname.size(); ++i) // wname.size() is correct: will copy terminating null
+ wname[i] = uchar(varName[i]);
+ size_t requiredSize = 0;
+ QString buffer;
+ _wgetenv_s(&requiredSize, 0, 0, wname.data());
+ if (requiredSize == 0)
+ return defaultValue;
+ buffer.resize(int(requiredSize));
+ _wgetenv_s(&requiredSize, reinterpret_cast<wchar_t *>(buffer.data()), requiredSize,
+ wname.data());
+ // requiredSize includes the terminating null, which we don't want.
+ Q_ASSERT(buffer.endsWith(QLatin1Char('\0')));
+ buffer.chop(1);
+ return buffer;
+#else
+ QByteArray value = qgetenv(varName);
+ if (value.isNull())
+ return defaultValue;
+// duplicated in qfile.h (QFile::decodeName)
+#if defined(Q_OS_DARWIN)
+ return QString::fromUtf8(value).normalized(QString::NormalizationForm_C);
+#else // other Unix
+ return QString::fromLocal8Bit(value);
+#endif
+#endif
+}
+
+QString qEnvironmentVariable(const char *varName)
+{
+ return qEnvironmentVariable(varName, QString());
+}
+
/*!
\relates <QtGlobal>
\since 5.1
@@ -3157,7 +3287,7 @@ QByteArray qgetenv(const char *varName)
\endcode
except that it's potentially much faster, and can't throw exceptions.
- \sa qgetenv(), qEnvironmentVariableIsSet()
+ \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet()
*/
bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT
{
@@ -3194,7 +3324,7 @@ bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT
are too long will either be truncated or this function will set \a ok to \c
false.
- \sa qgetenv(), qEnvironmentVariableIsSet()
+ \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet()
*/
int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT
{
@@ -3245,7 +3375,7 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT
\endcode
except that it's potentially much faster, and can't throw exceptions.
- \sa qgetenv(), qEnvironmentVariableIsEmpty()
+ \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsEmpty()
*/
bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT
{
@@ -3275,7 +3405,7 @@ bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT
uses the replacement function in VC, and calls the standard C
library's implementation on all other platforms.
- \sa qgetenv()
+ \sa qgetenv(), qEnvironmentVariable()
*/
bool qputenv(const char *varName, const QByteArray& value)
{
@@ -3306,7 +3436,7 @@ bool qputenv(const char *varName, const QByteArray& value)
\since 5.1
- \sa qputenv(), qgetenv()
+ \sa qputenv(), qgetenv(), qEnvironmentVariable()
*/
bool qunsetenv(const char *varName)
{
@@ -3331,138 +3461,6 @@ bool qunsetenv(const char *varName)
#endif
}
-#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0)
-
-# if defined(Q_OS_INTEGRITY) && defined(__GHS_VERSION_NUMBER) && (__GHS_VERSION_NUMBER < 500)
-// older versions of INTEGRITY used a long instead of a uint for the seed.
-typedef long SeedStorageType;
-# else
-typedef uint SeedStorageType;
-# endif
-
-typedef QThreadStorage<SeedStorageType *> SeedStorage;
-Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value
-
-#elif defined(Q_OS_ANDROID)
-typedef QThreadStorage<QJNIObjectPrivate> AndroidRandomStorage;
-Q_GLOBAL_STATIC(AndroidRandomStorage, randomTLS)
-#endif
-
-/*!
- \relates <QtGlobal>
- \since 4.2
-
- Thread-safe version of the standard C++ \c srand() function.
-
- Sets the argument \a seed to be used to generate a new random number sequence of
- pseudo random integers to be returned by qrand().
-
- The sequence of random numbers generated is deterministic per thread. For example,
- if two threads call qsrand(1) and subsequently call qrand(), the threads will get
- the same random number sequence.
-
- \sa qrand()
-*/
-void qsrand(uint seed)
-{
-#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0)
- SeedStorage *seedStorage = randTLS();
- if (seedStorage) {
- SeedStorageType *pseed = seedStorage->localData();
- if (!pseed)
- seedStorage->setLocalData(pseed = new SeedStorageType);
- *pseed = seed;
- } else {
- //global static seed storage should always exist,
- //except after being deleted by QGlobalStaticDeleter.
- //But since it still can be called from destructor of another
- //global static object, fallback to srand(seed)
- srand(seed);
- }
-#elif defined(Q_OS_ANDROID)
- if (randomTLS->hasLocalData()) {
- randomTLS->localData().callMethod<void>("setSeed", "(J)V", jlong(seed));
- return;
- }
-
- QJNIObjectPrivate random("java/util/Random",
- "(J)V",
- jlong(seed));
- if (!random.isValid()) {
- srand(seed);
- return;
- }
-
- randomTLS->setLocalData(random);
-#else
- // On Windows srand() and rand() already use Thread-Local-Storage
- // to store the seed between calls
- // this is also valid for QT_NO_THREAD
- srand(seed);
-#endif
-}
-
-/*!
- \relates <QtGlobal>
- \since 4.2
-
- Thread-safe version of the standard C++ \c rand() function.
-
- Returns a value between 0 and \c RAND_MAX (defined in \c <cstdlib> and
- \c <stdlib.h>), the next number in the current sequence of pseudo-random
- integers.
-
- Use \c qsrand() to initialize the pseudo-random number generator with
- a seed value.
-
- \sa qsrand()
-*/
-int qrand()
-{
-#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0)
- SeedStorage *seedStorage = randTLS();
- if (seedStorage) {
- SeedStorageType *pseed = seedStorage->localData();
- if (!pseed) {
- seedStorage->setLocalData(pseed = new SeedStorageType);
- *pseed = 1;
- }
- return rand_r(pseed);
- } else {
- //global static seed storage should always exist,
- //except after being deleted by QGlobalStaticDeleter.
- //But since it still can be called from destructor of another
- //global static object, fallback to rand()
- return rand();
- }
-#elif defined(Q_OS_ANDROID)
- AndroidRandomStorage *randomStorage = randomTLS();
- if (!randomStorage)
- return rand();
-
- if (randomStorage->hasLocalData()) {
- return randomStorage->localData().callMethod<jint>("nextInt",
- "(I)I",
- RAND_MAX);
- }
-
- QJNIObjectPrivate random("java/util/Random",
- "(J)V",
- jlong(1));
-
- if (!random.isValid())
- return rand();
-
- randomStorage->setLocalData(random);
- return random.callMethod<jint>("nextInt", "(I)I", RAND_MAX);
-#else
- // On Windows srand() and rand() already use Thread-Local-Storage
- // to store the seed between calls
- // this is also valid for QT_NO_THREAD
- return rand();
-#endif
-}
-
/*!
\macro forever
\relates <QtGlobal>
@@ -4362,8 +4360,11 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters)
stderr. Under Windows, the message is sent to the debugger.
On QNX the message is sent to slogger2. This
function does nothing if \c QT_NO_WARNING_OUTPUT was defined
- during compilation; it exits if the environment variable \c
- QT_FATAL_WARNINGS is not empty.
+ during compilation; it exits if at the nth warning corresponding to the
+ counter in environment variable \c QT_FATAL_WARNINGS. That is, if the
+ environment variable contains the value 1, it will exit on the 1st message;
+ if it contains the value 10, it will exit on the 10th message. Any
+ non-numeric value is equivalent to 1.
This function takes a format string and a list of arguments,
similar to the C printf() function. The format should be a Latin-1
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 6023cc8564..ff388770f5 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -46,8 +46,9 @@
# include <cstddef>
# include <utility>
#endif
-
-#include <stddef.h>
+#ifndef __ASSEMBLER__
+# include <stddef.h>
+#endif
/*
QT_VERSION is (major << 16) + (minor << 8) + patch.
@@ -188,6 +189,7 @@ namespace QT_NAMESPACE {}
# define QT_LARGEFILE_SUPPORT 64
#endif
+#ifndef __ASSEMBLER__
QT_BEGIN_NAMESPACE
/*
@@ -355,7 +357,7 @@ typedef double qreal;
#if !defined(QT_NAMESPACE) && defined(__cplusplus) && !defined(Q_QDOC)
extern "C"
#endif
-Q_CORE_EXPORT const char *qVersion() Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION const char *qVersion() Q_DECL_NOTHROW;
#if defined(__cplusplus)
@@ -436,6 +438,9 @@ namespace QtPrivate {
sizeof(void *) == sizeof(quintptr)
&& sizeof(void *) == sizeof(qptrdiff)
+
+ size_t and qssize_t are not guaranteed to be the same size as a pointer, but
+ they usually are.
*/
template <int> struct QIntegerForSize;
template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qint8 Signed; };
@@ -451,6 +456,7 @@ typedef QIntegerForSize<Q_PROCESSOR_WORDSIZE>::Unsigned qregisteruint;
typedef QIntegerForSizeof<void*>::Unsigned quintptr;
typedef QIntegerForSizeof<void*>::Signed qptrdiff;
typedef qptrdiff qintptr;
+using qssize_t = QIntegerForSizeof<std::size_t>::Signed;
/* moc compats (signals/slots) */
#ifndef QT_MOC_COMPAT
@@ -612,6 +618,18 @@ private:
void *pool;
};
+#else
+
+#define QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios, tvos, watchos) (0)
+#define QT_MACOS_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos, ios) (0)
+#define QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(macos) (0)
+#define QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(ios) (0)
+#define QT_TVOS_PLATFORM_SDK_EQUAL_OR_ABOVE(tvos) (0)
+#define QT_WATCHOS_PLATFORM_SDK_EQUAL_OR_ABOVE(watchos) (0)
+
+#define QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(osx, ios) (0)
+#define QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(osx) (0)
+
#endif // Q_OS_DARWIN
/*
@@ -660,7 +678,7 @@ Q_NORETURN Q_CORE_EXPORT void qTerminate() Q_DECL_NOTHROW;
# endif
#endif
-Q_CORE_EXPORT bool qSharedBuild() Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qSharedBuild() Q_DECL_NOTHROW;
#ifndef Q_OUTOFLINE_TEMPLATE
# define Q_OUTOFLINE_TEMPLATE
@@ -709,9 +727,9 @@ Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line)
#if !defined(Q_ASSERT)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
-# define Q_ASSERT(cond) do { } while ((false) && (cond))
+# define Q_ASSERT(cond) static_cast<void>(false && (cond))
# else
-# define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop())
+# define Q_ASSERT(cond) ((cond) ? static_cast<void>(0) : qt_assert(#cond, __FILE__, __LINE__))
# endif
#endif
@@ -726,9 +744,9 @@ Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *
#if !defined(Q_ASSERT_X)
# if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
-# define Q_ASSERT_X(cond, where, what) do { } while ((false) && (cond))
+# define Q_ASSERT_X(cond, where, what) static_cast<void>(false && (cond))
# else
-# define Q_ASSERT_X(cond, where, what) ((!(cond)) ? qt_assert_x(where, what,__FILE__,__LINE__) : qt_noop())
+# define Q_ASSERT_X(cond, where, what) ((cond) ? static_cast<void>(0) : qt_assert_x(where, what, __FILE__, __LINE__))
# endif
#endif
@@ -915,13 +933,9 @@ QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantic
# endif
#endif
-namespace QtPrivate {
-template <typename T> struct QAddConst { typedef const T Type; };
-}
-
// this adds const to non-const objects (like std::as_const)
template <typename T>
-Q_DECL_CONSTEXPR typename QtPrivate::QAddConst<T>::Type &qAsConst(T &t) Q_DECL_NOTHROW { return t; }
+Q_DECL_CONSTEXPR typename std::add_const<T>::type &qAsConst(T &t) Q_DECL_NOTHROW { return t; }
// prevent rvalue arguments:
template <typename T>
void qAsConst(const T &&) Q_DECL_EQ_DELETE;
@@ -1112,6 +1126,13 @@ template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QNonConstOverload<Args...>
class QByteArray;
Q_CORE_EXPORT QByteArray qgetenv(const char *varName);
+#ifdef Q_QDOC
+Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName,
+ const QString &defaultValue = QString());
+#else // need it as two functions because QString is only forward-declared here
+Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName);
+Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName, const QString &defaultValue);
+#endif
Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray& value);
Q_CORE_EXPORT bool qunsetenv(const char *varName);
@@ -1161,5 +1182,6 @@ QT_END_NAMESPACE
#include <QtCore/qversiontagging.h>
#endif /* __cplusplus */
+#endif /* !__ASSEMBLER__ */
#endif /* QGLOBAL_H */
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index b5ba935194..6602d53b08 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -153,19 +153,39 @@ Q_NORETURN
static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, const QString &message);
static void qt_message_print(QtMsgType, const QMessageLogContext &context, const QString &message);
+static int checked_var_value(const char *varname)
+{
+ // qEnvironmentVariableIntValue returns 0 on both parsing failure and on
+ // empty, but we need to distinguish between the two for backwards
+ // compatibility reasons.
+ QByteArray str = qgetenv(varname);
+ if (str.isEmpty())
+ return 0;
+
+ bool ok;
+ int value = str.toInt(&ok, 0);
+ return ok ? value : 1;
+}
+
static bool isFatal(QtMsgType msgType)
{
if (msgType == QtFatalMsg)
return true;
if (msgType == QtCriticalMsg) {
- static bool fatalCriticals = !qEnvironmentVariableIsEmpty("QT_FATAL_CRITICALS");
- return fatalCriticals;
+ static QAtomicInt fatalCriticals = checked_var_value("QT_FATAL_CRITICALS");
+
+ // it's fatal if the current value is exactly 1,
+ // otherwise decrement if it's non-zero
+ return fatalCriticals.load() && fatalCriticals.fetchAndAddRelaxed(-1) == 1;
}
if (msgType == QtWarningMsg || msgType == QtCriticalMsg) {
- static bool fatalWarnings = !qEnvironmentVariableIsEmpty("QT_FATAL_WARNINGS");
- return fatalWarnings;
+ static QAtomicInt fatalWarnings = checked_var_value("QT_FATAL_WARNINGS");
+
+ // it's fatal if the current value is exactly 1,
+ // otherwise decrement if it's non-zero
+ return fatalWarnings.load() && fatalWarnings.fetchAndAddRelaxed(-1) == 1;
}
return false;
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index da44c01594..fa3d5913b5 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -241,8 +241,11 @@ public:
TextForceRightToLeft = 0x40000,
// Ensures that the longest variant is always used when computing the
// size of a multi-variant string.
- TextLongestVariant = 0x80000,
- TextBypassShaping = 0x100000
+ TextLongestVariant = 0x80000
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ , TextBypassShaping = 0x100000
+#endif
};
enum TextElideMode {
@@ -508,6 +511,8 @@ public:
AA_CompressHighFrequencyEvents = 25,
AA_DontCheckOpenGLContextThreadAffinity = 26,
AA_DisableShaderDiskCache = 27,
+ AA_DontShowShortcutsInContextMenus = 28,
+ AA_CompressTabletEvents = 29,
// Add new attributes before this line
AA_AttributeCount
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index c030baa05c..4ddb89014e 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -114,6 +114,11 @@
\macos menubar \e{may not} pick up a change in this attribute. Changes
in the QAction::iconVisibleInMenu property will always be picked up.
+ \value AA_DontShowShortcutsInContextMenus Actions with the Shortcut property
+ won't be shown in any shortcut menus unless specifically set by the
+ QAction::shortcutVisibleInContextMenu property. This value has
+ been added in Qt 5.10.
+
\value AA_NativeWindows Ensures that widgets have native windows.
\value AA_DontCreateNativeWidgetSiblings Ensures that siblings of native
@@ -245,7 +250,14 @@
(In the future, the compression feature may be implemented across platforms.)
You can test the attribute to see whether compression is enabled.
If your application needs to handle all events with no compression,
- you can unset this attribute. This value has been added in Qt 5.7.
+ you can unset this attribute. Notice that input events from tablet devices
+ will not be compressed. See AA_CompressTabletEvents if you want these to be
+ compressed as well. This value has been added in Qt 5.7.
+
+ \value AA_CompressTabletEvents Enables compression of input events from tablet devices.
+ Notice that AA_CompressHighFrequencyEvents must be true for events compression
+ to be enabled, and that this flag extends the former to tablet events. Its default
+ value is false. This value has been added in Qt 5.10.
\value AA_DontCheckOpenGLContextThreadAffinity When making a context
current using QOpenGLContext, do not check that the
@@ -660,8 +672,9 @@
be short, localized names. This is basically equivalent to using the date format
string, "ddd MMM d yyyy". See QDate::toString() for more information.
- \value ISODate \l{ISO 8601} extended format: either \c{YYYY-MM-DD} for dates or
- \c{YYYY-MM-DDTHH:mm:ss}, \c{YYYY-MM-DDTHH:mm:ssTZD} (e.g., 1997-07-16T19:20:30+01:00)
+ \value ISODate \l{ISO 8601} extended format: either \c{yyyy-MM-dd} for dates or
+ \c{yyyy-MM-ddTHH:mm:ss} (e.g. 2017-07-24T15:46:29), or with a time-zone
+ suffix (Z for UTC otherwise an offset as [+|-]HH:mm) where appropriate
for combined dates and times.
\value ISODateWithMs \l{ISO 8601} extended format, including milliseconds if applicable.
diff --git a/src/corelib/global/qnumeric.h b/src/corelib/global/qnumeric.h
index 80be984bef..535a96aaec 100644
--- a/src/corelib/global/qnumeric.h
+++ b/src/corelib/global/qnumeric.h
@@ -45,15 +45,15 @@
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT bool qIsInf(double d);
-Q_CORE_EXPORT bool qIsNaN(double d);
-Q_CORE_EXPORT bool qIsFinite(double d);
-Q_CORE_EXPORT bool qIsInf(float f);
-Q_CORE_EXPORT bool qIsNaN(float f);
-Q_CORE_EXPORT bool qIsFinite(float f);
-Q_CORE_EXPORT double qSNaN();
-Q_CORE_EXPORT double qQNaN();
-Q_CORE_EXPORT double qInf();
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(double d);
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(double d);
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(double d);
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsInf(float f);
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsNaN(float f);
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qIsFinite(float f);
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qSNaN();
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN();
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qInf();
Q_CORE_EXPORT quint32 qFloatDistance(float a, float b);
Q_CORE_EXPORT quint64 qFloatDistance(double a, double b);
diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h
index 2291675501..37eddfa9b5 100644
--- a/src/corelib/global/qnumeric_p.h
+++ b/src/corelib/global/qnumeric_p.h
@@ -73,12 +73,12 @@
QT_BEGIN_NAMESPACE
namespace qnumeric_std_wrapper {
// the 'using namespace std' below is cases where the stdlib already put the math.h functions in the std namespace and undefined the macros.
-static inline bool math_h_isnan(double d) { using namespace std; return isnan(d); }
-static inline bool math_h_isinf(double d) { using namespace std; return isinf(d); }
-static inline bool math_h_isfinite(double d) { using namespace std; return isfinite(d); }
-static inline bool math_h_isnan(float f) { using namespace std; return isnan(f); }
-static inline bool math_h_isinf(float f) { using namespace std; return isinf(f); }
-static inline bool math_h_isfinite(float f) { using namespace std; return isfinite(f); }
+Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(double d) { using namespace std; return isnan(d); }
+Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(double d) { using namespace std; return isinf(d); }
+Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(double d) { using namespace std; return isfinite(d); }
+Q_DECL_CONST_FUNCTION static inline bool math_h_isnan(float f) { using namespace std; return isnan(f); }
+Q_DECL_CONST_FUNCTION static inline bool math_h_isinf(float f) { using namespace std; return isinf(f); }
+Q_DECL_CONST_FUNCTION static inline bool math_h_isfinite(float f) { using namespace std; return isfinite(f); }
}
QT_END_NAMESPACE
// These macros from math.h conflict with the real functions in the std namespace.
@@ -94,23 +94,23 @@ QT_BEGIN_NAMESPACE
namespace qnumeric_std_wrapper {
#if defined(QT_MATH_H_DEFINES_MACROS)
# undef QT_MATH_H_DEFINES_MACROS
-static inline bool isnan(double d) { return math_h_isnan(d); }
-static inline bool isinf(double d) { return math_h_isinf(d); }
-static inline bool isfinite(double d) { return math_h_isfinite(d); }
-static inline bool isnan(float f) { return math_h_isnan(f); }
-static inline bool isinf(float f) { return math_h_isinf(f); }
-static inline bool isfinite(float f) { return math_h_isfinite(f); }
+Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return math_h_isnan(d); }
+Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return math_h_isinf(d); }
+Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return math_h_isfinite(d); }
+Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return math_h_isnan(f); }
+Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return math_h_isinf(f); }
+Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return math_h_isfinite(f); }
#else
-static inline bool isnan(double d) { return std::isnan(d); }
-static inline bool isinf(double d) { return std::isinf(d); }
-static inline bool isfinite(double d) { return std::isfinite(d); }
-static inline bool isnan(float f) { return std::isnan(f); }
-static inline bool isinf(float f) { return std::isinf(f); }
-static inline bool isfinite(float f) { return std::isfinite(f); }
+Q_DECL_CONST_FUNCTION static inline bool isnan(double d) { return std::isnan(d); }
+Q_DECL_CONST_FUNCTION static inline bool isinf(double d) { return std::isinf(d); }
+Q_DECL_CONST_FUNCTION static inline bool isfinite(double d) { return std::isfinite(d); }
+Q_DECL_CONST_FUNCTION static inline bool isnan(float f) { return std::isnan(f); }
+Q_DECL_CONST_FUNCTION static inline bool isinf(float f) { return std::isinf(f); }
+Q_DECL_CONST_FUNCTION static inline bool isfinite(float f) { return std::isfinite(f); }
#endif
}
-Q_DECL_CONSTEXPR static inline double qt_inf() Q_DECL_NOEXCEPT
+Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_inf() Q_DECL_NOEXCEPT
{
Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_infinity,
"platform has no definition for infinity for type double");
@@ -118,7 +118,7 @@ Q_DECL_CONSTEXPR static inline double qt_inf() Q_DECL_NOEXCEPT
}
// Signaling NaN
-Q_DECL_CONSTEXPR static inline double qt_snan() Q_DECL_NOEXCEPT
+Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_snan() Q_DECL_NOEXCEPT
{
Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_signaling_NaN,
"platform has no definition for signaling NaN for type double");
@@ -126,39 +126,39 @@ Q_DECL_CONSTEXPR static inline double qt_snan() Q_DECL_NOEXCEPT
}
// Quiet NaN
-Q_DECL_CONSTEXPR static inline double qt_qnan() Q_DECL_NOEXCEPT
+Q_DECL_CONSTEXPR Q_DECL_CONST_FUNCTION static inline double qt_qnan() Q_DECL_NOEXCEPT
{
Q_STATIC_ASSERT_X(std::numeric_limits<double>::has_quiet_NaN,
"platform has no definition for quiet NaN for type double");
return std::numeric_limits<double>::quiet_NaN();
}
-static inline bool qt_is_inf(double d)
+Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(double d)
{
return qnumeric_std_wrapper::isinf(d);
}
-static inline bool qt_is_nan(double d)
+Q_DECL_CONST_FUNCTION static inline bool qt_is_nan(double d)
{
return qnumeric_std_wrapper::isnan(d);
}
-static inline bool qt_is_finite(double d)
+Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(double d)
{
return qnumeric_std_wrapper::isfinite(d);
}
-static inline bool qt_is_inf(float f)
+Q_DECL_CONST_FUNCTION static inline bool qt_is_inf(float f)
{
return qnumeric_std_wrapper::isinf(f);
}
-static inline bool qt_is_nan(float f)
+Q_DECL_CONST_FUNCTION static inline bool qt_is_nan(float f)
{
return qnumeric_std_wrapper::isnan(f);
}
-static inline bool qt_is_finite(float f)
+Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f)
{
return qnumeric_std_wrapper::isfinite(f);
}
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
new file mode 100644
index 0000000000..fb20f459b5
--- /dev/null
+++ b/src/corelib/global/qrandom.cpp
@@ -0,0 +1,1049 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// for rand_s
+#define _CRT_RAND_S
+
+#include "qrandom.h"
+#include "qrandom_p.h"
+#include <qobjectdefs.h>
+#include <qthreadstorage.h>
+#include <private/qsimd_p.h>
+
+#include <errno.h>
+
+#if QT_CONFIG(getentropy)
+# include <sys/random.h>
+#else
+# if QT_CONFIG(cxx11_random)
+# include <random>
+# include "qdeadlinetimer.h"
+# include "qhashfunctions.h"
+# endif
+
+# if QT_CONFIG(getauxval)
+# include <sys/auxv.h>
+# endif
+#endif // !QT_CONFIG(getentropy)
+
+#ifdef Q_OS_UNIX
+# include <fcntl.h>
+# include <private/qcore_unix_p.h>
+#else
+# include <qt_windows.h>
+
+// RtlGenRandom is not exported by its name in advapi32.dll, but as SystemFunction036
+// See https://msdn.microsoft.com/en-us/library/windows/desktop/aa387694(v=vs.85).aspx
+// Implementation inspired on https://hg.mozilla.org/mozilla-central/file/722fdbff1efc/security/nss/lib/freebl/win_rand.c#l146
+// Argument why this is safe to use: https://bugzilla.mozilla.org/show_bug.cgi?id=504270
+extern "C" {
+DECLSPEC_IMPORT BOOLEAN WINAPI SystemFunction036(PVOID RandomBuffer, ULONG RandomBufferLength);
+}
+#endif
+
+#if defined(Q_OS_ANDROID)
+# include <private/qjni_p.h>
+#endif
+
+// This file is too low-level for regular Q_ASSERT (the logging framework may
+// recurse back), so use regular assert()
+#undef NDEBUG
+#undef Q_ASSERT_X
+#undef Q_ASSERT
+#define Q_ASSERT(cond) assert(cond)
+#if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS)
+# define NDEBUG 1
+#endif
+#include <assert.h>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND)
+static qssize_t qt_random_cpu(void *buffer, qssize_t count);
+
+# ifdef Q_PROCESSOR_X86_64
+# define _rdrandXX_step _rdrand64_step
+# else
+# define _rdrandXX_step _rdrand32_step
+# endif
+
+static QT_FUNCTION_TARGET(RDRND) qssize_t qt_random_cpu(void *buffer, qssize_t count)
+{
+ unsigned *ptr = reinterpret_cast<unsigned *>(buffer);
+ unsigned *end = ptr + count;
+
+ while (ptr + sizeof(qregisteruint)/sizeof(*ptr) <= end) {
+ if (_rdrandXX_step(reinterpret_cast<qregisteruint *>(ptr)) == 0)
+ goto out;
+ ptr += sizeof(qregisteruint)/sizeof(*ptr);
+ }
+
+ if (sizeof(*ptr) != sizeof(qregisteruint) && ptr != end) {
+ if (_rdrand32_step(ptr))
+ goto out;
+ ++ptr;
+ }
+
+out:
+ return ptr - reinterpret_cast<unsigned *>(buffer);
+}
+#endif
+
+namespace {
+#if QT_CONFIG(getentropy)
+class SystemRandom
+{
+public:
+ enum { EfficientBufferFill = true };
+ static qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW
+ {
+ // getentropy can read at most 256 bytes, so break the reading
+ qssize_t read = 0;
+ while (count - read > 256) {
+ // getentropy can't fail under normal circumstances
+ int ret = getentropy(reinterpret_cast<uchar *>(buffer) + read, 256);
+ Q_ASSERT(ret == 0);
+ read += 256;
+ }
+
+ int ret = getentropy(reinterpret_cast<uchar *>(buffer) + read, count - read);
+ Q_ASSERT(ret == 0);
+ return count;
+ }
+};
+
+#elif defined(Q_OS_UNIX)
+class SystemRandom
+{
+ static QBasicAtomicInt s_fdp1; // "file descriptor plus 1"
+ static int openDevice();
+ SystemRandom() {}
+ ~SystemRandom();
+public:
+ enum { EfficientBufferFill = true };
+ static qssize_t fillBuffer(void *buffer, qssize_t count);
+};
+QBasicAtomicInt SystemRandom::s_fdp1 = Q_BASIC_ATOMIC_INITIALIZER(0);
+
+SystemRandom::~SystemRandom()
+{
+ int fd = s_fdp1.loadAcquire() - 1;
+ if (fd >= 0)
+ qt_safe_close(fd);
+}
+
+int SystemRandom::openDevice()
+{
+ int fd = s_fdp1.loadAcquire() - 1;
+ if (fd != -1)
+ return fd;
+
+ fd = qt_safe_open("/dev/urandom", O_RDONLY);
+ if (fd == -1)
+ fd = qt_safe_open("/dev/random", O_RDONLY | O_NONBLOCK);
+ if (fd == -1) {
+ // failed on both, set to -2 so we won't try again
+ fd = -2;
+ }
+
+ int opened_fdp1;
+ if (s_fdp1.testAndSetOrdered(0, fd + 1, opened_fdp1)) {
+ if (fd >= 0) {
+ static const SystemRandom closer;
+ Q_UNUSED(closer);
+ }
+ return fd;
+ }
+
+ // failed, another thread has opened the file descriptor
+ if (fd >= 0)
+ qt_safe_close(fd);
+ return opened_fdp1 - 1;
+}
+
+qssize_t SystemRandom::fillBuffer(void *buffer, qssize_t count)
+{
+ int fd = openDevice();
+ if (Q_UNLIKELY(fd < 0))
+ return 0;
+
+ qint64 n = qt_safe_read(fd, buffer, count);
+ return qMax<qssize_t>(n, 0); // ignore any errors
+}
+#endif // Q_OS_UNIX
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
+class SystemRandom
+{
+public:
+ enum { EfficientBufferFill = true };
+ static qssize_t fillBuffer(void *buffer, qssize_t count)
+ {
+ auto RtlGenRandom = SystemFunction036;
+ return RtlGenRandom(buffer, ULONG(count)) ? count: 0;
+ }
+};
+#elif defined(Q_OS_WINRT)
+class SystemRandom
+{
+public:
+ enum { EfficientBufferFill = false };
+ static qssize_t fillBuffer(void *, qssize_t)
+ {
+ // always use the fallback
+ return 0;
+ }
+};
+#endif // Q_OS_WINRT
+} // unnamed namespace
+
+#if defined(Q_OS_WIN)
+static void fallback_update_seed(unsigned) {}
+static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW
+{
+ // on Windows, rand_s is a high-quality random number generator
+ // and it requires no seeding
+ std::generate(ptr, ptr + left, []() {
+ unsigned value;
+ rand_s(&value);
+ return value;
+ });
+}
+#elif QT_CONFIG(getentropy)
+static void fallback_update_seed(unsigned) {}
+static void fallback_fill(quint32 *, qssize_t) Q_DECL_NOTHROW
+{
+ // no fallback necessary, getentropy cannot fail under normal circumstances
+}
+#elif defined(Q_OS_BSD4)
+static void fallback_update_seed(unsigned) {}
+static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW
+{
+ // BSDs have arc4random(4) and these work even in chroot(2)
+ arc4random_buf(ptr, left * sizeof(*ptr));
+}
+#elif QT_CONFIG(cxx11_random)
+static QBasicAtomicInteger<unsigned> seed = Q_BASIC_ATOMIC_INITIALIZER(0U);
+static void fallback_update_seed(unsigned value)
+{
+ // Update the seed to be used for the fallback mechansim, if we need to.
+ // We can't use QtPrivate::QHashCombine here because that is not an atomic
+ // operation. A simple XOR will have to do then.
+ seed.fetchAndXorRelaxed(value);
+}
+
+Q_NEVER_INLINE
+#ifdef Q_CC_GNU
+__attribute__((cold)) // this function is pretty big, so optimize for size
+#endif
+static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW
+{
+ quint32 scratch[12]; // see element count below
+ quint32 *end = scratch;
+
+ auto foldPointer = [](quintptr v) {
+ if (sizeof(quintptr) == sizeof(quint32)) {
+ // For 32-bit systems, we simply return the pointer.
+ return quint32(v);
+ } else {
+ // For 64-bit systems, we try to return the variable part of the
+ // pointer. On current x86-64 and AArch64, the top 17 bits are
+ // architecturally required to be the same, but in reality the top
+ // 24 bits on Linux are likely to be the same for all processes.
+ return quint32(v >> (32 - 24));
+ }
+ };
+
+ Q_ASSERT(left);
+
+ *end++ = foldPointer(quintptr(&seed)); // 1: variable in this library/executable's .data
+ *end++ = foldPointer(quintptr(&scratch)); // 2: variable in the stack
+ *end++ = foldPointer(quintptr(&errno)); // 3: veriable either in libc or thread-specific
+ *end++ = foldPointer(quintptr(reinterpret_cast<void*>(strerror))); // 4: function in libc (and unlikely to be a macro)
+
+#ifndef QT_BOOTSTRAPPED
+ quint64 nsecs = QDeadlineTimer::current(Qt::PreciseTimer).deadline();
+ *end++ = quint32(nsecs); // 5
+#endif
+
+ if (quint32 v = seed.load())
+ *end++ = v; // 6
+
+#if QT_CONFIG(getauxval)
+ // works on Linux -- all modern libc have getauxval
+# ifdef AT_RANDOM
+ // ELF's auxv AT_RANDOM has 16 random bytes
+ // (other ELF-based systems don't seem to have AT_RANDOM)
+ ulong auxvSeed = getauxval(AT_RANDOM);
+ if (auxvSeed) {
+ memcpy(scratch, reinterpret_cast<void *>(auxvSeed), 16);
+ end += 4; // 7 to 10
+ }
+# endif
+
+ // Both AT_BASE and AT_SYSINFO_EHDR have some randomness in them due to the
+ // system's ASLR, even if many bits are the same. They also have randomness
+ // between them.
+# ifdef AT_BASE
+ // present at least on the BSDs too, indicates the address of the loader
+ ulong base = getauxval(AT_BASE);
+ if (base)
+ *end++ = foldPointer(base); // 11
+# endif
+# ifdef AT_SYSINFO_EHDR
+ // seems to be Linux-only, indicates the global page of the sysinfo
+ ulong sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
+ if (sysinfo_ehdr)
+ *end++ = foldPointer(sysinfo_ehdr); // 12
+# endif
+#endif
+
+ Q_ASSERT(end <= std::end(scratch));
+
+ // this is highly inefficient, we should save the generator across calls...
+ std::seed_seq sseq(scratch, end);
+ std::mt19937 generator(sseq);
+ std::generate(ptr, ptr + left, generator);
+
+ fallback_update_seed(*ptr);
+}
+#else
+static void fallback_update_seed(unsigned) {}
+static Q_NORETURN void fallback_fill(quint32 *, qssize_t)
+{
+ qFatal("Random number generator failed and no high-quality backup available");
+}
+#endif
+
+static qssize_t fill_cpu(quint32 *buffer, qssize_t count)
+{
+#if defined(Q_PROCESSOR_X86) && QT_COMPILER_SUPPORTS_HERE(RDRND)
+ if (qCpuHasFeature(RDRND) && (uint(qt_randomdevice_control) & SkipHWRNG) == 0)
+ return qt_random_cpu(buffer, count);
+#else
+ Q_UNUSED(buffer);
+ Q_UNUSED(count);
+#endif
+ return 0;
+}
+
+static void fill_internal(quint32 *buffer, qssize_t count)
+{
+ if (Q_UNLIKELY(uint(qt_randomdevice_control) & SetRandomData)) {
+ uint value = uint(qt_randomdevice_control) & RandomDataMask;
+ std::fill_n(buffer, count, value);
+ return;
+ }
+
+ qssize_t filled = fill_cpu(buffer, count);
+ if (filled != count && (uint(qt_randomdevice_control) & SkipSystemRNG) == 0) {
+ qssize_t bytesFilled =
+ SystemRandom::fillBuffer(buffer + filled, (count - filled) * qssize_t(sizeof(*buffer)));
+ filled += bytesFilled / qssize_t(sizeof(*buffer));
+ }
+ if (filled)
+ fallback_update_seed(*buffer);
+
+ if (Q_UNLIKELY(filled != count)) {
+ // failed to fill the entire buffer, try the faillback mechanism
+ fallback_fill(buffer + filled, count - filled);
+ }
+}
+
+static Q_NEVER_INLINE void fill(void *buffer, void *bufferEnd)
+{
+ struct ThreadState {
+ enum {
+ DesiredBufferByteSize = 32,
+ BufferCount = DesiredBufferByteSize / sizeof(quint32)
+ };
+ quint32 buffer[BufferCount];
+ int idx = BufferCount;
+ };
+
+ // Verify that the pointers are properly aligned for 32-bit
+ Q_ASSERT(quintptr(buffer) % sizeof(quint32) == 0);
+ Q_ASSERT(quintptr(bufferEnd) % sizeof(quint32) == 0);
+
+ quint32 *ptr = reinterpret_cast<quint32 *>(buffer);
+ quint32 * const end = reinterpret_cast<quint32 *>(bufferEnd);
+
+#if defined(Q_COMPILER_THREAD_LOCAL) && !defined(QT_BOOTSTRAPPED)
+ if (SystemRandom::EfficientBufferFill && (end - ptr) < ThreadState::BufferCount
+ && uint(qt_randomdevice_control) == 0) {
+ thread_local ThreadState state;
+ qssize_t itemsAvailable = ThreadState::BufferCount - state.idx;
+
+ // copy as much as we already have
+ qssize_t itemsToCopy = qMin(qssize_t(end - ptr), itemsAvailable);
+ memcpy(ptr, state.buffer + state.idx, size_t(itemsToCopy) * sizeof(*ptr));
+ ptr += itemsToCopy;
+
+ if (ptr != end) {
+ // refill the buffer and try again
+ fill_internal(state.buffer, ThreadState::BufferCount);
+ state.idx = 0;
+
+ itemsToCopy = end - ptr;
+ memcpy(ptr, state.buffer + state.idx, size_t(itemsToCopy) * sizeof(*ptr));
+ ptr = end;
+ }
+
+ // erase what we copied and advance
+# ifdef Q_OS_WIN
+ // Microsoft recommends this
+ SecureZeroMemory(state.buffer + state.idx, size_t(itemsToCopy) * sizeof(*ptr));
+# else
+ // We're quite confident the compiler will not optimize this out because
+ // we're writing to a thread-local buffer
+ memset(state.buffer + state.idx, 0, size_t(itemsToCopy) * sizeof(*ptr));
+# endif
+ state.idx += itemsToCopy;
+ }
+#endif // Q_COMPILER_THREAD_LOCAL && !QT_BOOTSTRAPPED
+
+ if (ptr != end) {
+ // fill directly in the user buffer
+ fill_internal(ptr, end - ptr);
+ }
+}
+
+/*!
+ \class QRandomGenerator
+ \inmodule QtCore
+ \since 5.10
+
+ \brief The QRandomGenerator class allows one to obtain random values from a
+ high-quality, seed-less Random Number Generator.
+
+ QRandomGenerator may be used to generate random values from a high-quality
+ random number generator. Unlike qrand(), QRandomGenerator does not need to be
+ seeded. That also means it is not possible to force it to produce a
+ reliable sequence, which may be needed for debugging.
+
+ The class can generate 32-bit or 64-bit quantities, or fill an array of
+ those. The most common way of generating new values is to call the get32(),
+ get64() or fillRange() functions. One would use it as:
+
+ \code
+ quint32 value = QRandomGenerator::get32();
+ \endcode
+
+ Additionally, it provides a floating-point function getReal() that returns
+ a number in the range [0, 1) (that is, inclusive of zero and exclusive of
+ 1). There's also a set of convenience functions that facilitate obtaining a
+ random number in a bounded, integral range.
+
+ \warning This class is not suitable for bulk data creation. See below for the
+ technical reasons.
+
+ \section1 Frequency and entropy exhaustion
+
+ QRandomGenerator does not need to be seeded and instead uses operating system
+ or hardware facilities to generate random numbers. On some systems and with
+ certain hardware, those facilities are true Random Number Generators.
+ However, if they are true RNGs, those facilities have finite entropy source
+ and thus may fail to produce any results if the entropy pool is exhausted.
+
+ If that happens, first the operating system then QRandomGenerator will fall
+ back to Pseudo Random Number Generators of decreasing qualities (Qt's
+ fallback generator being the simplest). Therefore, QRandomGenerator should
+ not be used for high-frequency random number generation, lest the entropy
+ pool become empty. As a rule of thumb, this class should not be called upon
+ to generate more than a kilobyte per second of random data (note: this may
+ vary from system to system).
+
+ If an application needs true RNG data in bulk, it should use the operating
+ system facilities (such as \c{/dev/random} on Unix systems) directly and
+ wait for entropy to become available. If true RNG is not required,
+ applications should instead use a PRNG engines and can use QRandomGenerator to
+ seed those.
+
+ \section1 Standard C++ Library compatibility
+
+ QRandomGenerator is modeled after
+ \c{\l{http://en.cppreference.com/w/cpp/numeric/random/random_device}{std::random_device}}
+ and may be used in almost all contexts that the Standard Library can.
+ QRandomGenerator attempts to use either the same engine that backs
+ \c{std::random_device} or a better one. Note that \c{std::random_device} is
+ also allowed to fail if the source entropy pool becomes exhausted, in which
+ case it will throw an exception. QRandomGenerator never throws, but may abort
+ program execution instead.
+
+ Like the Standard Library class, QRandomGenerator can be used to seed Standard
+ Library deterministic random engines from \c{<random>}, such as the
+ Mersenne Twister. Unlike \c{std::random_device}, QRandomGenerator also
+ implements the API of
+ \c{\l{http://en.cppreference.com/w/cpp/numeric/random/seed_seq}{std::seed_seq}},
+ allowing it to seed the deterministic engines directly.
+
+ The following code can be used to create and seed the
+ implementation-defined default deterministic PRNG, then use it to fill a
+ block range:
+
+ \code
+ QRandomGenerator rd;
+ std::default_random_engine rng(rd);
+ std::generate(block.begin(), block.end(), rng);
+
+ // equivalent to:
+ for (auto &v : block)
+ v = rng();
+ \endcode
+
+ QRandomGenerator is also compatible with the uniform distribution classes
+ \c{std::uniform_int_distribution} and \c{std:uniform_real_distribution}, as
+ well as the free function \c{std::generate_canonical}. For example, the
+ following code may be used to generate a floating-point number in the range
+ [1, 2.5):
+
+ \code
+ QRandomGenerator64 rd;
+ std::uniform_real_distribution dist(1, 2.5);
+ return dist(rd);
+ \endcode
+
+ Note the use of the QRandomGenerator64 class instead of QRandomGenerator to
+ obtain 64 bits of random data in a single call, though it is not required
+ to make the algorithm work (the Standard Library functions will make as
+ many calls as required to obtain enough bits of random data for the desired
+ range).
+
+ \sa QRandomGenerator64, qrand()
+ */
+
+/*!
+ \fn QRandomGenerator::QRandomGenerator()
+ \internal
+ Defaulted constructor, does nothing.
+ */
+
+/*!
+ \typedef QRandomGenerator::result_type
+
+ A typedef to the type that operator()() returns. That is, quint32.
+
+ \sa operator()()
+ */
+
+/*!
+ \fn result_type QRandomGenerator::operator()()
+
+ Generates a 32-bit random quantity and returns it.
+
+ \sa QRandomGenerator::get32(), QRandomGenerator::get64()
+ */
+
+/*!
+ \fn double QRandomGenerator::entropy() const
+
+ Returns the estimate of the entropy in the random generator source.
+
+ This function exists to comply with the Standard Library requirements for
+ \c{\l{http://en.cppreference.com/w/cpp/numeric/random/random_device}{std::random_device}}
+ but it does not and cannot ever work. It is not possible to obtain a
+ reliable entropy value in a shared entropy pool in a multi-tasking system,
+ as other processes or threads may use that entropy. Any value non-zero
+ value that this function could return would be obsolete by the time the
+ user code reached it.
+
+ Since QRandomGenerator attempts to use a hardware Random Number Generator,
+ this function always returns 0.0.
+ */
+
+/*!
+ \fn result_type QRandomGenerator::min()
+
+ Returns the minimum value that QRandomGenerator may ever generate. That is, 0.
+
+ \sa max(), QRandomGenerator64::max()
+ */
+
+/*!
+ \fn result_type QRandomGenerator::max()
+
+ Returns the maximum value that QRandomGenerator may ever generate. That is,
+ \c {std::numeric_limits<result_type>::max()}.
+
+ \sa min(), QRandomGenerator64::max()
+ */
+
+/*!
+ \fn void QRandomGenerator::generate(ForwardIterator begin, ForwardIterator end)
+
+ Generates 32-bit quantities and stores them in the range between \a begin
+ and \a end. This function is equivalent to (and is implemented as):
+
+ \code
+ std::generate(begin, end, []() { return get32(); });
+ \endcode
+
+ This function complies with the requirements for the function
+ \c{\l{http://en.cppreference.com/w/cpp/numeric/random/seed_seq/generate}{std::seed_seq::generate}},
+ which requires unsigned 32-bit integer values.
+
+ Note that if the [begin, end) range refers to an area that can store more
+ than 32 bits per element, the elements will still be initialized with only
+ 32 bits of data. Any other bits will be zero. To fill the range with 64 bit
+ quantities, one can write:
+
+ \code
+ std::generate(begin, end, []() { return get64(); });
+ \endcode
+
+ If the range refers to contiguous memory (such as an array or the data from
+ a QVector), the fillRange() function may be used too.
+
+ \sa fillRange()
+ */
+
+/*!
+ \fn void QRandomGenerator::generate(quint32 *begin, quint32 *end)
+ \overload
+ \internal
+
+ Same as the other overload, but more efficiently fills \a begin to \a end.
+ */
+
+/*!
+ \fn void QRandomGenerator::fillRange(UInt *buffer, qssize_t count)
+
+ Generates \a count 32- or 64-bit quantities (depending on the type \c UInt)
+ and stores them in the buffer pointed by \a buffer. This is the most
+ efficient way to obtain more than one quantity at a time, as it reduces the
+ number of calls into the Random Number Generator source.
+
+ For example, to fill a vector of 16 entries with random values, one may
+ write:
+
+ \code
+ QVector<quint32> vector;
+ vector.resize(16);
+ QRandomGenerator::fillRange(vector.data(), vector.size());
+ \endcode
+
+ \sa generate()
+ */
+
+/*!
+ \fn void QRandomGenerator::fillRange(UInt (&buffer)[N})
+
+ Generates \c N 32- or 64-bit quantities (depending on the type \c UInt) and
+ stores them in the \a buffer array. This is the most efficient way to
+ obtain more than one quantity at a time, as it reduces the number of calls
+ into the Random Number Generator source.
+
+ For example, to fill generate two 32-bit quantities, one may write:
+
+ \code
+ quint32 array[2];
+ QRandomGenerator::fillRange(array);
+ \endcode
+
+ It would have also been possible to make one call to get64() and then split
+ the two halves of the 64-bit value.
+
+ \sa generate()
+ */
+
+/*!
+ \fn qreal QRandomGenerator::getReal()
+
+ Generates one random qreal in the canonical range [0, 1) (that is,
+ inclusive of zero and exclusive of 1).
+
+ This function is equivalent to:
+ \code
+ QRandomGenerator64 rd;
+ return std::generate_canonical<qreal, std::numeric_limits<qreal>::digits>(rd);
+ \endcode
+
+ The same may also be obtained by using
+ \c{\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution}{std::uniform_real_distribution}}
+ with parameters 0 and 1.
+
+ \sa get32(), get64(), bounded()
+ */
+
+/*!
+ \fn qreal QRandomGenerator::bounded(qreal sup)
+
+ Generates one random qreal in the range between 0 (inclusive) and \a
+ sup (exclusive). This function is equivalent to and is implemented as:
+
+ \code
+ return getReal() * sup;
+ \endcode
+
+ \sa getReal(), bounded()
+ */
+
+/*!
+ \fn quint32 QRandomGenerator::bounded(quint32 sup)
+ \overload
+
+ Generates one random 32-bit quantity in the range between 0 (inclusive) and
+ \a sup (exclusive). The same result may also be obtained by using
+ \c{\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{std::uniform_int_distribution}}
+ with parameters 0 and \c{sup - 1}. That class can also be used to obtain
+ quantities larger than 32 bits.
+
+ For example, to obtain a value between 0 and 255 (inclusive), one would write:
+
+ \code
+ quint32 v = QRandomGenerator::bounded(256);
+ \endcode
+
+ Naturally, the same could also be obtained by masking the result of get32()
+ to only the lower 8 bits. Either solution is as efficient.
+
+ Note that this function cannot be used to obtain values in the full 32-bit
+ range of quint32. Instead, use get32().
+
+ \sa get32(), get64(), getReal()
+ */
+
+/*!
+ \fn quint32 QRandomGenerator::bounded(int sup)
+ \overload
+
+ Generates one random 32-bit quantity in the range between 0 (inclusive) and
+ \a sup (exclusive). \a sup must not be negative.
+
+ Note that this function cannot be used to obtain values in the full 32-bit
+ range of int. Instead, use get32() and cast to int.
+
+ \sa get32(), get64(), getReal()
+ */
+
+/*!
+ \fn quint32 QRandomGenerator::bounded(quint32 min, quint32 sup)
+ \overload
+
+ Generates one random 32-bit quantity in the range between \a min (inclusive)
+ and \a sup (exclusive). The same result may also be obtained by using
+ \c{\l{http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution}{std::uniform_int_distribution}}
+ with parameters \a min and \c{\a sup - 1}. That class can also be used to
+ obtain quantities larger than 32 bits.
+
+ For example, to obtain a value between 1000 (incl.) and 2000 (excl.), one
+ would write:
+
+ \code
+ quint32 v = QRandomGenerator::bounded(1000, 2000);
+ \endcode
+
+
+ Note that this function cannot be used to obtain values in the full 32-bit
+ range of quint32. Instead, use get32().
+
+ \sa get32(), get64(), getReal()
+ */
+
+/*!
+ \fn quint32 QRandomGenerator::bounded(int min, int sup)
+ \overload
+
+ Generates one random 32-bit quantity in the range between \a min
+ (inclusive) and \a sup (exclusive), both of which may be negative.
+
+ Note that this function cannot be used to obtain values in the full 32-bit
+ range of int. Instead, use get32() and cast to int.
+
+ \sa get32(), get64(), getReal()
+ */
+
+/*!
+ \class QRandomGenerator64
+ \inmodule QtCore
+ \since 5.10
+
+ \brief The QRandomGenerator64 class allows one to obtain 64-bit random values
+ from a high-quality, seed-less Random Number Generator.
+
+ QRandomGenerator64 is a simple adaptor class around QRandomGenerator, making the
+ QRandomGenerator::get64() function the default for operator()(), instead of the
+ function that returns 32-bit quantities. This class is intended to be used
+ in conjunction with Standard Library algorithms that need 64-bit quantities
+ instead of 32-bit ones.
+
+ In all other aspects, the class is the same. Please refer to
+ QRandomGenerator's documentation for more information.
+
+ \sa QRandomGenerator
+*/
+
+/*!
+ \fn QRandomGenerator64::QRandomGenerator64()
+ \internal
+ Defaulted constructor, does nothing.
+ */
+
+/*!
+ \typedef QRandomGenerator64::result_type
+
+ A typedef to the type that operator()() returns. That is, quint64.
+
+ \sa operator()()
+ */
+
+/*!
+ \fn result_type QRandomGenerator64::operator()()
+
+ Generates a 64-bit random quantity and returns it.
+
+ \sa QRandomGenerator::get32(), QRandomGenerator::get64()
+ */
+
+/*!
+ \fn double QRandomGenerator64::entropy() const
+
+ Returns the estimate of the entropy in the random generator source.
+
+ This function exists to comply with the Standard Library requirements for
+ \c{\l{http://en.cppreference.com/w/cpp/numeric/random/random_device}{std::random_device}}
+ but it does not and cannot ever work. It is not possible to obtain a
+ reliable entropy value in a shared entropy pool in a multi-tasking system,
+ as other processes or threads may use that entropy. Any value non-zero
+ value that this function could return would be obsolete by the time the
+ user code reached it.
+
+ Since QRandomGenerator64 attempts to use a hardware Random Number Generator,
+ this function always returns 0.0.
+ */
+
+/*!
+ \fn result_type QRandomGenerator64::min()
+
+ Returns the minimum value that QRandomGenerator64 may ever generate. That is, 0.
+
+ \sa max(), QRandomGenerator::max()
+ */
+
+/*!
+ \fn result_type QRandomGenerator64::max()
+
+ Returns the maximum value that QRandomGenerator64 may ever generate. That is,
+ \c {std::numeric_limits<result_type>::max()}.
+
+ \sa min(), QRandomGenerator::max()
+ */
+
+/*!
+ Generates one 32-bit random value and returns it.
+
+ Note about casting to a signed integer: all bits returned by this function
+ are random, so there's a 50% chance that the most significant bit will be
+ set. If you wish to cast the returned value to int and keep it positive,
+ you should mask the sign bit off:
+
+ \code
+ int value = QRandomGenerator::get32() & std::numeric_limits<int>::max();
+ \endcode
+
+ \sa get64(), getReal()
+ */
+quint32 QRandomGenerator::get32()
+{
+ quint32 ret;
+ fill(&ret, &ret + 1);
+ return ret;
+}
+
+/*!
+ Generates one 64-bit random value and returns it.
+
+ Note about casting to a signed integer: all bits returned by this function
+ are random, so there's a 50% chance that the most significant bit will be
+ set. If you wish to cast the returned value to qint64 and keep it positive,
+ you should mask the sign bit off:
+
+ \code
+ qint64 value = QRandomGenerator::get64() & std::numeric_limits<qint64>::max();
+ \endcode
+
+ \sa get32(), getReal(), QRandomGenerator64
+ */
+quint64 QRandomGenerator::get64()
+{
+ quint64 ret;
+ fill(&ret, &ret + 1);
+ return ret;
+}
+
+/*!
+ \internal
+
+ Fills the range pointed by \a buffer and \a bufferEnd with 32-bit random
+ values. The buffer must be correctly aligned.
+ */
+void QRandomGenerator::fillRange_helper(void *buffer, void *bufferEnd)
+{
+ fill(buffer, bufferEnd);
+}
+
+#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0)
+using SeedStorageType = QtPrivate::FunctionPointer<decltype(&srand)>::Arguments::Car;
+
+typedef QThreadStorage<SeedStorageType *> SeedStorage;
+Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value
+
+#elif defined(Q_OS_ANDROID)
+typedef QThreadStorage<QJNIObjectPrivate> AndroidRandomStorage;
+Q_GLOBAL_STATIC(AndroidRandomStorage, randomTLS)
+#endif
+
+/*!
+ \relates <QtGlobal>
+ \since 4.2
+
+ Thread-safe version of the standard C++ \c srand() function.
+
+ Sets the argument \a seed to be used to generate a new random number sequence of
+ pseudo random integers to be returned by qrand().
+
+ The sequence of random numbers generated is deterministic per thread. For example,
+ if two threads call qsrand(1) and subsequently call qrand(), the threads will get
+ the same random number sequence.
+
+ \sa qrand(), QRandomGenerator
+*/
+void qsrand(uint seed)
+{
+#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0)
+ SeedStorage *seedStorage = randTLS();
+ if (seedStorage) {
+ SeedStorageType *pseed = seedStorage->localData();
+ if (!pseed)
+ seedStorage->setLocalData(pseed = new SeedStorageType);
+ *pseed = seed;
+ } else {
+ //global static seed storage should always exist,
+ //except after being deleted by QGlobalStaticDeleter.
+ //But since it still can be called from destructor of another
+ //global static object, fallback to srand(seed)
+ srand(seed);
+ }
+#elif defined(Q_OS_ANDROID)
+ if (randomTLS->hasLocalData()) {
+ randomTLS->localData().callMethod<void>("setSeed", "(J)V", jlong(seed));
+ return;
+ }
+
+ QJNIObjectPrivate random("java/util/Random",
+ "(J)V",
+ jlong(seed));
+ if (!random.isValid()) {
+ srand(seed);
+ return;
+ }
+
+ randomTLS->setLocalData(random);
+#else
+ // On Windows srand() and rand() already use Thread-Local-Storage
+ // to store the seed between calls
+ // this is also valid for QT_NO_THREAD
+ srand(seed);
+#endif
+}
+
+/*!
+ \relates <QtGlobal>
+ \since 4.2
+
+ Thread-safe version of the standard C++ \c rand() function.
+
+ Returns a value between 0 and \c RAND_MAX (defined in \c <cstdlib> and
+ \c <stdlib.h>), the next number in the current sequence of pseudo-random
+ integers.
+
+ Use \c qsrand() to initialize the pseudo-random number generator with a
+ seed value. Seeding must be performed at least once on each thread. If that
+ step is skipped, then the sequence will be pre-seeded with a constant
+ value.
+
+ \sa qsrand(), QRandomGenerator
+*/
+int qrand()
+{
+#if defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0)
+ SeedStorage *seedStorage = randTLS();
+ if (seedStorage) {
+ SeedStorageType *pseed = seedStorage->localData();
+ if (!pseed) {
+ seedStorage->setLocalData(pseed = new SeedStorageType);
+ *pseed = 1;
+ }
+ return rand_r(pseed);
+ } else {
+ //global static seed storage should always exist,
+ //except after being deleted by QGlobalStaticDeleter.
+ //But since it still can be called from destructor of another
+ //global static object, fallback to rand()
+ return rand();
+ }
+#elif defined(Q_OS_ANDROID)
+ AndroidRandomStorage *randomStorage = randomTLS();
+ if (!randomStorage)
+ return rand();
+
+ if (randomStorage->hasLocalData()) {
+ return randomStorage->localData().callMethod<jint>("nextInt",
+ "(I)I",
+ RAND_MAX);
+ }
+
+ QJNIObjectPrivate random("java/util/Random",
+ "(J)V",
+ jlong(1));
+
+ if (!random.isValid())
+ return rand();
+
+ randomStorage->setLocalData(random);
+ return random.callMethod<jint>("nextInt", "(I)I", RAND_MAX);
+#else
+ // On Windows srand() and rand() already use Thread-Local-Storage
+ // to store the seed between calls
+ // this is also valid for QT_NO_THREAD
+ return rand();
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/global/qrandom.h b/src/corelib/global/qrandom.h
new file mode 100644
index 0000000000..3bede87fa6
--- /dev/null
+++ b/src/corelib/global/qrandom.h
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QRANDOM_H
+#define QRANDOM_H
+
+#include <QtCore/qglobal.h>
+#include <algorithm> // for std::generate
+
+QT_BEGIN_NAMESPACE
+
+class QRandomGenerator
+{
+ // restrict the template parameters to unsigned integers 32 bits wide or larger
+ template <typename UInt> using IfValidUInt =
+ typename std::enable_if<std::is_unsigned<UInt>::value && sizeof(UInt) >= sizeof(uint), bool>::type;
+public:
+ QRandomGenerator() = default;
+
+ static Q_CORE_EXPORT quint32 get32();
+ static Q_CORE_EXPORT quint64 get64();
+ static qreal getReal()
+ {
+ const int digits = std::numeric_limits<qreal>::digits;
+ if (digits < std::numeric_limits<quint32>::digits) {
+ // use get32()
+ return qreal(get32()) / ((max)() + qreal(1.0));
+ } else {
+ // use get64()
+ // we won't have enough bits for a __float128 though
+ return qreal(get64()) / ((std::numeric_limits<quint64>::max)() + qreal(1.0));
+ }
+ }
+
+ static qreal bounded(qreal sup)
+ {
+ return getReal() * sup;
+ }
+
+ static quint32 bounded(quint32 sup)
+ {
+ quint64 value = get32();
+ value *= sup;
+ value /= (max)() + quint64(1);
+ return quint32(value);
+ }
+
+ static int bounded(int sup)
+ {
+ return int(bounded(quint32(sup)));
+ }
+
+ static quint32 bounded(quint32 min, quint32 sup)
+ {
+ return bounded(sup - min) + min;
+ }
+
+ static int bounded(int min, int sup)
+ {
+ return bounded(sup - min) + min;
+ }
+
+ template <typename UInt, IfValidUInt<UInt> = true>
+ static void fillRange(UInt *buffer, qssize_t count)
+ {
+ fillRange_helper(buffer, buffer + count);
+ }
+
+ template <typename UInt, size_t N, IfValidUInt<UInt> = true>
+ static void fillRange(UInt (&buffer)[N])
+ {
+ fillRange_helper(buffer, buffer + N);
+ }
+
+ // API like std::seed_seq
+ template <typename ForwardIterator>
+ void generate(ForwardIterator begin, ForwardIterator end)
+ {
+ std::generate(begin, end, &QRandomGenerator::get32);
+ }
+
+ void generate(quint32 *begin, quint32 *end)
+ {
+ fillRange_helper(begin, end);
+ }
+
+ // API like std::random_device
+ typedef quint32 result_type;
+ result_type operator()() { return get32(); }
+ double entropy() const Q_DECL_NOTHROW { return 0.0; }
+ static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
+ static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
+
+private:
+ Q_DISABLE_COPY(QRandomGenerator)
+ static Q_CORE_EXPORT void fillRange_helper(void *buffer, void *bufferEnd);
+};
+
+class QRandomGenerator64
+{
+public:
+ QRandomGenerator64() = default;
+
+ // API like std::random_device
+ typedef quint64 result_type;
+ result_type operator()() { return QRandomGenerator::get64(); }
+ double entropy() const Q_DECL_NOTHROW { return 0.0; }
+ static Q_DECL_CONSTEXPR result_type min() { return (std::numeric_limits<result_type>::min)(); }
+ static Q_DECL_CONSTEXPR result_type max() { return (std::numeric_limits<result_type>::max)(); }
+
+private:
+ Q_DISABLE_COPY(QRandomGenerator64)
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QRANDOM_H
diff --git a/src/corelib/tools/qpodlist_p.h b/src/corelib/global/qrandom_p.h
index 95990e0bb6..6ac2904e1b 100644
--- a/src/corelib/tools/qpodlist_p.h
+++ b/src/corelib/global/qrandom_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QPODLIST_P_H
-#define QPODLIST_P_H
+#ifndef QRANDOM_P_H
+#define QRANDOM_P_H
//
// W A R N I N G
@@ -51,59 +51,28 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
-#include <QtCore/qvarlengtharray.h>
+#include "qglobal_p.h"
QT_BEGIN_NAMESPACE
+enum QRandomGeneratorControl {
+ SkipMemfill = 1,
+ SkipSystemRNG = 2,
+ SkipHWRNG = 4,
+ SetRandomData = 8,
-template <typename T, int Prealloc>
-class QPodList : public QVarLengthArray<T, Prealloc>
-{
- using QVarLengthArray<T, Prealloc>::s;
- using QVarLengthArray<T, Prealloc>::a;
- using QVarLengthArray<T, Prealloc>::ptr;
- using QVarLengthArray<T, Prealloc>::realloc;
-public:
- inline explicit QPodList(int size = 0)
- : QVarLengthArray<T, Prealloc>(size)
- {}
-
- inline void insert(int idx, const T &t)
- {
- const int sz = s++;
- if (s == a)
- realloc(s, s << 1);
- ::memmove(ptr + idx + 1, ptr + idx, (sz - idx) * sizeof(T));
- ptr[idx] = t;
- }
-
- inline void removeAll(const T &t)
- {
- int i = 0;
- for (int j = 0; j < s; ++j) {
- if (ptr[j] != t)
- ptr[i++] = ptr[j];
- }
- s = i;
- }
-
- inline void removeAt(int idx)
- {
- Q_ASSERT(idx >= 0 && idx < s);
- ::memmove(ptr + idx, ptr + idx + 1, (s - idx - 1) * sizeof(T));
- --s;
- }
-
- inline T takeFirst()
- {
- Q_ASSERT(s > 0);
- T tmp = ptr[0];
- removeAt(0);
- return tmp;
- }
+ // 28 bits
+ RandomDataMask = 0xfffffff0
};
+#if defined(QT_BUILD_INTERNAL) && defined(QT_BUILD_CORE_LIB)
+Q_CORE_EXPORT QBasicAtomicInteger<uint> qt_randomdevice_control = Q_BASIC_ATOMIC_INITIALIZER(0U);
+#elif defined(QT_BUILD_INTERNAL)
+extern Q_CORE_EXPORT QBasicAtomicInteger<uint> qt_randomdevice_control;
+#else
+enum { qt_randomdevice_control = 0 };
+#endif
+
QT_END_NAMESPACE
-#endif // QPODLIST_P_H
+#endif // QRANDOM_P_H
diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h
index 7031021e16..4f79c48c51 100644
--- a/src/corelib/global/qtypeinfo.h
+++ b/src/corelib/global/qtypeinfo.h
@@ -311,14 +311,11 @@ Q_DECLARE_TYPEINFO(qint64, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(quint64, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(float, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(double, Q_PRIMITIVE_TYPE);
-#ifndef Q_OS_DARWIN
-Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE);
-#endif
-
#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
// ### Qt 6: remove the other branch
// This was required so that QList<T> for these types allocates out of the array storage
+Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE);
# ifdef Q_COMPILER_UNICODE_STRINGS
Q_DECLARE_TYPEINFO(char16_t, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(char32_t, Q_PRIMITIVE_TYPE);
@@ -327,6 +324,11 @@ Q_DECLARE_TYPEINFO(char32_t, Q_PRIMITIVE_TYPE);
Q_DECLARE_TYPEINFO(wchar_t, Q_PRIMITIVE_TYPE);
# endif
#else
+# ifndef Q_OS_DARWIN
+Q_DECLARE_TYPEINFO(long double, Q_PRIMITIVE_TYPE);
+# else
+Q_DECLARE_TYPEINFO(long double, Q_RELOCATABLE_TYPE);
+# endif
# ifdef Q_COMPILER_UNICODE_STRINGS
Q_DECLARE_TYPEINFO(char16_t, Q_RELOCATABLE_TYPE);
Q_DECLARE_TYPEINFO(char32_t, Q_RELOCATABLE_TYPE);
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index d24c290508..4614fe2a6b 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -121,18 +121,16 @@ win32 {
!winrt {
HEADERS += \
io/qwindowspipereader_p.h \
- io/qwindowspipewriter_p.h \
- io/qwinoverlappedionotifier_p.h
+ io/qwindowspipewriter_p.h
SOURCES += \
io/qsettings_win.cpp \
io/qstandardpaths_win.cpp \
io/qstorageinfo_win.cpp \
io/qwindowspipereader.cpp \
- io/qwindowspipewriter.cpp \
- io/qwinoverlappedionotifier.cpp
+ io/qwindowspipewriter.cpp
- LIBS += -lmpr
+ LIBS += -lmpr -lnetapi32 -luserenv
} else {
SOURCES += \
io/qstandardpaths_winrt.cpp \
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index 89727673d3..1163234b62 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -328,7 +328,8 @@ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
These are used by the fileTime() function.
- \value CreationTime When the file was created.
+ \value BirthTime When the file was born (created).
+ \value MetadataChangeTime When the file's metadata was last changed.
\value ModificationTime When the file was most recently modified.
\value AccessTime When the file was most recently accessed (e.g.
read or written to).
@@ -737,13 +738,31 @@ QString QAbstractFileEngine::owner(FileOwner owner) const
return QString();
}
+
/*!
- If \a time is \c CreationTime, return when the file was created.
- If \a time is \c ModificationTime, return when the file was most
- recently modified. If \a time is \c AccessTime, return when the
- file was most recently accessed (e.g. read or written).
- If the time cannot be determined return QDateTime() (an invalid
- date time).
+ \since 5.10
+
+ Sets the file \a time to \a newDate, returning true if successful;
+ otherwise returns false.
+
+ This virtual function must be reimplemented by all subclasses.
+
+ \sa fileTime()
+*/
+bool QAbstractFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
+{
+ Q_UNUSED(newDate);
+ Q_UNUSED(time);
+ return false;
+}
+
+/*!
+ If \a time is \c BirthTime, return when the file was born (created). If \a
+ time is \c MetadataChangeTime, return when the file's metadata was last
+ changed. If \a time is \c ModificationTime, return when the file was most
+ recently modified. If \a time is \c AccessTime, return when the file was
+ most recently accessed (e.g. read or written). If the time cannot be
+ determined return QDateTime() (an invalid date time).
This virtual function must be reimplemented by all subclasses.
@@ -843,6 +862,19 @@ bool QAbstractFileEngine::unmap(uchar *address)
}
/*!
+ \since 5.10
+
+ Copies the contents from the file specified by \a sourceHandle to this file
+ by cloning it.
+ Returns \c true on success; otherwise, \c false is returned.
+ */
+bool QAbstractFileEngine::clone(int sourceHandle)
+{
+ Q_UNUSED(sourceHandle);
+ return false;
+}
+
+/*!
\since 4.3
\class QAbstractFileEngineIterator
\inmodule QtCore
diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h
index 58fa776e49..c3f7619268 100644
--- a/src/corelib/io/qabstractfileengine_p.h
+++ b/src/corelib/io/qabstractfileengine_p.h
@@ -113,9 +113,10 @@ public:
OwnerGroup
};
enum FileTime {
- CreationTime,
- ModificationTime,
- AccessTime
+ AccessTime,
+ BirthTime,
+ MetadataChangeTime,
+ ModificationTime
};
virtual ~QAbstractFileEngine();
@@ -145,9 +146,11 @@ public:
virtual QString fileName(FileName file=DefaultName) const;
virtual uint ownerId(FileOwner) const;
virtual QString owner(FileOwner) const;
+ virtual bool setFileTime(const QDateTime &newDate, FileTime time);
virtual QDateTime fileTime(FileTime time) const;
virtual void setFileName(const QString &file);
virtual int handle() const;
+ virtual bool clone(int sourceHandle);
bool atEnd() const;
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
bool unmap(uchar *ptr);
diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/io/qdatastream.cpp
index 9a42fb4a37..9044ad74b1 100644
--- a/src/corelib/io/qdatastream.cpp
+++ b/src/corelib/io/qdatastream.cpp
@@ -562,6 +562,7 @@ void QDataStream::setByteOrder(ByteOrder bo)
\value Qt_5_7 Same as Qt_5_6
\value Qt_5_8 Same as Qt_5_6
\value Qt_5_9 Same as Qt_5_6
+ \value Qt_5_10 Same as Qt_5_6
\omitvalue Qt_DefaultCompiledVersion
\sa setVersion(), version()
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index 575607e147..0a429d091a 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -96,10 +96,11 @@ public:
Qt_5_7 = Qt_5_6,
Qt_5_8 = Qt_5_7,
Qt_5_9 = Qt_5_8,
-#if QT_VERSION >= 0x050a00
+ Qt_5_10 = Qt_5_9,
+#if QT_VERSION >= 0x050b00
#error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion
#endif
- Qt_DefaultCompiledVersion = Qt_5_9
+ Qt_DefaultCompiledVersion = Qt_5_10
};
enum ByteOrder {
diff --git a/src/corelib/io/qdebug.cpp b/src/corelib/io/qdebug.cpp
index be33ec2d23..341400fd93 100644
--- a/src/corelib/io/qdebug.cpp
+++ b/src/corelib/io/qdebug.cpp
@@ -648,6 +648,21 @@ QDebug &QDebug::resetFormat()
*/
/*!
+ \since 5.10
+ \fn QDebug &QDebug::operator<<(QStringView s)
+
+ Writes the string view, \a s, to the stream and returns a reference to the
+ stream. Normally, QDebug prints the string inside quotes and transforms
+ non-printable characters to their Unicode values (\\u1234).
+
+ To print non-printable characters without transformation, enable the
+ noquote() functionality. Note that some QDebug backends might not be 8-bit
+ clean.
+
+ See the QString overload for examples.
+*/
+
+/*!
\fn QDebug &QDebug::operator<<(QLatin1String s)
Writes the string, \a s, to the stream and returns a reference to the
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 186722b69b..ee8ef679a9 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -151,8 +151,11 @@ public:
inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromUtf8(t); return maybeSpace(); }
+#if QT_STRINGVIEW_LEVEL < 2
inline QDebug &operator<<(const QString & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
inline QDebug &operator<<(const QStringRef & t) { putString(t.constData(), uint(t.length())); return maybeSpace(); }
+#endif
+ inline QDebug &operator<<(QStringView s) { putString(s.data(), size_t(s.size())); return maybeSpace(); }
inline QDebug &operator<<(QLatin1String t) { putByteArray(t.latin1(), t.size(), ContainsLatin1); return maybeSpace(); }
inline QDebug &operator<<(const QByteArray & t) { putByteArray(t.constData(), t.size(), ContainsBinary); return maybeSpace(); }
inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 64d34aec59..5b487a1339 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -42,12 +43,14 @@
#include "qfile.h"
#include "qfsfileengine_p.h"
#include "qtemporaryfile.h"
+#include "qtemporaryfile_p.h"
#include "qlist.h"
#include "qfileinfo.h"
#include "private/qiodevice_p.h"
#include "private/qfile_p.h"
#include "private/qfilesystemengine_p.h"
#include "private/qsystemerror_p.h"
+#include "private/qtemporaryfile_p.h"
#if defined(QT_BUILD_CORE_LIB)
# include "qcoreapplication.h"
#endif
@@ -420,7 +423,7 @@ QFile::exists() const
Q_D(const QFile);
// 0x1000000 = QAbstractFileEngine::Refresh, forcing an update
return (d->engine()->fileFlags(QAbstractFileEngine::FlagsMask
- | QAbstractFileEngine::FileFlag(0x1000000)) & QAbstractFileEngine::ExistsFlag);
+ | QAbstractFileEngine::Refresh) & QAbstractFileEngine::ExistsFlag);
}
/*!
@@ -565,57 +568,64 @@ QFile::rename(const QString &newName)
d->setError(QFile::RenameError, tr("Source file does not exist."));
return false;
}
+
// If the file exists and it is a case-changing rename ("foo" -> "Foo"),
// compare Ids to make sure it really is a different file.
// Note: this does not take file engines into account.
+ bool changingCase = false;
QByteArray targetId = QFileSystemEngine::id(QFileSystemEntry(newName));
if (!targetId.isNull()) {
QByteArray fileId = d->fileEngine ?
d->fileEngine->id() :
QFileSystemEngine::id(QFileSystemEntry(d->fileName));
- if (fileId != targetId || d->fileName.compare(newName, Qt::CaseInsensitive)) {
- // ### Race condition. If a file is moved in after this, it /will/ be
- // overwritten. On Unix, the proper solution is to use hardlinks:
- // return ::link(old, new) && ::remove(old);
+ changingCase = (fileId == targetId && d->fileName.compare(newName, Qt::CaseInsensitive) == 0);
+ if (!changingCase) {
d->setError(QFile::RenameError, tr("Destination file exists"));
return false;
}
-#ifndef QT_NO_TEMPORARYFILE
- // This #ifndef disables the workaround it encloses. Therefore, this configuration is not recommended.
+
#ifdef Q_OS_LINUX
// rename() on Linux simply does nothing when renaming "foo" to "Foo" on a case-insensitive
// FS, such as FAT32. Move the file away and rename in 2 steps to work around.
- QTemporaryFile tempFile(d->fileName + QLatin1String(".XXXXXX"));
- tempFile.setAutoRemove(false);
- if (!tempFile.open(QIODevice::ReadWrite)) {
- d->setError(QFile::RenameError, tempFile.errorString());
- return false;
- }
- tempFile.close();
- if (!d->engine()->rename(tempFile.fileName())) {
- d->setError(QFile::RenameError, tr("Error while renaming."));
- return false;
- }
- if (tempFile.rename(newName)) {
- d->fileEngine->setFileName(newName);
- d->fileName = newName;
- return true;
- }
- d->setError(QFile::RenameError, tempFile.errorString());
- // We need to restore the original file.
- if (!tempFile.rename(d->fileName)) {
- d->setError(QFile::RenameError, errorString() + QLatin1Char('\n')
+ QTemporaryFileName tfn(d->fileName);
+ QFileSystemEntry src(d->fileName);
+ QSystemError error;
+ for (int attempt = 0; attempt < 16; ++attempt) {
+ QFileSystemEntry tmp(tfn.generateNext(), QFileSystemEntry::FromNativePath());
+
+ // rename to temporary name
+ if (!QFileSystemEngine::renameFile(src, tmp, error))
+ continue;
+
+ // rename to final name
+ if (QFileSystemEngine::renameFile(tmp, QFileSystemEntry(newName), error)) {
+ d->fileEngine->setFileName(newName);
+ d->fileName = newName;
+ return true;
+ }
+
+ // We need to restore the original file.
+ QSystemError error2;
+ if (QFileSystemEngine::renameFile(tmp, src, error2))
+ break; // report the original error, below
+
+ // report both errors
+ d->setError(QFile::RenameError,
+ tr("Error while renaming: %1").arg(error.toString())
+ + QLatin1Char('\n')
+ tr("Unable to restore from %1: %2").
- arg(QDir::toNativeSeparators(tempFile.fileName()), tempFile.errorString()));
+ arg(QDir::toNativeSeparators(tmp.filePath()), error2.toString()));
+ return false;
}
+ d->setError(QFile::RenameError,
+ tr("Error while renaming: %1").arg(error.toString()));
return false;
#endif // Q_OS_LINUX
-#endif // QT_NO_TEMPORARYFILE
}
unsetError();
close();
if(error() == QFile::NoError) {
- if (d->engine()->rename(newName)) {
+ if (changingCase ? d->engine()->renameOverwrite(newName) : d->engine()->rename(newName)) {
unsetError();
// engine was able to handle the new name so we just reset it
d->fileEngine->setFileName(newName);
@@ -794,25 +804,27 @@ QFile::copy(const QString &newName)
close();
d->setError(QFile::CopyError, tr("Cannot open for output"));
} else {
- char block[4096];
- qint64 totalRead = 0;
- while(!atEnd()) {
- qint64 in = read(block, sizeof(block));
- if (in <= 0)
- break;
- totalRead += in;
- if(in != out.write(block, in)) {
- close();
- d->setError(QFile::CopyError, tr("Failure to write block"));
- error = true;
- break;
+ if (!out.d_func()->engine()->clone(d->engine()->handle())) {
+ char block[4096];
+ qint64 totalRead = 0;
+ while (!atEnd()) {
+ qint64 in = read(block, sizeof(block));
+ if (in <= 0)
+ break;
+ totalRead += in;
+ if (in != out.write(block, in)) {
+ close();
+ d->setError(QFile::CopyError, tr("Failure to write block"));
+ error = true;
+ break;
+ }
}
- }
- if (totalRead != size()) {
- // Unable to read from the source. The error string is
- // already set from read().
- error = true;
+ if (totalRead != size()) {
+ // Unable to read from the source. The error string is
+ // already set from read().
+ error = true;
+ }
}
if (!error && !out.rename(newName)) {
error = true;
@@ -957,7 +969,9 @@ bool QFile::open(FILE *fh, OpenMode mode, FileHandleFlags handleFlags)
qWarning("QFile::open: File access not specified");
return false;
}
- if (d->openExternalFile(mode, fh, handleFlags)) {
+
+ // QIODevice provides the buffering, so request unbuffered file engines
+ if (d->openExternalFile(mode | Unbuffered, fh, handleFlags)) {
QIODevice::open(mode);
if (!(mode & Append) && !isSequential()) {
qint64 pos = (qint64)QT_FTELL(fh);
@@ -1013,7 +1027,9 @@ bool QFile::open(int fd, OpenMode mode, FileHandleFlags handleFlags)
qWarning("QFile::open: File access not specified");
return false;
}
- if (d->openExternalFile(mode, fd, handleFlags)) {
+
+ // QIODevice provides the buffering, so request unbuffered file engines
+ if (d->openExternalFile(mode | Unbuffered, fd, handleFlags)) {
QIODevice::open(mode);
if (!(mode & Append) && !isSequential()) {
qint64 pos = (qint64)QT_LSEEK(fd, QT_OFF_T(0), SEEK_CUR);
diff --git a/src/corelib/io/qfile.h b/src/corelib/io/qfile.h
index a2a1b25248..c5819e8076 100644
--- a/src/corelib/io/qfile.h
+++ b/src/corelib/io/qfile.h
@@ -81,6 +81,7 @@ public:
}
static QString decodeName(const QByteArray &localFileName)
{
+ // note: duplicated in qglobal.cpp (qEnvironmentVariable)
return QString::fromUtf8(localFileName).normalized(QString::NormalizationForm_C);
}
#else
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
index f50949e6c1..2f99775c65 100644
--- a/src/corelib/io/qfiledevice.cpp
+++ b/src/corelib/io/qfiledevice.cpp
@@ -740,6 +740,76 @@ bool QFileDevice::unmap(uchar *address)
return false;
}
+/*!
+ \enum QFileDevice::FileTime
+ \since 5.10
+
+ This enum is used by the fileTime() and setFileTime() functions.
+
+ \value FileAccessTime When the file was most recently accessed
+ (e.g. read or written to).
+ \value FileBirthTime When the file was created (may not be not
+ supported on UNIX).
+ \value FileMetadataChangeTime When the file's metadata was last changed.
+ \value FileModificationTime When the file was most recently modified.
+
+ \sa setFileTime(), fileTime(), QFileInfo::fileTime()
+*/
+
+static inline QAbstractFileEngine::FileTime FileDeviceTimeToAbstractFileEngineTime(QFileDevice::FileTime time)
+{
+ Q_STATIC_ASSERT(int(QFileDevice::FileAccessTime) == int(QAbstractFileEngine::AccessTime));
+ Q_STATIC_ASSERT(int(QFileDevice::FileBirthTime) == int(QAbstractFileEngine::BirthTime));
+ Q_STATIC_ASSERT(int(QFileDevice::FileMetadataChangeTime) == int(QAbstractFileEngine::MetadataChangeTime));
+ Q_STATIC_ASSERT(int(QFileDevice::FileModificationTime) == int(QAbstractFileEngine::ModificationTime));
+ return QAbstractFileEngine::FileTime(time);
+}
+
+/*!
+ \since 5.10
+ Returns the file time specified by \a time.
+ If the time cannot be determined return QDateTime() (an invalid
+ date time).
+
+ \sa setFileTime(), FileTime, QDateTime::isValid()
+*/
+QDateTime QFileDevice::fileTime(QFileDevice::FileTime time) const
+{
+ Q_D(const QFileDevice);
+
+ if (d->engine())
+ return d->engine()->fileTime(FileDeviceTimeToAbstractFileEngineTime(time));
+
+ return QDateTime();
+}
+
+/*!
+ \since 5.10
+ Sets the file time specified by \a fileTime to \a newDate, returning true
+ if successful; otherwise returns false.
+
+ \note The file must be open to use this function.
+
+ \sa fileTime(), FileTime
+*/
+bool QFileDevice::setFileTime(const QDateTime &newDate, QFileDevice::FileTime fileTime)
+{
+ Q_D(QFileDevice);
+
+ if (!d->engine()) {
+ d->setError(QFileDevice::UnspecifiedError, tr("No file engine available"));
+ return false;
+ }
+
+ if (!d->fileEngine->setFileTime(newDate, FileDeviceTimeToAbstractFileEngineTime(fileTime))) {
+ d->setError(d->fileEngine->error(), d->fileEngine->errorString());
+ return false;
+ }
+
+ unsetError();
+ return true;
+}
+
QT_END_NAMESPACE
#ifndef QT_NO_QOBJECT
diff --git a/src/corelib/io/qfiledevice.h b/src/corelib/io/qfiledevice.h
index 4cfda1b044..e941781c25 100644
--- a/src/corelib/io/qfiledevice.h
+++ b/src/corelib/io/qfiledevice.h
@@ -45,6 +45,7 @@
QT_BEGIN_NAMESPACE
+class QDateTime;
class QFileDevicePrivate;
class Q_CORE_EXPORT QFileDevice : public QIODevice
@@ -73,6 +74,13 @@ public:
CopyError = 14
};
+ enum FileTime {
+ FileAccessTime,
+ FileBirthTime,
+ FileMetadataChangeTime,
+ FileModificationTime
+ };
+
enum Permission {
ReadOwner = 0x4000, WriteOwner = 0x2000, ExeOwner = 0x1000,
ReadUser = 0x0400, WriteUser = 0x0200, ExeUser = 0x0100,
@@ -119,6 +127,9 @@ public:
uchar *map(qint64 offset, qint64 size, MemoryMapFlags flags = NoOptions);
bool unmap(uchar *address);
+ QDateTime fileTime(QFileDevice::FileTime time) const;
+ bool setFileTime(const QDateTime &newDate, QFileDevice::FileTime fileTime);
+
protected:
QFileDevice();
#ifdef QT_NO_QOBJECT
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index 12fd7d3048..104a171e99 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -42,6 +42,7 @@
#include "qglobal.h"
#include "qdir.h"
#include "qfileinfo_p.h"
+#include "qdebug.h"
QT_BEGIN_NAMESPACE
@@ -185,17 +186,25 @@ uint QFileInfoPrivate::getFileFlags(QAbstractFileEngine::FileFlags request) cons
QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request) const
{
Q_ASSERT(fileEngine); // should never be called when using the native FS
- if (fileTimes.size() != 3)
- fileTimes.resize(3);
if (!cache_enabled)
clearFlags();
- uint cf;
- if (request == QAbstractFileEngine::CreationTime)
- cf = CachedCTime;
- else if (request == QAbstractFileEngine::ModificationTime)
- cf = CachedMTime;
- else
+
+ uint cf = 0;
+ switch (request) {
+ case QAbstractFileEngine::AccessTime:
cf = CachedATime;
+ break;
+ case QAbstractFileEngine::BirthTime:
+ cf = CachedBTime;
+ break;
+ case QAbstractFileEngine::MetadataChangeTime:
+ cf = CachedMCTime;
+ break;
+ case QAbstractFileEngine::ModificationTime:
+ cf = CachedMTime;
+ break;
+ }
+
if (!getCachedFlag(cf)) {
fileTimes[request] = fileEngine->fileTime(request);
setCachedFlag(cf);
@@ -262,8 +271,8 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
info objects, just append one to the file name given to the constructors
or setFile().
- The file's dates are returned by created(), lastModified() and
- lastRead(). Information about the file's access permissions is
+ The file's dates are returned by created(), lastModified(), lastRead() and
+ fileTime(). Information about the file's access permissions is
obtained with isReadable(), isWritable() and isExecutable(). The
file's ownership is available from owner(), ownerId(), group() and
groupId(). You can examine a file's permissions and ownership in a
@@ -1294,50 +1303,65 @@ qint64 QFileInfo::size() const
return d->fileSize;
}
+#if QT_DEPRECATED_SINCE(5, 10)
/*!
- Returns the date and local time when the file was created.
+ \deprecated
- On most Unix systems, this function returns the time of the last
- status change. A status change occurs when the file is created,
- but it also occurs whenever the user writes or sets inode
- information (for example, changing the file permissions).
+ Returns the date and time when the file was created, the time its metadata
+ was last changed or the time of last modification, whichever one of the
+ three is available (in that order).
- If neither creation time nor "last status change" time are not
- available, returns the same as lastModified().
+ This function is deprecated. Instead, use the birthTime() function to get
+ the time the file was created, metadataChangeTime() to get the time its
+ metadata was last changed, or lastModified() to get the time it was last modified.
- \sa lastModified(), lastRead()
+ \sa birthTime(), metadataChangeTime(), lastModified(), lastRead()
*/
QDateTime QFileInfo::created() const
{
- Q_D(const QFileInfo);
- if (d->isDefaultConstructed)
- return QDateTime();
- if (d->fileEngine == 0) {
- if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::CreationTime))
- if (!QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::CreationTime))
- return QDateTime();
- return d->metaData.creationTime().toLocalTime();
- }
- return d->getFileTime(QAbstractFileEngine::CreationTime).toLocalTime();
+ QDateTime d = fileTime(QFile::FileBirthTime);
+ if (d.isValid())
+ return d;
+ return fileTime(QFile::FileMetadataChangeTime);
+}
+#endif
+
+/*!
+ \since 5.10
+ Returns the date and time when the file was created / born.
+
+ If the file birth time is not available, this function returns an invalid
+ QDateTime.
+
+ \sa lastModified(), lastRead(), metadataChangeTime()
+*/
+QDateTime QFileInfo::birthTime() const
+{
+ return fileTime(QFile::FileBirthTime);
+}
+
+/*!
+ \since 5.10
+ Returns the date and time when the file metadata was changed. A metadata
+ change occurs when the file is created, but it also occurs whenever the
+ user writes or sets inode information (for example, changing the file
+ permissions).
+
+ \sa lastModified(), lastRead()
+*/
+QDateTime QFileInfo::metadataChangeTime() const
+{
+ return fileTime(QFile::FileMetadataChangeTime);
}
/*!
Returns the date and local time when the file was last modified.
- \sa created(), lastRead()
+ \sa birthTime(), lastRead(), metadataChangeTime(), fileTime()
*/
QDateTime QFileInfo::lastModified() const
{
- Q_D(const QFileInfo);
- if (d->isDefaultConstructed)
- return QDateTime();
- if (d->fileEngine == 0) {
- if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::ModificationTime))
- if (!QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::ModificationTime))
- return QDateTime();
- return d->metaData.modificationTime().toLocalTime();
- }
- return d->getFileTime(QAbstractFileEngine::ModificationTime).toLocalTime();
+ return fileTime(QFile::FileModificationTime);
}
/*!
@@ -1346,20 +1370,55 @@ QDateTime QFileInfo::lastModified() const
On platforms where this information is not available, returns the
same as lastModified().
- \sa created(), lastModified()
+ \sa birthTime(), lastModified(), metadataChangeTime(), fileTime()
*/
QDateTime QFileInfo::lastRead() const
{
+ return fileTime(QFile::FileAccessTime);
+}
+
+/*!
+ \since 5.10
+
+ Returns the file time specified by \a time. If the time cannot be
+ determined, an invalid date time is returned.
+
+ \sa QFile::FileTime, QDateTime::isValid()
+*/
+QDateTime QFileInfo::fileTime(QFile::FileTime time) const
+{
+ Q_STATIC_ASSERT(int(QFile::FileAccessTime) == int(QAbstractFileEngine::AccessTime));
+ Q_STATIC_ASSERT(int(QFile::FileBirthTime) == int(QAbstractFileEngine::BirthTime));
+ Q_STATIC_ASSERT(int(QFile::FileMetadataChangeTime) == int(QAbstractFileEngine::MetadataChangeTime));
+ Q_STATIC_ASSERT(int(QFile::FileModificationTime) == int(QAbstractFileEngine::ModificationTime));
+
Q_D(const QFileInfo);
+ auto fetime = QAbstractFileEngine::FileTime(time);
if (d->isDefaultConstructed)
return QDateTime();
- if (d->fileEngine == 0) {
- if (!d->cache_enabled || !d->metaData.hasFlags(QFileSystemMetaData::AccessTime))
- if (!QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, QFileSystemMetaData::AccessTime))
- return QDateTime();
- return d->metaData.accessTime().toLocalTime();
+ if (d->fileEngine)
+ return d->getFileTime(fetime).toLocalTime();
+
+ QFileSystemMetaData::MetaDataFlags flag;
+ switch (time) {
+ case QFile::FileAccessTime:
+ flag = QFileSystemMetaData::AccessTime;
+ break;
+ case QFile::FileBirthTime:
+ flag = QFileSystemMetaData::BirthTime;
+ break;
+ case QFile::FileMetadataChangeTime:
+ flag = QFileSystemMetaData::MetadataChangeTime;
+ break;
+ case QFile::FileModificationTime:
+ flag = QFileSystemMetaData::ModificationTime;
+ break;
}
- return d->getFileTime(QAbstractFileEngine::AccessTime).toLocalTime();
+
+ if (!d->cache_enabled || !d->metaData.hasFlags(flag))
+ if (!QFileSystemEngine::fillMetaData(d->fileEntry, d->metaData, flag))
+ return QDateTime();
+ return d->metaData.fileTime(fetime).toLocalTime();
}
/*!
@@ -1406,4 +1465,15 @@ void QFileInfo::setCaching(bool enable)
Synonym for QList<QFileInfo>.
*/
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QFileInfo &fi)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace();
+ dbg.noquote();
+ dbg << "QFileInfo(" << QDir::toNativeSeparators(fi.filePath()) << ')';
+ return dbg;
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/corelib/io/qfileinfo.h b/src/corelib/io/qfileinfo.h
index a160e8463e..f295a86015 100644
--- a/src/corelib/io/qfileinfo.h
+++ b/src/corelib/io/qfileinfo.h
@@ -129,9 +129,16 @@ public:
qint64 size() const;
+ // ### Qt6: inline these functions
+#if QT_DEPRECATED_SINCE(5, 10)
+ QT_DEPRECATED_X("Use either birthTime() or metadataChangeTime()")
QDateTime created() const;
+#endif
+ QDateTime birthTime() const;
+ QDateTime metadataChangeTime() const;
QDateTime lastModified() const;
QDateTime lastRead() const;
+ QDateTime fileTime(QFile::FileTime time) const;
bool caching() const;
void setCaching(bool on);
@@ -151,6 +158,10 @@ Q_DECLARE_SHARED(QFileInfo)
typedef QList<QFileInfo> QFileInfoList;
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug, const QFileInfo &);
+#endif
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QFileInfo)
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
index 806df179e8..923247c62c 100644
--- a/src/corelib/io/qfileinfo_p.h
+++ b/src/corelib/io/qfileinfo_p.h
@@ -56,7 +56,6 @@
#include "qatomic.h"
#include "qshareddata.h"
#include "qfilesystemengine_p.h"
-#include "qvector.h"
#include <QtCore/private/qabstractfileengine_p.h>
#include <QtCore/private/qfilesystementry_p.h>
@@ -67,9 +66,18 @@ QT_BEGIN_NAMESPACE
class QFileInfoPrivate : public QSharedData
{
public:
- enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
- CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40,
- CachedSize =0x08, CachedPerms=0x80 };
+ enum {
+ // note: cachedFlags is only 30-bits wide
+ CachedFileFlags = 0x01,
+ CachedLinkTypeFlag = 0x02,
+ CachedBundleTypeFlag = 0x04,
+ CachedSize = 0x08,
+ CachedATime = 0x10,
+ CachedBTime = 0x20,
+ CachedMCTime = 0x40,
+ CachedMTime = 0x80,
+ CachedPerms = 0x100
+ };
inline QFileInfoPrivate()
: QSharedData(), fileEngine(0),
@@ -158,19 +166,14 @@ public:
QScopedPointer<QAbstractFileEngine> const fileEngine;
mutable QString fileNames[QAbstractFileEngine::NFileNames];
- mutable QString fileOwners[2];
+ mutable QString fileOwners[2]; // QAbstractFileEngine::FileOwner: OwnerUser and OwnerGroup
+ mutable QDateTime fileTimes[4]; // QAbstractFileEngine::FileTime: BirthTime, MetadataChangeTime, ModificationTime, AccessTime
mutable uint cachedFlags : 30;
bool const isDefaultConstructed : 1; // QFileInfo is a default constructed instance
bool cache_enabled : 1;
mutable uint fileFlags;
mutable qint64 fileSize;
- // ### Qt6: FIXME: This vector is essentially a plain array
- // mutable QDateTime fileTimes[3], but the array is slower
- // to initialize than the QVector as QDateTime has a pimpl.
- // In Qt 6, QDateTime should inline its data members,
- // and this here can be an array again.
- mutable QVector<QDateTime> fileTimes;
inline bool getCachedFlag(uint c) const
{ return cache_enabled ? (cachedFlags & c) : 0; }
inline void setCachedFlag(uint c) const
diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp
index ccbcdb1037..955b459bba 100644
--- a/src/corelib/io/qfilesystemengine.cpp
+++ b/src/corelib/io/qfilesystemengine.cpp
@@ -204,228 +204,6 @@ QAbstractFileEngine *QFileSystemEngine::resolveEntryAndCreateLegacyEngine(
return engine;
}
-//these unix functions are in this file, because they are shared by symbian port
-//for open C file handles.
-#ifdef Q_OS_UNIX
-//static
-bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
-{
- data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
- data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
-
- QT_STATBUF statBuffer;
- if (QT_FSTAT(fd, &statBuffer) == 0) {
- data.fillFromStatBuf(statBuffer);
- return true;
- }
-
- return false;
-}
-
-#if defined(_DEXTRA_FIRST)
-static void fillStat64fromStat32(struct stat64 *statBuf64, const struct stat &statBuf32)
-{
- statBuf64->st_mode = statBuf32.st_mode;
- statBuf64->st_size = statBuf32.st_size;
-#if _POSIX_VERSION >= 200809L
- statBuf64->st_ctim = statBuf32.st_ctim;
- statBuf64->st_mtim = statBuf32.st_mtim;
- statBuf64->st_atim = statBuf32.st_atim;
-#else
- statBuf64->st_ctime = statBuf32.st_ctime;
- statBuf64->st_mtime = statBuf32.st_mtime;
- statBuf64->st_atime = statBuf32.st_atime;
-#endif
- statBuf64->st_uid = statBuf32.st_uid;
- statBuf64->st_gid = statBuf32.st_gid;
-}
-#endif
-
-#if _POSIX_VERSION >= 200809L
-static qint64 timespecToMSecs(const timespec &spec)
-{
- return (qint64(spec.tv_sec) * 1000) + (spec.tv_nsec / 1000000);
-}
-#endif
-
-void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer)
-{
- // Permissions
- if (statBuffer.st_mode & S_IRUSR)
- entryFlags |= QFileSystemMetaData::OwnerReadPermission;
- if (statBuffer.st_mode & S_IWUSR)
- entryFlags |= QFileSystemMetaData::OwnerWritePermission;
- if (statBuffer.st_mode & S_IXUSR)
- entryFlags |= QFileSystemMetaData::OwnerExecutePermission;
-
- if (statBuffer.st_mode & S_IRGRP)
- entryFlags |= QFileSystemMetaData::GroupReadPermission;
- if (statBuffer.st_mode & S_IWGRP)
- entryFlags |= QFileSystemMetaData::GroupWritePermission;
- if (statBuffer.st_mode & S_IXGRP)
- entryFlags |= QFileSystemMetaData::GroupExecutePermission;
-
- if (statBuffer.st_mode & S_IROTH)
- entryFlags |= QFileSystemMetaData::OtherReadPermission;
- if (statBuffer.st_mode & S_IWOTH)
- entryFlags |= QFileSystemMetaData::OtherWritePermission;
- if (statBuffer.st_mode & S_IXOTH)
- entryFlags |= QFileSystemMetaData::OtherExecutePermission;
-
- // Type
- if ((statBuffer.st_mode & S_IFMT) == S_IFREG)
- entryFlags |= QFileSystemMetaData::FileType;
- else if ((statBuffer.st_mode & S_IFMT) == S_IFDIR)
- entryFlags |= QFileSystemMetaData::DirectoryType;
- else if ((statBuffer.st_mode & S_IFMT) != S_IFBLK)
- entryFlags |= QFileSystemMetaData::SequentialType;
-
- // Attributes
- entryFlags |= QFileSystemMetaData::ExistsAttribute;
- size_ = statBuffer.st_size;
-#if defined(Q_OS_DARWIN)
- if (statBuffer.st_flags & UF_HIDDEN) {
- entryFlags |= QFileSystemMetaData::HiddenAttribute;
- knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
- }
-#endif
-
- // Times
-#if _POSIX_VERSION >= 200809L
- modificationTime_ = timespecToMSecs(statBuffer.st_mtim);
- creationTime_ = timespecToMSecs(statBuffer.st_ctim);
- if (!creationTime_)
- creationTime_ = modificationTime_;
- accessTime_ = timespecToMSecs(statBuffer.st_atim);
-#else
- creationTime_ = qint64(statBuffer.st_ctime ? statBuffer.st_ctime : statBuffer.st_mtime) * 1000;
- modificationTime_ = qint64(statBuffer.st_mtime) * 1000;
- accessTime_ = qint64(statBuffer.st_atime) * 1000;
-#endif
- userId_ = statBuffer.st_uid;
- groupId_ = statBuffer.st_gid;
-}
-
-void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry)
-{
-#if defined(_DEXTRA_FIRST)
- knownFlagsMask = 0;
- entryFlags = 0;
- for (dirent_extra *extra = _DEXTRA_FIRST(&entry); _DEXTRA_VALID(extra, &entry);
- extra = _DEXTRA_NEXT(extra)) {
- if (extra->d_type == _DTYPE_STAT || extra->d_type == _DTYPE_LSTAT) {
-
- const struct dirent_extra_stat * const extra_stat =
- reinterpret_cast<struct dirent_extra_stat *>(extra);
-
- // Remember whether this was a link or not, this saves an lstat() call later.
- if (extra->d_type == _DTYPE_LSTAT) {
- knownFlagsMask |= QFileSystemMetaData::LinkType;
- if (S_ISLNK(extra_stat->d_stat.st_mode))
- entryFlags |= QFileSystemMetaData::LinkType;
- }
-
- // For symlinks, the extra type _DTYPE_LSTAT doesn't work for filling out the meta data,
- // as we need the stat() information there, not the lstat() information.
- // In this case, don't use the extra information.
- // Unfortunately, readdir() never seems to return extra info of type _DTYPE_STAT, so for
- // symlinks, we always incur the cost of an extra stat() call later.
- if (S_ISLNK(extra_stat->d_stat.st_mode) && extra->d_type == _DTYPE_LSTAT)
- continue;
-
-#if defined(QT_USE_XOPEN_LFS_EXTENSIONS) && defined(QT_LARGEFILE_SUPPORT)
- // Even with large file support, d_stat is always of type struct stat, not struct stat64,
- // so it needs to be converted
- struct stat64 statBuf;
- fillStat64fromStat32(&statBuf, extra_stat->d_stat);
- fillFromStatBuf(statBuf);
-#else
- fillFromStatBuf(extra_stat->d_stat);
-#endif
- knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
- if (!S_ISLNK(extra_stat->d_stat.st_mode)) {
- knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
- entryFlags |= QFileSystemMetaData::ExistsAttribute;
- }
- }
- }
-#elif defined(_DIRENT_HAVE_D_TYPE) || defined(Q_OS_BSD4)
- // BSD4 includes OS X and iOS
-
- // ### This will clear all entry flags and knownFlagsMask
- switch (entry.d_type)
- {
- case DT_DIR:
- knownFlagsMask = QFileSystemMetaData::LinkType
- | QFileSystemMetaData::FileType
- | QFileSystemMetaData::DirectoryType
- | QFileSystemMetaData::SequentialType
- | QFileSystemMetaData::ExistsAttribute;
-
- entryFlags = QFileSystemMetaData::DirectoryType
- | QFileSystemMetaData::ExistsAttribute;
-
- break;
-
- case DT_BLK:
- knownFlagsMask = QFileSystemMetaData::LinkType
- | QFileSystemMetaData::FileType
- | QFileSystemMetaData::DirectoryType
- | QFileSystemMetaData::BundleType
- | QFileSystemMetaData::AliasType
- | QFileSystemMetaData::SequentialType
- | QFileSystemMetaData::ExistsAttribute;
-
- entryFlags = QFileSystemMetaData::ExistsAttribute;
-
- break;
-
- case DT_CHR:
- case DT_FIFO:
- case DT_SOCK:
- // ### System attribute
- knownFlagsMask = QFileSystemMetaData::LinkType
- | QFileSystemMetaData::FileType
- | QFileSystemMetaData::DirectoryType
- | QFileSystemMetaData::BundleType
- | QFileSystemMetaData::AliasType
- | QFileSystemMetaData::SequentialType
- | QFileSystemMetaData::ExistsAttribute;
-
- entryFlags = QFileSystemMetaData::SequentialType
- | QFileSystemMetaData::ExistsAttribute;
-
- break;
-
- case DT_LNK:
- knownFlagsMask = QFileSystemMetaData::LinkType;
- entryFlags = QFileSystemMetaData::LinkType;
- break;
-
- case DT_REG:
- knownFlagsMask = QFileSystemMetaData::LinkType
- | QFileSystemMetaData::FileType
- | QFileSystemMetaData::DirectoryType
- | QFileSystemMetaData::BundleType
- | QFileSystemMetaData::SequentialType
- | QFileSystemMetaData::ExistsAttribute;
-
- entryFlags = QFileSystemMetaData::FileType
- | QFileSystemMetaData::ExistsAttribute;
-
- break;
-
- case DT_UNKNOWN:
- default:
- clear();
- }
-#else
- Q_UNUSED(entry)
-#endif
-}
-
-#endif
-
//static
QString QFileSystemEngine::resolveUserName(const QFileSystemEntry &entry, QFileSystemMetaData &metaData)
{
diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h
index e3e52f6eaa..a3c96ebd78 100644
--- a/src/corelib/io/qfilesystemengine_p.h
+++ b/src/corelib/io/qfilesystemengine_p.h
@@ -93,6 +93,8 @@ public:
#if defined(Q_OS_UNIX)
static bool fillMetaData(int fd, QFileSystemMetaData &data); // what = PosixStatFlags
static QByteArray id(int fd);
+ static bool setFileTime(int fd, const QDateTime &newDate,
+ QAbstractFileEngine::FileTime whatTime, QSystemError &error);
static bool setPermissions(int fd, QFile::Permissions permissions, QSystemError &error,
QFileSystemMetaData *data = nullptr);
#endif
@@ -106,6 +108,8 @@ public:
static bool fillPermissions(const QFileSystemEntry &entry, QFileSystemMetaData &data,
QFileSystemMetaData::MetaDataFlags what);
static QByteArray id(HANDLE fHandle);
+ static bool setFileTime(HANDLE fHandle, const QDateTime &newDate,
+ QAbstractFileEngine::FileTime whatTime, QSystemError &error);
static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own);
static QString nativeAbsoluteFilePath(const QString &path);
#endif
@@ -121,11 +125,16 @@ public:
static bool copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
static bool renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
+ static bool renameOverwriteFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error);
static bool removeFile(const QFileSystemEntry &entry, QSystemError &error);
static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error,
QFileSystemMetaData *data = 0);
+ // unused, therefore not implemented
+ static bool setFileTime(const QFileSystemEntry &entry, const QDateTime &newDate,
+ QAbstractFileEngine::FileTime whatTime, QSystemError &error);
+
static bool setCurrentPath(const QFileSystemEntry &entry);
static QFileSystemEntry currentPath();
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 6640e2b7e7..7f043582e8 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -43,6 +43,8 @@
#include "qfilesystemengine_p.h"
#include "qfile.h"
+#include <QtCore/qoperatingsystemversion.h>
+#include <QtCore/private/qcore_unix_p.h>
#include <QtCore/qvarlengtharray.h>
#include <stdlib.h> // for realpath()
@@ -52,7 +54,6 @@
#include <stdio.h>
#include <errno.h>
-
#if defined(Q_OS_MAC)
# include <QtCore/private/qcore_mac_p.h>
# include <CoreFoundation/CFBundle.h>
@@ -67,12 +68,25 @@
#endif
#if defined(Q_OS_DARWIN)
+# if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000)
+# include <sys/clonefile.h>
+# endif
// We cannot include <Foundation/Foundation.h> (it's an Objective-C header), but
// we need these declarations:
Q_FORWARD_DECLARE_OBJC_CLASS(NSString);
extern "C" NSString *NSTemporaryDirectory();
#endif
+#if defined(Q_OS_LINUX)
+# include <sys/syscall.h>
+# include <linux/fs.h>
+
+# if !QT_CONFIG(renameat2) && defined(SYS_renameat2)
+static int renameat2(int oldfd, const char *oldpath, int newfd, const char *newpath, unsigned flags)
+{ return syscall(SYS_renameat2, oldfd, oldpath, newfd, newpath, flags); }
+# endif
+#endif
+
QT_BEGIN_NAMESPACE
#if defined(Q_OS_DARWIN)
@@ -143,33 +157,329 @@ static bool isPackage(const QFileSystemMetaData &data, const QFileSystemEntry &e
}
#endif
+namespace {
+namespace GetFileTimes {
+#if !QT_CONFIG(futimens) && (QT_CONFIG(futimes))
+template <typename T>
+static inline typename QtPrivate::QEnableIf<(&T::st_atim, &T::st_mtim, true)>::Type get(const T *p, struct timeval *access, struct timeval *modification)
+{
+ access->tv_sec = p->st_atim.tv_sec;
+ access->tv_usec = p->st_atim.tv_nsec / 1000;
+
+ modification->tv_sec = p->st_mtim.tv_sec;
+ modification->tv_usec = p->st_mtim.tv_nsec / 1000;
+}
+
+template <typename T>
+static inline typename QtPrivate::QEnableIf<(&T::st_atimespec, &T::st_mtimespec, true)>::Type get(const T *p, struct timeval *access, struct timeval *modification)
+{
+ access->tv_sec = p->st_atimespec.tv_sec;
+ access->tv_usec = p->st_atimespec.tv_nsec / 1000;
+
+ modification->tv_sec = p->st_mtimespec.tv_sec;
+ modification->tv_usec = p->st_mtimespec.tv_nsec / 1000;
+}
+
+template <typename T>
+static inline typename QtPrivate::QEnableIf<(&T::st_atimensec, &T::st_mtimensec, true)>::Type get(const T *p, struct timeval *access, struct timeval *modification)
+{
+ access->tv_sec = p->st_atime;
+ access->tv_usec = p->st_atimensec / 1000;
+
+ modification->tv_sec = p->st_mtime;
+ modification->tv_usec = p->st_mtimensec / 1000;
+}
+#endif
+
+qint64 timespecToMSecs(const timespec &spec)
+{
+ return (qint64(spec.tv_sec) * 1000) + (spec.tv_nsec / 1000000);
+}
+
+// fallback set
+Q_DECL_UNUSED qint64 atime(const QT_STATBUF &statBuffer, ulong) { return qint64(statBuffer.st_atime) * 1000; }
+Q_DECL_UNUSED qint64 birthtime(const QT_STATBUF &, ulong) { return Q_INT64_C(0); }
+Q_DECL_UNUSED qint64 ctime(const QT_STATBUF &statBuffer, ulong) { return qint64(statBuffer.st_ctime) * 1000; }
+Q_DECL_UNUSED qint64 mtime(const QT_STATBUF &statBuffer, ulong) { return qint64(statBuffer.st_mtime) * 1000; }
+
+// Xtim, POSIX.1-2008
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_atim, true), qint64>::type
+atime(const T &statBuffer, int)
+{ return timespecToMSecs(statBuffer.st_atim); }
+
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_birthtim, true), qint64>::type
+birthtime(const T &statBuffer, int)
+{ return timespecToMSecs(statBuffer.st_birthtim); }
+
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_ctim, true), qint64>::type
+ctime(const T &statBuffer, int)
+{ return timespecToMSecs(statBuffer.st_ctim); }
+
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_mtim, true), qint64>::type
+mtime(const T &statBuffer, int)
+{ return timespecToMSecs(statBuffer.st_mtim); }
+
+#ifndef st_mtimespec
+// Xtimespec
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_atimespec, true), qint64>::type
+atime(const T &statBuffer, int)
+{ return timespecToMSecs(statBuffer.st_atimespec); }
+
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_birthtimespec, true), qint64>::type
+birthtime(const T &statBuffer, int)
+{ return timespecToMSecs(statBuffer.st_birthtimespec); }
+
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_ctimespec, true), qint64>::type
+ctime(const T &statBuffer, int)
+{ return timespecToMSecs(statBuffer.st_ctimespec); }
+
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_mtimespec, true), qint64>::type
+mtime(const T &statBuffer, int)
+{ return timespecToMSecs(statBuffer.st_mtimespec); }
+#endif
+
+// Xtimensec
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_atimensec, true), qint64>::type
+atime(const T &statBuffer, int)
+{ return statBuffer.st_atime * Q_INT64_C(1000) + statBuffer.st_atimensec / 1000000; }
+
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_birthtimensec, true), qint64>::type
+birthtime(const T &statBuffer, int)
+{ return statBuffer.st_birthtime * Q_INT64_C(1000) + statBuffer.st_birthtimensec / 1000000; }
+
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_ctimensec, true), qint64>::type
+ctime(const T &statBuffer, int)
+{ return statBuffer.st_ctime * Q_INT64_C(1000) + statBuffer.st_ctimensec / 1000000; }
+
+template <typename T>
+Q_DECL_UNUSED static typename std::enable_if<(&T::st_mtimensec, true), qint64>::type
+mtime(const T &statBuffer, int)
+{ return statBuffer.st_mtime * Q_INT64_C(1000) + statBuffer.st_mtimensec / 1000000; }
+}
+}
+
//static
-QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
+bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
{
-#if defined(__GLIBC__) && !defined(PATH_MAX)
-#define PATH_CHUNK_SIZE 256
- char *s = 0;
- int len = -1;
- int size = PATH_CHUNK_SIZE;
-
- while (1) {
- s = (char *) ::realloc(s, size);
- Q_CHECK_PTR(s);
- len = ::readlink(link.nativeFilePath().constData(), s, size);
- if (len < 0) {
- ::free(s);
- break;
- }
- if (len < size) {
- break;
+ data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
+ data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
+
+ QT_STATBUF statBuffer;
+ if (QT_FSTAT(fd, &statBuffer) == 0) {
+ data.fillFromStatBuf(statBuffer);
+ return true;
+ }
+
+ return false;
+}
+
+#if defined(_DEXTRA_FIRST)
+static void fillStat64fromStat32(struct stat64 *statBuf64, const struct stat &statBuf32)
+{
+ statBuf64->st_mode = statBuf32.st_mode;
+ statBuf64->st_size = statBuf32.st_size;
+#if _POSIX_VERSION >= 200809L
+ statBuf64->st_ctim = statBuf32.st_ctim;
+ statBuf64->st_mtim = statBuf32.st_mtim;
+ statBuf64->st_atim = statBuf32.st_atim;
+#else
+ statBuf64->st_ctime = statBuf32.st_ctime;
+ statBuf64->st_mtime = statBuf32.st_mtime;
+ statBuf64->st_atime = statBuf32.st_atime;
+#endif
+ statBuf64->st_uid = statBuf32.st_uid;
+ statBuf64->st_gid = statBuf32.st_gid;
+}
+#endif
+
+void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer)
+{
+ // Permissions
+ if (statBuffer.st_mode & S_IRUSR)
+ entryFlags |= QFileSystemMetaData::OwnerReadPermission;
+ if (statBuffer.st_mode & S_IWUSR)
+ entryFlags |= QFileSystemMetaData::OwnerWritePermission;
+ if (statBuffer.st_mode & S_IXUSR)
+ entryFlags |= QFileSystemMetaData::OwnerExecutePermission;
+
+ if (statBuffer.st_mode & S_IRGRP)
+ entryFlags |= QFileSystemMetaData::GroupReadPermission;
+ if (statBuffer.st_mode & S_IWGRP)
+ entryFlags |= QFileSystemMetaData::GroupWritePermission;
+ if (statBuffer.st_mode & S_IXGRP)
+ entryFlags |= QFileSystemMetaData::GroupExecutePermission;
+
+ if (statBuffer.st_mode & S_IROTH)
+ entryFlags |= QFileSystemMetaData::OtherReadPermission;
+ if (statBuffer.st_mode & S_IWOTH)
+ entryFlags |= QFileSystemMetaData::OtherWritePermission;
+ if (statBuffer.st_mode & S_IXOTH)
+ entryFlags |= QFileSystemMetaData::OtherExecutePermission;
+
+ // Type
+ if ((statBuffer.st_mode & S_IFMT) == S_IFREG)
+ entryFlags |= QFileSystemMetaData::FileType;
+ else if ((statBuffer.st_mode & S_IFMT) == S_IFDIR)
+ entryFlags |= QFileSystemMetaData::DirectoryType;
+ else if ((statBuffer.st_mode & S_IFMT) != S_IFBLK)
+ entryFlags |= QFileSystemMetaData::SequentialType;
+
+ // Attributes
+ entryFlags |= QFileSystemMetaData::ExistsAttribute; // inode exists
+ if (statBuffer.st_nlink == 0)
+ entryFlags |= QFileSystemMetaData::WasDeletedAttribute;
+ size_ = statBuffer.st_size;
+#if defined(Q_OS_DARWIN)
+ if (statBuffer.st_flags & UF_HIDDEN) {
+ entryFlags |= QFileSystemMetaData::HiddenAttribute;
+ knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
+ }
+#endif
+
+ // Times
+ accessTime_ = GetFileTimes::atime(statBuffer, 0);
+ birthTime_ = GetFileTimes::birthtime(statBuffer, 0);
+ metadataChangeTime_ = GetFileTimes::ctime(statBuffer, 0);
+ modificationTime_ = GetFileTimes::mtime(statBuffer, 0);
+
+ userId_ = statBuffer.st_uid;
+ groupId_ = statBuffer.st_gid;
+}
+
+void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry)
+{
+#if defined(_DEXTRA_FIRST)
+ knownFlagsMask = 0;
+ entryFlags = 0;
+ for (dirent_extra *extra = _DEXTRA_FIRST(&entry); _DEXTRA_VALID(extra, &entry);
+ extra = _DEXTRA_NEXT(extra)) {
+ if (extra->d_type == _DTYPE_STAT || extra->d_type == _DTYPE_LSTAT) {
+
+ const struct dirent_extra_stat * const extra_stat =
+ reinterpret_cast<struct dirent_extra_stat *>(extra);
+
+ // Remember whether this was a link or not, this saves an lstat() call later.
+ if (extra->d_type == _DTYPE_LSTAT) {
+ knownFlagsMask |= QFileSystemMetaData::LinkType;
+ if (S_ISLNK(extra_stat->d_stat.st_mode))
+ entryFlags |= QFileSystemMetaData::LinkType;
+ }
+
+ // For symlinks, the extra type _DTYPE_LSTAT doesn't work for filling out the meta data,
+ // as we need the stat() information there, not the lstat() information.
+ // In this case, don't use the extra information.
+ // Unfortunately, readdir() never seems to return extra info of type _DTYPE_STAT, so for
+ // symlinks, we always incur the cost of an extra stat() call later.
+ if (S_ISLNK(extra_stat->d_stat.st_mode) && extra->d_type == _DTYPE_LSTAT)
+ continue;
+
+#if defined(QT_USE_XOPEN_LFS_EXTENSIONS) && defined(QT_LARGEFILE_SUPPORT)
+ // Even with large file support, d_stat is always of type struct stat, not struct stat64,
+ // so it needs to be converted
+ struct stat64 statBuf;
+ fillStat64fromStat32(&statBuf, extra_stat->d_stat);
+ fillFromStatBuf(statBuf);
+#else
+ fillFromStatBuf(extra_stat->d_stat);
+#endif
+ knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
+ if (!S_ISLNK(extra_stat->d_stat.st_mode)) {
+ knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
+ entryFlags |= QFileSystemMetaData::ExistsAttribute;
+ }
}
- size *= 2;
+ }
+#elif defined(_DIRENT_HAVE_D_TYPE) || defined(Q_OS_BSD4)
+ // BSD4 includes OS X and iOS
+
+ // ### This will clear all entry flags and knownFlagsMask
+ switch (entry.d_type)
+ {
+ case DT_DIR:
+ knownFlagsMask = QFileSystemMetaData::LinkType
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ entryFlags = QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ break;
+
+ case DT_BLK:
+ knownFlagsMask = QFileSystemMetaData::LinkType
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::BundleType
+ | QFileSystemMetaData::AliasType
+ | QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ entryFlags = QFileSystemMetaData::ExistsAttribute;
+
+ break;
+
+ case DT_CHR:
+ case DT_FIFO:
+ case DT_SOCK:
+ // ### System attribute
+ knownFlagsMask = QFileSystemMetaData::LinkType
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::BundleType
+ | QFileSystemMetaData::AliasType
+ | QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ entryFlags = QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ break;
+
+ case DT_LNK:
+ knownFlagsMask = QFileSystemMetaData::LinkType;
+ entryFlags = QFileSystemMetaData::LinkType;
+ break;
+
+ case DT_REG:
+ knownFlagsMask = QFileSystemMetaData::LinkType
+ | QFileSystemMetaData::FileType
+ | QFileSystemMetaData::DirectoryType
+ | QFileSystemMetaData::BundleType
+ | QFileSystemMetaData::SequentialType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ entryFlags = QFileSystemMetaData::FileType
+ | QFileSystemMetaData::ExistsAttribute;
+
+ break;
+
+ case DT_UNKNOWN:
+ default:
+ clear();
}
#else
- char s[PATH_MAX+1];
- int len = readlink(link.nativeFilePath().constData(), s, PATH_MAX);
+ Q_UNUSED(entry)
#endif
- if (len > 0) {
+}
+
+//static
+QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
+{
+ QByteArray s = qt_readlink(link.nativeFilePath().constData());
+ if (s.length() > 0) {
QString ret;
if (!data.hasFlags(QFileSystemMetaData::DirectoryType))
fillMetaData(link, data, QFileSystemMetaData::DirectoryType);
@@ -180,11 +490,7 @@ QFileSystemEntry QFileSystemEngine::getLinkTarget(const QFileSystemEntry &link,
if (!ret.isEmpty() && !ret.endsWith(QLatin1Char('/')))
ret += QLatin1Char('/');
}
- s[len] = '\0';
- ret += QFile::decodeName(QByteArray(s));
-#if defined(__GLIBC__) && !defined(PATH_MAX)
- ::free(s);
-#endif
+ ret += QFile::decodeName(s);
if (!ret.startsWith(QLatin1Char('/'))) {
const QString linkFilePath = link.filePath();
@@ -454,45 +760,65 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
}
#endif // defined(Q_OS_DARWIN)
+ // if we're asking for any of the stat(2) flags, then we're getting them all
if (what & QFileSystemMetaData::PosixStatFlags)
what |= QFileSystemMetaData::PosixStatFlags;
- if (what & QFileSystemMetaData::ExistsAttribute) {
- // FIXME: Would other queries being performed provide this bit?
- what |= QFileSystemMetaData::PosixStatFlags;
- }
-
data.entryFlags &= ~what;
const QByteArray nativeFilePath = entry.nativeFilePath();
bool entryExists = true; // innocent until proven otherwise
+ // first, we may try lstat(2). Possible outcomes:
+ // - success and is a symlink: filesystem entry exists, but we need stat(2)
+ // -> statBufferValid = false
+ // - success and is not a symlink: filesystem entry exists and we're done
+ // -> statBufferValid = true
+ // - failure: really non-existent filesystem entry
+ // -> entryExists = false; statBufferValid = true
+ // both stat(2) and lstat(2) may generate a number of different errno
+ // conditions, but of those, the only ones that could happen and the
+ // entry still exist are EACCES, EFAULT, ENOMEM and EOVERFLOW. If we get
+ // EACCES or ENOMEM, then we have no choice on how to proceed, so we may
+ // as well conclude it doesn't exist; EFAULT can't happen and EOVERFLOW
+ // shouldn't happen because we build in _LARGEFIE64.
QT_STATBUF statBuffer;
bool statBufferValid = false;
if (what & QFileSystemMetaData::LinkType) {
if (QT_LSTAT(nativeFilePath, &statBuffer) == 0) {
if (S_ISLNK(statBuffer.st_mode)) {
+ // it's a symlink, we don't know if the file "exists"
data.entryFlags |= QFileSystemMetaData::LinkType;
} else {
+ // it's a reagular file and it exists
statBufferValid = true;
- data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
+ data.fillFromStatBuf(statBuffer);
+ data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags
+ | QFileSystemMetaData::ExistsAttribute;
+ data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
}
} else {
+ // it doesn't exist
entryExists = false;
+ data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
}
data.knownFlagsMask |= QFileSystemMetaData::LinkType;
}
+ // second, we try a regular stat(2)
if (statBufferValid || (what & QFileSystemMetaData::PosixStatFlags)) {
- if (entryExists && !statBufferValid)
+ if (entryExists && !statBufferValid) {
statBufferValid = (QT_STAT(nativeFilePath, &statBuffer) == 0);
+ data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
+ if (statBufferValid)
+ data.fillFromStatBuf(statBuffer);
+ }
- if (statBufferValid)
- data.fillFromStatBuf(statBuffer);
- else {
+ if (!statBufferValid) {
entryExists = false;
- data.creationTime_ = 0;
+ data.birthTime_ = 0;
+ data.metadataChangeTime_ = 0;
data.modificationTime_ = 0;
data.accessTime_ = 0;
data.size_ = 0;
@@ -505,34 +831,49 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
| QFileSystemMetaData::ExistsAttribute;
}
+ // third, we try access(2)
+ if (what & (QFileSystemMetaData::UserPermissions | QFileSystemMetaData::ExistsAttribute)) {
+ // calculate user permissions
+ auto checkAccess = [&](QFileSystemMetaData::MetaDataFlag flag, int mode) {
+ if (!entryExists || (what & flag) == 0)
+ return;
+ if (QT_ACCESS(nativeFilePath, mode) == 0) {
+ // access ok (and file exists)
+ data.entryFlags |= flag | QFileSystemMetaData::ExistsAttribute;
+ } else if (errno != EACCES && errno != EROFS) {
+ entryExists = false;
+ }
+ };
+
+ checkAccess(QFileSystemMetaData::UserReadPermission, R_OK);
+ checkAccess(QFileSystemMetaData::UserWritePermission, W_OK);
+ checkAccess(QFileSystemMetaData::UserExecutePermission, X_OK);
+
+ // if we still haven't found out if the file exists, try F_OK
+ if (entryExists && (data.entryFlags & QFileSystemMetaData::ExistsAttribute) == 0) {
+ entryExists = QT_ACCESS(nativeFilePath, F_OK) == 0;
+ if (entryExists)
+ data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
+ }
+
+ data.knownFlagsMask |= (what & QFileSystemMetaData::UserPermissions) |
+ QFileSystemMetaData::ExistsAttribute;
+ }
+
#if defined(Q_OS_DARWIN)
- if (what & QFileSystemMetaData::AliasType)
- {
+ if (what & QFileSystemMetaData::AliasType) {
if (entryExists && hasResourcePropertyFlag(data, entry, kCFURLIsAliasFileKey))
data.entryFlags |= QFileSystemMetaData::AliasType;
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
}
-#endif
- if (what & QFileSystemMetaData::UserPermissions) {
- // calculate user permissions
+ if (what & QFileSystemMetaData::BundleType) {
+ if (entryExists && isPackage(data, entry))
+ data.entryFlags |= QFileSystemMetaData::BundleType;
- if (entryExists) {
- if (what & QFileSystemMetaData::UserReadPermission) {
- if (QT_ACCESS(nativeFilePath, R_OK) == 0)
- data.entryFlags |= QFileSystemMetaData::UserReadPermission;
- }
- if (what & QFileSystemMetaData::UserWritePermission) {
- if (QT_ACCESS(nativeFilePath, W_OK) == 0)
- data.entryFlags |= QFileSystemMetaData::UserWritePermission;
- }
- if (what & QFileSystemMetaData::UserExecutePermission) {
- if (QT_ACCESS(nativeFilePath, X_OK) == 0)
- data.entryFlags |= QFileSystemMetaData::UserExecutePermission;
- }
- }
- data.knownFlagsMask |= (what & QFileSystemMetaData::UserPermissions);
+ data.knownFlagsMask |= QFileSystemMetaData::BundleType;
}
+#endif
if (what & QFileSystemMetaData::HiddenAttribute
&& !data.isHidden()) {
@@ -546,15 +887,8 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
}
-#if defined(Q_OS_DARWIN)
- if (what & QFileSystemMetaData::BundleType) {
- if (entryExists && isPackage(data, entry))
- data.entryFlags |= QFileSystemMetaData::BundleType;
-
- data.knownFlagsMask |= QFileSystemMetaData::BundleType;
- }
-#endif
if (!entryExists) {
+ what &= ~QFileSystemMetaData::LinkType; // don't clear link: could be broken symlink
data.clearFlags(what);
return false;
}
@@ -649,8 +983,22 @@ bool QFileSystemEngine::createLink(const QFileSystemEntry &source, const QFileSy
//static
bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
+#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(101200, 100000, 100000, 30000)
+ const auto current = QOperatingSystemVersion::current();
+ if (current >= QOperatingSystemVersion::MacOSSierra ||
+ current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 10) ||
+ current >= QOperatingSystemVersion(QOperatingSystemVersion::TvOS, 10) ||
+ current >= QOperatingSystemVersion(QOperatingSystemVersion::WatchOS, 3)) {
+ if (::clonefile(source.nativeFilePath().constData(),
+ target.nativeFilePath().constData(), 0) == 0)
+ return true;
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+#else
Q_UNUSED(source);
Q_UNUSED(target);
+#endif
error = QSystemError(ENOSYS, QSystemError::StandardLibraryError); //Function not implemented
return false;
}
@@ -658,6 +1006,77 @@ bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSyst
//static
bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
+ QFileSystemEntry::NativePath srcPath = source.nativeFilePath();
+ QFileSystemEntry::NativePath tgtPath = target.nativeFilePath();
+
+#if defined(RENAME_NOREPLACE) && (QT_CONFIG(renameat2) || defined(SYS_renameat2))
+ if (renameat2(AT_FDCWD, srcPath, AT_FDCWD, tgtPath, RENAME_NOREPLACE) == 0)
+ return true;
+
+ // If we're using syscall(), check for ENOSYS;
+ // if renameat2 came from libc, we don't accept ENOSYS.
+ if (QT_CONFIG(renameat2) || errno != ENOSYS) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+#endif
+#if defined(Q_OS_DARWIN) && defined(RENAME_EXCL)
+ const auto current = QOperatingSystemVersion::current();
+ if (current >= QOperatingSystemVersion::MacOSSierra ||
+ current >= QOperatingSystemVersion(QOperatingSystemVersion::IOS, 10) ||
+ current >= QOperatingSystemVersion(QOperatingSystemVersion::TvOS, 10) ||
+ current >= QOperatingSystemVersion(QOperatingSystemVersion::WatchOS, 3)) {
+ if (renameatx_np(AT_FDCWD, srcPath, AT_FDCWD, tgtPath, RENAME_EXCL) == 0)
+ return true;
+ if (errno != ENOTSUP) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+ }
+#endif
+
+ if (::link(srcPath, tgtPath) == 0) {
+ if (::unlink(srcPath) == 0)
+ return true;
+
+ // if we managed to link but can't unlink the source, it's likely
+ // it's in a directory we don't have write access to; fail the
+ // renaming instead
+ int savedErrno = errno;
+
+ // this could fail too, but there's nothing we can do about it now
+ ::unlink(tgtPath);
+
+ error = QSystemError(savedErrno, QSystemError::StandardLibraryError);
+ return false;
+ }
+
+ switch (errno) {
+ case EACCES:
+ case EEXIST:
+ case ENAMETOOLONG:
+ case ENOENT:
+ case ENOTDIR:
+ case EROFS:
+ case EXDEV:
+ // accept the error from link(2) (especially EEXIST) and don't retry
+ break;
+
+ default:
+ // fall back to rename()
+ // ### Race condition. If a file is moved in after this, it /will/ be
+ // overwritten.
+ if (::rename(srcPath, tgtPath) == 0)
+ return true;
+ }
+
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+}
+
+//static
+bool QFileSystemEngine::renameOverwriteFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+{
if (::rename(source.nativeFilePath().constData(), target.nativeFilePath().constData()) == 0)
return true;
error = QSystemError(errno, QSystemError::StandardLibraryError);
@@ -730,6 +1149,71 @@ bool QFileSystemEngine::setPermissions(int fd, QFile::Permissions permissions, Q
return success;
}
+//static
+bool QFileSystemEngine::setFileTime(int fd, const QDateTime &newDate, QAbstractFileEngine::FileTime time, QSystemError &error)
+{
+ if (!newDate.isValid() || time == QAbstractFileEngine::BirthTime ||
+ time == QAbstractFileEngine::MetadataChangeTime) {
+ error = QSystemError(EINVAL, QSystemError::StandardLibraryError);
+ return false;
+ }
+
+#if QT_CONFIG(futimens)
+ struct timespec ts[2];
+
+ ts[0].tv_sec = ts[1].tv_sec = 0;
+ ts[0].tv_nsec = ts[1].tv_nsec = UTIME_OMIT;
+
+ const qint64 msecs = newDate.toMSecsSinceEpoch();
+
+ if (time == QAbstractFileEngine::AccessTime) {
+ ts[0].tv_sec = msecs / 1000;
+ ts[0].tv_nsec = (msecs % 1000) * 1000000;
+ } else if (time == QAbstractFileEngine::ModificationTime) {
+ ts[1].tv_sec = msecs / 1000;
+ ts[1].tv_nsec = (msecs % 1000) * 1000000;
+ }
+
+ if (futimens(fd, ts) == -1) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+
+ return true;
+#elif QT_CONFIG(futimes)
+ struct timeval tv[2];
+ QT_STATBUF st;
+
+ if (QT_FSTAT(fd, &st) == -1) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+
+ GetFileTimes::get(&st, &tv[0], &tv[1]);
+
+ const qint64 msecs = newDate.toMSecsSinceEpoch();
+
+ if (time == QAbstractFileEngine::AccessTime) {
+ tv[0].tv_sec = msecs / 1000;
+ tv[0].tv_usec = (msecs % 1000) * 1000;
+ } else if (time == QAbstractFileEngine::ModificationTime) {
+ tv[1].tv_sec = msecs / 1000;
+ tv[1].tv_usec = (msecs % 1000) * 1000;
+ }
+
+ if (futimes(fd, tv) == -1) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ return false;
+ }
+
+ return true;
+#else
+ Q_UNUSED(fd);
+ error = QSystemError(ENOSYS, QSystemError::StandardLibraryError);
+ return false;
+#endif
+}
+
QString QFileSystemEngine::homePath()
{
QString home = QFile::decodeName(qgetenv("HOME"));
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 0542d9e16c..79a9936785 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -48,7 +48,6 @@
#include "qfile.h"
#include "qdir.h"
-#include "private/qmutexpool_p.h"
#include "qvarlengtharray.h"
#include "qdatetime.h"
#include "qt_windows.h"
@@ -60,6 +59,7 @@
#include <objbase.h>
#ifndef Q_OS_WINRT
# include <shlobj.h>
+# include <lm.h>
# include <accctrl.h>
#endif
#include <initguid.h>
@@ -147,48 +147,30 @@ typedef struct _REPARSE_DATA_BUFFER {
# define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
#endif
-QT_BEGIN_NAMESPACE
-
-Q_CORE_EXPORT int qt_ntfs_permission_lookup = 0;
-
-#if defined(Q_OS_WINRT)
-// As none of the functions we try to resolve do exist on WinRT we
-// avoid library loading on WinRT in general to shorten everything
-// up a little bit.
+#if defined(Q_OS_WINRT) || defined(QT_BOOTSTRAPPED)
# define QT_FEATURE_fslibs -1
#else
-# define QT_FEATURE_fslibs QT_FEATURE_library
+# define QT_FEATURE_fslibs 1
#endif // Q_OS_WINRT
#if QT_CONFIG(fslibs)
-QT_BEGIN_INCLUDE_NAMESPACE
-typedef DWORD (WINAPI *PtrGetNamedSecurityInfoW)(LPWSTR, SE_OBJECT_TYPE, SECURITY_INFORMATION, PSID*, PSID*, PACL*, PACL*, PSECURITY_DESCRIPTOR*);
-static PtrGetNamedSecurityInfoW ptrGetNamedSecurityInfoW = 0;
-typedef BOOL (WINAPI *PtrLookupAccountSidW)(LPCWSTR, PSID, LPWSTR, LPDWORD, LPWSTR, LPDWORD, PSID_NAME_USE);
-static PtrLookupAccountSidW ptrLookupAccountSidW = 0;
-typedef VOID (WINAPI *PtrBuildTrusteeWithSidW)(PTRUSTEE_W, PSID);
-static PtrBuildTrusteeWithSidW ptrBuildTrusteeWithSidW = 0;
-typedef DWORD (WINAPI *PtrGetEffectiveRightsFromAclW)(PACL, PTRUSTEE_W, OUT PACCESS_MASK);
-static PtrGetEffectiveRightsFromAclW ptrGetEffectiveRightsFromAclW = 0;
-typedef BOOL (WINAPI *PtrGetUserProfileDirectoryW)(HANDLE, LPWSTR, LPDWORD);
-static PtrGetUserProfileDirectoryW ptrGetUserProfileDirectoryW = 0;
-QT_END_INCLUDE_NAMESPACE
-
+#include <aclapi.h>
+#include <userenv.h>
static TRUSTEE_W currentUserTrusteeW;
static TRUSTEE_W worldTrusteeW;
static PSID currentUserSID = 0;
static PSID worldSID = 0;
-/*
- Deletes the allocated SIDs during global static cleanup
-*/
-class SidCleanup
+QT_BEGIN_NAMESPACE
+
+namespace {
+struct GlobalSid
{
-public:
- ~SidCleanup();
+ GlobalSid();
+ ~GlobalSid();
};
-SidCleanup::~SidCleanup()
+GlobalSid::~GlobalSid()
{
free(currentUserSID);
currentUserSID = 0;
@@ -200,39 +182,13 @@ SidCleanup::~SidCleanup()
}
}
-Q_GLOBAL_STATIC(SidCleanup, initSidCleanup)
-
-static void resolveLibs()
+GlobalSid::GlobalSid()
{
- static bool triedResolve = false;
- if (!triedResolve) {
- // need to resolve the security info functions
-
- // protect initialization
-#ifndef QT_NO_THREAD
- QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
- // check triedResolve again, since another thread may have already
- // done the initialization
- if (triedResolve) {
- // another thread did initialize the security function pointers,
- // so we shouldn't do it again.
- return;
- }
-#endif
-
- triedResolve = true;
- HINSTANCE advapiHnd = QSystemLibrary::load(L"advapi32");
- if (advapiHnd) {
- ptrGetNamedSecurityInfoW = (PtrGetNamedSecurityInfoW)GetProcAddress(advapiHnd, "GetNamedSecurityInfoW");
- ptrLookupAccountSidW = (PtrLookupAccountSidW)GetProcAddress(advapiHnd, "LookupAccountSidW");
- ptrBuildTrusteeWithSidW = (PtrBuildTrusteeWithSidW)GetProcAddress(advapiHnd, "BuildTrusteeWithSidW");
- ptrGetEffectiveRightsFromAclW = (PtrGetEffectiveRightsFromAclW)GetProcAddress(advapiHnd, "GetEffectiveRightsFromAclW");
- }
- if (ptrBuildTrusteeWithSidW) {
+ {
+ {
// Create TRUSTEE for current user
HANDLE hnd = ::GetCurrentProcess();
HANDLE token = 0;
- initSidCleanup();
if (::OpenProcessToken(hnd, TOKEN_QUERY, &token)) {
DWORD retsize = 0;
// GetTokenInformation requires a buffer big enough for the TOKEN_USER struct and
@@ -247,61 +203,69 @@ static void resolveLibs()
DWORD sidLen = ::GetLengthSid(tokenSid);
currentUserSID = reinterpret_cast<PSID>(malloc(sidLen));
if (::CopySid(sidLen, currentUserSID, tokenSid))
- ptrBuildTrusteeWithSidW(&currentUserTrusteeW, currentUserSID);
+ BuildTrusteeWithSid(&currentUserTrusteeW, currentUserSID);
}
free(tokenBuffer);
}
::CloseHandle(token);
}
- typedef BOOL (WINAPI *PtrAllocateAndInitializeSid)(PSID_IDENTIFIER_AUTHORITY, BYTE, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, DWORD, PSID*);
- PtrAllocateAndInitializeSid ptrAllocateAndInitializeSid = (PtrAllocateAndInitializeSid)GetProcAddress(advapiHnd, "AllocateAndInitializeSid");
- if (ptrAllocateAndInitializeSid) {
+ {
// Create TRUSTEE for Everyone (World)
SID_IDENTIFIER_AUTHORITY worldAuth = { SECURITY_WORLD_SID_AUTHORITY };
- if (ptrAllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &worldSID))
- ptrBuildTrusteeWithSidW(&worldTrusteeW, worldSID);
+ if (AllocateAndInitializeSid(&worldAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &worldSID))
+ BuildTrusteeWithSid(&worldTrusteeW, worldSID);
}
}
- HINSTANCE userenvHnd = QSystemLibrary::load(L"userenv");
- if (userenvHnd)
- ptrGetUserProfileDirectoryW = (PtrGetUserProfileDirectoryW)GetProcAddress(userenvHnd, "GetUserProfileDirectoryW");
}
}
+
+Q_GLOBAL_STATIC(GlobalSid, initGlobalSid)
+
+QT_END_NAMESPACE
+
+} // anonymous namespace
#endif // QT_CONFIG(fslibs)
-typedef DWORD (WINAPI *PtrNetShareEnum)(LPWSTR, DWORD, LPBYTE*, DWORD, LPDWORD, LPDWORD, LPDWORD);
-static PtrNetShareEnum ptrNetShareEnum = 0;
-typedef DWORD (WINAPI *PtrNetApiBufferFree)(LPVOID);
-static PtrNetApiBufferFree ptrNetApiBufferFree = 0;
-typedef struct _SHARE_INFO_1 {
- LPWSTR shi1_netname;
- DWORD shi1_type;
- LPWSTR shi1_remark;
-} SHARE_INFO_1;
+QT_BEGIN_NAMESPACE
+Q_CORE_EXPORT int qt_ntfs_permission_lookup = 0;
-static bool resolveUNCLibs()
+static inline bool toFileTime(const QDateTime &date, FILETIME *fileTime)
{
- static bool triedResolve = false;
- if (!triedResolve) {
-#ifndef QT_NO_THREAD
- QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
- if (triedResolve) {
- return ptrNetShareEnum && ptrNetApiBufferFree;
- }
-#endif
- triedResolve = true;
-#if !defined(Q_OS_WINRT)
- HINSTANCE hLib = QSystemLibrary::load(L"Netapi32");
- if (hLib) {
- ptrNetShareEnum = (PtrNetShareEnum)GetProcAddress(hLib, "NetShareEnum");
- if (ptrNetShareEnum)
- ptrNetApiBufferFree = (PtrNetApiBufferFree)GetProcAddress(hLib, "NetApiBufferFree");
- }
-#endif // !Q_OS_WINRT
+ SYSTEMTIME sTime;
+ if (date.timeSpec() == Qt::LocalTime) {
+ SYSTEMTIME lTime;
+ const QDate d = date.date();
+ const QTime t = date.time();
+
+ lTime.wYear = d.year();
+ lTime.wMonth = d.month();
+ lTime.wDay = d.day();
+ lTime.wHour = t.hour();
+ lTime.wMinute = t.minute();
+ lTime.wSecond = t.second();
+ lTime.wMilliseconds = t.msec();
+ lTime.wDayOfWeek = d.dayOfWeek() % 7;
+
+ if (!::TzSpecificLocalTimeToSystemTime(0, &lTime, &sTime))
+ return false;
+ } else {
+ QDateTime utcDate = date.toUTC();
+ const QDate d = utcDate.date();
+ const QTime t = utcDate.time();
+
+ sTime.wYear = d.year();
+ sTime.wMonth = d.month();
+ sTime.wDay = d.day();
+ sTime.wHour = t.hour();
+ sTime.wMinute = t.minute();
+ sTime.wSecond = t.second();
+ sTime.wMilliseconds = t.msec();
+ sTime.wDayOfWeek = d.dayOfWeek() % 7;
}
- return ptrNetShareEnum && ptrNetApiBufferFree;
+
+ return ::SystemTimeToFileTime(&sTime, fileTime);
}
static QString readSymLink(const QFileSystemEntry &link)
@@ -339,7 +303,7 @@ static QString readSymLink(const QFileSystemEntry &link)
CloseHandle(handle);
#if QT_CONFIG(fslibs)
- resolveLibs();
+ initGlobalSid();
QRegExp matchVolName(QLatin1String("^Volume\\{([a-z]|[0-9]|-)+\\}\\\\"), Qt::CaseInsensitive);
if (matchVolName.indexIn(result) == 0) {
DWORD len;
@@ -436,32 +400,35 @@ static inline bool getFindData(QString path, WIN32_FIND_DATA &findData)
bool QFileSystemEngine::uncListSharesOnServer(const QString &server, QStringList *list)
{
- if (resolveUNCLibs()) {
- SHARE_INFO_1 *BufPtr, *p;
- DWORD res;
- DWORD er = 0, tr = 0, resume = 0, i;
- do {
- res = ptrNetShareEnum((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume);
- if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) {
- p = BufPtr;
- for (i = 1; i <= er; ++i) {
- if (list && p->shi1_type == 0)
- list->append(QString::fromWCharArray(p->shi1_netname));
- p++;
- }
+ DWORD res = ERROR_NOT_SUPPORTED;
+#ifndef Q_OS_WINRT
+ SHARE_INFO_1 *BufPtr, *p;
+ DWORD er = 0, tr = 0, resume = 0, i;
+ do {
+ res = NetShareEnum((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume);
+ if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) {
+ p = BufPtr;
+ for (i = 1; i <= er; ++i) {
+ if (list && p->shi1_type == 0)
+ list->append(QString::fromWCharArray(p->shi1_netname));
+ p++;
}
- ptrNetApiBufferFree(BufPtr);
- } while (res == ERROR_MORE_DATA);
- return res == ERROR_SUCCESS;
- }
- return false;
+ }
+ NetApiBufferFree(BufPtr);
+ } while (res == ERROR_MORE_DATA);
+#else
+ Q_UNUSED(server);
+ Q_UNUSED(list);
+#endif
+ return res == ERROR_SUCCESS;
}
void QFileSystemEngine::clearWinStatData(QFileSystemMetaData &data)
{
data.size_ = 0;
data.fileAttribute_ = 0;
- data.creationTime_ = FILETIME();
+ data.birthTime_ = FILETIME();
+ data.changeTime_ = FILETIME();
data.lastAccessTime_ = FILETIME();
data.lastWriteTime_ = FILETIME();
}
@@ -642,36 +609,72 @@ QByteArray QFileSystemEngine::id(HANDLE fHandle)
}
//static
+bool QFileSystemEngine::setFileTime(HANDLE fHandle, const QDateTime &newDate,
+ QAbstractFileEngine::FileTime time, QSystemError &error)
+{
+ FILETIME fTime;
+ FILETIME *pLastWrite = NULL;
+ FILETIME *pLastAccess = NULL;
+ FILETIME *pCreationTime = NULL;
+
+ switch (time) {
+ case QAbstractFileEngine::ModificationTime:
+ pLastWrite = &fTime;
+ break;
+
+ case QAbstractFileEngine::AccessTime:
+ pLastAccess = &fTime;
+ break;
+
+ case QAbstractFileEngine::BirthTime:
+ pCreationTime = &fTime;
+ break;
+
+ default:
+ error = QSystemError(ERROR_INVALID_PARAMETER, QSystemError::NativeError);
+ return false;
+ }
+
+ if (!toFileTime(newDate, &fTime))
+ return false;
+
+ if (!::SetFileTime(fHandle, pCreationTime, pLastAccess, pLastWrite)) {
+ error = QSystemError(::GetLastError(), QSystemError::NativeError);
+ return false;
+ }
+ return true;
+}
+
QString QFileSystemEngine::owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own)
{
QString name;
#if QT_CONFIG(fslibs)
extern int qt_ntfs_permission_lookup;
- if((qt_ntfs_permission_lookup > 0) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) {
- resolveLibs();
- if (ptrGetNamedSecurityInfoW && ptrLookupAccountSidW) {
+ if (qt_ntfs_permission_lookup > 0) {
+ initGlobalSid();
+ {
PSID pOwner = 0;
PSECURITY_DESCRIPTOR pSD;
- if (ptrGetNamedSecurityInfoW((wchar_t*)entry.nativeFilePath().utf16(), SE_FILE_OBJECT,
- own == QAbstractFileEngine::OwnerGroup ? GROUP_SECURITY_INFORMATION : OWNER_SECURITY_INFORMATION,
- own == QAbstractFileEngine::OwnerUser ? &pOwner : 0, own == QAbstractFileEngine::OwnerGroup ? &pOwner : 0,
- 0, 0, &pSD) == ERROR_SUCCESS) {
+ if (GetNamedSecurityInfo(reinterpret_cast<const wchar_t*>(entry.nativeFilePath().utf16()), SE_FILE_OBJECT,
+ own == QAbstractFileEngine::OwnerGroup ? GROUP_SECURITY_INFORMATION : OWNER_SECURITY_INFORMATION,
+ own == QAbstractFileEngine::OwnerUser ? &pOwner : 0, own == QAbstractFileEngine::OwnerGroup ? &pOwner : 0,
+ 0, 0, &pSD) == ERROR_SUCCESS) {
DWORD lowner = 64;
DWORD ldomain = 64;
QVarLengthArray<wchar_t, 64> owner(lowner);
QVarLengthArray<wchar_t, 64> domain(ldomain);
SID_NAME_USE use = SidTypeUnknown;
// First call, to determine size of the strings (with '\0').
- if (!ptrLookupAccountSidW(NULL, pOwner, (LPWSTR)owner.data(), &lowner,
- (LPWSTR)domain.data(), &ldomain, (SID_NAME_USE*)&use)) {
+ if (!LookupAccountSid(NULL, pOwner, (LPWSTR)owner.data(), &lowner,
+ domain.data(), &ldomain, &use)) {
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
if (lowner > (DWORD)owner.size())
owner.resize(lowner);
if (ldomain > (DWORD)domain.size())
domain.resize(ldomain);
// Second call, try on resized buf-s
- if (!ptrLookupAccountSidW(NULL, pOwner, (LPWSTR)owner.data(), &lowner,
- (LPWSTR)domain.data(), &ldomain, (SID_NAME_USE*)&use)) {
+ if (!LookupAccountSid(NULL, pOwner, owner.data(), &lowner,
+ domain.data(), &ldomain, &use)) {
lowner = 0;
}
} else {
@@ -696,9 +699,9 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst
QFileSystemMetaData::MetaDataFlags what)
{
#if QT_CONFIG(fslibs)
- if((qt_ntfs_permission_lookup > 0) && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)) {
- resolveLibs();
- if(ptrGetNamedSecurityInfoW && ptrBuildTrusteeWithSidW && ptrGetEffectiveRightsFromAclW) {
+ if (qt_ntfs_permission_lookup > 0) {
+ initGlobalSid();
+ {
enum { ReadMask = 0x00000001, WriteMask = 0x00000002, ExecMask = 0x00000020 };
QString fname = entry.nativeFilePath();
@@ -706,15 +709,15 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst
PSID pGroup = 0;
PACL pDacl;
PSECURITY_DESCRIPTOR pSD;
- DWORD res = ptrGetNamedSecurityInfoW((wchar_t*)fname.utf16(), SE_FILE_OBJECT,
- OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
- &pOwner, &pGroup, &pDacl, 0, &pSD);
+ DWORD res = GetNamedSecurityInfo(reinterpret_cast<const wchar_t*>(fname.utf16()), SE_FILE_OBJECT,
+ OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION,
+ &pOwner, &pGroup, &pDacl, 0, &pSD);
if(res == ERROR_SUCCESS) {
ACCESS_MASK access_mask;
TRUSTEE_W trustee;
if (what & QFileSystemMetaData::UserPermissions) { // user
data.knownFlagsMask |= QFileSystemMetaData::UserPermissions;
- if(ptrGetEffectiveRightsFromAclW(pDacl, &currentUserTrusteeW, &access_mask) != ERROR_SUCCESS)
+ if (GetEffectiveRightsFromAcl(pDacl, &currentUserTrusteeW, &access_mask) != ERROR_SUCCESS)
access_mask = (ACCESS_MASK)-1;
if(access_mask & ReadMask)
data.entryFlags |= QFileSystemMetaData::UserReadPermission;
@@ -725,8 +728,8 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst
}
if (what & QFileSystemMetaData::OwnerPermissions) { // owner
data.knownFlagsMask |= QFileSystemMetaData::OwnerPermissions;
- ptrBuildTrusteeWithSidW(&trustee, pOwner);
- if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
+ BuildTrusteeWithSid(&trustee, pOwner);
+ if (GetEffectiveRightsFromAcl(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
access_mask = (ACCESS_MASK)-1;
if(access_mask & ReadMask)
data.entryFlags |= QFileSystemMetaData::OwnerReadPermission;
@@ -737,8 +740,8 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst
}
if (what & QFileSystemMetaData::GroupPermissions) { // group
data.knownFlagsMask |= QFileSystemMetaData::GroupPermissions;
- ptrBuildTrusteeWithSidW(&trustee, pGroup);
- if(ptrGetEffectiveRightsFromAclW(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
+ BuildTrusteeWithSid(&trustee, pGroup);
+ if (GetEffectiveRightsFromAcl(pDacl, &trustee, &access_mask) != ERROR_SUCCESS)
access_mask = (ACCESS_MASK)-1;
if(access_mask & ReadMask)
data.entryFlags |= QFileSystemMetaData::GroupReadPermission;
@@ -749,7 +752,7 @@ bool QFileSystemEngine::fillPermissions(const QFileSystemEntry &entry, QFileSyst
}
if (what & QFileSystemMetaData::OtherPermissions) { // other (world)
data.knownFlagsMask |= QFileSystemMetaData::OtherPermissions;
- if(ptrGetEffectiveRightsFromAclW(pDacl, &worldTrusteeW, &access_mask) != ERROR_SUCCESS)
+ if (GetEffectiveRightsFromAcl(pDacl, &worldTrusteeW, &access_mask) != ERROR_SUCCESS)
access_mask = (ACCESS_MASK)-1; // ###
if(access_mask & ReadMask)
data.entryFlags |= QFileSystemMetaData::OtherReadPermission;
@@ -902,8 +905,10 @@ bool QFileSystemEngine::fillMetaData(HANDLE fHandle, QFileSystemMetaData &data,
FILE_BASIC_INFO fileBasicInfo;
if (GetFileInformationByHandleEx(fHandle, FileBasicInfo, &fileBasicInfo, sizeof(fileBasicInfo))) {
data.fillFromFileAttribute(fileBasicInfo.FileAttributes);
- data.creationTime_.dwHighDateTime = fileBasicInfo.CreationTime.HighPart;
- data.creationTime_.dwLowDateTime = fileBasicInfo.CreationTime.LowPart;
+ data.birthTime_.dwHighDateTime = fileBasicInfo.CreationTime.HighPart;
+ data.birthTime_.dwLowDateTime = fileBasicInfo.CreationTime.LowPart;
+ data.changeTime_.dwHighDateTime = fileBasicInfo.ChangeTime.HighPart;
+ data.changeTime_.dwLowDateTime = fileBasicInfo.ChangeTime.LowPart;
data.lastAccessTime_.dwHighDateTime = fileBasicInfo.LastAccessTime.HighPart;
data.lastAccessTime_.dwLowDateTime = fileBasicInfo.LastAccessTime.LowPart;
data.lastWriteTime_.dwHighDateTime = fileBasicInfo.LastWriteTime.HighPart;
@@ -1160,19 +1165,19 @@ QString QFileSystemEngine::homePath()
{
QString ret;
#if QT_CONFIG(fslibs)
- resolveLibs();
- if (ptrGetUserProfileDirectoryW) {
+ initGlobalSid();
+ {
HANDLE hnd = ::GetCurrentProcess();
HANDLE token = 0;
BOOL ok = ::OpenProcessToken(hnd, TOKEN_QUERY, &token);
if (ok) {
DWORD dwBufferSize = 0;
// First call, to determine size of the strings (with '\0').
- ok = ptrGetUserProfileDirectoryW(token, NULL, &dwBufferSize);
+ ok = GetUserProfileDirectory(token, NULL, &dwBufferSize);
if (!ok && dwBufferSize != 0) { // We got the required buffer size
wchar_t *userDirectory = new wchar_t[dwBufferSize];
// Second call, now we can fill the allocated buffer.
- ok = ptrGetUserProfileDirectoryW(token, userDirectory, &dwBufferSize);
+ ok = GetUserProfileDirectory(token, userDirectory, &dwBufferSize);
if (ok)
ret = QString::fromWCharArray(userDirectory);
delete [] userDirectory;
@@ -1318,6 +1323,17 @@ bool QFileSystemEngine::renameFile(const QFileSystemEntry &source, const QFileSy
}
//static
+bool QFileSystemEngine::renameOverwriteFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
+{
+ bool ret = ::MoveFileEx(reinterpret_cast<const wchar_t *>(source.nativeFilePath().utf16()),
+ reinterpret_cast<const wchar_t *>(target.nativeFilePath().utf16()),
+ MOVEFILE_REPLACE_EXISTING) != 0;
+ if (!ret)
+ error = QSystemError(::GetLastError(), QSystemError::NativeError);
+ return ret;
+}
+
+//static
bool QFileSystemEngine::removeFile(const QFileSystemEntry &entry, QSystemError &error)
{
bool ret = ::DeleteFile((wchar_t*)entry.nativeFilePath().utf16()) != 0;
@@ -1349,6 +1365,9 @@ bool QFileSystemEngine::setPermissions(const QFileSystemEntry &entry, QFile::Per
static inline QDateTime fileTimeToQDateTime(const FILETIME *time)
{
+ if (time->dwHighDateTime == 0 && time->dwLowDateTime == 0)
+ return QDateTime();
+
SYSTEMTIME sTime;
FileTimeToSystemTime(time, &sTime);
return QDateTime(QDate(sTime.wYear, sTime.wMonth, sTime.wDay),
@@ -1356,9 +1375,13 @@ static inline QDateTime fileTimeToQDateTime(const FILETIME *time)
Qt::UTC);
}
-QDateTime QFileSystemMetaData::creationTime() const
+QDateTime QFileSystemMetaData::birthTime() const
+{
+ return fileTimeToQDateTime(&birthTime_);
+}
+QDateTime QFileSystemMetaData::metadataChangeTime() const
{
- return fileTimeToQDateTime(&creationTime_);
+ return fileTimeToQDateTime(&changeTime_);
}
QDateTime QFileSystemMetaData::modificationTime() const
{
diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h
index b09223d656..c4e1312c1d 100644
--- a/src/corelib/io/qfilesystemmetadata_p.h
+++ b/src/corelib/io/qfilesystemmetadata_p.h
@@ -120,16 +120,22 @@ public:
// Attributes
HiddenAttribute = 0x00100000,
SizeAttribute = 0x00200000, // Note: overlaps with QAbstractFileEngine::LocalDiskFlag
- ExistsAttribute = 0x00400000,
+ ExistsAttribute = 0x00400000, // For historical reasons, indicates existence of data, not the file
+#if defined(Q_OS_WIN)
+ WasDeletedAttribute = 0x0,
+#else
+ WasDeletedAttribute = 0x40000000, // Indicates the file was deleted
+#endif
- Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute,
+ Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute | WasDeletedAttribute,
- // Times
- CreationTime = 0x01000000, // Note: overlaps with QAbstractFileEngine::Refresh
+ // Times - if we know one of them, we know them all
+ AccessTime = 0x02000000,
+ BirthTime = 0x02000000,
+ MetadataChangeTime = 0x02000000,
ModificationTime = 0x02000000,
- AccessTime = 0x04000000,
- Times = CreationTime | ModificationTime | AccessTime,
+ Times = AccessTime | BirthTime | MetadataChangeTime | ModificationTime,
// Owner IDs
UserId = 0x10000000,
@@ -144,6 +150,7 @@ public:
| QFileSystemMetaData::DirectoryType
| QFileSystemMetaData::SequentialType
| QFileSystemMetaData::SizeAttribute
+ | QFileSystemMetaData::WasDeletedAttribute
| QFileSystemMetaData::Times
| QFileSystemMetaData::OwnerIds,
@@ -191,6 +198,7 @@ public:
bool isLegacyLink() const { return (entryFlags & LegacyLinkType); }
bool isSequential() const { return (entryFlags & SequentialType); }
bool isHidden() const { return (entryFlags & HiddenAttribute); }
+ bool wasDeleted() const { return (entryFlags & WasDeletedAttribute); }
#if defined(Q_OS_WIN)
bool isLnkFile() const { return (entryFlags & WinLnkType); }
#else
@@ -201,9 +209,10 @@ public:
QFile::Permissions permissions() const { return QFile::Permissions(Permissions & entryFlags); }
- QDateTime creationTime() const;
- QDateTime modificationTime() const;
QDateTime accessTime() const;
+ QDateTime birthTime() const;
+ QDateTime metadataChangeTime() const;
+ QDateTime modificationTime() const;
QDateTime fileTime(QAbstractFileEngine::FileTime time) const;
uint userId() const;
@@ -233,14 +242,16 @@ private:
// Platform-specific data goes here:
#if defined(Q_OS_WIN)
DWORD fileAttribute_;
- FILETIME creationTime_;
+ FILETIME birthTime_;
+ FILETIME changeTime_;
FILETIME lastAccessTime_;
FILETIME lastWriteTime_;
#else
// msec precision
- qint64 creationTime_;
- qint64 modificationTime_;
qint64 accessTime_;
+ qint64 birthTime_;
+ qint64 metadataChangeTime_;
+ qint64 modificationTime_;
uint userId_;
uint groupId_;
@@ -268,8 +279,11 @@ inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime tim
case QAbstractFileEngine::AccessTime:
return accessTime();
- case QAbstractFileEngine::CreationTime:
- return creationTime();
+ case QAbstractFileEngine::BirthTime:
+ return birthTime();
+
+ case QAbstractFileEngine::MetadataChangeTime:
+ return metadataChangeTime();
}
return QDateTime();
@@ -277,9 +291,14 @@ inline QDateTime QFileSystemMetaData::fileTime(QAbstractFileEngine::FileTime tim
#endif
#if defined(Q_OS_UNIX)
-inline QDateTime QFileSystemMetaData::creationTime() const { return QDateTime::fromMSecsSinceEpoch(creationTime_); }
-inline QDateTime QFileSystemMetaData::modificationTime() const { return QDateTime::fromMSecsSinceEpoch(modificationTime_); }
-inline QDateTime QFileSystemMetaData::accessTime() const { return QDateTime::fromMSecsSinceEpoch(accessTime_); }
+inline QDateTime QFileSystemMetaData::birthTime() const
+{ return birthTime_ ? QDateTime::fromMSecsSinceEpoch(birthTime_) : QDateTime(); }
+inline QDateTime QFileSystemMetaData::metadataChangeTime() const
+{ return metadataChangeTime_ ? QDateTime::fromMSecsSinceEpoch(metadataChangeTime_) : QDateTime(); }
+inline QDateTime QFileSystemMetaData::modificationTime() const
+{ return modificationTime_ ? QDateTime::fromMSecsSinceEpoch(modificationTime_) : QDateTime(); }
+inline QDateTime QFileSystemMetaData::accessTime() const
+{ return accessTime_ ? QDateTime::fromMSecsSinceEpoch(accessTime_) : QDateTime(); }
inline uint QFileSystemMetaData::userId() const { return userId_; }
inline uint QFileSystemMetaData::groupId() const { return groupId_; }
@@ -318,9 +337,9 @@ inline void QFileSystemMetaData::fillFromFileAttribute(DWORD fileAttribute,bool
inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, bool setLinkType, bool isDriveRoot)
{
fillFromFileAttribute(findData.dwFileAttributes, isDriveRoot);
- creationTime_ = findData.ftCreationTime;
+ birthTime_ = findData.ftCreationTime;
lastAccessTime_ = findData.ftLastAccessTime;
- lastWriteTime_ = findData.ftLastWriteTime;
+ changeTime_ = lastWriteTime_ = findData.ftLastWriteTime;
if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
size_ = 0;
} else {
@@ -343,9 +362,9 @@ inline void QFileSystemMetaData::fillFromFindData(WIN32_FIND_DATA &findData, boo
inline void QFileSystemMetaData::fillFromFindInfo(BY_HANDLE_FILE_INFORMATION &fileInfo)
{
fillFromFileAttribute(fileInfo.dwFileAttributes);
- creationTime_ = fileInfo.ftCreationTime;
+ birthTime_ = fileInfo.ftCreationTime;
lastAccessTime_ = fileInfo.ftLastAccessTime;
- lastWriteTime_ = fileInfo.ftLastWriteTime;
+ changeTime_ = lastWriteTime_ = fileInfo.ftLastWriteTime;
if (fileAttribute_ & FILE_ATTRIBUTE_DIRECTORY) {
size_ = 0;
} else {
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 88e8baedca..b7a5440224 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -195,6 +195,9 @@ void QFSFileEngine::setFileName(const QString &file)
*/
bool QFSFileEngine::open(QIODevice::OpenMode openMode)
{
+ Q_ASSERT_X(openMode & QIODevice::Unbuffered, "QFSFileEngine::open",
+ "QFSFileEngine no longer supports buffered mode; upper layer must buffer");
+
Q_D(QFSFileEngine);
if (d->fileEntry.isEmpty()) {
qWarning("QFSFileEngine::open: No file name specified");
@@ -230,6 +233,9 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh)
bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHandleFlags handleFlags)
{
+ Q_ASSERT_X(openMode & QIODevice::Unbuffered, "QFSFileEngine::open",
+ "QFSFileEngine no longer supports buffered mode; upper layer must buffer");
+
Q_D(QFSFileEngine);
// Append implies WriteOnly.
@@ -255,6 +261,9 @@ bool QFSFileEngine::open(QIODevice::OpenMode openMode, FILE *fh, QFile::FileHand
*/
bool QFSFileEnginePrivate::openFh(QIODevice::OpenMode openMode, FILE *fh)
{
+ Q_ASSERT_X(openMode & QIODevice::Unbuffered, "QFSFileEngine::open",
+ "QFSFileEngine no longer supports buffered mode; upper layer must buffer");
+
Q_Q(QFSFileEngine);
this->fh = fh;
fd = -1;
@@ -516,6 +525,25 @@ bool QFSFileEngine::seek(qint64 pos)
}
/*!
+ \reimp
+*/
+QDateTime QFSFileEngine::fileTime(FileTime time) const
+{
+ Q_D(const QFSFileEngine);
+
+ if (time == AccessTime) {
+ // always refresh for the access time
+ d->metaData.clearFlags(QFileSystemMetaData::AccessTime);
+ }
+
+ if (d->doStat(QFileSystemMetaData::Times))
+ return d->metaData.fileTime(time);
+
+ return QDateTime();
+}
+
+
+/*!
\internal
*/
bool QFSFileEnginePrivate::seekFdFh(qint64 pos)
@@ -699,6 +727,7 @@ qint64 QFSFileEnginePrivate::readLineFdFh(char *data, qint64 maxlen)
qint64 QFSFileEngine::write(const char *data, qint64 len)
{
Q_D(QFSFileEngine);
+ d->metaData.clearFlags(QFileSystemMetaData::Times);
// On Windows' stdlib implementation, the results of calling fread and
// fwrite are undefined if not called either in sequence, or if preceded
@@ -860,9 +889,9 @@ bool QFSFileEngine::supportsExtension(Extension extension) const
/*! \fn bool QFSFileEngine::copy(const QString &copyName)
- For windows, copy the file to file \a copyName.
+ For Windows or Apple platforms, copy the file to file \a copyName.
- Not implemented for Unix.
+ Not implemented for other Unix platforms.
*/
/*! \fn QString QFSFileEngine::currentPath(const QString &fileName)
@@ -890,7 +919,7 @@ bool QFSFileEngine::supportsExtension(Extension extension) const
\reimp
*/
-/*! \fn QDateTime QFSFileEngine::fileTime(FileTime time) const
+/*! \fn bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
\reimp
*/
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index ab9ad3aa6b..f352fcd475 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -97,6 +97,7 @@ public:
QString fileName(FileName file) const Q_DECL_OVERRIDE;
uint ownerId(FileOwner) const Q_DECL_OVERRIDE;
QString owner(FileOwner) const Q_DECL_OVERRIDE;
+ bool setFileTime(const QDateTime &newDate, FileTime time) Q_DECL_OVERRIDE;
QDateTime fileTime(FileTime time) const Q_DECL_OVERRIDE;
void setFileName(const QString &file) Q_DECL_OVERRIDE;
int handle() const Q_DECL_OVERRIDE;
@@ -109,6 +110,7 @@ public:
qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
qint64 readLine(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE;
+ bool clone(int sourceHandle) override;
bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) Q_DECL_OVERRIDE;
bool supportsExtension(Extension extension) const Q_DECL_OVERRIDE;
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index c613368a91..bb9b3dc87a 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -65,46 +65,6 @@ QT_BEGIN_NAMESPACE
/*!
\internal
- Returns the stdlib open string corresponding to a QIODevice::OpenMode.
-*/
-static inline QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QFileSystemEntry &fileEntry,
- QFileSystemMetaData &metaData)
-{
- QByteArray mode;
- if ((flags & QIODevice::ReadOnly) && !(flags & QIODevice::Truncate)) {
- mode = "rb";
- if (flags & QIODevice::WriteOnly) {
- metaData.clearFlags(QFileSystemMetaData::FileType);
- if (!fileEntry.isEmpty()
- && QFileSystemEngine::fillMetaData(fileEntry, metaData, QFileSystemMetaData::FileType)
- && metaData.isFile()) {
- mode += '+';
- } else {
- mode = "wb+";
- }
- }
- } else if (flags & QIODevice::WriteOnly) {
- mode = "wb";
- if (flags & QIODevice::ReadOnly)
- mode += '+';
- }
- if (flags & QIODevice::Append) {
- mode = "ab";
- if (flags & QIODevice::ReadOnly)
- mode += '+';
- }
-
-#if defined(__GLIBC__) && (__GLIBC__ * 0x100 + __GLIBC_MINOR__) >= 0x0207
- // must be glibc >= 2.7
- mode += 'e';
-#endif
-
- return mode;
-}
-
-/*!
- \internal
-
Returns the stdio open flags corresponding to a QIODevice::OpenMode.
*/
static inline int openModeToOpenFlags(QIODevice::OpenMode mode)
@@ -130,17 +90,6 @@ static inline int openModeToOpenFlags(QIODevice::OpenMode mode)
return oflags;
}
-/*!
- \internal
-
- Sets the file descriptor to close on exec. That is, the file
- descriptor is not inherited by child processes.
-*/
-static inline bool setCloseOnExec(int fd)
-{
- return fd != -1 && fcntl(fd, F_SETFD, FD_CLOEXEC) != -1;
-}
-
static inline QString msgOpenDirectory()
{
const char message[] = QT_TRANSLATE_NOOP("QIODevice", "file to open is a directory");
@@ -158,6 +107,8 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
{
Q_Q(QFSFileEngine);
+ Q_ASSERT_X(openMode & QIODevice::Unbuffered, "QFSFileEngine::open",
+ "QFSFileEngine no longer supports buffered mode; upper layer must buffer");
if (openMode & QIODevice::Unbuffered) {
int flags = openModeToOpenFlags(openMode);
@@ -199,49 +150,6 @@ bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
}
fh = 0;
- } else {
- QByteArray fopenMode = openModeToFopenMode(openMode, fileEntry, metaData);
-
- // Try to open the file in buffered mode.
- do {
- fh = QT_FOPEN(fileEntry.nativeFilePath().constData(), fopenMode.constData());
- } while (!fh && errno == EINTR);
-
- // On failure, return and report the error.
- if (!fh) {
- q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
- qt_error_string(int(errno)));
- return false;
- }
-
- if (!(openMode & QIODevice::WriteOnly)) {
- // we don't need this check if we tried to open for writing because then
- // we had received EISDIR anyway.
- if (QFileSystemEngine::fillMetaData(QT_FILENO(fh), metaData)
- && metaData.isDirectory()) {
- q->setError(QFile::OpenError, msgOpenDirectory());
- fclose(fh);
- return false;
- }
- }
-
- setCloseOnExec(fileno(fh)); // ignore failure
-
- // Seek to the end when in Append mode.
- if (openMode & QIODevice::Append) {
- int ret;
- do {
- ret = QT_FSEEK(fh, 0, SEEK_END);
- } while (ret == -1 && errno == EINTR);
-
- if (ret == -1) {
- q->setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError,
- qt_error_string(int(errno)));
- return false;
- }
- }
-
- fd = -1;
}
closeFileHandle = true;
@@ -416,8 +324,14 @@ bool QFSFileEngine::copy(const QString &newName)
bool QFSFileEngine::renameOverwrite(const QString &newName)
{
- // On Unix, rename() overwrites.
- return rename(newName);
+ Q_D(QFSFileEngine);
+ QSystemError error;
+ bool ret = QFileSystemEngine::renameOverwriteFile(d->fileEntry, QFileSystemEntry(newName), error);
+
+ if (!ret)
+ setError(QFile::RenameError, error.toString());
+
+ return ret;
}
bool QFSFileEngine::rename(const QString &newName)
@@ -549,11 +463,14 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
| QFileSystemMetaData::LinkType
| QFileSystemMetaData::FileType
| QFileSystemMetaData::DirectoryType
- | QFileSystemMetaData::BundleType;
+ | QFileSystemMetaData::BundleType
+ | QFileSystemMetaData::WasDeletedAttribute;
if (type & FlagsMask)
queryFlags |= QFileSystemMetaData::HiddenAttribute
| QFileSystemMetaData::ExistsAttribute;
+ else if (type & ExistsFlag)
+ queryFlags |= QFileSystemMetaData::WasDeletedAttribute;
queryFlags |= QFileSystemMetaData::LinkType;
@@ -585,7 +502,8 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
}
if (type & FlagsMask) {
- if (exists)
+ // the inode existing does not mean the file exists
+ if (!d->metaData.wasDeleted())
ret |= ExistsFlag;
if (d->fileEntry.isRoot())
ret |= RootFlag;
@@ -689,14 +607,23 @@ bool QFSFileEngine::setSize(qint64 size)
return ret;
}
-QDateTime QFSFileEngine::fileTime(FileTime time) const
+bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
{
- Q_D(const QFSFileEngine);
+ Q_D(QFSFileEngine);
- if (d->doStat(QFileSystemMetaData::Times))
- return d->metaData.fileTime(time);
+ if (d->openMode == QIODevice::NotOpen) {
+ setError(QFile::PermissionsError, qt_error_string(EACCES));
+ return false;
+ }
+
+ QSystemError error;
+ if (!QFileSystemEngine::setFileTime(d->nativeHandle(), newDate, time, error)) {
+ setError(QFile::PermissionsError, error.toString());
+ return false;
+ }
- return QDateTime();
+ d->metaData.clearFlags(QFileSystemMetaData::Times);
+ return true;
}
uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
@@ -715,7 +642,6 @@ uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size, QFile::MemoryMapFla
#endif
Q_Q(QFSFileEngine);
- Q_UNUSED(flags);
if (openMode == QIODevice::NotOpen) {
q->setError(QFile::PermissionsError, qt_error_string(int(EACCES)));
return 0;
@@ -806,6 +732,23 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr)
#endif
}
+/*!
+ \reimp
+*/
+bool QFSFileEngine::clone(int sourceHandle)
+{
+#if defined(Q_OS_LINUX)
+ Q_D(QFSFileEngine);
+# if !defined FICLONE
+# define FICLONE _IOW (0x94, 9, int)
+# endif
+ return ::ioctl(d->fd, FICLONE, sourceHandle) == 0;
+#else
+ Q_UNUSED(sourceHandle);
+ return false;
+#endif
+}
+
QT_END_NAMESPACE
#endif // QT_NO_FSFILEENGINE
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index c99a25f30d..97fefe8927 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -474,11 +474,10 @@ bool QFSFileEngine::rename(const QString &newName)
bool QFSFileEngine::renameOverwrite(const QString &newName)
{
Q_D(QFSFileEngine);
- bool ret = ::MoveFileEx((wchar_t*)d->fileEntry.nativeFilePath().utf16(),
- (wchar_t*)QFileSystemEntry(newName).nativeFilePath().utf16(),
- MOVEFILE_REPLACE_EXISTING) != 0;
+ QSystemError error;
+ bool ret = QFileSystemEngine::renameOverwriteFile(d->fileEntry, QFileSystemEntry(newName), error);
if (!ret)
- setError(QFile::RenameError, QSystemError(::GetLastError(), QSystemError::NativeError).toString());
+ setError(QFile::RenameError, error.toString());
return ret;
}
@@ -694,6 +693,8 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil
}
if (type & FlagsMask) {
if (d->metaData.exists()) {
+ // if we succeeded in querying, then the file exists: a file on
+ // Windows cannot be deleted if we have an open handle to it
ret |= ExistsFlag;
if (d->fileEntry.isRoot())
ret |= RootFlag;
@@ -854,15 +855,41 @@ bool QFSFileEngine::setSize(qint64 size)
return false;
}
-
-QDateTime QFSFileEngine::fileTime(FileTime time) const
+bool QFSFileEngine::setFileTime(const QDateTime &newDate, FileTime time)
{
- Q_D(const QFSFileEngine);
+ Q_D(QFSFileEngine);
+
+ if (d->openMode == QFile::NotOpen) {
+ setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
+ return false;
+ }
+
+ if (!newDate.isValid() || time == QAbstractFileEngine::MetadataChangeTime) {
+ setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER));
+ return false;
+ }
+
+ HANDLE handle = d->fileHandle;
+ if (handle == INVALID_HANDLE_VALUE) {
+ if (d->fh)
+ handle = reinterpret_cast<HANDLE>(::_get_osfhandle(QT_FILENO(d->fh)));
+ else if (d->fd != -1)
+ handle = reinterpret_cast<HANDLE>(::_get_osfhandle(d->fd));
+ }
+
+ if (handle == INVALID_HANDLE_VALUE) {
+ setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
+ return false;
+ }
- if (d->doStat(QFileSystemMetaData::Times))
- return d->metaData.fileTime(time);
+ QSystemError error;
+ if (!QFileSystemEngine::setFileTime(handle, newDate, time, error)) {
+ setError(QFile::PermissionsError, error.toString());
+ return false;
+ }
- return QDateTime();
+ d->metaData.clearFlags(QFileSystemMetaData::Times);
+ return true;
}
uchar *QFSFileEnginePrivate::map(qint64 offset, qint64 size,
@@ -1002,4 +1029,13 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr)
return true;
}
+/*!
+ \reimp
+*/
+bool QFSFileEngine::clone(int sourceHandle)
+{
+ Q_UNUSED(sourceHandle);
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index ccc607afd5..1ee8ce889c 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -199,7 +199,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys()
}
if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) {
- close(fd);
+ qt_safe_close(fd);
if (!QFile::remove(fileName))
qWarning("QLockFile: Could not remove our own lock file %s.", qPrintable(fileName));
return QLockFile::UnknownError; // partition full
@@ -258,17 +258,17 @@ QString QLockFilePrivate::processNameByPid(qint64 pid)
proc_name(pid, name, sizeof(name) / sizeof(char));
return QFile::decodeName(name);
#elif defined(Q_OS_LINUX)
- if (!QFile::exists(QStringLiteral("/proc/version")))
+ if (!qt_haveLinuxProcfs())
return QString();
+
char exePath[64];
- char buf[PATH_MAX + 1];
sprintf(exePath, "/proc/%lld/exe", pid);
- size_t len = (size_t)readlink(exePath, buf, sizeof(buf));
- if (len >= sizeof(buf)) {
+
+ QByteArray buf = qt_readlink(exePath);
+ if (buf.isEmpty()) {
// The pid is gone. Return some invalid process name to fail the test.
return QStringLiteral("/ERROR/");
}
- buf[len] = 0;
return QFileInfo(QFile::decodeName(buf)).fileName();
#elif defined(Q_OS_HAIKU)
thread_info info;
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 2226b4435b..bb16b0c427 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -450,11 +450,6 @@ void QProcessPrivate::Channel::clear()
process = 0;
}
-/*! \fn bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
-
-\internal
- */
-
/*!
\class QProcess
\inmodule QtCore
@@ -2112,6 +2107,60 @@ void QProcess::start(OpenMode mode)
}
/*!
+ \since 5.10
+
+ Starts the program set by setProgram() with arguments set by setArguments()
+ in a new process, and detaches from it. Returns \c true on success;
+ otherwise returns \c false. If the calling process exits, the
+ detached process will continue to run unaffected.
+
+ \b{Unix:} The started process will run in its own session and act
+ like a daemon.
+
+ The process will be started in the directory set by setWorkingDirectory().
+ If workingDirectory() is empty, the working directory is inherited
+ from the calling process.
+
+ \note On QNX, this may cause all application threads to
+ temporarily freeze.
+
+ If the function is successful then *\a pid is set to the process
+ identifier of the started process.
+
+ Only the following property setters are supported by startDetached():
+ \list
+ \li setArguments()
+ \li setCreateProcessArgumentsModifier()
+ \li setNativeArguments()
+ \li setProcessEnvironment()
+ \li setProgram()
+ \li setStandardErrorFile()
+ \li setStandardInputFile()
+ \li setStandardOutputFile()
+ \li setWorkingDirectory()
+ \endlist
+ All other properties of the QProcess object are ignored.
+
+ \sa start()
+ \sa startDetached(const QString &program, const QStringList &arguments,
+ const QString &workingDirectory, qint64 *pid)
+ \sa startDetached(const QString &command)
+*/
+bool QProcess::startDetached(qint64 *pid)
+{
+ Q_D(QProcess);
+ if (d->processState != NotRunning) {
+ qWarning("QProcess::startDetached: Process is already running");
+ return false;
+ }
+ if (d->program.isEmpty()) {
+ d->setErrorAndEmit(QProcess::FailedToStart, tr("No program defined"));
+ return false;
+ }
+ return d->startDetached(pid);
+}
+
+/*!
Starts the program set by setProgram() with arguments set by setArguments().
The OpenMode is set to \a mode.
@@ -2445,6 +2494,8 @@ int QProcess::execute(const QString &command)
}
/*!
+ \overload startDetached()
+
Starts the program \a program with the arguments \a arguments in a
new process, and detaches from it. Returns \c true on success;
otherwise returns \c false. If the calling process exits, the
@@ -2452,16 +2503,10 @@ int QProcess::execute(const QString &command)
Argument handling is identical to the respective start() overload.
- \b{Unix:} The started process will run in its own session and act
- like a daemon.
-
The process will be started in the directory \a workingDirectory.
If \a workingDirectory is empty, the working directory is inherited
from the calling process.
- \note On QNX, this may cause all application threads to
- temporarily freeze.
-
If the function is successful then *\a pid is set to the process
identifier of the started process.
@@ -2472,10 +2517,11 @@ bool QProcess::startDetached(const QString &program,
const QString &workingDirectory,
qint64 *pid)
{
- return QProcessPrivate::startDetached(program,
- arguments,
- workingDirectory,
- pid);
+ QProcess process;
+ process.setProgram(program);
+ process.setArguments(arguments);
+ process.setWorkingDirectory(workingDirectory);
+ return process.startDetached(pid);
}
/*!
@@ -2484,11 +2530,14 @@ bool QProcess::startDetached(const QString &program,
bool QProcess::startDetached(const QString &program,
const QStringList &arguments)
{
- return QProcessPrivate::startDetached(program, arguments);
+ QProcess process;
+ process.setProgram(program);
+ process.setArguments(arguments);
+ return process.startDetached();
}
/*!
- \overload
+ \overload startDetached()
Starts the command \a command in a new process, and detaches from it.
Returns \c true on success; otherwise returns \c false.
@@ -2506,9 +2555,10 @@ bool QProcess::startDetached(const QString &command)
if (args.isEmpty())
return false;
- const QString prog = args.takeFirst();
-
- return QProcessPrivate::startDetached(prog, args);
+ QProcess process;
+ process.setProgram(args.takeFirst());
+ process.setArguments(args);
+ return process.startDetached();
}
QT_BEGIN_INCLUDE_NAMESPACE
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index 19157bdd02..c8aef2f0b1 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -163,6 +163,7 @@ public:
void start(const QString &command, OpenMode mode = ReadWrite);
#endif
void start(OpenMode mode = ReadWrite);
+ bool startDetached(qint64 *pid = nullptr);
bool open(OpenMode mode = ReadWrite) Q_DECL_OVERRIDE;
QString program() const;
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index c5abf7b762..deb29dca0a 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -350,7 +350,7 @@ public:
void start(QIODevice::OpenMode mode);
void startProcess();
#if defined(Q_OS_UNIX)
- void execChild(const char *workingDirectory, char **path, char **argv, char **envp);
+ void execChild(const char *workingDirectory, char **argv, char **envp);
#endif
bool processStarted(QString *errorMessage = Q_NULLPTR);
void terminateProcess();
@@ -360,13 +360,13 @@ public:
bool waitForDeadChild();
#endif
#ifdef Q_OS_WIN
+ bool callCreateProcess(QProcess::CreateProcessArguments *cpargs);
bool drainOutputPipes();
void flushPipeWriter();
qint64 pipeWriterBytesToWrite() const;
#endif
- static bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory = QString(),
- qint64 *pid = 0);
+ bool startDetached(qint64 *pPid);
int exitCode;
QProcess::ExitStatus exitStatus;
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 6b7f187fee..cf9d38097a 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -87,6 +87,7 @@ QT_END_NAMESPACE
#include "qprocess.h"
#include "qprocess_p.h"
+#include "qstandardpaths.h"
#include "private/qcore_unix_p.h"
#ifdef Q_OS_MAC
@@ -420,8 +421,16 @@ void QProcessPrivate::startProcess()
#endif
// Add the program name to the argument list.
- char *dupProgramName = ::strdup(encodedProgramName.constData());
- argv[0] = dupProgramName;
+ argv[0] = nullptr;
+ if (!program.contains(QLatin1Char('/'))) {
+ const QString &exeFilePath = QStandardPaths::findExecutable(program);
+ if (!exeFilePath.isEmpty()) {
+ const QByteArray &tmp = QFile::encodeName(exeFilePath);
+ argv[0] = ::strdup(tmp.constData());
+ }
+ }
+ if (!argv[0])
+ argv[0] = ::strdup(encodedProgramName.constData());
// Add every argument to the list
for (int i = 0; i < arguments.count(); ++i)
@@ -443,29 +452,6 @@ void QProcessPrivate::startProcess()
workingDirPtr = encodedWorkingDirectory.constData();
}
- // If the program does not specify a path, generate a list of possible
- // locations for the binary using the PATH environment variable.
- char **path = 0;
- int pathc = 0;
- if (!program.contains(QLatin1Char('/'))) {
- const QString pathEnv = QString::fromLocal8Bit(qgetenv("PATH"));
- if (!pathEnv.isEmpty()) {
- QStringList pathEntries = pathEnv.split(QLatin1Char(':'), QString::SkipEmptyParts);
- if (!pathEntries.isEmpty()) {
- pathc = pathEntries.size();
- path = new char *[pathc + 1];
- path[pathc] = 0;
-
- for (int k = 0; k < pathEntries.size(); ++k) {
- QByteArray tmp = QFile::encodeName(pathEntries.at(k));
- if (!tmp.endsWith('/')) tmp += '/';
- tmp += encodedProgramName;
- path[k] = ::strdup(tmp.constData());
- }
- }
- }
- }
-
// Start the process manager, and fork off the child process.
pid_t childPid;
forkfd = ::forkfd(FFD_CLOEXEC, &childPid);
@@ -473,16 +459,12 @@ void QProcessPrivate::startProcess()
if (forkfd != FFD_CHILD_PROCESS) {
// Parent process.
// Clean up duplicated memory.
- free(dupProgramName);
- for (int i = 1; i <= arguments.count(); ++i)
+ for (int i = 0; i <= arguments.count(); ++i)
free(argv[i]);
for (int i = 0; i < envc; ++i)
free(envp[i]);
- for (int i = 0; i < pathc; ++i)
- free(path[i]);
delete [] argv;
delete [] envp;
- delete [] path;
}
// On QNX, if spawnChild failed, childPid will be -1 but forkfd is still 0.
@@ -503,7 +485,7 @@ void QProcessPrivate::startProcess()
// Start the child.
if (forkfd == FFD_CHILD_PROCESS) {
- execChild(workingDirPtr, path, argv, envp);
+ execChild(workingDirPtr, argv, envp);
::_exit(-1);
}
@@ -550,7 +532,7 @@ struct ChildError
char function[8];
};
-void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv, char **envp)
+void QProcessPrivate::execChild(const char *workingDir, char **argv, char **envp)
{
::signal(SIGPIPE, SIG_DFL); // reset the signal that we ignored
@@ -574,7 +556,7 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
}
}
- // make sure this fd is closed if execvp() succeeds
+ // make sure this fd is closed if execv() succeeds
qt_safe_close(childStartedPipe[0]);
// enter the working directory
@@ -589,25 +571,13 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
// execute the process
if (!envp) {
- qt_safe_execvp(argv[0], argv);
+ qt_safe_execv(argv[0], argv);
strcpy(error.function, "execvp");
} else {
- if (path) {
- char **arg = path;
- while (*arg) {
- argv[0] = *arg;
#if defined (QPROCESS_DEBUG)
- fprintf(stderr, "QProcessPrivate::execChild() searching / starting %s\n", argv[0]);
+ fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
#endif
- qt_safe_execve(argv[0], argv, envp);
- ++arg;
- }
- } else {
-#if defined (QPROCESS_DEBUG)
- fprintf(stderr, "QProcessPrivate::execChild() starting %s\n", argv[0]);
-#endif
- qt_safe_execve(argv[0], argv, envp);
- }
+ qt_safe_execve(argv[0], argv, envp);
strcpy(error.function, "execve");
}
@@ -921,7 +891,7 @@ bool QProcessPrivate::waitForDeadChild()
return true;
}
-bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
+bool QProcessPrivate::startDetached(qint64 *pid)
{
QByteArray encodedWorkingDirectory = QFile::encodeName(workingDirectory);
@@ -937,6 +907,17 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
return false;
}
+ if ((stdinChannel.type == Channel::Redirect && !openChannel(stdinChannel))
+ || (stdoutChannel.type == Channel::Redirect && !openChannel(stdoutChannel))
+ || (stderrChannel.type == Channel::Redirect && !openChannel(stderrChannel))) {
+ closeChannel(&stdinChannel);
+ closeChannel(&stdoutChannel);
+ closeChannel(&stderrChannel);
+ qt_safe_close(startedPipe[0]);
+ qt_safe_close(startedPipe[1]);
+ return false;
+ }
+
pid_t childPid = fork();
if (childPid == 0) {
struct sigaction noaction;
@@ -953,6 +934,18 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
if (doubleForkPid == 0) {
qt_safe_close(pidPipe[1]);
+ // copy the stdin socket if asked to (without closing on exec)
+ if (inputChannelMode != QProcess::ForwardedInputChannel)
+ qt_safe_dup2(stdinChannel.pipe[0], STDIN_FILENO, 0);
+
+ // copy the stdout and stderr if asked to
+ if (processChannelMode != QProcess::ForwardedChannels) {
+ if (processChannelMode != QProcess::ForwardedOutputChannel)
+ qt_safe_dup2(stdoutChannel.pipe[1], STDOUT_FILENO, 0);
+ if (processChannelMode != QProcess::ForwardedErrorChannel)
+ qt_safe_dup2(stderrChannel.pipe[1], STDERR_FILENO, 0);
+ }
+
if (!encodedWorkingDirectory.isEmpty()) {
if (QT_CHDIR(encodedWorkingDirectory.constData()) == -1)
qWarning("QProcessPrivate::startDetached: failed to chdir to %s", encodedWorkingDirectory.constData());
@@ -963,23 +956,28 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
argv[i + 1] = ::strdup(QFile::encodeName(arguments.at(i)).constData());
argv[arguments.size() + 1] = 0;
+ // Duplicate the environment.
+ int envc = 0;
+ char **envp = nullptr;
+ if (environment.d.constData()) {
+ QProcessEnvironmentPrivate::MutexLocker locker(environment.d);
+ envp = _q_dupEnvironment(environment.d.constData()->vars, &envc);
+ }
+
+ QByteArray tmp;
if (!program.contains(QLatin1Char('/'))) {
- const QString path = QString::fromLocal8Bit(qgetenv("PATH"));
- if (!path.isEmpty()) {
- QStringList pathEntries = path.split(QLatin1Char(':'));
- for (int k = 0; k < pathEntries.size(); ++k) {
- QByteArray tmp = QFile::encodeName(pathEntries.at(k));
- if (!tmp.endsWith('/')) tmp += '/';
- tmp += QFile::encodeName(program);
- argv[0] = tmp.data();
- qt_safe_execv(argv[0], argv);
- }
- }
- } else {
- QByteArray tmp = QFile::encodeName(program);
- argv[0] = tmp.data();
- qt_safe_execv(argv[0], argv);
+ const QString &exeFilePath = QStandardPaths::findExecutable(program);
+ if (!exeFilePath.isEmpty())
+ tmp = QFile::encodeName(exeFilePath);
}
+ if (tmp.isEmpty())
+ tmp = QFile::encodeName(program);
+ argv[0] = tmp.data();
+
+ if (envp)
+ qt_safe_execve(argv[0], argv, envp);
+ else
+ qt_safe_execv(argv[0], argv);
struct sigaction noaction;
memset(&noaction, 0, sizeof(noaction));
@@ -1009,6 +1007,9 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
::_exit(1);
}
+ closeChannel(&stdinChannel);
+ closeChannel(&stdoutChannel);
+ closeChannel(&stderrChannel);
qt_safe_close(startedPipe[1]);
qt_safe_close(pidPipe[1]);
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 05c9d6594c..2bbc4eddd0 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -358,7 +358,8 @@ void QProcessPrivate::closeChannel(Channel *channel)
destroyPipe(channel->pipe);
}
-static QString qt_create_commandline(const QString &program, const QStringList &arguments)
+static QString qt_create_commandline(const QString &program, const QStringList &arguments,
+ const QString &nativeArguments)
{
QString args;
if (!program.isEmpty()) {
@@ -387,6 +388,13 @@ static QString qt_create_commandline(const QString &program, const QStringList &
}
args += QLatin1Char(' ') + tmp;
}
+
+ if (!nativeArguments.isEmpty()) {
+ if (!args.isEmpty())
+ args += QLatin1Char(' ');
+ args += nativeArguments;
+ }
+
return args;
}
@@ -450,6 +458,30 @@ static QByteArray qt_create_environment(const QProcessEnvironmentPrivate::Map &e
return envlist;
}
+bool QProcessPrivate::callCreateProcess(QProcess::CreateProcessArguments *cpargs)
+{
+ if (modifyCreateProcessArgs)
+ modifyCreateProcessArgs(cpargs);
+ bool success = CreateProcess(cpargs->applicationName, cpargs->arguments,
+ cpargs->processAttributes, cpargs->threadAttributes,
+ cpargs->inheritHandles, cpargs->flags, cpargs->environment,
+ cpargs->currentDirectory, cpargs->startupInfo,
+ cpargs->processInformation);
+ if (stdinChannel.pipe[0] != INVALID_Q_PIPE) {
+ CloseHandle(stdinChannel.pipe[0]);
+ stdinChannel.pipe[0] = INVALID_Q_PIPE;
+ }
+ if (stdoutChannel.pipe[1] != INVALID_Q_PIPE) {
+ CloseHandle(stdoutChannel.pipe[1]);
+ stdoutChannel.pipe[1] = INVALID_Q_PIPE;
+ }
+ if (stderrChannel.pipe[1] != INVALID_Q_PIPE) {
+ CloseHandle(stderrChannel.pipe[1]);
+ stderrChannel.pipe[1] = INVALID_Q_PIPE;
+ }
+ return success;
+}
+
void QProcessPrivate::startProcess()
{
Q_Q(QProcess);
@@ -472,15 +504,10 @@ void QProcessPrivate::startProcess()
!openChannel(stderrChannel))
return;
- QString args = qt_create_commandline(program, arguments);
+ const QString args = qt_create_commandline(program, arguments, nativeArguments);
QByteArray envlist;
if (environment.d.constData())
envlist = qt_create_environment(environment.d.constData()->vars);
- if (!nativeArguments.isEmpty()) {
- if (!args.isEmpty())
- args += QLatin1Char(' ');
- args += nativeArguments;
- }
#if defined QPROCESS_DEBUG
qDebug("Creating process");
@@ -507,18 +534,14 @@ void QProcessPrivate::startProcess()
const QString nativeWorkingDirectory = QDir::toNativeSeparators(workingDirectory);
QProcess::CreateProcessArguments cpargs = {
- 0, (wchar_t*)args.utf16(),
- 0, 0, TRUE, dwCreationFlags,
- environment.isEmpty() ? 0 : envlist.data(),
- nativeWorkingDirectory.isEmpty() ? Q_NULLPTR : (wchar_t*)nativeWorkingDirectory.utf16(),
+ nullptr, reinterpret_cast<wchar_t *>(const_cast<ushort *>(args.utf16())),
+ nullptr, nullptr, true, dwCreationFlags,
+ environment.isEmpty() ? nullptr : envlist.data(),
+ nativeWorkingDirectory.isEmpty()
+ ? nullptr : reinterpret_cast<const wchar_t *>(nativeWorkingDirectory.utf16()),
&startupInfo, pid
};
- if (modifyCreateProcessArgs)
- modifyCreateProcessArgs(&cpargs);
- success = CreateProcess(cpargs.applicationName, cpargs.arguments, cpargs.processAttributes,
- cpargs.threadAttributes, cpargs.inheritHandles, cpargs.flags,
- cpargs.environment, cpargs.currentDirectory, cpargs.startupInfo,
- cpargs.processInformation);
+ success = callCreateProcess(&cpargs);
QString errorString;
if (!success) {
@@ -526,19 +549,6 @@ void QProcessPrivate::startProcess()
errorString = QProcess::tr("Process failed to start: %1").arg(qt_error_string());
}
- if (stdinChannel.pipe[0] != INVALID_Q_PIPE) {
- CloseHandle(stdinChannel.pipe[0]);
- stdinChannel.pipe[0] = INVALID_Q_PIPE;
- }
- if (stdoutChannel.pipe[1] != INVALID_Q_PIPE) {
- CloseHandle(stdoutChannel.pipe[1]);
- stdoutChannel.pipe[1] = INVALID_Q_PIPE;
- }
- if (stderrChannel.pipe[1] != INVALID_Q_PIPE) {
- CloseHandle(stderrChannel.pipe[1]);
- stderrChannel.pipe[1] = INVALID_Q_PIPE;
- }
-
if (!success) {
cleanup();
setErrorAndEmit(QProcess::FailedToStart, errorString);
@@ -826,6 +836,7 @@ bool QProcessPrivate::writeToStdin()
// Use ShellExecuteEx() to trigger an UAC prompt when CreateProcess()fails
// with ERROR_ELEVATION_REQUIRED.
static bool startDetachedUacPrompt(const QString &programIn, const QStringList &arguments,
+ const QString &nativeArguments,
const QString &workingDir, qint64 *pid)
{
typedef BOOL (WINAPI *ShellExecuteExType)(SHELLEXECUTEINFOW *);
@@ -836,7 +847,8 @@ static bool startDetachedUacPrompt(const QString &programIn, const QStringList &
if (!shellExecuteEx)
return false;
- const QString args = qt_create_commandline(QString(), arguments); // needs arguments only
+ const QString args = qt_create_commandline(QString(), // needs arguments only
+ arguments, nativeArguments);
SHELLEXECUTEINFOW shellExecuteExInfo;
memset(&shellExecuteExInfo, 0, sizeof(SHELLEXECUTEINFOW));
shellExecuteExInfo.cbSize = sizeof(SHELLEXECUTEINFOW);
@@ -859,25 +871,52 @@ static bool startDetachedUacPrompt(const QString &programIn, const QStringList &
return true;
}
-bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
+bool QProcessPrivate::startDetached(qint64 *pid)
{
static const DWORD errorElevationRequired = 740;
- QString args = qt_create_commandline(program, arguments);
+ if ((stdinChannel.type == Channel::Redirect && !openChannel(stdinChannel))
+ || (stdoutChannel.type == Channel::Redirect && !openChannel(stdoutChannel))
+ || (stderrChannel.type == Channel::Redirect && !openChannel(stderrChannel))) {
+ closeChannel(&stdinChannel);
+ closeChannel(&stdoutChannel);
+ closeChannel(&stderrChannel);
+ return false;
+ }
+
+ QString args = qt_create_commandline(program, arguments, nativeArguments);
bool success = false;
PROCESS_INFORMATION pinfo;
+ void *envPtr = nullptr;
+ QByteArray envlist;
+ if (environment.d.constData()) {
+ envlist = qt_create_environment(environment.d.constData()->vars);
+ envPtr = envlist.data();
+ }
+
DWORD dwCreationFlags = (GetConsoleWindow() ? 0 : CREATE_NO_WINDOW);
dwCreationFlags |= CREATE_UNICODE_ENVIRONMENT;
STARTUPINFOW startupInfo = { sizeof( STARTUPINFO ), 0, 0, 0,
(ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
(ulong)CW_USEDEFAULT, (ulong)CW_USEDEFAULT,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0, 0, 0,
+ STARTF_USESTDHANDLES,
+ 0, 0, 0,
+ stdinChannel.pipe[0], stdoutChannel.pipe[1], stderrChannel.pipe[1]
};
- success = CreateProcess(0, (wchar_t*)args.utf16(),
- 0, 0, FALSE, dwCreationFlags, 0,
- workingDir.isEmpty() ? 0 : (wchar_t*)workingDir.utf16(),
- &startupInfo, &pinfo);
+
+ const bool inheritHandles = stdinChannel.type == Channel::Redirect
+ || stdoutChannel.type == Channel::Redirect
+ || stderrChannel.type == Channel::Redirect;
+ QProcess::CreateProcessArguments cpargs = {
+ nullptr, reinterpret_cast<wchar_t *>(const_cast<ushort *>(args.utf16())),
+ nullptr, nullptr, inheritHandles, dwCreationFlags, envPtr,
+ workingDirectory.isEmpty()
+ ? nullptr : reinterpret_cast<const wchar_t *>(workingDirectory.utf16()),
+ &startupInfo, &pinfo
+ };
+ success = callCreateProcess(&cpargs);
if (success) {
CloseHandle(pinfo.hThread);
@@ -885,9 +924,19 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
if (pid)
*pid = pinfo.dwProcessId;
} else if (GetLastError() == errorElevationRequired) {
- success = startDetachedUacPrompt(program, arguments, workingDir, pid);
+ if (envPtr)
+ qWarning("QProcess: custom environment will be ignored for detached elevated process.");
+ if (!stdinChannel.file.isEmpty() || !stdoutChannel.file.isEmpty()
+ || !stderrChannel.file.isEmpty()) {
+ qWarning("QProcess: file redirection is unsupported for detached elevated processes.");
+ }
+ success = startDetachedUacPrompt(program, arguments, nativeArguments,
+ workingDirectory, pid);
}
+ closeChannel(&stdinChannel);
+ closeChannel(&stdoutChannel);
+ closeChannel(&stderrChannel);
return success;
}
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 4e7120a3b8..c1187e5145 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -67,10 +67,9 @@ QT_BEGIN_NAMESPACE
class QStringSplitter
{
public:
- QStringSplitter(const QString &s)
- : m_string(s), m_data(m_string.constData()), m_len(s.length()), m_pos(0)
+ explicit QStringSplitter(QStringView sv)
+ : m_data(sv.data()), m_len(sv.size())
{
- m_splitChar = QLatin1Char('/');
}
inline bool hasNext() {
@@ -79,18 +78,17 @@ public:
return m_pos < m_len;
}
- inline QStringRef next() {
+ inline QStringView next() {
int start = m_pos;
while (m_pos < m_len && m_data[m_pos] != m_splitChar)
++m_pos;
- return QStringRef(&m_string, start, m_pos - start);
+ return QStringView(m_data + start, m_pos - start);
}
- QString m_string;
const QChar *m_data;
- QChar m_splitChar;
- int m_len;
- int m_pos;
+ qssize_t m_len;
+ qssize_t m_pos = 0;
+ QChar m_splitChar = QLatin1Char('/');
};
@@ -679,7 +677,7 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
QStringSplitter splitter(path);
while (child_count && splitter.hasNext()) {
- QStringRef segment = splitter.next();
+ QStringView segment = splitter.next();
#ifdef DEBUG_RESOURCE_MATCH
qDebug() << " CHILDREN" << segment;
@@ -836,24 +834,24 @@ QStringList QResourceRoot::children(int node) const
bool QResourceRoot::mappingRootSubdir(const QString &path, QString *match) const
{
const QString root = mappingRoot();
- if(!root.isEmpty()) {
- const QVector<QStringRef> root_segments = root.splitRef(QLatin1Char('/'), QString::SkipEmptyParts),
- path_segments = path.splitRef(QLatin1Char('/'), QString::SkipEmptyParts);
- if(path_segments.size() <= root_segments.size()) {
- int matched = 0;
- for(int i = 0; i < path_segments.size(); ++i) {
- if(root_segments[i] != path_segments[i])
- break;
- ++matched;
- }
- if(matched == path_segments.size()) {
- if(match && root_segments.size() > matched)
- *match = root_segments.at(matched).toString();
- return true;
- }
+ if (root.isEmpty())
+ return false;
+
+ QStringSplitter rootIt(root);
+ QStringSplitter pathIt(path);
+ while (rootIt.hasNext()) {
+ if (pathIt.hasNext()) {
+ if (rootIt.next() != pathIt.next()) // mismatch
+ return false;
+ } else {
+ // end of path, but not of root:
+ if (match)
+ *match = rootIt.next().toString();
+ return true;
}
}
- return false;
+ // end of root
+ return !pathIt.hasNext();
}
Q_CORE_EXPORT bool qRegisterResourceData(int version, const unsigned char *tree,
diff --git a/src/corelib/io/qsavefile.cpp b/src/corelib/io/qsavefile.cpp
index 3f45ca5f91..63f2284ef5 100644
--- a/src/corelib/io/qsavefile.cpp
+++ b/src/corelib/io/qsavefile.cpp
@@ -231,7 +231,38 @@ bool QSaveFile::open(OpenMode mode)
d->finalFileName = existingFile.filePath();
}
- d->fileEngine = new QTemporaryFileEngine;
+ auto openDirectly = [&]() {
+ d->fileEngine = QAbstractFileEngine::create(d->finalFileName);
+ if (d->fileEngine->open(mode | QIODevice::Unbuffered)) {
+ d->useTemporaryFile = false;
+ QFileDevice::open(mode);
+ return true;
+ }
+ return false;
+ };
+
+#ifdef Q_OS_WIN
+ // check if it is an Alternate Data Stream
+ if (d->finalFileName == d->fileName && d->fileName.indexOf(QLatin1Char(':'), 2) > 1) {
+ // yes, we can't rename onto it...
+ if (d->directWriteFallback) {
+ if (openDirectly())
+ return true;
+ d->setError(d->fileEngine->error(), d->fileEngine->errorString());
+ delete d->fileEngine;
+ d->fileEngine = 0;
+ } else {
+ QString msg =
+ QSaveFile::tr("QSaveFile cannot open '%1' without direct write fallback "
+ "enabled: path contains an Alternate Data Stream specifier")
+ .arg(QDir::toNativeSeparators(d->fileName));
+ d->setError(QFileDevice::OpenError, msg);
+ }
+ return false;
+ }
+#endif
+
+ d->fileEngine = new QTemporaryFileEngine(&d->finalFileName);
// if the target file exists, we'll copy its permissions below,
// but until then, let's ensure the temporary file is not accessible
// to a third party
@@ -243,12 +274,8 @@ bool QSaveFile::open(OpenMode mode)
#ifdef Q_OS_UNIX
if (d->directWriteFallback && err == QFileDevice::OpenError && errno == EACCES) {
delete d->fileEngine;
- d->fileEngine = QAbstractFileEngine::create(d->finalFileName);
- if (d->fileEngine->open(mode | QIODevice::Unbuffered)) {
- d->useTemporaryFile = false;
- QFileDevice::open(mode);
+ if (openDirectly())
return true;
- }
err = d->fileEngine->error();
}
#endif
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index d5460238ec..d0cbc82c56 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -1405,6 +1405,11 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
return;
}
+ if (!readOnly && !confFile->isWritable()) {
+ setStatus(QSettings::AccessError);
+ return;
+ }
+
#ifndef QT_BOOTSTRAPPED
/*
Use a lockfile in order to protect us against other QSettings instances
@@ -1414,17 +1419,11 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
Concurrent read and write are not a problem because the writing operation is atomic.
*/
QLockFile lockFile(confFile->name + QLatin1String(".lock"));
-#endif
- if (!readOnly) {
- if (!confFile->isWritable()
-#ifndef QT_BOOTSTRAPPED
- || !lockFile.lock()
-#endif
- ) {
- setStatus(QSettings::AccessError);
- return;
- }
+ if (!readOnly && !lockFile.lock() && atomicSyncOnly) {
+ setStatus(QSettings::AccessError);
+ return;
}
+#endif
/*
We hold the lock. Let's reread the file if it has changed
@@ -1496,6 +1495,7 @@ void QConfFileSettingsPrivate::syncConfFile(QConfFile *confFile)
#if !defined(QT_BOOTSTRAPPED) && QT_CONFIG(temporaryfile)
QSaveFile sf(confFile->name);
+ sf.setDirectWriteFallback(!atomicSyncOnly);
#else
QFile sf(confFile->name);
#endif
@@ -1802,6 +1802,8 @@ struct QSettingsIniSection
inline QSettingsIniSection() : position(-1) {}
};
+Q_DECLARE_TYPEINFO(QSettingsIniSection, Q_MOVABLE_TYPE);
+
typedef QMap<QString, QSettingsIniSection> IniMap;
/*
@@ -2199,10 +2201,16 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
QSettings can safely be used from different processes (which can
be different instances of your application running at the same
time or different applications altogether) to read and write to
- the same system locations. It uses advisory file locking and a
- smart merging algorithm to ensure data integrity. Note that sync()
- imports changes made by other processes (in addition to writing
- the changes from this QSettings).
+ the same system locations, provided certain conditions are met. For
+ QSettings::IniFormat, it uses advisory file locking and a smart merging
+ algorithm to ensure data integrity. The condition for that to work is that
+ the writeable configuration file must be a regular file and must reside in
+ a directory that the current user can create new, temporary files in. If
+ that is not the case, then one must use setAtomicSyncRequired() to turn the
+ safety off.
+
+ Note that sync() imports changes made by other processes (in addition to
+ writing the changes from this QSettings).
\section1 Platform-Specific Notes
@@ -2883,6 +2891,50 @@ QSettings::Status QSettings::status() const
}
/*!
+ \since 5.10
+
+ Returns \c true if QSettings is only allowed to perform atomic saving and
+ reloading (synchronization) of the settings. Returns \c false if it is
+ allowed to save the settings contents directly to the configuration file.
+
+ The default is \c true.
+
+ \sa setAtomicSyncRequired(), QSaveFile
+*/
+bool QSettings::isAtomicSyncRequired() const
+{
+ Q_D(const QSettings);
+ return d->atomicSyncOnly;
+}
+
+/*!
+ \since 5.10
+
+ Configures whether QSettings is required to perform atomic saving and
+ reloading (synchronization) of the settings. If the \a enable argument is
+ \c true (the default), sync() will only perform synchronization operations
+ that are atomic. If this is not possible, sync() will fail and status()
+ will be an error condition.
+
+ Setting this property to \c false will allow QSettings to write directly to
+ the configuration file and ignore any errors trying to lock it against
+ other processes trying to write at the same time. Because of the potential
+ for corruption, this option should be used with care, but is required in
+ certain conditions, like a QSettings::IniFormat configuration file that
+ exists in an otherwise non-writeable directory or NTFS Alternate Data
+ Streams.
+
+ See \l QSaveFile for more information on the feature.
+
+ \sa isAtomicSyncRequired(), QSaveFile
+*/
+void QSettings::setAtomicSyncRequired(bool enable)
+{
+ Q_D(QSettings);
+ d->atomicSyncOnly = enable;
+}
+
+/*!
Appends \a prefix to the current group.
The current group is automatically prepended to all keys
diff --git a/src/corelib/io/qsettings.h b/src/corelib/io/qsettings.h
index edd59026ed..da5502e5ca 100644
--- a/src/corelib/io/qsettings.h
+++ b/src/corelib/io/qsettings.h
@@ -146,6 +146,8 @@ public:
void clear();
void sync();
Status status() const;
+ bool isAtomicSyncRequired() const;
+ void setAtomicSyncRequired(bool enable);
void beginGroup(const QString &prefix);
void endGroup();
diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h
index 639605d8c4..7923c24770 100644
--- a/src/corelib/io/qsettings_p.h
+++ b/src/corelib/io/qsettings_p.h
@@ -109,6 +109,8 @@ private:
};
#endif
+Q_DECLARE_TYPEINFO(QSettingsKey, Q_MOVABLE_TYPE);
+
typedef QMap<QSettingsKey, QByteArray> UnparsedSettingsMap;
typedef QMap<QSettingsKey, QVariant> ParsedSettingsMap;
@@ -247,6 +249,7 @@ protected:
QString groupPrefix;
bool fallbacks;
bool pendingChanges;
+ bool atomicSyncOnly = true;
mutable QSettings::Status status;
};
diff --git a/src/corelib/io/qstandardpaths.cpp b/src/corelib/io/qstandardpaths.cpp
index f2368c3b23..c3d45caf0e 100644
--- a/src/corelib/io/qstandardpaths.cpp
+++ b/src/corelib/io/qstandardpaths.cpp
@@ -183,7 +183,7 @@ QT_BEGIN_NAMESPACE
\li "C:/Users/<USER>"
\row \li DataLocation
\li "~/Library/Application Support/<APPNAME>", "/Library/Application Support/<APPNAME>". "<APPDIR>/../Resources"
- \li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data"
+ \li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data", "<APPDIR>/data/<APPNAME>"
\row \li CacheLocation
\li "~/Library/Caches/<APPNAME>", "/Library/Caches/<APPNAME>"
\li "C:/Users/<USER>/AppData/Local/<APPNAME>/cache"
@@ -207,10 +207,10 @@ QT_BEGIN_NAMESPACE
\li "C:/Users/<USER>/AppData/Local/cache"
\row \li AppDataLocation
\li "~/Library/Application Support/<APPNAME>", "/Library/Application Support/<APPNAME>". "<APPDIR>/../Resources"
- \li "C:/Users/<USER>/AppData/Roaming/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data"
+ \li "C:/Users/<USER>/AppData/Roaming/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data", "<APPDIR>/data/<APPNAME>"
\row \li AppLocalDataLocation
\li "~/Library/Application Support/<APPNAME>", "/Library/Application Support/<APPNAME>". "<APPDIR>/../Resources"
- \li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data"
+ \li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>", "<APPDIR>", "<APPDIR>/data", "<APPDIR>/data/<APPNAME>"
\row \li AppConfigLocation
\li "~/Library/Preferences/<APPNAME>"
\li "C:/Users/<USER>/AppData/Local/<APPNAME>", "C:/ProgramData/<APPNAME>"
diff --git a/src/corelib/io/qstandardpaths_unix.cpp b/src/corelib/io/qstandardpaths_unix.cpp
index f0ff46fe7f..d06778e2a1 100644
--- a/src/corelib/io/qstandardpaths_unix.cpp
+++ b/src/corelib/io/qstandardpaths_unix.cpp
@@ -42,6 +42,7 @@
#include <qfile.h>
#include <qhash.h>
#include <qtextstream.h>
+#include <qregularexpression.h>
#include <private/qfilesystemengine_p.h>
#include <errno.h>
#include <stdlib.h>
@@ -179,11 +180,12 @@ QString QStandardPaths::writableLocation(StandardLocation type)
QHash<QString, QString> lines;
QTextStream stream(&file);
// Only look for lines like: XDG_DESKTOP_DIR="$HOME/Desktop"
- QRegExp exp(QLatin1String("^XDG_(.*)_DIR=(.*)$"));
+ QRegularExpression exp(QLatin1String("^XDG_(.*)_DIR=(.*)$"));
while (!stream.atEnd()) {
const QString &line = stream.readLine();
- if (exp.indexIn(line) != -1) {
- const QStringList lst = exp.capturedTexts();
+ QRegularExpressionMatch match = exp.match(line);
+ if (match.hasMatch()) {
+ const QStringList lst = match.capturedTexts();
const QString key = lst.at(1);
QString value = lst.at(2);
if (value.length() > 2
diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp
index a64bde6fb4..41fd31df8b 100644
--- a/src/corelib/io/qstandardpaths_win.cpp
+++ b/src/corelib/io/qstandardpaths_win.cpp
@@ -218,7 +218,15 @@ QStringList QStandardPaths::standardLocations(StandardLocation type)
}
#ifndef QT_BOOTSTRAPPED
dirs.append(QCoreApplication::applicationDirPath());
- dirs.append(QCoreApplication::applicationDirPath() + QLatin1String("/data"));
+ const QString dataDir = QCoreApplication::applicationDirPath() + QLatin1String("/data");
+ dirs.append(dataDir);
+
+ if (!isGenericConfigLocation(type)) {
+ QString appDataDir = dataDir;
+ appendOrganizationAndApp(appDataDir);
+ if (appDataDir != dataDir)
+ dirs.append(appDataDir);
+ }
#endif // !QT_BOOTSTRAPPED
} // isConfigLocation()
diff --git a/src/corelib/io/qstorageinfo.cpp b/src/corelib/io/qstorageinfo.cpp
index 27f0552a31..e2c1f0232f 100644
--- a/src/corelib/io/qstorageinfo.cpp
+++ b/src/corelib/io/qstorageinfo.cpp
@@ -40,6 +40,8 @@
#include "qstorageinfo.h"
#include "qstorageinfo_p.h"
+#include "qdebug.h"
+
QT_BEGIN_NAMESPACE
/*!
@@ -431,4 +433,37 @@ QStorageInfo QStorageInfo::root()
volume than the \a second; otherwise returns false.
*/
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QStorageInfo &s)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug.noquote();
+ debug << "QStorageInfo(";
+ if (s.isValid()) {
+ const QStorageInfoPrivate *d = s.d.constData();
+ debug << '"' << d->rootPath << '"';
+ if (!d->fileSystemType.isEmpty())
+ debug << ", type=" << d->fileSystemType;
+ if (!d->name.isEmpty())
+ debug << ", name=\"" << d->name << '"';
+ if (!d->device.isEmpty())
+ debug << ", device=\"" << d->device << '"';
+ if (!d->subvolume.isEmpty())
+ debug << ", subvolume=\"" << d->subvolume << '"';
+ if (d->readOnly)
+ debug << " [read only]";
+ debug << (d->ready ? " [ready]" : " [not ready]");
+ if (d->bytesTotal > 0) {
+ debug << ", bytesTotal=" << d->bytesTotal << ", bytesFree=" << d->bytesFree
+ << ", bytesAvailable=" << d->bytesAvailable;
+ }
+ } else {
+ debug << "invalid";
+ }
+ debug<< ')';
+ return debug;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
QT_END_NAMESPACE
diff --git a/src/corelib/io/qstorageinfo.h b/src/corelib/io/qstorageinfo.h
index e2d9747ceb..4ab7a353ef 100644
--- a/src/corelib/io/qstorageinfo.h
+++ b/src/corelib/io/qstorageinfo.h
@@ -49,6 +49,8 @@
QT_BEGIN_NAMESPACE
+class QDebug;
+
class QStorageInfoPrivate;
class Q_CORE_EXPORT QStorageInfo
{
@@ -94,6 +96,7 @@ public:
private:
friend class QStorageInfoPrivate;
friend bool operator==(const QStorageInfo &first, const QStorageInfo &second);
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug, const QStorageInfo &);
QExplicitlySharedDataPointer<QStorageInfoPrivate> d;
};
@@ -114,6 +117,10 @@ inline bool QStorageInfo::isRoot() const
Q_DECLARE_SHARED(QStorageInfo)
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QStorageInfo &);
+#endif
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QStorageInfo)
diff --git a/src/corelib/io/qtemporarydir.cpp b/src/corelib/io/qtemporarydir.cpp
index ffaee9c683..2779246c5b 100644
--- a/src/corelib/io/qtemporarydir.cpp
+++ b/src/corelib/io/qtemporarydir.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2017 The Qt Company Ltd.
-** Copyright (C) 2016 Intel Corporation.
+** Copyright (C) 2017 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -44,22 +44,15 @@
#include "qdiriterator.h"
#include "qplatformdefs.h"
+#include "private/qtemporaryfile_p.h"
#include <QDebug>
#include <QPair>
+#include <QRandomGenerator>
#if defined(QT_BUILD_CORE_LIB)
#include "qcoreapplication.h"
#endif
-#if !defined(Q_OS_QNX) && !defined(Q_OS_WIN) && !defined(Q_OS_ANDROID) && !defined(Q_OS_INTEGRITY)
-# define USE_SYSTEM_MKDTEMP
-#endif
-
-#include <stdlib.h> // mkdtemp
-#ifndef USE_SYSTEM_MKDTEMP
-#include <private/qfilesystemengine_p.h>
-#endif
-
#if !defined(Q_OS_WIN)
#include <errno.h>
#endif
@@ -102,38 +95,12 @@ static QString defaultTemplateName()
return QDir::tempPath() + QLatin1Char('/') + baseName + QLatin1String("-XXXXXX");
}
-#ifndef USE_SYSTEM_MKDTEMP
-static int nextRand(int &v)
-{
- int r = v % 62;
- v /= 62;
- if (v < 62)
- v = qrand();
- return r;
-}
-
-QPair<QString, bool> q_mkdtemp(QString templateName)
+void QTemporaryDirPrivate::create(const QString &templateName)
{
- Q_ASSERT(templateName.endsWith(QLatin1String("XXXXXX")));
-
- static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-
- const int length = templateName.size();
-
- QChar *XXXXXX = templateName.data() + length - 6;
-
+ QTemporaryFileName tfn(templateName);
for (int i = 0; i < 256; ++i) {
- int v = qrand();
-
- /* Fill in the random bits. */
- XXXXXX[0] = QLatin1Char(letters[nextRand(v)]);
- XXXXXX[1] = QLatin1Char(letters[nextRand(v)]);
- XXXXXX[2] = QLatin1Char(letters[nextRand(v)]);
- XXXXXX[3] = QLatin1Char(letters[nextRand(v)]);
- XXXXXX[4] = QLatin1Char(letters[nextRand(v)]);
- XXXXXX[5] = QLatin1Char(letters[v % 62]);
-
- QFileSystemEntry fileSystemEntry(templateName);
+ tfn.generateNext();
+ QFileSystemEntry fileSystemEntry(tfn.path, QFileSystemEntry::FromNativePath());
if (QFileSystemEngine::createDirectory(fileSystemEntry, false)) {
QSystemError error;
QFileSystemEngine::setPermissions(fileSystemEntry,
@@ -145,7 +112,9 @@ QPair<QString, bool> q_mkdtemp(QString templateName)
qWarning() << "Unable to remove unused directory" << templateName;
continue;
}
- return qMakePair(templateName, true);
+ success = true;
+ pathOrError = fileSystemEntry.filePath();
+ return;
}
# ifdef Q_OS_WIN
const int exists = ERROR_ALREADY_EXISTS;
@@ -155,36 +124,10 @@ QPair<QString, bool> q_mkdtemp(QString templateName)
int code = errno;
# endif
if (code != exists)
- return qMakePair(qt_error_string(code), false);
+ break;
}
- return qMakePair(qt_error_string(), false);
-}
-
-#else // !USE_SYSTEM_MKDTEMP
-
-QPair<QString, bool> q_mkdtemp(char *templateName)
-{
- bool ok = (mkdtemp(templateName) != 0);
- return qMakePair(ok ? QFile::decodeName(templateName) : qt_error_string(), ok);
-}
-
-#endif // USE_SYSTEM_MKDTEMP
-
-void QTemporaryDirPrivate::create(const QString &templateName)
-{
-#ifndef USE_SYSTEM_MKDTEMP
- QString buffer = templateName;
- if (!buffer.endsWith(QLatin1String("XXXXXX")))
- buffer += QLatin1String("XXXXXX");
- const QPair<QString, bool> result = q_mkdtemp(buffer);
-#else // !USE_SYSTEM_MKDTEMP
- QByteArray buffer = QFile::encodeName(templateName);
- if (!buffer.endsWith("XXXXXX"))
- buffer += "XXXXXX";
- QPair<QString, bool> result = q_mkdtemp(buffer.data()); // modifies buffer
-#endif // USE_SYSTEM_MKDTEMP
- pathOrError = result.first;
- success = result.second;
+ pathOrError = qt_error_string();
+ success = false;
}
//************* QTemporaryDir
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index 8a99873fee..4e8e40123c 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -39,9 +39,8 @@
#include "qtemporaryfile.h"
-#ifndef QT_NO_TEMPORARYFILE
-
#include "qplatformdefs.h"
+#include "qrandom.h"
#include "private/qtemporaryfile_p.h"
#include "private/qfile_p.h"
#include "private/qsystemerror_p.h"
@@ -53,6 +52,8 @@
#if defined(QT_BUILD_CORE_LIB)
#include "qcoreapplication.h"
+#else
+#define tr(X) QString::fromLatin1(X)
#endif
QT_BEGIN_NAMESPACE
@@ -73,82 +74,145 @@ typedef char Latin1Char;
typedef int NativeFileHandle;
#endif
-/*
- * Copyright (c) 1987, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
+QTemporaryFileName::QTemporaryFileName(const QString &templateName)
+{
+ // Ensure there is a placeholder mask
+ QString qfilename = templateName;
+ uint phPos = qfilename.length();
+ uint phLength = 0;
+
+ while (phPos != 0) {
+ --phPos;
+
+ if (qfilename[phPos] == QLatin1Char('X')) {
+ ++phLength;
+ continue;
+ }
+
+ if (phLength >= 6
+ || qfilename[phPos] == QLatin1Char('/')) {
+ ++phPos;
+ break;
+ }
+
+ // start over
+ phLength = 0;
+ }
+
+ if (phLength < 6)
+ qfilename.append(QLatin1String(".XXXXXX"));
+
+ // "Nativify" :-)
+ QFileSystemEntry::NativePath filename = QFileSystemEngine::absoluteName(
+ QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath()))
+ .nativeFilePath();
+
+ // Find mask in native path
+ phPos = filename.length();
+ phLength = 0;
+ while (phPos != 0) {
+ --phPos;
+
+ if (filename[phPos] == Latin1Char('X')) {
+ ++phLength;
+ continue;
+ }
+
+ if (phLength >= 6) {
+ ++phPos;
+ break;
+ }
+
+ // start over
+ phLength = 0;
+ }
+
+ Q_ASSERT(phLength >= 6);
+ path = filename;
+ pos = phPos;
+ length = phLength;
+}
/*!
\internal
- Generates a unique file path and returns a native handle to the open file.
- \a path is used as a template when generating unique paths, \a pos
- identifies the position of the first character that will be replaced in the
- template and \a length the number of characters that may be substituted.
- \a mode specifies the file mode bits (not used on Windows).
-
- Returns an open handle to the newly created file if successful, an invalid
- handle otherwise. In both cases, the string in \a path will be changed and
- contain the generated path name.
+ Generates a unique file path from the template \a templ and returns it.
+ The path in \c templ.path is modified.
*/
-static bool createFileFromTemplate(NativeFileHandle &file,
- QFileSystemEntry::NativePath &path, size_t pos, size_t length, quint32 mode,
- QSystemError &error)
+QFileSystemEntry::NativePath QTemporaryFileName::generateNext()
{
Q_ASSERT(length != 0);
- Q_ASSERT(pos < size_t(path.length()));
- Q_ASSERT(length <= size_t(path.length()) - pos);
+ Q_ASSERT(pos < path.length());
+ Q_ASSERT(length <= path.length() - pos);
Char *const placeholderStart = (Char *)path.data() + pos;
Char *const placeholderEnd = placeholderStart + length;
- // Initialize placeholder with random chars + PID.
+ // Replace placeholder with random chars.
{
+ // Since our dictionary is 26+26 characters, it would seem we only need
+ // a random number from 0 to 63 to select a character. However, due to
+ // the limited range, that would mean 12 (64-52) characters have double
+ // the probability of the others: 1 in 32 instead of 1 in 64.
+ //
+ // To overcome this limitation, we use more bits per character. With 10
+ // bits, there are 16 characters with probability 19/1024 and the rest
+ // at 20/1024 (i.e, less than .1% difference). This allows us to do 3
+ // characters per 32-bit random number, which is also half the typical
+ // placeholder length.
+ enum { BitsPerCharacter = 10 };
+
Char *rIter = placeholderEnd;
+ while (rIter != placeholderStart) {
+ quint32 rnd = QRandomGenerator::get32();
+ auto applyOne = [&]() {
+ quint32 v = rnd & ((1 << BitsPerCharacter) - 1);
+ rnd >>= BitsPerCharacter;
+ char ch = char((26 + 26) * v / (1 << BitsPerCharacter));
+ if (ch < 26)
+ *--rIter = Latin1Char(ch + 'A');
+ else
+ *--rIter = Latin1Char(ch - 26 + 'a');
+ };
+
+ applyOne();
+ if (rIter == placeholderStart)
+ break;
-#if defined(QT_BUILD_CORE_LIB)
- quint64 pid = quint64(QCoreApplication::applicationPid());
- do {
- *--rIter = Latin1Char((pid % 10) + '0');
- pid /= 10;
- } while (rIter != placeholderStart && pid != 0);
-#endif
+ applyOne();
+ if (rIter == placeholderStart)
+ break;
- while (rIter != placeholderStart) {
- char ch = char((qrand() & 0xffff) % (26 + 26));
- if (ch < 26)
- *--rIter = Latin1Char(ch + 'A');
- else
- *--rIter = Latin1Char(ch - 26 + 'a');
+ applyOne();
}
}
- for (;;) {
+ return path;
+}
+
+#ifndef QT_NO_TEMPORARYFILE
+
+/*!
+ \internal
+
+ Generates a unique file path from the template \a templ and creates a new
+ file based based on those parameters: the \c templ.length characters in \c
+ templ.path starting at \c templ.pos will be replacd by a random sequence of
+ characters. \a mode specifies the file mode bits (not used on Windows).
+
+ Returns true on success and sets the file handle on \a file. On error,
+ returns false, sets an invalid handle on \a handle and sets the error
+ condition in \a error. In both cases, the string in \a templ will be
+ changed and contain the generated path name.
+*/
+static bool createFileFromTemplate(NativeFileHandle &file, QTemporaryFileName &templ,
+ quint32 mode, QSystemError &error)
+{
+ const int maxAttempts = 16;
+ for (int attempt = 0; attempt < maxAttempts; ++attempt) {
// Atomically create file and obtain handle
+ const QFileSystemEntry::NativePath &path = templ.generateNext();
+
#if defined(Q_OS_WIN)
Q_UNUSED(mode);
@@ -195,42 +259,8 @@ static bool createFileFromTemplate(NativeFileHandle &file,
return false;
}
#endif
-
- /* tricky little algorwwithm for backward compatibility */
- for (Char *iter = placeholderStart;;) {
- // Character progression: [0-9] => 'a' ... 'z' => 'A' .. 'Z'
- // String progression: "ZZaiC" => "aabiC"
- switch (char(*iter)) {
- case 'Z':
- // Rollover, advance next character
- *iter = Latin1Char('a');
- if (++iter == placeholderEnd) {
- // Out of alternatives. Return file exists error, previously set.
- error = QSystemError(err, QSystemError::NativeError);
- return false;
- }
-
- continue;
-
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- *iter = Latin1Char('a');
- break;
-
- case 'z':
- // increment 'z' to 'A'
- *iter = Latin1Char('A');
- break;
-
- default:
- ++*iter;
- break;
- }
- break;
- }
}
- Q_ASSERT(false);
return false;
}
@@ -264,13 +294,6 @@ void QTemporaryFileEngine::setFileName(const QString &file)
QFSFileEngine::setFileName(file);
}
-void QTemporaryFileEngine::setFileTemplate(const QString &fileTemplate)
-{
- Q_D(QFSFileEngine);
- if (filePathIsTemplate)
- d->fileEntry = QFileSystemEntry(fileTemplate);
-}
-
bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
{
Q_D(QFSFileEngine);
@@ -281,59 +304,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
if (!filePathIsTemplate)
return QFSFileEngine::open(openMode);
- QString qfilename = d->fileEntry.filePath();
-
- // Ensure there is a placeholder mask
- uint phPos = qfilename.length();
- uint phLength = 0;
-
- while (phPos != 0) {
- --phPos;
-
- if (qfilename[phPos] == QLatin1Char('X')) {
- ++phLength;
- continue;
- }
-
- if (phLength >= 6
- || qfilename[phPos] == QLatin1Char('/')) {
- ++phPos;
- break;
- }
-
- // start over
- phLength = 0;
- }
-
- if (phLength < 6)
- qfilename.append(QLatin1String(".XXXXXX"));
-
- // "Nativify" :-)
- QFileSystemEntry::NativePath filename = QFileSystemEngine::absoluteName(
- QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath()))
- .nativeFilePath();
-
- // Find mask in native path
- phPos = filename.length();
- phLength = 0;
- while (phPos != 0) {
- --phPos;
-
- if (filename[phPos] == Latin1Char('X')) {
- ++phLength;
- continue;
- }
-
- if (phLength >= 6) {
- ++phPos;
- break;
- }
-
- // start over
- phLength = 0;
- }
-
- Q_ASSERT(phLength >= 6);
+ QTemporaryFileName tfn(templateName);
QSystemError error;
#if defined(Q_OS_WIN)
@@ -342,12 +313,12 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
NativeFileHandle &file = d->fd;
#endif
- if (!createFileFromTemplate(file, filename, phPos, phLength, fileMode, error)) {
+ if (!createFileFromTemplate(file, tfn, fileMode, error)) {
setError(QFile::OpenError, error.toString());
return false;
}
- d->fileEntry = QFileSystemEntry(filename, QFileSystemEntry::FromNativePath());
+ d->fileEntry = QFileSystemEntry(tfn.path, QFileSystemEntry::FromNativePath());
#if !defined(Q_OS_WIN) || defined(Q_OS_WINRT)
d->closeFileHandle = true;
@@ -420,7 +391,7 @@ QTemporaryFilePrivate::~QTemporaryFilePrivate()
QAbstractFileEngine *QTemporaryFilePrivate::engine() const
{
if (!fileEngine) {
- fileEngine = new QTemporaryFileEngine;
+ fileEngine = new QTemporaryFileEngine(&templateName);
resetFileEngine();
}
return fileEngine;
@@ -679,8 +650,36 @@ void QTemporaryFile::setFileTemplate(const QString &name)
{
Q_D(QTemporaryFile);
d->templateName = name;
- if (d->fileEngine)
- static_cast<QTemporaryFileEngine*>(d->fileEngine)->setFileTemplate(name);
+}
+
+/*!
+ \internal
+
+ This is just a simplified version of QFile::rename() because we know a few
+ extra details about what kind of file we have. The documentation is hidden
+ from the user because QFile::rename() should be enough.
+*/
+bool QTemporaryFile::rename(const QString &newName)
+{
+ Q_D(QTemporaryFile);
+ auto tef = static_cast<QTemporaryFileEngine *>(d->fileEngine);
+ if (!tef || !tef->isReallyOpen() || !tef->filePathWasTemplate)
+ return QFile::rename(newName);
+
+ unsetError();
+ close();
+ if (error() == QFile::NoError) {
+ if (tef->rename(newName)) {
+ unsetError();
+ // engine was able to handle the new name so we just reset it
+ tef->setFileName(newName);
+ d->fileName = newName;
+ return true;
+ }
+
+ d->setError(QFile::RenameError, tef->errorString());
+ }
+ return false;
}
/*!
@@ -792,10 +791,10 @@ bool QTemporaryFile::open(OpenMode flags)
return false;
}
-QT_END_NAMESPACE
-
#endif // QT_NO_TEMPORARYFILE
+QT_END_NAMESPACE
+
#ifndef QT_NO_QOBJECT
#include "moc_qtemporaryfile.cpp"
#endif
diff --git a/src/corelib/io/qtemporaryfile.h b/src/corelib/io/qtemporaryfile.h
index 3dc2e75f50..7fc5a299fc 100644
--- a/src/corelib/io/qtemporaryfile.h
+++ b/src/corelib/io/qtemporaryfile.h
@@ -80,6 +80,10 @@ public:
QString fileName() const Q_DECL_OVERRIDE;
QString fileTemplate() const;
void setFileTemplate(const QString &name);
+
+ // Hides QFile::rename
+ bool rename(const QString &newName);
+
#if QT_DEPRECATED_SINCE(5,1)
QT_DEPRECATED inline static QTemporaryFile *createLocalFile(const QString &fileName)
{ return createNativeFile(fileName); }
diff --git a/src/corelib/io/qtemporaryfile_p.h b/src/corelib/io/qtemporaryfile_p.h
index 7f365f0e8a..97ffc48507 100644
--- a/src/corelib/io/qtemporaryfile_p.h
+++ b/src/corelib/io/qtemporaryfile_p.h
@@ -53,19 +53,30 @@
#include <QtCore/qglobal.h>
-#ifndef QT_NO_TEMPORARYFILE
-
#include "private/qfsfileengine_p.h"
#include "private/qfilesystemengine_p.h"
#include "private/qfile_p.h"
+#include "qtemporaryfile.h"
QT_BEGIN_NAMESPACE
+struct QTemporaryFileName
+{
+ QFileSystemEntry::NativePath path;
+ qssize_t pos;
+ qssize_t length;
+
+ QTemporaryFileName(const QString &templateName);
+ QFileSystemEntry::NativePath generateNext();
+};
+
+#ifndef QT_NO_TEMPORARYFILE
+
class QTemporaryFilePrivate : public QFilePrivate
{
Q_DECLARE_PUBLIC(QTemporaryFile)
-protected:
+public:
QTemporaryFilePrivate();
explicit QTemporaryFilePrivate(const QString &templateNameIn);
~QTemporaryFilePrivate();
@@ -85,22 +96,28 @@ class QTemporaryFileEngine : public QFSFileEngine
{
Q_DECLARE_PRIVATE(QFSFileEngine)
public:
+ QTemporaryFileEngine(const QString *templateName)
+ : templateName(*templateName)
+ {}
+
void initialize(const QString &file, quint32 mode, bool nameIsTemplate = true)
{
Q_D(QFSFileEngine);
Q_ASSERT(!isReallyOpen());
fileMode = mode;
filePathIsTemplate = filePathWasTemplate = nameIsTemplate;
- d->fileEntry = QFileSystemEntry(file);
- if (!filePathIsTemplate)
+ if (filePathIsTemplate) {
+ d->fileEntry.clear();
+ } else {
+ d->fileEntry = QFileSystemEntry(file);
QFSFileEngine::setFileName(file);
+ }
}
~QTemporaryFileEngine();
bool isReallyOpen() const;
void setFileName(const QString &file) override;
- void setFileTemplate(const QString &fileTemplate);
bool open(QIODevice::OpenMode flags) override;
bool remove() override;
@@ -108,14 +125,15 @@ public:
bool renameOverwrite(const QString &newName) override;
bool close() override;
+ const QString &templateName;
quint32 fileMode;
bool filePathIsTemplate;
bool filePathWasTemplate;
};
-QT_END_NAMESPACE
-
#endif // QT_NO_TEMPORARYFILE
+QT_END_NAMESPACE
+
#endif /* QTEMPORARYFILE_P_H */
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 5144ac0ec9..ee3cb4efcb 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -954,8 +954,7 @@ QTextStreamPrivate::PaddingResult QTextStreamPrivate::padding(int len) const
right = padSize - padSize/2;
break;
}
- const PaddingResult result = { left, right };
- return result;
+ return { left, right };
}
/*!
diff --git a/src/corelib/io/qtldurl.cpp b/src/corelib/io/qtldurl.cpp
index 96543bbbfd..a934d19fa2 100644
--- a/src/corelib/io/qtldurl.cpp
+++ b/src/corelib/io/qtldurl.cpp
@@ -50,9 +50,21 @@
QT_BEGIN_NAMESPACE
-static bool containsTLDEntry(const QStringRef &entry)
+enum TLDMatchType {
+ ExactMatch,
+ SuffixMatch,
+ ExceptionMatch,
+};
+
+static bool containsTLDEntry(QStringView entry, TLDMatchType match)
{
- int index = qt_hash(entry) % tldCount;
+ const QStringView matchSymbols[] = {
+ QStringViewLiteral(""),
+ QStringViewLiteral("*"),
+ QStringViewLiteral("!"),
+ };
+ const auto symbol = matchSymbols[match];
+ int index = qt_hash(entry, qt_hash(symbol)) % tldCount;
// select the right chunk from the big table
short chunk = 0;
@@ -65,19 +77,14 @@ static bool containsTLDEntry(const QStringRef &entry)
// check all the entries from the given index
while (chunkIndex < tldIndices[index+1] - offset) {
- QString currentEntry = QString::fromUtf8(tldData[chunk] + chunkIndex);
- if (currentEntry == entry)
+ const auto utf8 = tldData[chunk] + chunkIndex;
+ if ((symbol.isEmpty() || QLatin1Char(*utf8) == symbol) && entry == QString::fromUtf8(utf8 + symbol.size()))
return true;
- chunkIndex += qstrlen(tldData[chunk] + chunkIndex) + 1; // +1 for the ending \0
+ chunkIndex += qstrlen(utf8) + 1; // +1 for the ending \0
}
return false;
}
-static inline bool containsTLDEntry(const QString &entry)
-{
- return containsTLDEntry(QStringRef(&entry));
-}
-
/*!
\internal
@@ -111,19 +118,16 @@ Q_CORE_EXPORT bool qIsEffectiveTLD(const QStringRef &domain)
{
// for domain 'foo.bar.com':
// 1. return if TLD table contains 'foo.bar.com'
- if (containsTLDEntry(domain))
+ // 2. else if table contains '*.bar.com',
+ // 3. test that table does not contain '!foo.bar.com'
+
+ if (containsTLDEntry(domain, ExactMatch)) // 1
return true;
const int dot = domain.indexOf(QLatin1Char('.'));
if (dot >= 0) {
- int count = domain.size() - dot;
- QString wildCardDomain = QLatin1Char('*') + domain.right(count);
- // 2. if table contains '*.bar.com',
- // test if table contains '!foo.bar.com'
- if (containsTLDEntry(wildCardDomain)) {
- QString exceptionDomain = QLatin1Char('!') + domain;
- return (! containsTLDEntry(exceptionDomain));
- }
+ if (containsTLDEntry(domain.mid(dot), SuffixMatch)) // 2
+ return !containsTLDEntry(domain, ExceptionMatch); // 3
}
return false;
}
diff --git a/src/corelib/io/qwindowspipereader.cpp b/src/corelib/io/qwindowspipereader.cpp
index b93fed5ba8..ef5ff2d827 100644
--- a/src/corelib/io/qwindowspipereader.cpp
+++ b/src/corelib/io/qwindowspipereader.cpp
@@ -132,17 +132,8 @@ qint64 QWindowsPipeReader::read(char *data, qint64 maxlen)
actualReadBufferSize--;
readSoFar = 1;
} else {
- qint64 bytesToRead = qMin(actualReadBufferSize, maxlen);
- readSoFar = 0;
- while (readSoFar < bytesToRead) {
- const char *ptr = readBuffer.readPointer();
- qint64 bytesToReadFromThisBlock = qMin(bytesToRead - readSoFar,
- readBuffer.nextDataBlockSize());
- memcpy(data + readSoFar, ptr, bytesToReadFromThisBlock);
- readSoFar += bytesToReadFromThisBlock;
- readBuffer.free(bytesToReadFromThisBlock);
- actualReadBufferSize -= bytesToReadFromThisBlock;
- }
+ readSoFar = readBuffer.read(data, qMin(actualReadBufferSize, maxlen));
+ actualReadBufferSize -= readSoFar;
}
if (!pipeBroken) {
diff --git a/src/corelib/io/qwindowspipewriter.cpp b/src/corelib/io/qwindowspipewriter.cpp
index 846891102f..75cb8a7ede 100644
--- a/src/corelib/io/qwindowspipewriter.cpp
+++ b/src/corelib/io/qwindowspipewriter.cpp
@@ -57,7 +57,6 @@ QWindowsPipeWriter::QWindowsPipeWriter(HANDLE pipeWriteEnd, QObject *parent)
: QObject(parent),
handle(pipeWriteEnd),
overlapped(nullptr),
- numberOfBytesToWrite(0),
pendingBytesWrittenValue(0),
stopped(true),
writeSequenceStarted(false),
@@ -98,7 +97,7 @@ bool QWindowsPipeWriter::waitForWrite(int msecs)
qint64 QWindowsPipeWriter::bytesToWrite() const
{
- return numberOfBytesToWrite + pendingBytesWrittenValue;
+ return buffer.size() + pendingBytesWrittenValue;
}
void QWindowsPipeWriter::emitPendingBytesWrittenValue()
@@ -137,7 +136,6 @@ void QWindowsPipeWriter::notified(DWORD errorCode, DWORD numberOfBytesWritten)
{
notifiedCalled = true;
writeSequenceStarted = false;
- numberOfBytesToWrite = 0;
Q_ASSERT(errorCode != ERROR_SUCCESS || numberOfBytesWritten == DWORD(buffer.size()));
buffer.clear();
@@ -193,13 +191,11 @@ bool QWindowsPipeWriter::write(const QByteArray &ba)
overlapped = new Overlapped(this);
overlapped->clear();
buffer = ba;
- numberOfBytesToWrite = buffer.size();
stopped = false;
writeSequenceStarted = true;
- if (!WriteFileEx(handle, buffer.constData(), numberOfBytesToWrite,
+ if (!WriteFileEx(handle, buffer.constData(), buffer.size(),
overlapped, &writeFileCompleted)) {
writeSequenceStarted = false;
- numberOfBytesToWrite = 0;
buffer.clear();
const DWORD errorCode = GetLastError();
diff --git a/src/corelib/io/qwindowspipewriter_p.h b/src/corelib/io/qwindowspipewriter_p.h
index c8252e2a4b..d6671c3f27 100644
--- a/src/corelib/io/qwindowspipewriter_p.h
+++ b/src/corelib/io/qwindowspipewriter_p.h
@@ -145,7 +145,6 @@ private:
HANDLE handle;
Overlapped *overlapped;
QByteArray buffer;
- qint64 numberOfBytesToWrite;
qint64 pendingBytesWrittenValue;
bool stopped;
bool writeSequenceStarted;
diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp
deleted file mode 100644
index d7745ae1b6..0000000000
--- a/src/corelib/io/qwinoverlappedionotifier.cpp
+++ /dev/null
@@ -1,428 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwinoverlappedionotifier_p.h"
-#include <qdebug.h>
-#include <qatomic.h>
-#include <qelapsedtimer.h>
-#include <qmutex.h>
-#include <qpointer.h>
-#include <qqueue.h>
-#include <qset.h>
-#include <qthread.h>
-#include <qt_windows.h>
-#include <private/qobject_p.h>
-#include <private/qiodevice_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*!
- \class QWinOverlappedIoNotifier
- \inmodule QtCore
- \brief The QWinOverlappedIoNotifier class provides support for overlapped I/O notifications on Windows.
- \since 5.0
- \internal
-
- The QWinOverlappedIoNotifier class makes it possible to use efficient
- overlapped (asynchronous) I/O notifications on Windows by using an
- I/O completion port.
-
- Once you have obtained a file handle, you can use setHandle() to get
- notifications for I/O operations. Whenever an I/O operation completes,
- the notified() signal is emitted which will pass the number of transferred
- bytes, the operation's error code and a pointer to the operation's
- OVERLAPPED object to the receiver.
-
- Every handle that supports overlapped I/O can be used by
- QWinOverlappedIoNotifier. That includes file handles, TCP sockets
- and named pipes.
-
- Note that you must not use ReadFileEx() and WriteFileEx() together
- with QWinOverlappedIoNotifier. They are not supported as they use a
- different I/O notification mechanism.
-
- The hEvent member in the OVERLAPPED structure passed to ReadFile()
- or WriteFile() is ignored and can be used for other purposes.
-
- \warning This class is only available on Windows.
-
- Due to peculiarities of the Windows I/O completion port API, users of
- QWinOverlappedIoNotifier must pay attention to the following restrictions:
- \list
- \li File handles with a QWinOverlappedIoNotifer are assigned to an I/O
- completion port until the handle is closed. It is impossible to
- disassociate the file handle from the I/O completion port.
- \li There can be only one QWinOverlappedIoNotifer per file handle. Creating
- another QWinOverlappedIoNotifier for that file, even with a duplicated
- handle, will fail.
- \li Certain Windows API functions are unavailable for file handles that are
- assigned to an I/O completion port. This includes the functions
- \c{ReadFileEx} and \c{WriteFileEx}.
- \endlist
- See also the remarks in the MSDN documentation for the
- \c{CreateIoCompletionPort} function.
-*/
-
-struct IOResult
-{
- IOResult(DWORD n = 0, DWORD e = 0, OVERLAPPED *p = 0)
- : numberOfBytes(n), errorCode(e), overlapped(p)
- {}
-
- DWORD numberOfBytes;
- DWORD errorCode;
- OVERLAPPED *overlapped;
-};
-
-
-class QWinIoCompletionPort;
-
-class QWinOverlappedIoNotifierPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QWinOverlappedIoNotifier)
-public:
- QWinOverlappedIoNotifierPrivate()
- : hHandle(INVALID_HANDLE_VALUE)
- {
- }
-
- OVERLAPPED *waitForAnyNotified(int msecs);
- void notify(DWORD numberOfBytes, DWORD errorCode, OVERLAPPED *overlapped);
- void _q_notified();
- OVERLAPPED *dispatchNextIoResult();
-
- static QWinIoCompletionPort *iocp;
- static HANDLE iocpInstanceLock;
- static unsigned int iocpInstanceRefCount;
- HANDLE hHandle;
- HANDLE hSemaphore;
- HANDLE hResultsMutex;
- QAtomicInt waiting;
- QQueue<IOResult> results;
-};
-
-QWinIoCompletionPort *QWinOverlappedIoNotifierPrivate::iocp = 0;
-HANDLE QWinOverlappedIoNotifierPrivate::iocpInstanceLock = CreateMutex(NULL, FALSE, NULL);
-unsigned int QWinOverlappedIoNotifierPrivate::iocpInstanceRefCount = 0;
-
-
-class QWinIoCompletionPort : protected QThread
-{
-public:
- QWinIoCompletionPort()
- : finishThreadKey(reinterpret_cast<ULONG_PTR>(this)),
- drainQueueKey(reinterpret_cast<ULONG_PTR>(this + 1)),
- hPort(INVALID_HANDLE_VALUE)
- {
- setObjectName(QLatin1String("I/O completion port thread"));
- HANDLE hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
- if (!hIOCP) {
- qErrnoWarning("CreateIoCompletionPort failed.");
- return;
- }
- hPort = hIOCP;
- hQueueDrainedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!hQueueDrainedEvent) {
- qErrnoWarning("CreateEvent failed.");
- return;
- }
- }
-
- ~QWinIoCompletionPort()
- {
- PostQueuedCompletionStatus(hPort, 0, finishThreadKey, NULL);
- QThread::wait();
- CloseHandle(hPort);
- CloseHandle(hQueueDrainedEvent);
- }
-
- void registerNotifier(QWinOverlappedIoNotifierPrivate *notifier)
- {
- const HANDLE hHandle = notifier->hHandle;
- HANDLE hIOCP = CreateIoCompletionPort(hHandle, hPort,
- reinterpret_cast<ULONG_PTR>(notifier), 0);
- if (!hIOCP) {
- qErrnoWarning("Can't associate file handle %x with I/O completion port.", hHandle);
- return;
- }
- mutex.lock();
- notifiers += notifier;
- mutex.unlock();
- if (!QThread::isRunning())
- QThread::start();
- }
-
- void unregisterNotifier(QWinOverlappedIoNotifierPrivate *notifier)
- {
- mutex.lock();
- notifiers.remove(notifier);
- mutex.unlock();
- }
-
- void drainQueue()
- {
- QMutexLocker locker(&drainQueueMutex);
- ResetEvent(hQueueDrainedEvent);
- PostQueuedCompletionStatus(hPort, 0, drainQueueKey, NULL);
- WaitForSingleObject(hQueueDrainedEvent, INFINITE);
- }
-
- using QThread::isRunning;
-
-protected:
- void run()
- {
- DWORD dwBytesRead;
- ULONG_PTR pulCompletionKey;
- OVERLAPPED *overlapped;
- DWORD msecs = INFINITE;
-
- forever {
- BOOL success = GetQueuedCompletionStatus(hPort,
- &dwBytesRead,
- &pulCompletionKey,
- &overlapped,
- msecs);
-
- DWORD errorCode = success ? ERROR_SUCCESS : GetLastError();
- if (!success && !overlapped) {
- if (!msecs) {
- // Time out in drain mode. The completion status queue is empty.
- msecs = INFINITE;
- SetEvent(hQueueDrainedEvent);
- continue;
- }
- qErrnoWarning(errorCode, "GetQueuedCompletionStatus failed.");
- return;
- }
-
- if (pulCompletionKey == finishThreadKey)
- return;
- if (pulCompletionKey == drainQueueKey) {
- // Enter drain mode.
- Q_ASSERT(msecs == INFINITE);
- msecs = 0;
- continue;
- }
-
- QWinOverlappedIoNotifierPrivate *notifier
- = reinterpret_cast<QWinOverlappedIoNotifierPrivate *>(pulCompletionKey);
- mutex.lock();
- if (notifiers.contains(notifier))
- notifier->notify(dwBytesRead, errorCode, overlapped);
- mutex.unlock();
- }
- }
-
-private:
- const ULONG_PTR finishThreadKey;
- const ULONG_PTR drainQueueKey;
- HANDLE hPort;
- QSet<QWinOverlappedIoNotifierPrivate *> notifiers;
- QMutex mutex;
- QMutex drainQueueMutex;
- HANDLE hQueueDrainedEvent;
-};
-
-
-QWinOverlappedIoNotifier::QWinOverlappedIoNotifier(QObject *parent)
- : QObject(*new QWinOverlappedIoNotifierPrivate, parent)
-{
- Q_D(QWinOverlappedIoNotifier);
- WaitForSingleObject(d->iocpInstanceLock, INFINITE);
- if (!d->iocp)
- d->iocp = new QWinIoCompletionPort;
- d->iocpInstanceRefCount++;
- ReleaseMutex(d->iocpInstanceLock);
-
- d->hSemaphore = CreateSemaphore(NULL, 0, 255, NULL);
- d->hResultsMutex = CreateMutex(NULL, FALSE, NULL);
- connect(this, SIGNAL(_q_notify()), this, SLOT(_q_notified()), Qt::QueuedConnection);
-}
-
-QWinOverlappedIoNotifier::~QWinOverlappedIoNotifier()
-{
- Q_D(QWinOverlappedIoNotifier);
- setEnabled(false);
- CloseHandle(d->hResultsMutex);
- CloseHandle(d->hSemaphore);
-
- WaitForSingleObject(d->iocpInstanceLock, INFINITE);
- if (!--d->iocpInstanceRefCount) {
- delete d->iocp;
- d->iocp = 0;
- }
- ReleaseMutex(d->iocpInstanceLock);
-}
-
-void QWinOverlappedIoNotifier::setHandle(Qt::HANDLE h)
-{
- Q_D(QWinOverlappedIoNotifier);
- d->hHandle = h;
-}
-
-Qt::HANDLE QWinOverlappedIoNotifier::handle() const
-{
- Q_D(const QWinOverlappedIoNotifier);
- return d->hHandle;
-}
-
-void QWinOverlappedIoNotifier::setEnabled(bool enabled)
-{
- Q_D(QWinOverlappedIoNotifier);
- if (enabled)
- d->iocp->registerNotifier(d);
- else
- d->iocp->unregisterNotifier(d);
-}
-
-OVERLAPPED *QWinOverlappedIoNotifierPrivate::waitForAnyNotified(int msecs)
-{
- if (!iocp->isRunning()) {
- qWarning("Called QWinOverlappedIoNotifier::waitForAnyNotified on inactive notifier.");
- return 0;
- }
-
- if (msecs == 0)
- iocp->drainQueue();
-
- const DWORD wfso = WaitForSingleObject(hSemaphore, msecs == -1 ? INFINITE : DWORD(msecs));
- switch (wfso) {
- case WAIT_OBJECT_0:
- return dispatchNextIoResult();
- case WAIT_TIMEOUT:
- return 0;
- default:
- qErrnoWarning("QWinOverlappedIoNotifier::waitForAnyNotified: WaitForSingleObject failed.");
- return 0;
- }
-}
-
-class QScopedAtomicIntIncrementor
-{
-public:
- QScopedAtomicIntIncrementor(QAtomicInt &i)
- : m_int(i)
- {
- ++m_int;
- }
-
- ~QScopedAtomicIntIncrementor()
- {
- --m_int;
- }
-
-private:
- QAtomicInt &m_int;
-};
-
-/*!
- * Wait synchronously for any notified signal.
- *
- * The function returns a pointer to the OVERLAPPED object corresponding to the completed I/O
- * operation. In case no I/O operation was completed during the \a msec timeout, this function
- * returns a null pointer.
- */
-OVERLAPPED *QWinOverlappedIoNotifier::waitForAnyNotified(int msecs)
-{
- Q_D(QWinOverlappedIoNotifier);
- QScopedAtomicIntIncrementor saii(d->waiting);
- OVERLAPPED *result = d->waitForAnyNotified(msecs);
- return result;
-}
-
-/*!
- * Wait synchronously for the notified signal.
- *
- * The function returns true if the notified signal was emitted for
- * the I/O operation that corresponds to the OVERLAPPED object.
- */
-bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped)
-{
- Q_D(QWinOverlappedIoNotifier);
- QScopedAtomicIntIncrementor saii(d->waiting);
- int t = msecs;
- QElapsedTimer stopWatch;
- stopWatch.start();
- forever {
- OVERLAPPED *triggeredOverlapped = waitForAnyNotified(t);
- if (!triggeredOverlapped)
- return false;
- if (triggeredOverlapped == overlapped)
- return true;
- t = qt_subtract_from_timeout(msecs, stopWatch.elapsed());
- if (t == 0)
- return false;
- }
-}
-
-/*!
- * Note: This function runs in the I/O completion port thread.
- */
-void QWinOverlappedIoNotifierPrivate::notify(DWORD numberOfBytes, DWORD errorCode,
- OVERLAPPED *overlapped)
-{
- Q_Q(QWinOverlappedIoNotifier);
- WaitForSingleObject(hResultsMutex, INFINITE);
- results.enqueue(IOResult(numberOfBytes, errorCode, overlapped));
- ReleaseMutex(hResultsMutex);
- ReleaseSemaphore(hSemaphore, 1, NULL);
- if (!waiting)
- emit q->_q_notify();
-}
-
-void QWinOverlappedIoNotifierPrivate::_q_notified()
-{
- if (WaitForSingleObject(hSemaphore, 0) == WAIT_OBJECT_0)
- dispatchNextIoResult();
-}
-
-OVERLAPPED *QWinOverlappedIoNotifierPrivate::dispatchNextIoResult()
-{
- Q_Q(QWinOverlappedIoNotifier);
- WaitForSingleObject(hResultsMutex, INFINITE);
- IOResult ioresult = results.dequeue();
- ReleaseMutex(hResultsMutex);
- emit q->notified(ioresult.numberOfBytes, ioresult.errorCode, ioresult.overlapped);
- return ioresult.overlapped;
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qwinoverlappedionotifier_p.cpp"
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 226a2401e1..ef3281df30 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -56,6 +56,15 @@ QT_BEGIN_NAMESPACE
typedef QVector<QPair<QModelIndex, QPersistentModelIndex> > QModelIndexPairList;
+struct QSortFilterProxyModelDataChanged
+{
+ QSortFilterProxyModelDataChanged(const QModelIndex &tl, const QModelIndex &br)
+ : topLeft(tl), bottomRight(br) { }
+
+ QModelIndex topLeft;
+ QModelIndex bottomRight;
+};
+
static inline QSet<int> qVectorToSet(const QVector<int> &vector)
{
QSet<int> set;
@@ -164,9 +173,12 @@ public:
bool sort_localeaware;
int filter_column;
- QRegExp filter_regexp;
int filter_role;
+ QRegExp filter_regexp;
+ QModelIndex last_top_source;
+ bool filter_recursive;
+ bool complete_insert;
bool dynamic_sortfilter;
QRowsRemoval itemsBeingRemoved;
@@ -289,6 +301,11 @@ public:
Qt::Orientation orient, int start, int end, int delta_item_count, bool remove);
virtual void _q_sourceModelDestroyed() Q_DECL_OVERRIDE;
+
+ bool needsReorder(const QVector<int> &source_rows, const QModelIndex &source_parent) const;
+
+ bool filterAcceptsRowInternal(int source_row, const QModelIndex &source_parent) const;
+ bool filterRecursiveAcceptsRow(int source_row, const QModelIndex &source_parent) const;
};
typedef QHash<QModelIndex, QSortFilterProxyModelPrivate::Mapping *> IndexMap;
@@ -300,6 +317,32 @@ void QSortFilterProxyModelPrivate::_q_sourceModelDestroyed()
source_index_mapping.clear();
}
+bool QSortFilterProxyModelPrivate::filterAcceptsRowInternal(int source_row, const QModelIndex &source_parent) const
+{
+ Q_Q(const QSortFilterProxyModel);
+ return filter_recursive
+ ? filterRecursiveAcceptsRow(source_row, source_parent)
+ : q->filterAcceptsRow(source_row, source_parent);
+}
+
+bool QSortFilterProxyModelPrivate::filterRecursiveAcceptsRow(int source_row, const QModelIndex &source_parent) const
+{
+ Q_Q(const QSortFilterProxyModel);
+
+ if (q->filterAcceptsRow(source_row, source_parent))
+ return true;
+
+ const QModelIndex index = model->index(source_row, 0, source_parent);
+ const int count = model->rowCount(index);
+
+ for (int i = 0; i < count; ++i) {
+ if (filterRecursiveAcceptsRow(i, index))
+ return true;
+ }
+
+ return false;
+}
+
void QSortFilterProxyModelPrivate::remove_from_mapping(const QModelIndex &source_parent)
{
if (Mapping *m = source_index_mapping.take(source_parent)) {
@@ -340,7 +383,7 @@ IndexMap::const_iterator QSortFilterProxyModelPrivate::create_mapping(
int source_rows = model->rowCount(source_parent);
m->source_rows.reserve(source_rows);
for (int i = 0; i < source_rows; ++i) {
- if (q->filterAcceptsRow(i, source_parent))
+ if (filterAcceptsRowInternal(i, source_parent))
m->source_rows.append(i);
}
int source_cols = model->columnCount(source_parent);
@@ -794,7 +837,7 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
QVector<int> source_items;
for (int i = start; i <= end; ++i) {
if ((orient == Qt::Vertical)
- ? q->filterAcceptsRow(i, source_parent)
+ ? filterAcceptsRowInternal(i, source_parent)
: q->filterAcceptsColumn(i, source_parent)) {
source_items.append(i);
}
@@ -814,7 +857,7 @@ void QSortFilterProxyModelPrivate::source_items_inserted(
orthogonal_source_to_proxy.resize(ortho_end);
for (int ortho_item = 0; ortho_item < ortho_end; ++ortho_item) {
- if ((orient == Qt::Horizontal) ? q->filterAcceptsRow(ortho_item, source_parent)
+ if ((orient == Qt::Horizontal) ? filterAcceptsRowInternal(ortho_item, source_parent)
: q->filterAcceptsColumn(ortho_item, source_parent)) {
orthogonal_proxy_to_source.append(ortho_item);
}
@@ -969,12 +1012,7 @@ void QSortFilterProxyModelPrivate::updateChildrenMapping(const QModelIndex &sour
// reinsert moved, mapped indexes
QVector<QPair<QModelIndex, Mapping*> >::iterator it = moved_source_index_mappings.begin();
for (; it != moved_source_index_mappings.end(); ++it) {
-#ifdef QT_STRICT_ITERATORS
- source_index_mapping.insert((*it).first, (*it).second);
- (*it).second->map_iter = source_index_mapping.constFind((*it).first);
-#else
- (*it).second->map_iter = source_index_mapping.insert((*it).first, (*it).second);
-#endif
+ (*it).second->map_iter = QHash<QModelIndex, Mapping *>::const_iterator(source_index_mapping.insert((*it).first, (*it).second));
}
}
@@ -1125,7 +1163,7 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
for (int i = 0; i < proxy_to_source.count(); ++i) {
const int source_item = proxy_to_source.at(i);
if ((orient == Qt::Vertical)
- ? !q->filterAcceptsRow(source_item, source_parent)
+ ? !filterAcceptsRowInternal(source_item, source_parent)
: !q->filterAcceptsColumn(source_item, source_parent)) {
// This source item does not satisfy the filter, so it must be removed
source_items_remove.append(source_item);
@@ -1137,7 +1175,7 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
for (int source_item = 0; source_item < source_count; ++source_item) {
if (source_to_proxy.at(source_item) == -1) {
if ((orient == Qt::Vertical)
- ? q->filterAcceptsRow(source_item, source_parent)
+ ? filterAcceptsRowInternal(source_item, source_parent)
: q->filterAcceptsColumn(source_item, source_parent)) {
// This source item satisfies the filter, so it must be added
source_items_insert.append(source_item);
@@ -1156,6 +1194,33 @@ QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
return qVectorToSet(source_items_remove);
}
+bool QSortFilterProxyModelPrivate::needsReorder(const QVector<int> &source_rows, const QModelIndex &source_parent) const
+{
+ Q_Q(const QSortFilterProxyModel);
+ Q_ASSERT(source_sort_column != -1);
+ const int proxyRowCount = q->rowCount(source_to_proxy(source_parent));
+ // If any modified proxy row no longer passes lessThan(previous, current) or lessThan(current, next) then we need to reorder.
+ return std::any_of(source_rows.begin(), source_rows.end(),
+ [this, q, proxyRowCount, source_parent](int sourceRow) -> bool {
+ const QModelIndex sourceIndex = model->index(sourceRow, source_sort_column, source_parent);
+ const QModelIndex proxyIndex = source_to_proxy(sourceIndex);
+ Q_ASSERT(proxyIndex.isValid()); // caller ensured source_rows were not filtered out
+ if (proxyIndex.row() > 0) {
+ const QModelIndex prevProxyIndex = q->sibling(proxyIndex.row() - 1, proxy_sort_column, proxyIndex);
+ const QModelIndex prevSourceIndex = proxy_to_source(prevProxyIndex);
+ if (sort_order == Qt::AscendingOrder ? q->lessThan(sourceIndex, prevSourceIndex) : q->lessThan(prevSourceIndex, sourceIndex))
+ return true;
+ }
+ if (proxyIndex.row() < proxyRowCount - 1) {
+ const QModelIndex nextProxyIndex = q->sibling(proxyIndex.row() + 1, proxy_sort_column, proxyIndex);
+ const QModelIndex nextSourceIndex = proxy_to_source(nextProxyIndex);
+ if (sort_order == Qt::AscendingOrder ? q->lessThan(nextSourceIndex, sourceIndex) : q->lessThan(sourceIndex, nextSourceIndex))
+ return true;
+ }
+ return false;
+ });
+}
+
void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &source_top_left,
const QModelIndex &source_bottom_right,
const QVector<int> &roles)
@@ -1163,106 +1228,127 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
Q_Q(QSortFilterProxyModel);
if (!source_top_left.isValid() || !source_bottom_right.isValid())
return;
- QModelIndex source_parent = source_top_left.parent();
- IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
- if (it == source_index_mapping.constEnd()) {
- // Don't care, since we don't have mapping for this index
- return;
+
+ std::vector<QSortFilterProxyModelDataChanged> data_changed_list;
+ data_changed_list.emplace_back(source_top_left, source_bottom_right);
+
+ // Do check parents if the filter role have changed and we are recursive
+ if (filter_recursive && (roles.isEmpty() || roles.contains(filter_role))) {
+ QModelIndex source_parent = source_top_left.parent();
+
+ while (source_parent.isValid()) {
+ data_changed_list.emplace_back(source_parent, source_parent);
+ source_parent = source_parent.parent();
+ }
}
- Mapping *m = it.value();
- // Figure out how the source changes affect us
- QVector<int> source_rows_remove;
- QVector<int> source_rows_insert;
- QVector<int> source_rows_change;
- QVector<int> source_rows_resort;
- int end = qMin(source_bottom_right.row(), m->proxy_rows.count() - 1);
- for (int source_row = source_top_left.row(); source_row <= end; ++source_row) {
- if (dynamic_sortfilter) {
- if (m->proxy_rows.at(source_row) != -1) {
- if (!q->filterAcceptsRow(source_row, source_parent)) {
- // This source row no longer satisfies the filter, so it must be removed
- source_rows_remove.append(source_row);
- } else if (source_sort_column >= source_top_left.column() && source_sort_column <= source_bottom_right.column()) {
- // This source row has changed in a way that may affect sorted order
- source_rows_resort.append(source_row);
+ for (const QSortFilterProxyModelDataChanged &data_changed : data_changed_list) {
+ const QModelIndex &source_top_left = data_changed.topLeft;
+ const QModelIndex &source_bottom_right = data_changed.bottomRight;
+ const QModelIndex source_parent = source_top_left.parent();
+
+ IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
+ if (it == source_index_mapping.constEnd()) {
+ // Don't care, since we don't have mapping for this index
+ continue;
+ }
+ Mapping *m = it.value();
+
+ // Figure out how the source changes affect us
+ QVector<int> source_rows_remove;
+ QVector<int> source_rows_insert;
+ QVector<int> source_rows_change;
+ QVector<int> source_rows_resort;
+ int end = qMin(source_bottom_right.row(), m->proxy_rows.count() - 1);
+ for (int source_row = source_top_left.row(); source_row <= end; ++source_row) {
+ if (dynamic_sortfilter) {
+ if (m->proxy_rows.at(source_row) != -1) {
+ if (!filterAcceptsRowInternal(source_row, source_parent)) {
+ // This source row no longer satisfies the filter, so it must be removed
+ source_rows_remove.append(source_row);
+ } else if (source_sort_column >= source_top_left.column() && source_sort_column <= source_bottom_right.column()) {
+ // This source row has changed in a way that may affect sorted order
+ source_rows_resort.append(source_row);
+ } else {
+ // This row has simply changed, without affecting filtering nor sorting
+ source_rows_change.append(source_row);
+ }
} else {
- // This row has simply changed, without affecting filtering nor sorting
- source_rows_change.append(source_row);
+ if (!itemsBeingRemoved.contains(source_parent, source_row) && filterAcceptsRowInternal(source_row, source_parent)) {
+ // This source row now satisfies the filter, so it must be added
+ source_rows_insert.append(source_row);
+ }
}
} else {
- if (!itemsBeingRemoved.contains(source_parent, source_row) && q->filterAcceptsRow(source_row, source_parent)) {
- // This source row now satisfies the filter, so it must be added
- source_rows_insert.append(source_row);
+ if (m->proxy_rows.at(source_row) != -1)
+ source_rows_change.append(source_row);
+ }
+ }
+
+ if (!source_rows_remove.isEmpty()) {
+ remove_source_items(m->proxy_rows, m->source_rows,
+ source_rows_remove, source_parent, Qt::Vertical);
+ QSet<int> source_rows_remove_set = qVectorToSet(source_rows_remove);
+ QVector<QModelIndex>::iterator childIt = m->mapped_children.end();
+ while (childIt != m->mapped_children.begin()) {
+ --childIt;
+ const QModelIndex source_child_index = *childIt;
+ if (source_rows_remove_set.contains(source_child_index.row())) {
+ childIt = m->mapped_children.erase(childIt);
+ remove_from_mapping(source_child_index);
}
}
- } else {
- if (m->proxy_rows.at(source_row) != -1)
- source_rows_change.append(source_row);
}
- }
- if (!source_rows_remove.isEmpty()) {
- remove_source_items(m->proxy_rows, m->source_rows,
- source_rows_remove, source_parent, Qt::Vertical);
- QSet<int> source_rows_remove_set = qVectorToSet(source_rows_remove);
- QVector<QModelIndex>::iterator childIt = m->mapped_children.end();
- while (childIt != m->mapped_children.begin()) {
- --childIt;
- const QModelIndex source_child_index = *childIt;
- if (source_rows_remove_set.contains(source_child_index.row())) {
- childIt = m->mapped_children.erase(childIt);
- remove_from_mapping(source_child_index);
+ if (!source_rows_resort.isEmpty()) {
+ if (needsReorder(source_rows_resort, source_parent)) {
+ // Re-sort the rows of this level
+ QList<QPersistentModelIndex> parents;
+ parents << q->mapFromSource(source_parent);
+ emit q->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint);
+ QModelIndexPairList source_indexes = store_persistent_indexes();
+ remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
+ source_parent, Qt::Vertical, false);
+ sort_source_rows(source_rows_resort, source_parent);
+ insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
+ source_parent, Qt::Vertical, false);
+ update_persistent_indexes(source_indexes);
+ emit q->layoutChanged(parents, QAbstractItemModel::VerticalSortHint);
}
+ // Make sure we also emit dataChanged for the rows
+ source_rows_change += source_rows_resort;
}
- }
- if (!source_rows_resort.isEmpty()) {
- // Re-sort the rows of this level
- QList<QPersistentModelIndex> parents;
- parents << q->mapFromSource(source_parent);
- emit q->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint);
- QModelIndexPairList source_indexes = store_persistent_indexes();
- remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
- source_parent, Qt::Vertical, false);
- sort_source_rows(source_rows_resort, source_parent);
- insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
- source_parent, Qt::Vertical, false);
- update_persistent_indexes(source_indexes);
- emit q->layoutChanged(parents, QAbstractItemModel::VerticalSortHint);
- // Make sure we also emit dataChanged for the rows
- source_rows_change += source_rows_resort;
- }
-
- if (!source_rows_change.isEmpty()) {
- // Find the proxy row range
- int proxy_start_row;
- int proxy_end_row;
- proxy_item_range(m->proxy_rows, source_rows_change,
- proxy_start_row, proxy_end_row);
- // ### Find the proxy column range also
- if (proxy_end_row >= 0) {
- // the row was accepted, but some columns might still be filtered out
- int source_left_column = source_top_left.column();
- while (source_left_column < source_bottom_right.column()
- && m->proxy_columns.at(source_left_column) == -1)
- ++source_left_column;
- const QModelIndex proxy_top_left = create_index(
- proxy_start_row, m->proxy_columns.at(source_left_column), it);
- int source_right_column = source_bottom_right.column();
- while (source_right_column > source_top_left.column()
- && m->proxy_columns.at(source_right_column) == -1)
- --source_right_column;
- const QModelIndex proxy_bottom_right = create_index(
- proxy_end_row, m->proxy_columns.at(source_right_column), it);
- emit q->dataChanged(proxy_top_left, proxy_bottom_right, roles);
+ if (!source_rows_change.isEmpty()) {
+ // Find the proxy row range
+ int proxy_start_row;
+ int proxy_end_row;
+ proxy_item_range(m->proxy_rows, source_rows_change,
+ proxy_start_row, proxy_end_row);
+ // ### Find the proxy column range also
+ if (proxy_end_row >= 0) {
+ // the row was accepted, but some columns might still be filtered out
+ int source_left_column = source_top_left.column();
+ while (source_left_column < source_bottom_right.column()
+ && m->proxy_columns.at(source_left_column) == -1)
+ ++source_left_column;
+ const QModelIndex proxy_top_left = create_index(
+ proxy_start_row, m->proxy_columns.at(source_left_column), it);
+ int source_right_column = source_bottom_right.column();
+ while (source_right_column > source_top_left.column()
+ && m->proxy_columns.at(source_right_column) == -1)
+ --source_right_column;
+ const QModelIndex proxy_bottom_right = create_index(
+ proxy_end_row, m->proxy_columns.at(source_right_column), it);
+ emit q->dataChanged(proxy_top_left, proxy_bottom_right, roles);
+ }
}
- }
- if (!source_rows_insert.isEmpty()) {
- sort_source_rows(source_rows_insert, source_parent);
- insert_source_items(m->proxy_rows, m->source_rows,
- source_rows_insert, source_parent, Qt::Vertical);
+ if (!source_rows_insert.isEmpty()) {
+ sort_source_rows(source_rows_insert, source_parent);
+ insert_source_items(m->proxy_rows, m->source_rows,
+ source_rows_insert, source_parent, Qt::Vertical);
+ }
}
}
@@ -1322,7 +1408,7 @@ void QSortFilterProxyModelPrivate::_q_sourceReset()
// All internal structures are deleted in clear()
q->endResetModel();
update_source_sort_column();
- if (dynamic_sortfilter)
+ if (dynamic_sortfilter && update_source_sort_column())
sort();
}
@@ -1386,18 +1472,60 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeInserted(
{
Q_UNUSED(start);
Q_UNUSED(end);
+
+ const bool toplevel = !source_parent.isValid();
+ const bool recursive_accepted = filter_recursive && !toplevel && filterAcceptsRowInternal(source_parent.row(), source_parent.parent());
//Force the creation of a mapping now, even if its empty.
//We need it because the proxy can be acessed at the moment it emits rowsAboutToBeInserted in insert_source_items
- if (can_create_mapping(source_parent))
- create_mapping(source_parent);
+ if (!filter_recursive || toplevel || recursive_accepted) {
+ if (can_create_mapping(source_parent))
+ create_mapping(source_parent);
+ if (filter_recursive)
+ complete_insert = true;
+ } else {
+ // The row could have been rejected or the parent might be not yet known... let's try to discover it
+ QModelIndex top_source_parent = source_parent;
+ QModelIndex parent = source_parent.parent();
+ QModelIndex grandParent = parent.parent();
+
+ while (parent.isValid() && !filterAcceptsRowInternal(parent.row(), grandParent)) {
+ top_source_parent = parent;
+ parent = grandParent;
+ grandParent = parent.parent();
+ }
+
+ last_top_source = top_source_parent;
+ }
}
void QSortFilterProxyModelPrivate::_q_sourceRowsInserted(
const QModelIndex &source_parent, int start, int end)
{
- source_items_inserted(source_parent, start, end, Qt::Vertical);
- if (update_source_sort_column() && dynamic_sortfilter) //previous call to update_source_sort_column may fail if the model has no column.
- sort(); // now it should succeed so we need to make sure to sort again
+ if (!filter_recursive || complete_insert) {
+ if (filter_recursive)
+ complete_insert = false;
+ source_items_inserted(source_parent, start, end, Qt::Vertical);
+ if (update_source_sort_column() && dynamic_sortfilter) //previous call to update_source_sort_column may fail if the model has no column.
+ sort(); // now it should succeed so we need to make sure to sort again
+ return;
+ }
+
+ if (filter_recursive) {
+ bool accept = false;
+
+ for (int row = start; row <= end; ++row) {
+ if (filterAcceptsRowInternal(row, source_parent)) {
+ accept = true;
+ break;
+ }
+ }
+
+ if (!accept) // the new rows have no descendants that match the filter, filter them out.
+ return;
+
+ // last_top_source should now become visible
+ _q_sourceDataChanged(last_top_source, last_top_source, QVector<int>());
+ }
}
void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeRemoved(
@@ -1413,6 +1541,27 @@ void QSortFilterProxyModelPrivate::_q_sourceRowsRemoved(
{
itemsBeingRemoved = QRowsRemoval();
source_items_removed(source_parent, start, end, Qt::Vertical);
+
+ if (filter_recursive) {
+ // Find out if removing this visible row means that some ascendant
+ // row can now be hidden.
+ // We go up until we find a row that should still be visible
+ // and then make QSFPM re-evaluate the last one we saw before that, to hide it.
+
+ QModelIndex to_hide;
+ QModelIndex source_ascendant = source_parent;
+
+ while (source_ascendant.isValid()) {
+ if (filterAcceptsRowInternal(source_ascendant.row(), source_ascendant.parent()))
+ break;
+
+ to_hide = source_ascendant;
+ source_ascendant = source_ascendant.parent();
+ }
+
+ if (to_hide.isValid())
+ _q_sourceDataChanged(to_hide, to_hide, QVector<int>());
+ }
}
void QSortFilterProxyModelPrivate::_q_sourceRowsAboutToBeMoved(
@@ -1685,7 +1834,9 @@ QSortFilterProxyModel::QSortFilterProxyModel(QObject *parent)
d->sort_localeaware = false;
d->filter_column = 0;
d->filter_role = Qt::DisplayRole;
+ d->filter_recursive = false;
d->dynamic_sortfilter = true;
+ d->complete_insert = false;
connect(this, SIGNAL(modelReset()), this, SLOT(_q_clearMapping()));
}
@@ -2506,6 +2657,32 @@ void QSortFilterProxyModel::setFilterRole(int role)
}
/*!
+ \since 5.9
+ \property QSortFilterProxyModel::recursiveFiltering
+ \brief whether the filter to be applied recursively on children, and for
+ any matching child, its parents will be visible as well.
+
+ The default value is false.
+
+ \sa filterAcceptsRow()
+*/
+bool QSortFilterProxyModel::recursiveFiltering() const
+{
+ Q_D(const QSortFilterProxyModel);
+ return d->filter_recursive;
+}
+
+void QSortFilterProxyModel::setRecursiveFiltering(bool recursive)
+{
+ Q_D(QSortFilterProxyModel);
+ if (d->filter_recursive == recursive)
+ return;
+ d->filter_about_to_be_changed();
+ d->filter_recursive = recursive;
+ d->filter_changed();
+}
+
+/*!
\obsolete
This function is obsolete. Use invalidate() instead.
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.h b/src/corelib/itemmodels/qsortfilterproxymodel.h
index 06ff79ef5f..6f2e9806ed 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.h
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.h
@@ -67,6 +67,7 @@ class Q_CORE_EXPORT QSortFilterProxyModel : public QAbstractProxyModel
Q_PROPERTY(bool isSortLocaleAware READ isSortLocaleAware WRITE setSortLocaleAware)
Q_PROPERTY(int sortRole READ sortRole WRITE setSortRole)
Q_PROPERTY(int filterRole READ filterRole WRITE setFilterRole)
+ Q_PROPERTY(bool recursiveFiltering READ recursiveFiltering WRITE setRecursiveFiltering)
public:
explicit QSortFilterProxyModel(QObject *parent = Q_NULLPTR);
@@ -107,6 +108,9 @@ public:
int filterRole() const;
void setFilterRole(int role);
+ bool recursiveFiltering() const;
+ void setRecursiveFiltering(bool recursive);
+
public Q_SLOTS:
void setFilterRegExp(const QString &pattern);
void setFilterWildcard(const QString &pattern);
diff --git a/src/corelib/itemmodels/qstringlistmodel.cpp b/src/corelib/itemmodels/qstringlistmodel.cpp
index 2b47d43469..bcfd88fb19 100644
--- a/src/corelib/itemmodels/qstringlistmodel.cpp
+++ b/src/corelib/itemmodels/qstringlistmodel.cpp
@@ -131,7 +131,7 @@ int QStringListModel::rowCount(const QModelIndex &parent) const
*/
QModelIndex QStringListModel::sibling(int row, int column, const QModelIndex &idx) const
{
- if (!idx.isValid() || column != 0 || row >= lst.count())
+ if (!idx.isValid() || column != 0 || row >= lst.count() || row < 0)
return QModelIndex();
return createIndex(row, 0);
diff --git a/src/corelib/json/qjson.cpp b/src/corelib/json/qjson.cpp
index d509349a51..e4bca3bcd0 100644
--- a/src/corelib/json/qjson.cpp
+++ b/src/corelib/json/qjson.cpp
@@ -45,15 +45,8 @@ QT_BEGIN_NAMESPACE
namespace QJsonPrivate
{
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
-#define Q_TO_LITTLE_ENDIAN(x) (x)
-#else
-#define Q_TO_LITTLE_ENDIAN(x) ( ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x & 0xff0000) >> 8) | ((x & 0xff000000) >> 24) )
-#endif
-
-static const Base emptyArray = { { Q_TO_LITTLE_ENDIAN(sizeof(Base)) }, { 0 }, { 0 } };
-static const Base emptyObject = { { Q_TO_LITTLE_ENDIAN(sizeof(Base)) }, { 0 }, { 0 } };
-
+static Q_CONSTEXPR Base emptyArray = { { qle_uint(sizeof(Base)) }, { 0 }, { qle_uint(0) } };
+static Q_CONSTEXPR Base emptyObject = { { qle_uint(sizeof(Base)) }, { 0 }, { qle_uint(0) } };
void Data::compact()
{
@@ -394,7 +387,7 @@ int Value::requiredStorage(QJsonValue &v, bool *compressed)
v.d->compact();
v.base = static_cast<QJsonPrivate::Base *>(v.d->header->root());
}
- return v.base ? v.base->size : sizeof(QJsonPrivate::Base);
+ return v.base ? uint(v.base->size) : sizeof(QJsonPrivate::Base);
case QJsonValue::Undefined:
case QJsonValue::Null:
case QJsonValue::Bool:
diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h
index c012ec2662..131528376b 100644
--- a/src/corelib/json/qjson_p.h
+++ b/src/corelib/json/qjson_p.h
@@ -61,6 +61,7 @@
#include <qendian.h>
#include <qnumeric.h>
+#include "private/qendian_p.h"
#include "private/qsimd_p.h"
#include <limits.h>
@@ -131,42 +132,7 @@ class Value;
class Entry;
template<typename T>
-class q_littleendian
-{
-public:
- T val;
-
- q_littleendian &operator =(T i) { val = qToLittleEndian(i); return *this; }
- operator T() const { return qFromLittleEndian(val); }
-
- bool operator ==(T i) { return qFromLittleEndian(val) == i; }
- bool operator !=(T i) { return qFromLittleEndian(val) != i; }
- bool operator ==(q_littleendian<T> i) { return val == i.val; }
- bool operator !=(q_littleendian<T> i) { return val != i.val; }
- bool operator <(T i) { return qFromLittleEndian(val) < i; }
- bool operator >(T i) { return qFromLittleEndian(val) > i; }
- bool operator <=(T i) { return qFromLittleEndian(val) <= i; }
- bool operator >=(T i) { return qFromLittleEndian(val) >= i; }
- q_littleendian &operator +=(T i) {
- val = qToLittleEndian(qFromLittleEndian(val) + i);
- return *this;
- }
- q_littleendian &operator |=(T i) {
- val = qToLittleEndian(qFromLittleEndian(val) | i);
- return *this;
- }
- q_littleendian &operator &=(T i) {
- val = qToLittleEndian(qFromLittleEndian(val) & i);
- return *this;
- }
-};
-} // namespace QJsonPrivate
-
-template <typename T>
-class QTypeInfo<QJsonPrivate::q_littleendian<T> >
- : public QTypeInfoMerger<QJsonPrivate::q_littleendian<T>, T> {};
-
-namespace QJsonPrivate {
+using q_littleendian = QLEInteger<T>;
typedef q_littleendian<short> qle_short;
typedef q_littleendian<unsigned short> qle_ushort;
@@ -174,97 +140,10 @@ typedef q_littleendian<int> qle_int;
typedef q_littleendian<unsigned int> qle_uint;
template<int pos, int width>
-class qle_bitfield
-{
-public:
- uint val;
-
- enum {
- mask = ((1u << width) - 1) << pos
- };
-
- void operator =(uint t) {
- uint i = qFromLittleEndian(val);
- i &= ~mask;
- i |= t << pos;
- val = qToLittleEndian(i);
- }
- operator uint() const {
- uint t = qFromLittleEndian(val);
- t &= mask;
- t >>= pos;
- return t;
- }
- bool operator !() const {
- return !operator uint();
- }
-
- bool operator ==(uint t) { return uint(*this) == t; }
- bool operator !=(uint t) { return uint(*this) != t; }
- bool operator <(uint t) { return uint(*this) < t; }
- bool operator >(uint t) { return uint(*this) > t; }
- bool operator <=(uint t) { return uint(*this) <= t; }
- bool operator >=(uint t) { return uint(*this) >= t; }
- qle_bitfield &operator +=(uint i) {
- *this = (uint(*this) + i);
- return *this;
- }
- qle_bitfield &operator -=(uint i) {
- *this = (uint(*this) - i);
- return *this;
- }
- qle_bitfield &operator |=(uint i) {
- *this = (uint(*this) | i);
- return *this;
- }
- qle_bitfield &operator &=(uint i) {
- *this = (uint(*this) & i);
- return *this;
- }
-};
+using qle_bitfield = QLEIntegerBitfield<uint, pos, width>;
template<int pos, int width>
-class qle_signedbitfield
-{
-public:
- uint val;
-
- enum {
- mask = ((1u << width) - 1) << pos
- };
-
- void operator =(int t) {
- uint i = qFromLittleEndian(val);
- i &= ~mask;
- i |= t << pos;
- val = qToLittleEndian(i);
- }
- operator int() const {
- uint i = qFromLittleEndian(val);
- i <<= 32 - width - pos;
- int t = (int) i;
- t >>= 32 - width;
- return t;
- }
- bool operator !() const {
- return !operator int();
- }
-
- bool operator ==(int t) { return int(*this) == t; }
- bool operator !=(int t) { return int(*this) != t; }
- bool operator <(int t) { return int(*this) < t; }
- bool operator >(int t) { return int(*this) > t; }
- bool operator <=(int t) { return int(*this) <= t; }
- bool operator >=(int t) { return int(*this) >= t; }
- qle_signedbitfield &operator +=(int i) {
- *this = (int(*this) + i);
- return *this;
- }
- qle_signedbitfield &operator -=(int i) {
- *this = (int(*this) - i);
- return *this;
- }
-};
+using qle_signedbitfield = QLEIntegerBitfield<int, pos, width>;
typedef qle_uint offset;
diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp
index d4cc4b81df..c5a5aaf39d 100644
--- a/src/corelib/json/qjsonarray.cpp
+++ b/src/corelib/json/qjsonarray.cpp
@@ -212,6 +212,27 @@ QJsonArray &QJsonArray::operator =(const QJsonArray &other)
return *this;
}
+/*!
+ \fn QJsonArray::QJsonArray(QJsonArray &&other)
+ \since 5.10
+
+ Move-constructs a QJsonArray from \a other.
+*/
+
+/*!
+ \fn QJsonArray &QJsonArray::operator =(QJsonArray &&other)
+ \since 5.10
+
+ Move-assigns \a other to this array.
+*/
+
+/*!
+ \fn void QJsonArray::swap(QJsonArray &other)
+ \since 5.10
+
+ Swaps the array \a other with this. This operation is very fast and never fails.
+*/
+
/*! \fn QJsonArray &QJsonArray::operator+=(const QJsonValue &value)
Appends \a value to the array, and returns a reference to the array itself.
diff --git a/src/corelib/json/qjsonarray.h b/src/corelib/json/qjsonarray.h
index 3b6fa37cfa..ddba2ca78e 100644
--- a/src/corelib/json/qjsonarray.h
+++ b/src/corelib/json/qjsonarray.h
@@ -72,6 +72,20 @@ public:
QJsonArray(const QJsonArray &other);
QJsonArray &operator =(const QJsonArray &other);
+ QJsonArray(QJsonArray &&other) Q_DECL_NOTHROW
+ : d(other.d),
+ a(other.a)
+ {
+ other.d = nullptr;
+ other.a = nullptr;
+ }
+
+ QJsonArray &operator =(QJsonArray &&other) Q_DECL_NOTHROW
+ {
+ swap(other);
+ return *this;
+ }
+
static QJsonArray fromStringList(const QStringList &list);
static QJsonArray fromVariantList(const QVariantList &list);
QVariantList toVariantList() const;
@@ -101,6 +115,12 @@ public:
bool operator==(const QJsonArray &other) const;
bool operator!=(const QJsonArray &other) const;
+ void swap(QJsonArray &other) Q_DECL_NOTHROW
+ {
+ qSwap(d, other.d);
+ qSwap(a, other.a);
+ }
+
class const_iterator;
class iterator {
@@ -243,6 +263,8 @@ private:
QJsonPrivate::Array *a;
};
+Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonArray)
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonArray &);
#endif
diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/json/qjsondocument.cpp
index ed454d5442..6469412054 100644
--- a/src/corelib/json/qjsondocument.cpp
+++ b/src/corelib/json/qjsondocument.cpp
@@ -153,6 +153,28 @@ QJsonDocument &QJsonDocument::operator =(const QJsonDocument &other)
return *this;
}
+/*!
+ \fn QJsonDocument::QJsonDocument(QJsonDocument &&other)
+ \since 5.10
+
+ Move-constructs a QJsonDocument from \a other.
+*/
+
+/*!
+ \fn QJsonDocument &QJsonDocument::operator =(QJsonDocument &&other)
+ \since 5.10
+
+ Move-assigns \a other to this document.
+*/
+
+/*!
+ \fn void QJsonDocument::swap(QJsonDocument &other)
+ \since 5.10
+
+ Swaps the document \a other with this. This operation is very fast and never fails.
+*/
+
+
/*! \enum QJsonDocument::DataValidation
This value is used to tell QJsonDocument whether to validate the binary data
@@ -529,6 +551,58 @@ void QJsonDocument::setArray(const QJsonArray &array)
}
/*!
+ Returns a QJsonValue representing the value for the key \a key.
+
+ Equivalent to calling object().value(key).
+
+ The returned QJsonValue is QJsonValue::Undefined if the key does not exist,
+ or if isObject() is false.
+
+ \since 5.10
+
+ \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject
+ */
+const QJsonValue QJsonDocument::operator[](const QString &key) const
+{
+ if (!isObject())
+ return QJsonValue(QJsonValue::Undefined);
+
+ return object().value(key);
+}
+
+/*!
+ \overload
+ \since 5.10
+*/
+const QJsonValue QJsonDocument::operator[](QLatin1String key) const
+{
+ if (!isObject())
+ return QJsonValue(QJsonValue::Undefined);
+
+ return object().value(key);
+}
+
+/*!
+ Returns a QJsonValue representing the value for index \a i.
+
+ Equivalent to calling array().at(i).
+
+ The returned QJsonValue is QJsonValue::Undefined, if \a i is out of bounds,
+ or if isArray() is false.
+
+ \since 5.10
+
+ \sa QJsonValue, QJsonValue::isUndefined(), QJsonArray
+ */
+const QJsonValue QJsonDocument::operator[](int i) const
+{
+ if (!isArray())
+ return QJsonValue(QJsonValue::Undefined);
+
+ return array().at(i);
+}
+
+/*!
Returns \c true if the \a other document is equal to this document.
*/
bool QJsonDocument::operator==(const QJsonDocument &other) const
diff --git a/src/corelib/json/qjsondocument.h b/src/corelib/json/qjsondocument.h
index 19885a8d56..4e76af21e2 100644
--- a/src/corelib/json/qjsondocument.h
+++ b/src/corelib/json/qjsondocument.h
@@ -93,6 +93,23 @@ public:
QJsonDocument(const QJsonDocument &other);
QJsonDocument &operator =(const QJsonDocument &other);
+ QJsonDocument(QJsonDocument &&other) Q_DECL_NOTHROW
+ : d(other.d)
+ {
+ other.d = nullptr;
+ }
+
+ QJsonDocument &operator =(QJsonDocument &&other) Q_DECL_NOTHROW
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(QJsonDocument &other) Q_DECL_NOTHROW
+ {
+ qSwap(d, other.d);
+ }
+
enum DataValidation {
Validate,
BypassValidation
@@ -131,6 +148,10 @@ public:
void setObject(const QJsonObject &object);
void setArray(const QJsonArray &array);
+ const QJsonValue operator[](const QString &key) const;
+ const QJsonValue operator[](QLatin1String key) const;
+ const QJsonValue operator[](int i) const;
+
bool operator==(const QJsonDocument &other) const;
bool operator!=(const QJsonDocument &other) const { return !(*this == other); }
@@ -147,6 +168,8 @@ private:
QJsonPrivate::Data *d;
};
+Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonDocument)
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonDocument &);
#endif
diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp
index b5b6f36bc6..4a316c8a6f 100644
--- a/src/corelib/json/qjsonobject.cpp
+++ b/src/corelib/json/qjsonobject.cpp
@@ -194,6 +194,28 @@ QJsonObject &QJsonObject::operator =(const QJsonObject &other)
}
/*!
+ \fn QJsonObject::QJsonObject(QJsonObject &&other)
+ \since 5.10
+
+ Move-constructs a QJsonObject from \a other.
+*/
+
+/*!
+ \fn QJsonObject &QJsonObject::operator =(QJsonObject &&other)
+ \since 5.10
+
+ Move-assigns \a other to this object.
+*/
+
+/*!
+ \fn void QJsonObject::swap(QJsonObject &other)
+ \since 5.10
+
+ Swaps the object \a other with this. This operation is very fast and never fails.
+*/
+
+
+/*!
Converts the variant map \a map to a QJsonObject.
The keys in \a map will be used as the keys in the JSON object,
diff --git a/src/corelib/json/qjsonobject.h b/src/corelib/json/qjsonobject.h
index e238c84d98..c77e2164a8 100644
--- a/src/corelib/json/qjsonobject.h
+++ b/src/corelib/json/qjsonobject.h
@@ -74,6 +74,25 @@ public:
QJsonObject(const QJsonObject &other);
QJsonObject &operator =(const QJsonObject &other);
+ QJsonObject(QJsonObject &&other) Q_DECL_NOTHROW
+ : d(other.d), o(other.o)
+ {
+ other.d = nullptr;
+ other.o = nullptr;
+ }
+
+ QJsonObject &operator =(QJsonObject &&other) Q_DECL_NOTHROW
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(QJsonObject &other) Q_DECL_NOTHROW
+ {
+ qSwap(d, other.d);
+ qSwap(o, other.o);
+ }
+
static QJsonObject fromVariantMap(const QVariantMap &map);
QVariantMap toVariantMap() const;
static QJsonObject fromVariantHash(const QVariantHash &map);
@@ -241,6 +260,8 @@ private:
QJsonPrivate::Object *o;
};
+Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonObject)
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonObject &);
#endif
diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp
index 4b52014db1..33707b6ec3 100644
--- a/src/corelib/json/qjsonvalue.cpp
+++ b/src/corelib/json/qjsonvalue.cpp
@@ -276,14 +276,32 @@ QJsonValue::QJsonValue(const QJsonValue &other)
QJsonValue &QJsonValue::operator =(const QJsonValue &other)
{
QJsonValue copy(other);
- // swap(copy);
- qSwap(dbl, copy.dbl);
- qSwap(d, copy.d);
- qSwap(t, copy.t);
+ swap(copy);
return *this;
}
/*!
+ \fn QJsonValue::QJsonValue(QJsonValue &&other)
+ \since 5.10
+
+ Move-constructs a QJsonValue from \a other.
+*/
+
+/*!
+ \fn QJsonValue &QJsonValue::operator =(QJsonValue &&other)
+ \since 5.10
+
+ Move-assigns \a other to this value.
+*/
+
+/*!
+ \fn void QJsonValue::swap(QJsonValue &other)
+ \since 5.10
+
+ Swaps the value \a other with this. This operation is very fast and never fails.
+*/
+
+/*!
\fn bool QJsonValue::isNull() const
Returns \c true if the value is null.
@@ -625,6 +643,58 @@ QJsonObject QJsonValue::toObject() const
}
/*!
+ Returns a QJsonValue representing the value for the key \a key.
+
+ Equivalent to calling toObject().value(key).
+
+ The returned QJsonValue is QJsonValue::Undefined if the key does not exist,
+ or if isObject() is false.
+
+ \since 5.10
+
+ \sa QJsonValue, QJsonValue::isUndefined(), QJsonObject
+ */
+const QJsonValue QJsonValue::operator[](const QString &key) const
+{
+ if (!isObject())
+ return QJsonValue(QJsonValue::Undefined);
+
+ return toObject().value(key);
+}
+
+/*!
+ \overload
+ \since 5.10
+*/
+const QJsonValue QJsonValue::operator[](QLatin1String key) const
+{
+ if (!isObject())
+ return QJsonValue(QJsonValue::Undefined);
+
+ return toObject().value(key);
+}
+
+/*!
+ Returns a QJsonValue representing the value for index \a i.
+
+ Equivalent to calling toArray().at(i).
+
+ The returned QJsonValue is QJsonValue::Undefined, if \a i is out of bounds,
+ or if isArray() is false.
+
+ \since 5.10
+
+ \sa QJsonValue, QJsonValue::isUndefined(), QJsonArray
+ */
+const QJsonValue QJsonValue::operator[](int i) const
+{
+ if (!isArray())
+ return QJsonValue(QJsonValue::Undefined);
+
+ return toArray().at(i);
+}
+
+/*!
Returns \c true if the value is equal to \a other.
*/
bool QJsonValue::operator==(const QJsonValue &other) const
diff --git a/src/corelib/json/qjsonvalue.h b/src/corelib/json/qjsonvalue.h
index a853acaddd..5d5ec72605 100644
--- a/src/corelib/json/qjsonvalue.h
+++ b/src/corelib/json/qjsonvalue.h
@@ -92,6 +92,29 @@ public:
QJsonValue(const QJsonValue &other);
QJsonValue &operator =(const QJsonValue &other);
+ QJsonValue(QJsonValue &&other) Q_DECL_NOTHROW
+ : ui(other.ui),
+ d(other.d),
+ t(other.t)
+ {
+ other.ui = 0;
+ other.d = nullptr;
+ other.t = Null;
+ }
+
+ QJsonValue &operator =(QJsonValue &&other) Q_DECL_NOTHROW
+ {
+ swap(other);
+ return *this;
+ }
+
+ void swap(QJsonValue &other) Q_DECL_NOTHROW
+ {
+ qSwap(ui, other.ui);
+ qSwap(d, other.d);
+ qSwap(t, other.t);
+ }
+
static QJsonValue fromVariant(const QVariant &variant);
QVariant toVariant() const;
@@ -114,6 +137,10 @@ public:
QJsonObject toObject() const;
QJsonObject toObject(const QJsonObject &defaultValue) const;
+ const QJsonValue operator[](const QString &key) const;
+ const QJsonValue operator[](QLatin1String key) const;
+ const QJsonValue operator[](int i) const;
+
bool operator==(const QJsonValue &other) const;
bool operator!=(const QJsonValue &other) const;
@@ -217,6 +244,8 @@ public:
};
#endif
+Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QJsonValue)
+
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_JSON_READONLY)
Q_CORE_EXPORT QDebug operator<<(QDebug, const QJsonValue &);
#endif
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 29bd5bbc6c..8abe9b2b44 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -79,7 +79,8 @@ win32 {
kernel/qsharedmemory_win.cpp \
kernel/qsystemsemaphore_win.cpp
HEADERS += \
- kernel/qwineventnotifier.h
+ kernel/qwineventnotifier.h \
+ kernel/qwineventnotifier_p.h
winrt {
SOURCES += kernel/qeventdispatcher_winrt.cpp
diff --git a/src/corelib/kernel/qabstracteventdispatcher.cpp b/src/corelib/kernel/qabstracteventdispatcher.cpp
index d234949d14..d1e436c371 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.cpp
+++ b/src/corelib/kernel/qabstracteventdispatcher.cpp
@@ -375,8 +375,7 @@ void QAbstractEventDispatcher::closingDown()
*/
/*!
- Installs an event filter \a filterObj for all native event filters
- received by the application.
+ Installs an event filter \a filterObj for all native events received by the application.
The event filter \a filterObj receives events via its \l {QAbstractNativeEventFilter::}{nativeEventFilter()}
function, which is called for all events received by all threads.
diff --git a/src/corelib/kernel/qabstracteventdispatcher.h b/src/corelib/kernel/qabstracteventdispatcher.h
index 0d3e53e4a7..3a530cf1de 100644
--- a/src/corelib/kernel/qabstracteventdispatcher.h
+++ b/src/corelib/kernel/qabstracteventdispatcher.h
@@ -124,6 +124,8 @@ protected:
QObject *parent);
};
+Q_DECLARE_TYPEINFO(QAbstractEventDispatcher::TimerInfo, (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) ? Q_PRIMITIVE_TYPE : Q_RELOCATABLE_TYPE));
+
QT_END_NAMESPACE
#endif // QABSTRACTEVENTDISPATCHER_H
diff --git a/src/corelib/kernel/qcore_mac.cpp b/src/corelib/kernel/qcore_mac.cpp
index c689f47d8f..bfb3b2ff07 100644
--- a/src/corelib/kernel/qcore_mac.cpp
+++ b/src/corelib/kernel/qcore_mac.cpp
@@ -45,16 +45,16 @@ QT_BEGIN_NAMESPACE
QCFString::operator QString() const
{
- if (string.isEmpty() && type)
- const_cast<QCFString*>(this)->string = QString::fromCFString(type);
+ if (string.isEmpty() && value)
+ const_cast<QCFString*>(this)->string = QString::fromCFString(value);
return string;
}
QCFString::operator CFStringRef() const
{
- if (!type)
- const_cast<QCFString*>(this)->type = string.toCFString();
- return type;
+ if (!value)
+ const_cast<QCFString*>(this)->value = string.toCFString();
+ return value;
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 231afb991c..ce4f01625e 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -42,7 +42,6 @@
#ifdef Q_OS_OSX
#include <AppKit/NSText.h>
-#include <Carbon/Carbon.h>
#endif
#include <qdebug.h>
@@ -53,7 +52,11 @@ QT_BEGIN_NAMESPACE
QDebug operator<<(QDebug dbg, const NSObject *nsObject)
{
- return dbg << (nsObject ? nsObject.description.UTF8String : "NSObject(0x0)");
+ return dbg << (nsObject ?
+ dbg.verbosity() > 2 ?
+ nsObject.debugDescription.UTF8String :
+ nsObject.description.UTF8String
+ : "NSObject(0x0)");
}
QDebug operator<<(QDebug dbg, CFStringRef stringRef)
@@ -94,6 +97,45 @@ QMacAutoReleasePool::~QMacAutoReleasePool()
[static_cast<NSAutoreleasePool*>(pool) drain];
}
+#ifdef Q_OS_MACOS
+/*
+ Ensure that Objective-C objects auto-released in main(), directly or indirectly,
+ after QCoreApplication construction, are released when the app goes out of scope.
+ The memory will be reclaimed by the system either way when the process exits,
+ but by having a root level pool we ensure that the objects get their dealloc
+ methods called, which is useful for debugging object ownership graphs, etc.
+*/
+
+QT_END_NAMESPACE
+#define ROOT_LEVEL_POOL_MARKER QT_ROOT_LEVEL_POOL__THESE_OBJECTS_WILL_BE_RELEASED_WHEN_QAPP_GOES_OUT_OF_SCOPE
+@interface QT_MANGLE_NAMESPACE(ROOT_LEVEL_POOL_MARKER) : NSObject @end
+@implementation QT_MANGLE_NAMESPACE(ROOT_LEVEL_POOL_MARKER) @end
+QT_NAMESPACE_ALIAS_OBJC_CLASS(ROOT_LEVEL_POOL_MARKER);
+QT_BEGIN_NAMESPACE
+
+const char ROOT_LEVEL_POOL_DISABLE_SWITCH[] = "QT_DISABLE_ROOT_LEVEL_AUTORELEASE_POOL";
+
+QMacRootLevelAutoReleasePool::QMacRootLevelAutoReleasePool()
+{
+ if (qEnvironmentVariableIsSet(ROOT_LEVEL_POOL_DISABLE_SWITCH))
+ return;
+
+ pool.reset(new QMacAutoReleasePool);
+
+ [[[ROOT_LEVEL_POOL_MARKER alloc] init] autorelease];
+
+ if (qstrcmp(qgetenv("OBJC_DEBUG_MISSING_POOLS"), "YES") == 0) {
+ qDebug("QCoreApplication root level NSAutoreleasePool in place. Break on ~%s and use\n" \
+ "'p [NSAutoreleasePool showPools]' to show leaked objects, or set %s",
+ __FUNCTION__, ROOT_LEVEL_POOL_DISABLE_SWITCH);
+ }
+}
+
+QMacRootLevelAutoReleasePool::~QMacRootLevelAutoReleasePool()
+{
+}
+#endif
+
// -------------------------------------------------------------------------
#ifdef Q_OS_OSX
@@ -140,6 +182,7 @@ struct qtKey2CocoaKeySortLessThan
}
};
+static const int NSEscapeCharacter = 27; // not defined by Cocoa headers
static const int NumEntries = 59;
static const KeyPair entries[NumEntries] = {
{ NSEnterCharacter, Qt::Key_Enter },
@@ -148,7 +191,7 @@ static const KeyPair entries[NumEntries] = {
{ NSNewlineCharacter, Qt::Key_Return },
{ NSCarriageReturnCharacter, Qt::Key_Return },
{ NSBackTabCharacter, Qt::Key_Backtab },
- { kEscapeCharCode, Qt::Key_Escape },
+ { NSEscapeCharacter, Qt::Key_Escape },
// Cocoa sends us delete when pressing backspace!
// (NB when we reverse this list in qtKey2CocoaKey, there
// will be two indices of Qt::Key_Backspace. But is seems to work
@@ -237,6 +280,36 @@ Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode)
#endif // Q_OS_OSX
+void qt_apple_check_os_version()
+{
+#if defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
+ const char *os = "iOS";
+ const int version = __IPHONE_OS_VERSION_MIN_REQUIRED;
+#elif defined(__TV_OS_VERSION_MIN_REQUIRED)
+ const char *os = "tvOS";
+ const int version = __TV_OS_VERSION_MIN_REQUIRED;
+#elif defined(__WATCH_OS_VERSION_MIN_REQUIRED)
+ const char *os = "watchOS";
+ const int version = __WATCH_OS_VERSION_MIN_REQUIRED;
+#elif defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
+ const char *os = "macOS";
+ const int version = __MAC_OS_X_VERSION_MIN_REQUIRED;
+#endif
+ const NSOperatingSystemVersion required = version >= 100000
+ ? (NSOperatingSystemVersion){version / 10000, version / 100 % 100, version % 100}
+ : (NSOperatingSystemVersion){version / 100, version / 10 % 10, version % 10};
+ const NSOperatingSystemVersion current = NSProcessInfo.processInfo.operatingSystemVersion;
+ if (![NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:required]) {
+ fprintf(stderr, "You can't use this version of %s with this version of %s. "
+ "You have %s %ld.%ld.%ld. Qt requires %s %ld.%ld.%ld or later.\n",
+ ((NSString *)NSBundle.mainBundle.infoDictionary[@"CFBundleName"]).UTF8String,
+ os,
+ os, current.majorVersion, current.minorVersion, current.patchVersion,
+ os, required.majorVersion, required.minorVersion, required.patchVersion);
+ abort();
+ }
+}
+
// -------------------------------------------------------------------------
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index d0edef33a2..5be8df1a48 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -68,6 +68,7 @@
#endif
#include "qstring.h"
+#include "qscopedpointer.h"
#if defined( __OBJC__) && defined(QT_NAMESPACE)
#define QT_NAMESPACE_ALIAS_OBJC_CLASS(__KLASS__) @compatibility_alias __KLASS__ QT_MANGLE_NAMESPACE(__KLASS__)
@@ -76,6 +77,37 @@
#endif
QT_BEGIN_NAMESPACE
+template <typename T, typename U, U (*RetainFunction)(U), void (*ReleaseFunction)(U)>
+class QAppleRefCounted
+{
+public:
+ QAppleRefCounted(const T &t = T()) : value(t) {}
+ QAppleRefCounted(QAppleRefCounted &&other) : value(other.value) { other.value = T(); }
+ QAppleRefCounted(const QAppleRefCounted &other) : value(other.value) { if (value) RetainFunction(value); }
+ ~QAppleRefCounted() { if (value) ReleaseFunction(value); }
+ operator T() { return value; }
+ void swap(QAppleRefCounted &other) Q_DECL_NOEXCEPT_EXPR(noexcept(qSwap(value, other.value)))
+ { qSwap(value, other.value); }
+ QAppleRefCounted &operator=(const QAppleRefCounted &other)
+ { QAppleRefCounted copy(other); swap(copy); return *this; }
+ QAppleRefCounted &operator=(QAppleRefCounted &&other)
+ { QAppleRefCounted moved(std::move(other)); swap(moved); return *this; }
+ T *operator&() { return &value; }
+protected:
+ T value;
+};
+
+
+#ifdef Q_OS_MACOS
+class QMacRootLevelAutoReleasePool
+{
+public:
+ QMacRootLevelAutoReleasePool();
+ ~QMacRootLevelAutoReleasePool();
+private:
+ QScopedPointer<QMacAutoReleasePool> pool;
+};
+#endif
/*
Helper class that automates refernce counting for CFtypes.
@@ -90,32 +122,16 @@ QT_BEGIN_NAMESPACE
HIThemeGet*Shape functions, which in reality are "Copy" functions.
*/
template <typename T>
-class Q_CORE_EXPORT QCFType
+class QCFType : public QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>
{
public:
- inline QCFType(const T &t = 0) : type(t) {}
- inline QCFType(const QCFType &helper) : type(helper.type) { if (type) CFRetain(type); }
- inline ~QCFType() { if (type) CFRelease(type); }
- inline operator T() { return type; }
- inline QCFType operator =(const QCFType &helper)
- {
- if (helper.type)
- CFRetain(helper.type);
- CFTypeRef type2 = type;
- type = helper.type;
- if (type2)
- CFRelease(type2);
- return *this;
- }
- inline T *operator&() { return &type; }
- template <typename X> X as() const { return reinterpret_cast<X>(type); }
+ using QAppleRefCounted<T, CFTypeRef, CFRetain, CFRelease>::QAppleRefCounted;
+ template <typename X> X as() const { return reinterpret_cast<X>(this->value); }
static QCFType constructFromGet(const T &t)
{
CFRetain(t);
return QCFType<T>(t);
}
-protected:
- T type;
};
class Q_CORE_EXPORT QCFString : public QCFType<CFStringRef>
@@ -136,6 +152,8 @@ Q_CORE_EXPORT QChar qt_mac_qtKey2CocoaKey(Qt::Key key);
Q_CORE_EXPORT Qt::Key qt_mac_cocoaKey2QtKey(QChar keyCode);
#endif
+Q_CORE_EXPORT void qt_apple_check_os_version();
+
QT_END_NAMESPACE
#endif // QCORE_MAC_P_H
diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp
index 686143f8c7..3b0da136ca 100644
--- a/src/corelib/kernel/qcore_unix.cpp
+++ b/src/corelib/kernel/qcore_unix.cpp
@@ -50,6 +50,37 @@
QT_BEGIN_NAMESPACE
+QByteArray qt_readlink(const char *path)
+{
+#ifndef PATH_MAX
+ // suitably large value that won't consume too much memory
+# define PATH_MAX 1024*1024
+#endif
+
+ QByteArray buf(256, Qt::Uninitialized);
+
+ ssize_t len = ::readlink(path, buf.data(), buf.size());
+ while (len == buf.size()) {
+ // readlink(2) will fill our buffer and not necessarily terminate with NUL;
+ if (buf.size() >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return QByteArray();
+ }
+
+ // double the size and try again
+ buf.resize(buf.size() * 2);
+ len = ::readlink(path, buf.data(), buf.size());
+ }
+
+ if (len == -1)
+ return QByteArray();
+
+ buf.resize(len);
+ return buf;
+}
+
+#ifndef QT_BOOTSTRAPPED
+
#if QT_CONFIG(poll_pollts)
# define ppoll pollts
#endif
@@ -121,4 +152,6 @@ int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout
}
}
+#endif // QT_BOOTSTRAPPED
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcore_unix_p.h b/src/corelib/kernel/qcore_unix_p.h
index 86bace3260..f78d2b9f24 100644
--- a/src/corelib/kernel/qcore_unix_p.h
+++ b/src/corelib/kernel/qcore_unix_p.h
@@ -55,6 +55,7 @@
#include <QtCore/private/qglobal_p.h>
#include "qplatformdefs.h"
#include "qatomic.h"
+#include "qbytearray.h"
#ifndef Q_OS_UNIX
# error "qcore_unix_p.h included on a non-Unix system"
@@ -102,6 +103,8 @@ struct sockaddr;
QT_BEGIN_NAMESPACE
+Q_DECLARE_TYPEINFO(pollfd, Q_PRIMITIVE_TYPE);
+
// Internal operator functions for timespecs
inline timespec &normalizedTimespec(timespec &t)
{
@@ -183,10 +186,11 @@ static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 07
int fd;
EINTR_LOOP(fd, QT_OPEN(pathname, flags, mode));
- // unknown flags are ignored, so we have no way of verifying if
- // O_CLOEXEC was accepted
+#ifndef O_CLOEXEC
if (fd != -1)
::fcntl(fd, F_SETFD, FD_CLOEXEC);
+#endif
+
return fd;
}
#undef QT_OPEN
@@ -337,6 +341,22 @@ static inline pid_t qt_safe_waitpid(pid_t pid, int *status, int options)
// in qelapsedtimer_mac.cpp or qtimestamp_unix.cpp
timespec qt_gettime() Q_DECL_NOTHROW;
void qt_nanosleep(timespec amount);
+QByteArray qt_readlink(const char *path);
+
+/* non-static */
+inline bool qt_haveLinuxProcfs()
+{
+#ifdef Q_OS_LINUX
+# ifdef QT_LINUX_ALWAYS_HAVE_PROCFS
+ return true;
+# else
+ static const bool present = (access("/proc/version", F_OK) == 0);
+ return present;
+# endif
+#else
+ return false;
+#endif
+}
Q_CORE_EXPORT int qt_safe_poll(struct pollfd *fds, nfds_t nfds, const struct timespec *timeout_ts);
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index cba279c184..6b6009d757 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -437,6 +437,9 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint
, q_ptr(0)
#endif
{
+#if defined(Q_OS_DARWIN)
+ qt_apple_check_os_version();
+#endif
app_compile_version = flags & 0xffffff;
static const char *const empty = "";
if (argc == 0 || argv == 0) {
@@ -1019,6 +1022,21 @@ bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
}
/*!
+ \internal
+ \since 5.10
+
+ Forwards the \a event to the \a receiver, using the spontaneous
+ state of the \a originatingEvent if specified.
+*/
+bool QCoreApplication::forwardEvent(QObject *receiver, QEvent *event, QEvent *originatingEvent)
+{
+ if (event && originatingEvent)
+ event->spont = originatingEvent->spont;
+
+ return notifyInternal2(receiver, event);
+}
+
+/*!
Sends \a event to \a receiver: \a {receiver}->event(\a event).
Returns the value that is returned from the receiver's event
handler. Note that this function is called for all events sent to
@@ -1916,7 +1934,10 @@ bool QCoreApplication::installTranslator(QTranslator *translationFile)
if (!QCoreApplicationPrivate::checkInstance("installTranslator"))
return false;
QCoreApplicationPrivate *d = self->d_func();
- d->translators.prepend(translationFile);
+ {
+ QWriteLocker locker(&d->translateMutex);
+ d->translators.prepend(translationFile);
+ }
#ifndef QT_NO_TRANSLATION_BUILDER
if (translationFile->isEmpty())
@@ -1948,8 +1969,10 @@ bool QCoreApplication::removeTranslator(QTranslator *translationFile)
if (!QCoreApplicationPrivate::checkInstance("removeTranslator"))
return false;
QCoreApplicationPrivate *d = self->d_func();
+ QWriteLocker locker(&d->translateMutex);
if (d->translators.removeAll(translationFile)) {
#ifndef QT_NO_QOBJECT
+ locker.unlock();
if (!self->closingDown()) {
QEvent ev(QEvent::LanguageChange);
QCoreApplication::sendEvent(self, &ev);
@@ -1985,7 +2008,7 @@ static void replacePercentN(QString *result, int n)
}
/*!
- \reentrant
+ \threadsafe
Returns the translation text for \a sourceText, by querying the
installed translation files. The translation files are searched
@@ -2014,13 +2037,7 @@ static void replacePercentN(QString *result, int n)
This function is not virtual. You can use alternative translation
techniques by subclassing \l QTranslator.
- \warning This method is reentrant only if all translators are
- installed \e before calling this method. Installing or removing
- translators while performing translations is not supported. Doing
- so will most likely result in crashes or other undesirable
- behavior.
-
- \sa QObject::tr(), installTranslator()
+ \sa QObject::tr(), installTranslator(), removeTranslator(), translate()
*/
QString QCoreApplication::translate(const char *context, const char *sourceText,
const char *disambiguation, int n)
@@ -2030,14 +2047,18 @@ QString QCoreApplication::translate(const char *context, const char *sourceText,
if (!sourceText)
return result;
- if (self && !self->d_func()->translators.isEmpty()) {
- QList<QTranslator*>::ConstIterator it;
- QTranslator *translationFile;
- for (it = self->d_func()->translators.constBegin(); it != self->d_func()->translators.constEnd(); ++it) {
- translationFile = *it;
- result = translationFile->translate(context, sourceText, disambiguation, n);
- if (!result.isNull())
- break;
+ if (self) {
+ QCoreApplicationPrivate *d = self->d_func();
+ QReadLocker locker(&d->translateMutex);
+ if (!d->translators.isEmpty()) {
+ QList<QTranslator*>::ConstIterator it;
+ QTranslator *translationFile;
+ for (it = d->translators.constBegin(); it != d->translators.constEnd(); ++it) {
+ translationFile = *it;
+ result = translationFile->translate(context, sourceText, disambiguation, n);
+ if (!result.isNull())
+ break;
+ }
}
}
@@ -2061,8 +2082,11 @@ QString qtTrId(const char *id, int n)
bool QCoreApplicationPrivate::isTranslatorInstalled(QTranslator *translator)
{
- return QCoreApplication::self
- && QCoreApplication::self->d_func()->translators.contains(translator);
+ if (!QCoreApplication::self)
+ return false;
+ QCoreApplicationPrivate *d = QCoreApplication::self->d_func();
+ QReadLocker locker(&d->translateMutex);
+ return d->translators.contains(translator);
}
#else
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index 0fee7b3de8..34133533f0 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -206,6 +206,7 @@ private:
QT_DEPRECATED bool notifyInternal(QObject *receiver, QEvent *event); // ### Qt6 BIC: remove me
# endif
static bool notifyInternal2(QObject *receiver, QEvent *);
+ static bool forwardEvent(QObject *receiver, QEvent *event, QEvent *originatingEvent = nullptr);
#endif
static QCoreApplication *self;
diff --git a/src/corelib/kernel/qcoreapplication_p.h b/src/corelib/kernel/qcoreapplication_p.h
index c646786296..963aec70e8 100644
--- a/src/corelib/kernel/qcoreapplication_p.h
+++ b/src/corelib/kernel/qcoreapplication_p.h
@@ -58,6 +58,10 @@
#include "private/qobject_p.h"
#endif
+#ifdef Q_OS_MACOS
+#include "private/qcore_mac_p.h"
+#endif
+
QT_BEGIN_NAMESPACE
typedef QList<QTranslator*> QTranslatorList;
@@ -85,6 +89,10 @@ public:
QString appName() const;
QString appVersion() const;
+#ifdef Q_OS_MACOS
+ QMacRootLevelAutoReleasePool autoReleasePool;
+#endif
+
#ifdef Q_OS_DARWIN
static QString infoDictionaryStringProperty(const QString &propertyName);
#endif
@@ -134,7 +142,7 @@ public:
#ifndef QT_NO_TRANSLATION
QTranslatorList translators;
-
+ QReadWriteLock translateMutex;
static bool isTranslatorInstalled(QTranslator *translator);
#endif
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 50888dd0aa..00548365d2 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -67,43 +67,33 @@ int appCmdShow = 0;
Q_CORE_EXPORT QString qAppFileName() // get application file name
{
- // We do MAX_PATH + 2 here, and request with MAX_PATH + 1, so we can handle all paths
- // up to, and including MAX_PATH size perfectly fine with string termination, as well
- // as easily detect if the file path is indeed larger than MAX_PATH, in which case we
- // need to use the heap instead. This is a work-around, since contrary to what the
- // MSDN documentation states, GetModuleFileName sometimes doesn't set the
- // ERROR_INSUFFICIENT_BUFFER error number, and we thus cannot rely on this value if
- // GetModuleFileName(0, buffer, MAX_PATH) == MAX_PATH.
- // GetModuleFileName(0, buffer, MAX_PATH + 1) == MAX_PATH just means we hit the normal
- // file path limit, and we handle it normally, if the result is MAX_PATH + 1, we use
- // heap (even if the result _might_ be exactly MAX_PATH + 1, but that's ok).
- wchar_t buffer[MAX_PATH + 2];
- DWORD v = GetModuleFileName(0, buffer, MAX_PATH + 1);
- buffer[MAX_PATH + 1] = 0;
-
- if (v == 0)
- return QString();
- else if (v <= MAX_PATH)
- return QString::fromWCharArray(buffer);
-
- // MAX_PATH sized buffer wasn't large enough to contain the full path, use heap
- wchar_t *b = 0;
- int i = 1;
- size_t size;
+ /*
+ GetModuleFileName() returns the length of the module name, when it has
+ space to store it and 0-terminate; this return is necessarily smaller than
+ the buffer size, as it doesn't include the terminator. When it lacks
+ space, the function returns the full size of the buffer and fills the
+ buffer, truncating the full path to make it fit. We have reports that
+ GetModuleFileName sometimes doesn't set the error number to
+ ERROR_INSUFFICIENT_BUFFER, as claimed by the MSDN documentation; so we
+ only trust the answer when the return is actually less than the buffer
+ size we pass in. (When truncating, except on XP, it does so by enough to
+ still have space to 0-terminate; in either case, it fills the claimed
+ space and returns the size of the space. While XP might thus give us the
+ full name, without a 0 terminator, and return its actual length, we can
+ never be sure that's what's happened until a later call with bigger buffer
+ confirms it by returning less than its buffer size.)
+ */
+ // Full path may be longer than MAX_PATH - expand until we have enough space:
+ QVarLengthArray<wchar_t, MAX_PATH + 1> space;
+ DWORD v;
+ size_t size = 1;
do {
- ++i;
- size = MAX_PATH * i;
- b = reinterpret_cast<wchar_t *>(realloc(b, (size + 1) * sizeof(wchar_t)));
- if (b)
- v = GetModuleFileName(NULL, b, DWORD(size));
- } while (b && v == size);
-
- if (b)
- *(b + size) = 0;
- QString res = QString::fromWCharArray(b);
- free(b);
+ size += MAX_PATH;
+ space.resize(int(size));
+ v = GetModuleFileName(NULL, space.data(), DWORD(space.size()));
+ } while (Q_UNLIKELY(v >= size));
- return res;
+ return QString::fromWCharArray(space.data(), v);
}
QString QCoreApplicationPrivate::appName() const
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index d728040343..bcf5b10baa 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -55,7 +55,6 @@
#include "QtCore/qlist.h"
#include "private/qabstracteventdispatcher_p.h"
#include "private/qcore_unix_p.h"
-#include "private/qpodlist_p.h"
#include "QtCore/qvarlengtharray.h"
#include "private/qtimerinfo_unix_p.h"
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 7a6149b405..569fbc2796 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -53,6 +53,7 @@
#include "qcoreapplication_p.h"
#include <private/qthread_p.h>
#include <private/qmutexpool_p.h>
+#include <private/qwineventnotifier_p.h>
QT_BEGIN_NAMESPACE
@@ -96,13 +97,14 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA
QEventDispatcherWin32Private::QEventDispatcherWin32Private()
: threadId(GetCurrentThreadId()), interrupt(false), closingDown(false), internalHwnd(0),
getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0),
- wakeUps(0)
- , activateNotifiersPosted(false)
+ wakeUps(0), activateNotifiersPosted(false), winEventNotifierActivatedEvent(NULL)
{
}
QEventDispatcherWin32Private::~QEventDispatcherWin32Private()
{
+ if (winEventNotifierActivatedEvent)
+ CloseHandle(winEventNotifierActivatedEvent);
if (internalHwnd)
DestroyWindow(internalHwnd);
}
@@ -538,12 +540,14 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
bool needWM_QT_SENDPOSTEDEVENTS = false;
do {
DWORD waitRet = 0;
- HANDLE pHandles[MAXIMUM_WAIT_OBJECTS - 1];
+ DWORD nCount = 0;
+ HANDLE *pHandles = nullptr;
+ if (d->winEventNotifierActivatedEvent) {
+ nCount = 1;
+ pHandles = &d->winEventNotifierActivatedEvent;
+ }
QVarLengthArray<MSG> processedTimers;
while (!d->interrupt) {
- DWORD nCount = d->winEventNotifierList.count();
- Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
-
MSG msg;
bool haveMessage;
@@ -585,8 +589,6 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
}
if (!haveMessage) {
// no message - check for signalled objects
- for (int i=0; i<(int)nCount; i++)
- pHandles[i] = d->winEventNotifierList.at(i)->handle();
waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, 0, QS_ALLINPUT, MWMO_ALERTABLE);
if ((haveMessage = (waitRet == WAIT_OBJECT_0 + nCount))) {
// a new message has arrived, process it
@@ -627,7 +629,7 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
DispatchMessage(&msg);
}
} else if (waitRet - WAIT_OBJECT_0 < nCount) {
- d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
+ activateEventNotifiers();
} else {
// nothing todo so break
break;
@@ -640,16 +642,11 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
&& !d->interrupt
&& (flags & QEventLoop::WaitForMoreEvents));
if (canWait) {
- DWORD nCount = d->winEventNotifierList.count();
- Q_ASSERT(nCount < MAXIMUM_WAIT_OBJECTS - 1);
- for (int i=0; i<(int)nCount; i++)
- pHandles[i] = d->winEventNotifierList.at(i)->handle();
-
emit aboutToBlock();
waitRet = MsgWaitForMultipleObjectsEx(nCount, pHandles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
emit awake();
if (waitRet - WAIT_OBJECT_0 < nCount) {
- d->activateEventNotifier(d->winEventNotifierList.at(waitRet - WAIT_OBJECT_0));
+ activateEventNotifiers();
retVal = true;
}
}
@@ -907,12 +904,12 @@ bool QEventDispatcherWin32::registerEventNotifier(QWinEventNotifier *notifier)
if (d->winEventNotifierList.contains(notifier))
return true;
- if (d->winEventNotifierList.count() >= MAXIMUM_WAIT_OBJECTS - 2) {
- qWarning("QWinEventNotifier: Cannot have more than %d enabled at one time", MAXIMUM_WAIT_OBJECTS - 2);
- return false;
- }
d->winEventNotifierList.append(notifier);
- return true;
+
+ if (!d->winEventNotifierActivatedEvent)
+ d->winEventNotifierActivatedEvent = CreateEvent(0, TRUE, FALSE, nullptr);
+
+ return QWinEventNotifierPrivate::get(notifier)->registerWaitObject();
}
void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
@@ -928,17 +925,35 @@ void QEventDispatcherWin32::unregisterEventNotifier(QWinEventNotifier *notifier)
Q_D(QEventDispatcherWin32);
int i = d->winEventNotifierList.indexOf(notifier);
- if (i != -1)
- d->winEventNotifierList.takeAt(i);
+ if (i == -1)
+ return;
+ d->winEventNotifierList.takeAt(i);
+ QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
+ if (nd->waitHandle)
+ nd->unregisterWaitObject();
}
void QEventDispatcherWin32::activateEventNotifiers()
{
Q_D(QEventDispatcherWin32);
- //### this could break if events are removed/added in the activation
- for (int i=0; i<d->winEventNotifierList.count(); i++) {
- if (WaitForSingleObjectEx(d->winEventNotifierList.at(i)->handle(), 0, TRUE) == WAIT_OBJECT_0)
- d->activateEventNotifier(d->winEventNotifierList.at(i));
+ ResetEvent(d->winEventNotifierActivatedEvent);
+
+ // Iterate backwards, because the notifier might remove itself on activate().
+ for (int i = d->winEventNotifierList.count(); --i >= 0;) {
+ QWinEventNotifier *notifier = d->winEventNotifierList.at(i);
+ QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
+ if (WaitForSingleObject(nd->handleToEvent, 0) == WAIT_OBJECT_0) {
+ nd->unregisterWaitObject();
+ d->activateEventNotifier(notifier);
+ }
+ }
+
+ // Re-register the remaining activated notifiers.
+ for (int i = 0; i < d->winEventNotifierList.count(); ++i) {
+ QWinEventNotifier *notifier = d->winEventNotifierList.at(i);
+ QWinEventNotifierPrivate *nd = QWinEventNotifierPrivate::get(notifier);
+ if (!nd->waitHandle)
+ nd->registerWaitObject();
}
}
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
index f6d1bffdf5..683c7f8f36 100644
--- a/src/corelib/kernel/qeventdispatcher_win_p.h
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -161,6 +161,7 @@ class Q_CORE_EXPORT QEventDispatcherWin32Private : public QAbstractEventDispatch
public:
QEventDispatcherWin32Private();
~QEventDispatcherWin32Private();
+ static QEventDispatcherWin32Private *get(QEventDispatcherWin32 *q) { return q->d_func(); }
DWORD threadId;
@@ -192,6 +193,7 @@ public:
void postActivateSocketNotifiers();
void doWsaAsyncSelect(int socket, long event);
+ HANDLE winEventNotifierActivatedEvent;
QList<QWinEventNotifier *> winEventNotifierList;
void activateEventNotifier(QWinEventNotifier * wen);
diff --git a/src/corelib/kernel/qfunctions_fake_env_p.h b/src/corelib/kernel/qfunctions_fake_env_p.h
index 16d18c4d88..7010d2cf5d 100644
--- a/src/corelib/kernel/qfunctions_fake_env_p.h
+++ b/src/corelib/kernel/qfunctions_fake_env_p.h
@@ -77,7 +77,9 @@ struct NameEquals {
{ return qstrcmp(other.name, name) == 0; }
};
+#ifndef Q_CLANG_QDOC
Q_GLOBAL_STATIC(QVector<Variable>, qt_app_environment)
+#endif
errno_t qt_fake_getenv_s(size_t *sizeNeeded, char *buffer, size_t bufferSize, const char *varName)
{
diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp
index cb4b93905e..02c58858ff 100644
--- a/src/corelib/kernel/qjnihelpers.cpp
+++ b/src/corelib/kernel/qjnihelpers.cpp
@@ -75,6 +75,11 @@ static jmethodID g_hideSplashScreenMethodID = Q_NULLPTR;
Q_GLOBAL_STATIC(std::deque<QtAndroidPrivate::Runnable>, g_pendingRunnables);
static QBasicMutex g_pendingRunnablesMutex;
+Q_GLOBAL_STATIC_WITH_ARGS(QtAndroidPrivate::OnBindListener*, g_onBindListener, (nullptr));
+Q_GLOBAL_STATIC(QMutex, g_onBindListenerMutex);
+Q_GLOBAL_STATIC(QSemaphore, g_waitForServiceSetupSemaphore);
+Q_GLOBAL_STATIC(QAtomicInt, g_serviceSetupLockers);
+
class PermissionsResultClass : public QObject
{
Q_OBJECT
@@ -406,7 +411,7 @@ jint QtAndroidPrivate::initJNI(JavaVM *vm, JNIEnv *env)
g_runPendingCppRunnablesMethodID = env->GetStaticMethodID(jQtNative,
"runPendingCppRunnablesOnAndroidThread",
"()V");
- g_hideSplashScreenMethodID = env->GetStaticMethodID(jQtNative, "hideSplashScreen", "()V");
+ g_hideSplashScreenMethodID = env->GetStaticMethodID(jQtNative, "hideSplashScreen", "(I)V");
g_jNativeClass = static_cast<jclass>(env->NewGlobalRef(jQtNative));
env->DeleteLocalRef(jQtNative);
@@ -511,7 +516,7 @@ void QtAndroidPrivate::requestPermissions(JNIEnv *env, const QStringList &permis
}, env);
}
-QHash<QString, QtAndroidPrivate::PermissionsResult> QtAndroidPrivate::requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs)
+QtAndroidPrivate::PermissionsHash QtAndroidPrivate::requestPermissionsSync(JNIEnv *env, const QStringList &permissions, int timeoutMs)
{
QSharedPointer<QHash<QString, QtAndroidPrivate::PermissionsResult>> res(new QHash<QString, QtAndroidPrivate::PermissionsResult>());
QSharedPointer<QSemaphore> sem(new QSemaphore);
@@ -567,9 +572,36 @@ void QtAndroidPrivate::unregisterKeyEventListener(QtAndroidPrivate::KeyEventList
g_keyEventListeners()->listeners.removeOne(listener);
}
-void QtAndroidPrivate::hideSplashScreen(JNIEnv *env)
+void QtAndroidPrivate::hideSplashScreen(JNIEnv *env, int duration)
+{
+ env->CallStaticVoidMethod(g_jNativeClass, g_hideSplashScreenMethodID, duration);
+}
+
+void QtAndroidPrivate::waitForServiceSetup()
+{
+ g_waitForServiceSetupSemaphore->acquire();
+}
+
+int QtAndroidPrivate::acuqireServiceSetup(int flags)
+{
+ g_serviceSetupLockers->ref();
+ return flags;
+}
+
+void QtAndroidPrivate::setOnBindListener(QtAndroidPrivate::OnBindListener *listener)
+{
+ QMutexLocker lock(g_onBindListenerMutex);
+ *g_onBindListener = listener;
+ if (!(*g_serviceSetupLockers)--)
+ g_waitForServiceSetupSemaphore->release();
+}
+
+jobject QtAndroidPrivate::callOnBindListener(jobject intent)
{
- env->CallStaticVoidMethod(g_jNativeClass, g_hideSplashScreenMethodID);
+ QMutexLocker lock(g_onBindListenerMutex);
+ if (g_onBindListener)
+ return (*g_onBindListener)->onBind(intent);
+ return nullptr;
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qjnihelpers_p.h b/src/corelib/kernel/qjnihelpers_p.h
index d88e4fc19e..ea5103c173 100644
--- a/src/corelib/kernel/qjnihelpers_p.h
+++ b/src/corelib/kernel/qjnihelpers_p.h
@@ -100,6 +100,13 @@ namespace QtAndroidPrivate
virtual bool handleKeyEvent(jobject event) = 0;
};
+ class Q_CORE_EXPORT OnBindListener
+ {
+ public:
+ virtual ~OnBindListener() {}
+ virtual jobject onBind(jobject intent) = 0;
+ };
+
enum class PermissionsResult {
Granted,
Denied
@@ -142,7 +149,14 @@ namespace QtAndroidPrivate
Q_CORE_EXPORT void registerKeyEventListener(KeyEventListener *listener);
Q_CORE_EXPORT void unregisterKeyEventListener(KeyEventListener *listener);
- Q_CORE_EXPORT void hideSplashScreen(JNIEnv *env);
+ Q_CORE_EXPORT void hideSplashScreen(JNIEnv *env, int duration = 0);
+
+
+ Q_CORE_EXPORT void waitForServiceSetup();
+ Q_CORE_EXPORT int acuqireServiceSetup(int flags);
+ Q_CORE_EXPORT void setOnBindListener(OnBindListener *listener);
+ Q_CORE_EXPORT jobject callOnBindListener(jobject intent);
+
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qmath.h b/src/corelib/kernel/qmath.h
index 773884047a..305e9065e9 100644
--- a/src/corelib/kernel/qmath.h
+++ b/src/corelib/kernel/qmath.h
@@ -149,6 +149,8 @@ inline qreal qPow(qreal x, qreal y)
return pow(x, y);
}
+// TODO: use template variables (e.g. Qt::pi<type>) for these once we have C++14 support:
+
#ifndef M_E
#define M_E (2.7182818284590452354)
#endif
@@ -242,16 +244,13 @@ Q_DECL_CONSTEXPR inline double qRadiansToDegrees(double radians)
}
-#if defined(QT_HAS_BUILTIN_CLZ)
-inline quint32 qNextPowerOfTwo(quint32 v)
+Q_DECL_RELAXED_CONSTEXPR inline quint32 qNextPowerOfTwo(quint32 v)
{
+#if defined(QT_HAS_BUILTIN_CLZ)
if (v == 0)
return 1;
return 2U << (31 ^ QAlgorithmsPrivate::qt_builtin_clz(v));
-}
#else
-inline quint32 qNextPowerOfTwo(quint32 v)
-{
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
@@ -259,19 +258,16 @@ inline quint32 qNextPowerOfTwo(quint32 v)
v |= v >> 16;
++v;
return v;
-}
#endif
+}
-#if defined(QT_HAS_BUILTIN_CLZLL)
-inline quint64 qNextPowerOfTwo(quint64 v)
+Q_DECL_RELAXED_CONSTEXPR inline quint64 qNextPowerOfTwo(quint64 v)
{
+#if defined(QT_HAS_BUILTIN_CLZLL)
if (v == 0)
return 1;
return Q_UINT64_C(2) << (63 ^ QAlgorithmsPrivate::qt_builtin_clzll(v));
-}
#else
-inline quint64 qNextPowerOfTwo(quint64 v)
-{
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
@@ -280,15 +276,15 @@ inline quint64 qNextPowerOfTwo(quint64 v)
v |= v >> 32;
++v;
return v;
-}
#endif
+}
-inline quint32 qNextPowerOfTwo(qint32 v)
+Q_DECL_RELAXED_CONSTEXPR inline quint32 qNextPowerOfTwo(qint32 v)
{
return qNextPowerOfTwo(quint32(v));
}
-inline quint64 qNextPowerOfTwo(qint64 v)
+Q_DECL_RELAXED_CONSTEXPR inline quint64 qNextPowerOfTwo(qint64 v)
{
return qNextPowerOfTwo(quint64(v));
}
diff --git a/src/corelib/kernel/qmath.qdoc b/src/corelib/kernel/qmath.qdoc
index 3a692d5935..a2e24e925b 100644
--- a/src/corelib/kernel/qmath.qdoc
+++ b/src/corelib/kernel/qmath.qdoc
@@ -35,7 +35,24 @@
These functions are partly convenience definitions for basic math operations
not available in the C or Standard Template Libraries.
- \pagekeywords math trigonometry qmath floor ceiling absolute sine cosine tangent inverse tan exponent power natural logarithm
+ The header also ensures some constants specified in POSIX, but not present
+ in C++ standards (so absent from <math.h> on some platforms), are defined:
+
+ \value M_E The base of the natural logarithms, e = exp(1)
+ \value M_LOG2E The base-two logarithm of e
+ \value M_LOG10E The base-ten logarithm of e
+ \value M_LN2 The natural logarithm of two
+ \value M_LN10 The natural logarithm of ten
+ \value M_PI The ratio of a circle's circumference to diameter, \unicode{0x3C0}
+ \value M_PI_2 Half M_PI, \unicode{0x3C0} / 2
+ \value M_PI_4 Quarter M_PI, \unicode{0x3C0} / 4
+ \value M_1_PI The inverse of M_PI, 1 / \unicode{0x3C0}
+ \value M_2_PI Twice the inverse of M_PI, 2 / \unicode{0x3C0}
+ \value M_2_SQRTPI Two divided by the square root of pi, 2 / \unicode{0x221A}\unicode{0x3C0}
+ \value M_SQRT2 The square root of two, \unicode{0x221A}2
+ \value M_SQRT1_2 The square roof of half, 1 / \unicode{0x221A}2
+
+ \pagekeywords math trigonometry qmath floor ceiling absolute sine cosine tangent inverse tan exponent power natural logarithm pi
*/
/*!
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index a8003f7e46..f07b463482 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -1489,6 +1489,51 @@ bool QMetaObject::invokeMethod(QObject *obj,
val0, val1, val2, val3, val4, val5, val6, val7, val8, val9);
}
+bool QMetaObject::invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret)
+{
+ if (! object)
+ return false;
+
+ QThread *currentThread = QThread::currentThread();
+ QThread *objectThread = object->thread();
+ if (type == Qt::AutoConnection)
+ type = (currentThread == objectThread) ? Qt::DirectConnection : Qt::QueuedConnection;
+
+ void *argv[] = { ret };
+
+ if (type == Qt::DirectConnection) {
+ slot->call(object, argv);
+ } else if (type == Qt::QueuedConnection) {
+ if (argv[0]) {
+ qWarning("QMetaObject::invokeMethod: Unable to invoke methods with return values in "
+ "queued connections");
+ return false;
+ }
+
+ // args and typesCopy will be deallocated by ~QMetaCallEvent() using free()
+ void **args = static_cast<void **>(calloc(1, sizeof(void *)));
+ Q_CHECK_PTR(args);
+
+ int *types = static_cast<int *>(calloc(1, sizeof(int)));
+ Q_CHECK_PTR(types);
+
+ QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 1, types, args));
+ } else if (type == Qt::BlockingQueuedConnection) {
+#ifndef QT_NO_THREAD
+ if (currentThread == objectThread)
+ qWarning("QMetaObject::invokeMethod: Dead lock detected");
+
+ QSemaphore semaphore;
+ QCoreApplication::postEvent(object, new QMetaCallEvent(slot, 0, -1, 0, 0, argv, &semaphore));
+ semaphore.acquire();
+#endif // QT_NO_THREAD
+ } else {
+ qWarning("QMetaObject::invokeMethod: Unknown connection type");
+ return false;
+ }
+ return true;
+}
+
/*! \fn bool QMetaObject::invokeMethod(QObject *obj, const char *member,
QGenericReturnArgument ret,
QGenericArgument val0 = QGenericArgument(0),
@@ -1544,6 +1589,44 @@ bool QMetaObject::invokeMethod(QObject *obj,
*/
/*!
+ \fn bool QMetaObject::invokeMethod(QObject *receiver, PointerToMemberFunction function, Qt::ConnectionType type = Qt::AutoConnection, MemberFunctionReturnType *ret = Q_NULLPTR)
+
+ \since 5.10
+
+ \overload
+*/
+
+/*!
+ \fn bool QMetaObject::invokeMethod(QObject *receiver, PointerToMemberFunction function, MemberFunctionReturnType *ret)
+
+ \since 5.10
+
+ \overload
+
+ This overload invokes the member function using the connection type Qt::AutoConnection.
+*/
+
+/*!
+ \fn bool QMetaObject::invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = Q_NULLPTR)
+
+ \since 5.10
+
+ \overload
+
+ Call the functor in the event loop of \a context.
+*/
+
+/*!
+ \fn bool QMetaObject::invokeMethod(QObject *context, Functor function, FunctorReturnType *ret = Q_NULLPTR)
+
+ \since 5.10
+
+ \overload
+
+ Call the functor in the event loop of \a context using the connection type Qt::AutoConnection.
+*/
+
+/*!
\fn QMetaObject::Connection::Connection(const Connection &other)
Constructs a copy of \a other.
@@ -3264,7 +3347,21 @@ int QMetaProperty::notifySignalIndex() const
if (hasNotifySignal()) {
int offset = priv(mobj->d.data)->propertyData +
priv(mobj->d.data)->propertyCount * 3 + idx;
- return mobj->d.data[offset] + mobj->methodOffset();
+ int methodIndex = mobj->d.data[offset];
+ if (methodIndex & IsUnresolvedSignal) {
+ methodIndex &= ~IsUnresolvedSignal;
+ const QByteArray signalName = stringData(mobj, methodIndex);
+ const QMetaObject *m = mobj;
+ const int idx = indexOfMethodRelative<MethodSignal>(&m, signalName, 0, nullptr);
+ if (idx >= 0) {
+ return idx + m->methodOffset();
+ } else {
+ qWarning("QMetaProperty::notifySignal: cannot find the NOTIFY signal %s in class %s for property '%s'",
+ signalName.constData(), objectClassName(mobj), name());
+ return -1;
+ }
+ }
+ return methodIndex + mobj->methodOffset();
} else {
return -1;
}
diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h
index e247c48703..434ef84808 100644
--- a/src/corelib/kernel/qmetaobject_p.h
+++ b/src/corelib/kernel/qmetaobject_p.h
@@ -111,7 +111,8 @@ enum MetaObjectFlags {
enum MetaDataFlags {
IsUnresolvedType = 0x80000000,
- TypeNameIndexMask = 0x7FFFFFFF
+ TypeNameIndexMask = 0x7FFFFFFF,
+ IsUnresolvedSignal = 0x70000000
};
enum EnumFlags {
diff --git a/src/corelib/kernel/qmetaobjectbuilder.cpp b/src/corelib/kernel/qmetaobjectbuilder.cpp
index 56f187a59d..e3b70638c6 100644
--- a/src/corelib/kernel/qmetaobjectbuilder.cpp
+++ b/src/corelib/kernel/qmetaobjectbuilder.cpp
@@ -190,12 +190,13 @@ class QMetaEnumBuilderPrivate
{
public:
QMetaEnumBuilderPrivate(const QByteArray& _name)
- : name(_name), isFlag(false)
+ : name(_name), isFlag(false), isScoped(false)
{
}
QByteArray name;
bool isFlag;
+ bool isScoped;
QList<QByteArray> keys;
QVector<int> values;
};
@@ -637,6 +638,7 @@ QMetaEnumBuilder QMetaObjectBuilder::addEnumerator(const QMetaEnum& prototype)
{
QMetaEnumBuilder en = addEnumerator(prototype.name());
en.setIsFlag(prototype.isFlag());
+ en.setIsScoped(prototype.isScoped());
int count = prototype.keyCount();
for (int index = 0; index < count; ++index)
en.addKey(prototype.key(index), prototype.value(index));
@@ -1408,12 +1410,13 @@ static int buildMetaObject(QMetaObjectBuilderPrivate *d, char *buf,
Q_ASSERT(!buf || dataIndex == pmeta->enumeratorData);
for (const auto &enumerator : d->enumerators) {
int name = strings.enter(enumerator.name);
- int isFlag = (int)(enumerator.isFlag);
+ int isFlag = enumerator.isFlag ? EnumIsFlag : 0;
+ int isScoped = enumerator.isScoped ? EnumIsScoped : 0;
int count = enumerator.keys.size();
int enumOffset = enumIndex;
if (buf) {
data[dataIndex] = name;
- data[dataIndex + 1] = isFlag;
+ data[dataIndex + 1] = isFlag | isScoped;
data[dataIndex + 2] = count;
data[dataIndex + 3] = enumOffset;
}
@@ -1641,6 +1644,7 @@ void QMetaObjectBuilder::serialize(QDataStream& stream) const
for (const auto &enumerator : d->enumerators) {
stream << enumerator.name;
stream << enumerator.isFlag;
+ stream << enumerator.isScoped;
stream << enumerator.keys;
stream << enumerator.values;
}
@@ -1807,6 +1811,7 @@ void QMetaObjectBuilder::deserialize
addEnumerator(name);
QMetaEnumBuilderPrivate &enumerator = d->enumerators[index];
stream >> enumerator.isFlag;
+ stream >> enumerator.isScoped;
stream >> enumerator.keys;
stream >> enumerator.values;
if (enumerator.keys.size() != enumerator.values.size()) {
@@ -2633,6 +2638,31 @@ void QMetaEnumBuilder::setIsFlag(bool value)
}
/*!
+ Return \c true if this enumerator should be considered scoped (C++11 enum class).
+
+ \sa setIsScoped()
+*/
+bool QMetaEnumBuilder::isScoped() const
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ return d->isScoped;
+ return false;
+}
+
+/*!
+ Sets this enumerator to be a scoped enum if \value is true
+
+ \sa isScoped()
+*/
+void QMetaEnumBuilder::setIsScoped(bool value)
+{
+ QMetaEnumBuilderPrivate *d = d_func();
+ if (d)
+ d->isScoped = value;
+}
+
+/*!
Returns the number of keys.
\sa key(), addKey()
diff --git a/src/corelib/kernel/qmetaobjectbuilder_p.h b/src/corelib/kernel/qmetaobjectbuilder_p.h
index 144595330d..03b2afaebc 100644
--- a/src/corelib/kernel/qmetaobjectbuilder_p.h
+++ b/src/corelib/kernel/qmetaobjectbuilder_p.h
@@ -300,6 +300,9 @@ public:
bool isFlag() const;
void setIsFlag(bool value);
+ bool isScoped() const;
+ void setIsScoped(bool value);
+
int keyCount() const;
QByteArray key(int index) const;
int value(int index) const;
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index b75f2ad9dc..e48807ea49 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -308,6 +308,7 @@ struct DefinedTypesFilter {
\omitvalue TrackingPointerToQObject
\omitvalue WasDeclaredAsMetaType
\omitvalue IsGadget This type is a Q_GADGET and it's corresponding QMetaObject can be accessed with QMetaType::metaObject Since 5.5.
+ \omitvalue PointerToGadget
*/
/*!
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index d88f469e0f..f704c5b21a 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -462,7 +462,8 @@ public:
WeakPointerToQObject = 0x40,
TrackingPointerToQObject = 0x80,
WasDeclaredAsMetaType = 0x100,
- IsGadget = 0x200
+ IsGadget = 0x200,
+ PointerToGadget = 0x400
};
Q_DECLARE_FLAGS(TypeFlags, TypeFlag)
@@ -1388,6 +1389,19 @@ namespace QtPrivate
enum { Value = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) };
};
+ template<typename T, typename Enable = void>
+ struct IsPointerToGadgetHelper { enum { Value = false }; };
+
+ template<typename T>
+ struct IsPointerToGadgetHelper<T*, typename T::QtGadgetHelper>
+ {
+ using BaseType = T;
+ template <typename X>
+ static char checkType(void (X::*)());
+ static void *checkType(void (T::*)());
+ enum { Value = sizeof(checkType(&T::qt_check_for_QGADGET_macro)) == sizeof(void *) };
+ };
+
template<typename T> char qt_getEnumMetaObject(const T&);
@@ -1423,6 +1437,11 @@ namespace QtPrivate
static inline const QMetaObject *value() { return &T::staticMetaObject; }
};
template<typename T>
+ struct MetaObjectForType<T, typename QEnableIf<IsPointerToGadgetHelper<T>::Value>::Type>
+ {
+ static inline const QMetaObject *value() { return &IsPointerToGadgetHelper<T>::BaseType::staticMetaObject; }
+ };
+ template<typename T>
struct MetaObjectForType<T, typename std::enable_if<IsQEnumHelper<T>::Value>::type >
{
static inline const QMetaObject *value() { return qt_getEnumMetaObject(T()); }
@@ -1578,6 +1597,7 @@ namespace QtPrivate
template <typename T, int =
QtPrivate::IsPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::PointerToQObject :
QtPrivate::IsGadgetHelper<T>::Value ? QMetaType::IsGadget :
+ QtPrivate::IsPointerToGadgetHelper<T>::Value ? QMetaType::PointerToGadget :
QtPrivate::IsQEnumHelper<T>::Value ? QMetaType::IsEnumeration : 0>
struct QMetaTypeIdQObject
{
@@ -1631,6 +1651,7 @@ namespace QtPrivate {
| (IsTrackingPointerToTypeDerivedFromQObject<T>::Value ? QMetaType::TrackingPointerToQObject : 0)
| (std::is_enum<T>::value ? QMetaType::IsEnumeration : 0)
| (IsGadgetHelper<T>::Value ? QMetaType::IsGadget : 0)
+ | (IsPointerToGadgetHelper<T>::Value ? QMetaType::PointerToGadget : 0)
};
};
@@ -1798,6 +1819,30 @@ struct QMetaTypeIdQObject<T, QMetaType::IsGadget>
};
template <typename T>
+struct QMetaTypeIdQObject<T*, QMetaType::PointerToGadget>
+{
+ enum {
+ Defined = 1
+ };
+
+ static int qt_metatype_id()
+ {
+ static QBasicAtomicInt metatype_id = Q_BASIC_ATOMIC_INITIALIZER(0);
+ if (const int id = metatype_id.loadAcquire())
+ return id;
+ const char * const cName = T::staticMetaObject.className();
+ QByteArray typeName;
+ typeName.reserve(int(strlen(cName)) + 1);
+ typeName.append(cName).append('*');
+ const int newId = qRegisterNormalizedMetaType<T*>(
+ typeName,
+ reinterpret_cast<T**>(quintptr(-1)));
+ metatype_id.storeRelease(newId);
+ return newId;
+ }
+};
+
+template <typename T>
struct QMetaTypeIdQObject<T, QMetaType::IsEnumeration>
{
enum {
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 3f50716cd7..3b0f7ead09 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -2339,7 +2339,7 @@ static void err_info_about_objects(const char * func,
a thread different from this object's thread. Do not use this
function in this type of scenario.
- \sa senderSignalIndex(), QSignalMapper
+ \sa senderSignalIndex()
*/
QObject *QObject::sender() const
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index 6941c55896..2e66daa914 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -304,7 +304,7 @@ public:
static inline typename std::enable_if<QtPrivate::FunctionPointer<Func2>::ArgumentCount == -1, QMetaObject::Connection>::type
connect(const typename QtPrivate::FunctionPointer<Func1>::Object *sender, Func1 signal, Func2 slot)
{
- return connect(sender, signal, sender, slot, Qt::DirectConnection);
+ return connect(sender, signal, sender, std::move(slot), Qt::DirectConnection);
}
//connect to a functor, with a "context" object defining in which event loop is going to be executed
@@ -334,7 +334,7 @@ public:
return connectImpl(sender, reinterpret_cast<void **>(&signal), context, Q_NULLPTR,
new QtPrivate::QFunctorSlotObject<Func2, SlotArgumentCount,
typename QtPrivate::List_Left<typename SignalType::Arguments, SlotArgumentCount>::Value,
- typename SignalType::ReturnType>(slot),
+ typename SignalType::ReturnType>(std::move(slot)),
type, types, &SignalType::Object::staticMetaObject);
}
#endif //Q_QDOC
diff --git a/src/corelib/kernel/qobject_impl.h b/src/corelib/kernel/qobject_impl.h
index d7ae63a98c..c775d807b1 100644
--- a/src/corelib/kernel/qobject_impl.h
+++ b/src/corelib/kernel/qobject_impl.h
@@ -74,60 +74,6 @@ namespace QtPrivate {
template <typename... Args> struct ConnectionTypes<List<Args...>, true>
{ static const int *types() { static const int t[sizeof...(Args) + 1] = { (QtPrivate::QMetaTypeIdHelper<Args>::qt_metatype_id())..., 0 }; return t; } };
- // internal base class (interface) containing functions required to call a slot managed by a pointer to function.
- class QSlotObjectBase {
- QAtomicInt m_ref;
- // don't use virtual functions here; we don't want the
- // compiler to create tons of per-polymorphic-class stuff that
- // we'll never need. We just use one function pointer.
- typedef void (*ImplFn)(int which, QSlotObjectBase* this_, QObject *receiver, void **args, bool *ret);
- const ImplFn m_impl;
- protected:
- enum Operation {
- Destroy,
- Call,
- Compare,
-
- NumOperations
- };
- public:
- explicit QSlotObjectBase(ImplFn fn) : m_ref(1), m_impl(fn) {}
-
- inline int ref() Q_DECL_NOTHROW { return m_ref.ref(); }
- inline void destroyIfLastRef() Q_DECL_NOTHROW
- { if (!m_ref.deref()) m_impl(Destroy, this, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR); }
-
- inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, Q_NULLPTR, a, &ret); return ret; }
- inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, Q_NULLPTR); }
- protected:
- ~QSlotObjectBase() {}
- private:
- Q_DISABLE_COPY(QSlotObjectBase)
- };
- // implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject
- // Args and R are the List of arguments and the returntype of the signal to which the slot is connected.
- template<typename Func, typename Args, typename R> class QSlotObject : public QSlotObjectBase
- {
- typedef QtPrivate::FunctionPointer<Func> FuncType;
- Func function;
- static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
- {
- switch (which) {
- case Destroy:
- delete static_cast<QSlotObject*>(this_);
- break;
- case Call:
- FuncType::template call<Args, R>(static_cast<QSlotObject*>(this_)->function, static_cast<typename FuncType::Object *>(r), a);
- break;
- case Compare:
- *ret = *reinterpret_cast<Func *>(a) == static_cast<QSlotObject*>(this_)->function;
- break;
- case NumOperations: ;
- }
- }
- public:
- explicit QSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {}
- };
// implementation of QSlotObjectBase for which the slot is a static function
// Args and R are the List of arguments and the returntype of the signal to which the slot is connected.
template<typename Func, typename Args, typename R> class QStaticSlotObject : public QSlotObjectBase
@@ -151,30 +97,6 @@ namespace QtPrivate {
public:
explicit QStaticSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {}
};
- // implementation of QSlotObjectBase for which the slot is a functor (or lambda)
- // N is the number of arguments
- // Args and R are the List of arguments and the returntype of the signal to which the slot is connected.
- template<typename Func, int N, typename Args, typename R> class QFunctorSlotObject : public QSlotObjectBase
- {
- typedef QtPrivate::Functor<Func, N> FuncType;
- Func function;
- static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
- {
- switch (which) {
- case Destroy:
- delete static_cast<QFunctorSlotObject*>(this_);
- break;
- case Call:
- FuncType::template call<Args, R>(static_cast<QFunctorSlotObject*>(this_)->function, r, a);
- break;
- case Compare: // not implemented
- case NumOperations:
- Q_UNUSED(ret);
- }
- }
- public:
- explicit QFunctorSlotObject(const Func &f) : QSlotObjectBase(&impl), function(f) {}
- };
}
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 7b9253ac64..ad88bcf274 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -235,7 +235,7 @@ public:
mutable quint32 connectedSignals[2];
union {
- QObject *currentChildBeingDeleted;
+ QObject *currentChildBeingDeleted; // should only be used when QObjectData::isDeletingChildren is set
QAbstractDeclarativeData *declarativeData; //extra data used by the declarative module
};
@@ -244,6 +244,7 @@ public:
QAtomicPointer<QtSharedPointer::ExternalRefCountData> sharedRefcount;
};
+Q_DECLARE_TYPEINFO(QObjectPrivate::ConnectionList, Q_MOVABLE_TYPE);
/*! \internal
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index cec822ad14..5fc8937f23 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -57,7 +57,6 @@ struct QArrayData;
typedef QArrayData QByteArrayData;
class QString;
-
#ifndef Q_MOC_OUTPUT_REVISION
#define Q_MOC_OUTPUT_REVISION 67
#endif
@@ -467,6 +466,91 @@ struct Q_CORE_EXPORT QMetaObject
val1, val2, val3, val4, val5, val6, val7, val8, val9);
}
+#ifdef Q_QDOC
+ template<typename PointerToMemberFunction, typename MemberFunctionReturnType>
+ static bool invokeMethod(QObject *receiver, PointerToMemberFunction function, Qt::ConnectionType type = Qt::AutoConnection, MemberFunctionReturnType *ret = nullptr);
+ template<typename PointerToMemberFunction, typename MemberFunctionReturnType>
+ static bool invokeMethod(QObject *receiver, PointerToMemberFunction function, MemberFunctionReturnType *ret);
+ template<typename Functor, typename FunctorReturnType>
+ static bool invokeMethod(QObject *context, Functor function, Qt::ConnectionType type = Qt::AutoConnection, FunctorReturnType *ret = nullptr);
+ template<typename Functor, typename FunctorReturnType>
+ static bool invokeMethod(QObject *context, Functor function, FunctorReturnType *ret);
+#else
+
+ // invokeMethod() for member function pointer
+ template <typename Func>
+ static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
+ && !std::is_convertible<Func, const char*>::value
+ && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
+ invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object,
+ Func function,
+ Qt::ConnectionType type = Qt::AutoConnection,
+ typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr)
+ {
+ return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), type, ret);
+ }
+
+ template <typename Func>
+ static typename std::enable_if<QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
+ && !std::is_convertible<Func, const char*>::value
+ && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
+ invokeMethod(typename QtPrivate::FunctionPointer<Func>::Object *object,
+ Func function,
+ typename QtPrivate::FunctionPointer<Func>::ReturnType *ret)
+ {
+ return invokeMethodImpl(object, new QtPrivate::QSlotObjectWithNoArgs<Func>(function), Qt::AutoConnection, ret);
+ }
+
+ // invokeMethod() for function pointer (not member)
+ template <typename Func>
+ static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
+ && !std::is_convertible<Func, const char*>::value
+ && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
+ invokeMethod(QObject *context, Func function,
+ Qt::ConnectionType type = Qt::AutoConnection,
+ typename QtPrivate::FunctionPointer<Func>::ReturnType *ret = nullptr)
+ {
+ return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), type, ret);
+ }
+
+ template <typename Func>
+ static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
+ && !std::is_convertible<Func, const char*>::value
+ && QtPrivate::FunctionPointer<Func>::ArgumentCount == 0, bool>::type
+ invokeMethod(QObject *context, Func function,
+ typename QtPrivate::FunctionPointer<Func>::ReturnType *ret)
+ {
+ return invokeMethodImpl(context, new QtPrivate::QFunctorSlotObjectWithNoArgsImplicitReturn<Func>(function), Qt::AutoConnection, ret);
+ }
+
+ // invokeMethod() for Functor
+ template <typename Func>
+ static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
+ && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1
+ && !std::is_convertible<Func, const char*>::value, bool>::type
+ invokeMethod(QObject *context, Func function,
+ Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr)
+ {
+ return invokeMethodImpl(context,
+ new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
+ type,
+ ret);
+ }
+
+ template <typename Func>
+ static typename std::enable_if<!QtPrivate::FunctionPointer<Func>::IsPointerToMemberFunction
+ && QtPrivate::FunctionPointer<Func>::ArgumentCount == -1
+ && !std::is_convertible<Func, const char*>::value, bool>::type
+ invokeMethod(QObject *context, Func function, typename std::result_of<Func()>::type *ret)
+ {
+ return invokeMethodImpl(context,
+ new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
+ Qt::AutoConnection,
+ ret);
+ }
+
+#endif
+
QObject *newInstance(QGenericArgument val0 = QGenericArgument(Q_NULLPTR),
QGenericArgument val1 = QGenericArgument(),
QGenericArgument val2 = QGenericArgument(),
@@ -506,6 +590,9 @@ struct Q_CORE_EXPORT QMetaObject
const QMetaObject * const *relatedMetaObjects;
void *extradata; //reserved for future use
} d;
+
+private:
+ static bool invokeMethodImpl(QObject *object, QtPrivate::QSlotObjectBase *slot, Qt::ConnectionType type, void *ret);
};
class Q_CORE_EXPORT QMetaObject::Connection {
diff --git a/src/corelib/kernel/qobjectdefs_impl.h b/src/corelib/kernel/qobjectdefs_impl.h
index 29ab77b269..b9f2e47e32 100644
--- a/src/corelib/kernel/qobjectdefs_impl.h
+++ b/src/corelib/kernel/qobjectdefs_impl.h
@@ -51,7 +51,7 @@
#endif
QT_BEGIN_NAMESPACE
-
+class QObject;
namespace QtPrivate {
template <typename T> struct RemoveRef { typedef T Type; };
@@ -350,6 +350,98 @@ namespace QtPrivate {
template <typename D> static D dummy();
typedef decltype(dummy<Functor>().operator()((dummy<ArgList>())...)) Value;
};
+
+ // internal base class (interface) containing functions required to call a slot managed by a pointer to function.
+ class QSlotObjectBase {
+ QAtomicInt m_ref;
+ // don't use virtual functions here; we don't want the
+ // compiler to create tons of per-polymorphic-class stuff that
+ // we'll never need. We just use one function pointer.
+ typedef void (*ImplFn)(int which, QSlotObjectBase* this_, QObject *receiver, void **args, bool *ret);
+ const ImplFn m_impl;
+ protected:
+ enum Operation {
+ Destroy,
+ Call,
+ Compare,
+
+ NumOperations
+ };
+ public:
+ explicit QSlotObjectBase(ImplFn fn) : m_ref(1), m_impl(fn) {}
+
+ inline int ref() Q_DECL_NOTHROW { return m_ref.ref(); }
+ inline void destroyIfLastRef() Q_DECL_NOTHROW
+ { if (!m_ref.deref()) m_impl(Destroy, this, Q_NULLPTR, Q_NULLPTR, Q_NULLPTR); }
+
+ inline bool compare(void **a) { bool ret = false; m_impl(Compare, this, Q_NULLPTR, a, &ret); return ret; }
+ inline void call(QObject *r, void **a) { m_impl(Call, this, r, a, Q_NULLPTR); }
+ protected:
+ ~QSlotObjectBase() {}
+ private:
+ Q_DISABLE_COPY(QSlotObjectBase)
+ };
+
+ // implementation of QSlotObjectBase for which the slot is a pointer to member function of a QObject
+ // Args and R are the List of arguments and the returntype of the signal to which the slot is connected.
+ template<typename Func, typename Args, typename R> class QSlotObject : public QSlotObjectBase
+ {
+ typedef QtPrivate::FunctionPointer<Func> FuncType;
+ Func function;
+ static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
+ {
+ switch (which) {
+ case Destroy:
+ delete static_cast<QSlotObject*>(this_);
+ break;
+ case Call:
+ FuncType::template call<Args, R>(static_cast<QSlotObject*>(this_)->function, static_cast<typename FuncType::Object *>(r), a);
+ break;
+ case Compare:
+ *ret = *reinterpret_cast<Func *>(a) == static_cast<QSlotObject*>(this_)->function;
+ break;
+ case NumOperations: ;
+ }
+ }
+ public:
+ explicit QSlotObject(Func f) : QSlotObjectBase(&impl), function(f) {}
+ };
+ // implementation of QSlotObjectBase for which the slot is a functor (or lambda)
+ // N is the number of arguments
+ // Args and R are the List of arguments and the returntype of the signal to which the slot is connected.
+ template<typename Func, int N, typename Args, typename R> class QFunctorSlotObject : public QSlotObjectBase
+ {
+ typedef QtPrivate::Functor<Func, N> FuncType;
+ Func function;
+ static void impl(int which, QSlotObjectBase *this_, QObject *r, void **a, bool *ret)
+ {
+ switch (which) {
+ case Destroy:
+ delete static_cast<QFunctorSlotObject*>(this_);
+ break;
+ case Call:
+ FuncType::template call<Args, R>(static_cast<QFunctorSlotObject*>(this_)->function, r, a);
+ break;
+ case Compare: // not implemented
+ case NumOperations:
+ Q_UNUSED(ret);
+ }
+ }
+ public:
+ explicit QFunctorSlotObject(Func f) : QSlotObjectBase(&impl), function(std::move(f)) {}
+ };
+
+ // typedefs for readability for when there are no parameters
+ template <typename Func>
+ using QSlotObjectWithNoArgs = QSlotObject<Func,
+ QtPrivate::List<>,
+ typename QtPrivate::FunctionPointer<Func>::ReturnType>;
+
+ template <typename Func, typename R>
+ using QFunctorSlotObjectWithNoArgs = QFunctorSlotObject<Func, 0, QtPrivate::List<>, R>;
+
+ template <typename Func>
+ using QFunctorSlotObjectWithNoArgsImplicitReturn = QFunctorSlotObjectWithNoArgs<Func, typename QtPrivate::FunctionPointer<Func>::ReturnType>;
}
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp
index a483717da5..d56965281e 100644
--- a/src/corelib/kernel/qsignalmapper.cpp
+++ b/src/corelib/kernel/qsignalmapper.cpp
@@ -58,10 +58,10 @@ public:
};
-
/*!
\class QSignalMapper
\inmodule QtCore
+ \obsolete
\brief The QSignalMapper class bundles signals from identifiable senders.
\ingroup objectmodel
@@ -108,6 +108,12 @@ public:
widget will emit a single \c clicked() signal whose argument is
the text of the button the user clicked.
+ This class was mostly useful before lambda functions could be used as
+ slots. The example above can be rewritten simpler without QSignalMapper
+ by connecting to a lambda function.
+
+ \snippet qsignalmapper/buttonwidget.cpp 3
+
\sa QObject, QButtonGroup, QActionGroup
*/
diff --git a/src/corelib/kernel/qsignalmapper.h b/src/corelib/kernel/qsignalmapper.h
index f960c7cabf..6c4cfa9627 100644
--- a/src/corelib/kernel/qsignalmapper.h
+++ b/src/corelib/kernel/qsignalmapper.h
@@ -42,6 +42,8 @@
#include <QtCore/qobject.h>
+#if QT_DEPRECATED_SINCE(5, 10)
+
QT_BEGIN_NAMESPACE
class QSignalMapperPrivate;
@@ -51,7 +53,7 @@ class Q_CORE_EXPORT QSignalMapper : public QObject
Q_OBJECT
Q_DECLARE_PRIVATE(QSignalMapper)
public:
- explicit QSignalMapper(QObject *parent = Q_NULLPTR);
+ QT_DEPRECATED explicit QSignalMapper(QObject *parent = nullptr);
~QSignalMapper();
void setMapping(QObject *sender, int id);
@@ -82,4 +84,6 @@ private:
QT_END_NAMESPACE
+#endif
+
#endif // QSIGNALMAPPER_H
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index 6e61ca10cb..7db5fc759b 100644
--- a/src/corelib/kernel/qtimer.h
+++ b/src/corelib/kernel/qtimer.h
@@ -122,14 +122,14 @@ public:
!std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval, Func1 slot)
{
- singleShot(interval, defaultTypeFor(interval), nullptr, slot);
+ singleShot(interval, defaultTypeFor(interval), nullptr, std::move(slot));
}
template <typename Duration, typename Func1>
static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
!std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval, Qt::TimerType timerType, Func1 slot)
{
- singleShot(interval, timerType, nullptr, slot);
+ singleShot(interval, timerType, nullptr, std::move(slot));
}
// singleShot to a functor or function pointer (with context)
template <typename Duration, typename Func1>
@@ -137,7 +137,7 @@ public:
!std::is_same<const char*, Func1>::value, void>::type
singleShot(Duration interval, QObject *context, Func1 slot)
{
- singleShot(interval, defaultTypeFor(interval), context, slot);
+ singleShot(interval, defaultTypeFor(interval), context, std::move(slot));
}
template <typename Duration, typename Func1>
static inline typename std::enable_if<!QtPrivate::FunctionPointer<Func1>::IsPointerToMemberFunction &&
@@ -150,7 +150,7 @@ public:
singleShotImpl(interval, timerType, context,
new QtPrivate::QFunctorSlotObject<Func1, 0,
- typename QtPrivate::List_Left<void, 0>::Value, void>(slot));
+ typename QtPrivate::List_Left<void, 0>::Value, void>(std::move(slot)));
}
#endif
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index e6262124fb..b79716ff4c 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -470,6 +470,9 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
case QVariant::Uuid:
*str = v_cast<QUuid>(d)->toString();
break;
+ case QMetaType::Nullptr:
+ *str = QString();
+ break;
default:
#ifndef QT_NO_QOBJECT
{
@@ -652,6 +655,9 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
case QVariant::Uuid:
*ba = v_cast<QUuid>(d)->toByteArray();
break;
+ case QMetaType::Nullptr:
+ *ba = QByteArray();
+ break;
default:
#ifndef QT_NO_QOBJECT
{
@@ -938,6 +944,107 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok)
return false;
}
break;
+#ifndef QT_BOOTSTRAPPED
+ case QMetaType::QJsonValue:
+ switch (d->type) {
+ case QMetaType::Nullptr:
+ *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Null);
+ break;
+ case QVariant::Bool:
+ *static_cast<QJsonValue *>(result) = QJsonValue(d->data.b);
+ break;
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ case QMetaType::Double:
+ case QMetaType::Float:
+ case QMetaType::ULong:
+ case QMetaType::Long:
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ case QMetaType::UShort:
+ case QMetaType::UChar:
+ case QMetaType::Char:
+ case QMetaType::SChar:
+ case QMetaType::Short:
+ *static_cast<QJsonValue *>(result) = QJsonValue(qConvertToRealNumber(d, ok));
+ Q_ASSERT(ok);
+ break;
+ case QVariant::String:
+ *static_cast<QJsonValue *>(result) = QJsonValue(*v_cast<QString>(d));
+ break;
+ case QVariant::StringList:
+ *static_cast<QJsonValue *>(result) = QJsonValue(QJsonArray::fromStringList(*v_cast<QStringList>(d)));
+ break;
+ case QVariant::List:
+ *static_cast<QJsonValue *>(result) = QJsonValue(QJsonArray::fromVariantList(*v_cast<QVariantList>(d)));
+ break;
+ case QVariant::Map:
+ *static_cast<QJsonValue *>(result) = QJsonValue(QJsonObject::fromVariantMap(*v_cast<QVariantMap>(d)));
+ break;
+ case QVariant::Hash:
+ *static_cast<QJsonValue *>(result) = QJsonValue(QJsonObject::fromVariantHash(*v_cast<QVariantHash>(d)));
+ break;
+ case QMetaType::QJsonObject:
+ *static_cast<QJsonValue *>(result) = *v_cast<QJsonObject>(d);
+ break;
+ case QMetaType::QJsonArray:
+ *static_cast<QJsonValue *>(result) = *v_cast<QJsonArray>(d);
+ break;
+ case QMetaType::QJsonDocument: {
+ QJsonDocument doc = *v_cast<QJsonDocument>(d);
+ *static_cast<QJsonValue *>(result) = doc.isArray() ? QJsonValue(doc.array()) : QJsonValue(doc.object());
+ break;
+ }
+ default:
+ *static_cast<QJsonValue *>(result) = QJsonValue(QJsonValue::Undefined);
+ return false;
+ }
+ break;
+ case QMetaType::QJsonArray:
+ switch (d->type) {
+ case QVariant::StringList:
+ *static_cast<QJsonArray *>(result) = QJsonArray::fromStringList(*v_cast<QStringList>(d));
+ break;
+ case QVariant::List:
+ *static_cast<QJsonArray *>(result) = QJsonArray::fromVariantList(*v_cast<QVariantList>(d));
+ break;
+ case QMetaType::QJsonValue:
+ if (!v_cast<QJsonValue>(d)->isArray())
+ return false;
+ *static_cast<QJsonArray *>(result) = v_cast<QJsonValue>(d)->toArray();
+ break;
+ case QMetaType::QJsonDocument:
+ if (!v_cast<QJsonDocument>(d)->isArray())
+ return false;
+ *static_cast<QJsonArray *>(result) = v_cast<QJsonDocument>(d)->array();
+ break;
+ default:
+ return false;
+ }
+ break;
+ case QMetaType::QJsonObject:
+ switch (d->type) {
+ case QVariant::Map:
+ *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantMap(*v_cast<QVariantMap>(d));
+ break;
+ case QVariant::Hash:
+ *static_cast<QJsonObject *>(result) = QJsonObject::fromVariantHash(*v_cast<QVariantHash>(d));
+ break;
+ case QMetaType::QJsonValue:
+ if (!v_cast<QJsonValue>(d)->isObject())
+ return false;
+ *static_cast<QJsonObject *>(result) = v_cast<QJsonValue>(d)->toObject();
+ break;
+ case QMetaType::QJsonDocument:
+ if (v_cast<QJsonDocument>(d)->isArray())
+ return false;
+ *static_cast<QJsonObject *>(result) = v_cast<QJsonDocument>(d)->object();
+ break;
+ default:
+ return false;
+ }
+ break;
+#endif
default:
#ifndef QT_NO_QOBJECT
if (d->type == QVariant::String || d->type == QVariant::ByteArray) {
@@ -1076,7 +1183,17 @@ static void customClear(QVariant::Private *d)
static bool customIsNull(const QVariant::Private *d)
{
- return d->is_null;
+ if (d->is_null)
+ return true;
+ const char *const typeName = QMetaType::typeName(d->type);
+ if (Q_UNLIKELY(!typeName) && Q_LIKELY(!QMetaType::isRegistered(d->type)))
+ qFatal("QVariant::isNull: type %d unknown to QVariant.", d->type);
+ uint typeNameLen = qstrlen(typeName);
+ if (typeNameLen > 0 && typeName[typeNameLen - 1] == '*') {
+ const void *d_ptr = d->is_shared ? d->data.shared->ptr : &(d->data.ptr);
+ return *static_cast<void *const *>(d_ptr) == nullptr;
+ }
+ return false;
}
static bool customCompare(const QVariant::Private *a, const QVariant::Private *b)
@@ -1358,7 +1475,11 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names
/*!
\fn QVariant::QVariant(Type type)
- Constructs a null variant of type \a type.
+ Constructs an uninitialized variant of type \a type. This will create a
+ variant in a special null state that if accessed will return a default
+ constructed value of the \a type.
+
+ \sa isNull()
*/
@@ -3106,8 +3227,8 @@ bool QVariant::canConvert(int targetTypeId) const
}
}
- if (currentType == QMetaType::QJsonValue) {
- switch (targetTypeId) {
+ if (currentType == QMetaType::QJsonValue || targetTypeId == QMetaType::QJsonValue) {
+ switch (currentType == QMetaType::QJsonValue ? targetTypeId : currentType) {
case QMetaType::Nullptr:
case QMetaType::QString:
case QMetaType::Bool:
@@ -3163,11 +3284,11 @@ bool QVariant::canConvert(int targetTypeId) const
case QVariant::Bitmap:
return currentType == QVariant::Pixmap || currentType == QVariant::Image;
case QVariant::ByteArray:
- return currentType == QVariant::Color
+ return currentType == QVariant::Color || currentType == QMetaType::Nullptr
|| ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
case QVariant::String:
return currentType == QVariant::KeySequence || currentType == QVariant::Font
- || currentType == QVariant::Color
+ || currentType == QVariant::Color || currentType == QMetaType::Nullptr
|| ((QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration) && QMetaType::metaObjectForType(currentType));
case QVariant::KeySequence:
return currentType == QVariant::String || currentType == QVariant::Int;
@@ -3204,17 +3325,20 @@ bool QVariant::canConvert(int targetTypeId) const
/*!
Casts the variant to the requested type, \a targetTypeId. If the cast cannot be
- done, the variant is cleared. Returns \c true if the current type of
- the variant was successfully cast; otherwise returns \c false.
+ done, the variant is still changed to the requested type, but is left in a cleared
+ null state similar to that constructed by QVariant(Type).
+
+ Returns \c true if the current type of the variant was successfully cast;
+ otherwise returns \c false.
A QVariant containing a pointer to a type derived from QObject will also convert
and return true for this function if a qobject_cast to the type described
by \a targetTypeId would succeed. Note that this only works for QObject subclasses
which use the Q_OBJECT macro.
- \warning For historical reasons, converting a null QVariant results
- in a null value of the desired type (e.g., an empty string for
- QString) and a result of false.
+ \note converting QVariants that are null due to not being initialized or having
+ failed a previous conversion will always fail, changing the type, remaining null,
+ and returning \c false.
\sa canConvert(), clear()
*/
@@ -3231,7 +3355,8 @@ bool QVariant::convert(int targetTypeId)
return false;
create(targetTypeId, 0);
- if (oldValue.isNull())
+ // Fail if the value is not initialized or was forced null by a previous failed convert.
+ if (oldValue.d.is_null)
return false;
if ((QMetaType::typeFlags(oldValue.userType()) & QMetaType::PointerToQObject) && (QMetaType::typeFlags(targetTypeId) & QMetaType::PointerToQObject)) {
@@ -3631,12 +3756,15 @@ void* QVariant::data()
/*!
Returns \c true if this is a null variant, false otherwise. A variant is
- considered null if it contains a default constructed value or a built-in
- type instance that has an isNull method, in which case the result
- would be the same as calling isNull on the wrapped object.
+ considered null if it contains no initialized value, or the contained value
+ is a null pointer or is an instance of a built-in type that has an isNull
+ method, in which case the result would be the same as calling isNull on the
+ wrapped object.
+
+ \warning Null variants is not a single state and two null variants may easily
+ return \c false on the == operator if they do not contain similar null values.
- \warning The result of the function doesn't affect == operator, which means
- that two values can be equal even if one of them is null and another is not.
+ \sa QVariant(Type), convert(int)
*/
bool QVariant::isNull() const
{
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 487949431c..75c269d710 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -187,6 +187,16 @@ public:
}
};
+template <typename T>
+struct PrimitiveIsNull<T*>
+{
+public:
+ static bool isNull(const QVariant::Private *d)
+ {
+ return d->is_null || d->data.ptr == nullptr;
+ }
+};
+
template <>
struct PrimitiveIsNull<std::nullptr_t>
{
diff --git a/src/corelib/kernel/qwineventnotifier.cpp b/src/corelib/kernel/qwineventnotifier.cpp
index 0808374a6a..6bfa6ca729 100644
--- a/src/corelib/kernel/qwineventnotifier.cpp
+++ b/src/corelib/kernel/qwineventnotifier.cpp
@@ -37,7 +37,7 @@
**
****************************************************************************/
-#include "qwineventnotifier.h"
+#include "qwineventnotifier_p.h"
#ifdef Q_OS_WINRT
#include "qeventdispatcher_winrt_p.h"
@@ -50,19 +50,6 @@
QT_BEGIN_NAMESPACE
-class QWinEventNotifierPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QWinEventNotifier)
-public:
- QWinEventNotifierPrivate()
- : handleToEvent(0), enabled(false) {}
- QWinEventNotifierPrivate(HANDLE h, bool e)
- : handleToEvent(h), enabled(e) {}
-
- HANDLE handleToEvent;
- bool enabled;
-};
-
/*!
\class QWinEventNotifier
\inmodule QtCore
@@ -246,4 +233,49 @@ bool QWinEventNotifier::event(QEvent * e)
return false;
}
+#if defined(Q_OS_WINRT)
+
+bool QWinEventNotifierPrivate::registerWaitObject()
+{
+ Q_UNIMPLEMENTED();
+ return false;
+}
+
+void QWinEventNotifierPrivate::unregisterWaitObject()
+{
+ Q_UNIMPLEMENTED();
+}
+
+#else // defined(Q_OS_WINRT)
+
+static void CALLBACK wfsoCallback(void *context, BOOLEAN /*ignore*/)
+{
+ QWinEventNotifierPrivate *nd = reinterpret_cast<QWinEventNotifierPrivate *>(context);
+ QAbstractEventDispatcher *eventDispatcher = nd->threadData->eventDispatcher.load();
+ QEventDispatcherWin32Private *edp = QEventDispatcherWin32Private::get(
+ static_cast<QEventDispatcherWin32 *>(eventDispatcher));
+ SetEvent(edp->winEventNotifierActivatedEvent);
+}
+
+bool QWinEventNotifierPrivate::registerWaitObject()
+{
+ if (RegisterWaitForSingleObject(&waitHandle, handleToEvent, wfsoCallback, this,
+ INFINITE, WT_EXECUTEONLYONCE) == 0) {
+ qErrnoWarning("QWinEventNotifier: RegisterWaitForSingleObject failed.");
+ return false;
+ }
+ return true;
+}
+
+void QWinEventNotifierPrivate::unregisterWaitObject()
+{
+ // Unregister the wait handle and wait for pending callbacks to finish.
+ if (UnregisterWaitEx(waitHandle, INVALID_HANDLE_VALUE))
+ waitHandle = NULL;
+ else
+ qErrnoWarning("QWinEventNotifier: UnregisterWaitEx failed.");
+}
+
+#endif // !defined(Q_OS_WINRT)
+
QT_END_NAMESPACE
diff --git a/src/corelib/io/qwinoverlappedionotifier_p.h b/src/corelib/kernel/qwineventnotifier_p.h
index 276a1d861e..bddeaaf134 100644
--- a/src/corelib/io/qwinoverlappedionotifier_p.h
+++ b/src/corelib/kernel/qwineventnotifier_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QWINOVERLAPPEDIONOTIFIER_P_H
-#define QWINOVERLAPPEDIONOTIFIER_P_H
+#ifndef QWINEVENTNOTIFIER_P_H
+#define QWINEVENTNOTIFIER_P_H
//
// W A R N I N G
@@ -51,40 +51,31 @@
// We mean it.
//
-#include <QtCore/private/qglobal_p.h>
-#include <qobject.h>
+#include "qwineventnotifier.h"
-typedef struct _OVERLAPPED OVERLAPPED;
+#include <private/qobject_p.h>
+#include <QtCore/qt_windows.h>
QT_BEGIN_NAMESPACE
-class QWinOverlappedIoNotifierPrivate;
-
-class Q_CORE_EXPORT QWinOverlappedIoNotifier : public QObject
+class QWinEventNotifierPrivate : public QObjectPrivate
{
- Q_OBJECT
- Q_DISABLE_COPY(QWinOverlappedIoNotifier)
- Q_DECLARE_PRIVATE(QWinOverlappedIoNotifier)
- Q_PRIVATE_SLOT(d_func(), void _q_notified())
- friend class QWinIoCompletionPort;
+ Q_DECLARE_PUBLIC(QWinEventNotifier)
public:
- QWinOverlappedIoNotifier(QObject *parent = 0);
- ~QWinOverlappedIoNotifier();
-
- void setHandle(Qt::HANDLE h);
- Qt::HANDLE handle() const;
+ QWinEventNotifierPrivate()
+ : handleToEvent(0), enabled(false) {}
+ QWinEventNotifierPrivate(HANDLE h, bool e)
+ : handleToEvent(h), enabled(e) {}
- void setEnabled(bool enabled);
- OVERLAPPED *waitForAnyNotified(int msecs);
- bool waitForNotified(int msecs, OVERLAPPED *overlapped);
+ static QWinEventNotifierPrivate *get(QWinEventNotifier *q) { return q->d_func(); }
+ bool registerWaitObject();
+ void unregisterWaitObject();
-Q_SIGNALS:
- void notified(quint32 numberOfBytes, quint32 errorCode, OVERLAPPED *overlapped);
-#if !defined(Q_QDOC)
- void _q_notify();
-#endif
+ HANDLE handleToEvent;
+ HANDLE waitHandle = NULL;
+ bool enabled;
};
QT_END_NAMESPACE
-#endif // QWINOVERLAPPEDIONOTIFIER_P_H
+#endif // QWINEVENTNOTIFIER_P_H
diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp
index 5c0acce4c3..ed7ebb2ef5 100644
--- a/src/corelib/mimetypes/qmimeprovider.cpp
+++ b/src/corelib/mimetypes/qmimeprovider.cpp
@@ -655,7 +655,7 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data)
}
// Binary search in the icons or generic-icons list
-QString QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime)
+QLatin1String QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime)
{
const int iconsListOffset = cacheFile->getUint32(posListOffset);
const int numIcons = cacheFile->getUint32(iconsListOffset);
@@ -676,7 +676,7 @@ QString QMimeBinaryProvider::iconForMime(CacheFile *cacheFile, int posListOffset
return QLatin1String(cacheFile->getCharStar(iconOffset));
}
}
- return QString();
+ return QLatin1String();
}
void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
@@ -684,7 +684,7 @@ void QMimeBinaryProvider::loadIcon(QMimeTypePrivate &data)
checkCache();
const QByteArray inputMime = data.name.toLatin1();
for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- const QString icon = iconForMime(cacheFile, PosIconsListOffset, inputMime);
+ const QLatin1String icon = iconForMime(cacheFile, PosIconsListOffset, inputMime);
if (!icon.isEmpty()) {
data.iconName = icon;
return;
@@ -697,7 +697,7 @@ void QMimeBinaryProvider::loadGenericIcon(QMimeTypePrivate &data)
checkCache();
const QByteArray inputMime = data.name.toLatin1();
for (CacheFile *cacheFile : qAsConst(m_cacheFiles)) {
- const QString icon = iconForMime(cacheFile, PosGenericIconsListOffset, inputMime);
+ const QLatin1String icon = iconForMime(cacheFile, PosGenericIconsListOffset, inputMime);
if (!icon.isEmpty()) {
data.genericIconName = icon;
return;
diff --git a/src/corelib/mimetypes/qmimeprovider_p.h b/src/corelib/mimetypes/qmimeprovider_p.h
index f410e62267..0be01d2fd0 100644
--- a/src/corelib/mimetypes/qmimeprovider_p.h
+++ b/src/corelib/mimetypes/qmimeprovider_p.h
@@ -116,7 +116,7 @@ private:
void matchGlobList(QMimeGlobMatchResult &result, CacheFile *cacheFile, int offset, const QString &fileName);
bool matchSuffixTree(QMimeGlobMatchResult &result, CacheFile *cacheFile, int numEntries, int firstOffset, const QString &fileName, int charPos, bool caseSensitiveCheck);
bool matchMagicRule(CacheFile *cacheFile, int numMatchlets, int firstOffset, const QByteArray &data);
- QString iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
+ QLatin1String iconForMime(CacheFile *cacheFile, int posListOffset, const QByteArray &inputMime);
void loadMimeTypeList();
void checkCache();
diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp
index 98a0e8eb1b..28113babfe 100644
--- a/src/corelib/mimetypes/qmimetype.cpp
+++ b/src/corelib/mimetypes/qmimetype.cpp
@@ -206,10 +206,14 @@ uint qHash(const QMimeType &key, uint seed) Q_DECL_NOTHROW
*/
/*!
- \fn bool QMimeType::isValid() const;
- Returns \c true if the QMimeType object contains valid data, otherwise returns \c false.
+ \property QMimeType::valid
+ \brief \c true if the QMimeType object contains valid data, \c false otherwise
+
A valid MIME type has a non-empty name().
The invalid MIME type is the default-constructed QMimeType.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
bool QMimeType::isValid() const
{
@@ -217,9 +221,12 @@ bool QMimeType::isValid() const
}
/*!
- \fn bool QMimeType::isDefault() const;
- Returns \c true if this MIME type is the default MIME type which
+ \property QMimeType::isDefault
+ \brief \c true if this MIME type is the default MIME type which
applies to all files: application/octet-stream.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
bool QMimeType::isDefault() const
{
@@ -227,8 +234,11 @@ bool QMimeType::isDefault() const
}
/*!
- \fn QString QMimeType::name() const;
- Returns the name of the MIME type.
+ \property QMimeType::name
+ \brief the name of the MIME type
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QString QMimeType::name() const
{
@@ -236,9 +246,13 @@ QString QMimeType::name() const
}
/*!
- Returns the description of the MIME type to be displayed on user interfaces.
+ \property QMimeType::comment
+ \brief the description of the MIME type to be displayed on user interfaces
The default language (QLocale().name()) is used to select the appropriate translation.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QString QMimeType::comment() const
{
@@ -267,8 +281,8 @@ QString QMimeType::comment() const
}
/*!
- \fn QString QMimeType::genericIconName() const;
- Returns the file name of a generic icon that represents the MIME type.
+ \property QMimeType::genericIconName
+ \brief the file name of a generic icon that represents the MIME type
This should be used if the icon returned by iconName() cannot be found on
the system. It is used for categories of similar types (like spreadsheets
@@ -276,6 +290,9 @@ QString QMimeType::comment() const
The freedesktop.org Icon Naming Specification lists a set of such icon names.
The icon name can be given to QIcon::fromTheme() in order to load the icon.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QString QMimeType::genericIconName() const
{
@@ -297,10 +314,13 @@ QString QMimeType::genericIconName() const
}
/*!
- \fn QString QMimeType::iconName() const;
- Returns the file name of an icon image that represents the MIME type.
+ \property QMimeType::iconName
+ \brief the file name of an icon image that represents the MIME type
The icon name can be given to QIcon::fromTheme() in order to load the icon.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QString QMimeType::iconName() const
{
@@ -316,8 +336,11 @@ QString QMimeType::iconName() const
}
/*!
- \fn QStringList QMimeType::globPatterns() const;
- Returns the list of glob matching patterns.
+ \property QMimeType::globPatterns
+ \brief the list of glob matching patterns
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QStringList QMimeType::globPatterns() const
{
@@ -326,6 +349,9 @@ QStringList QMimeType::globPatterns() const
}
/*!
+ \property QMimeType::parentMimeTypes
+ \brief the names of parent MIME types
+
A type is a subclass of another type if any instance of the first type is
also an instance of the second. For example, all image/svg+xml files are also
text/xml, text/plain and application/octet-stream files. Subclassing is about
@@ -336,6 +362,9 @@ QStringList QMimeType::globPatterns() const
A mimetype can have multiple parents. For instance application/x-perl
has two parents: application/x-executable and text/plain. This makes
it possible to both execute perl scripts, and to open them in text editors.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QStringList QMimeType::parentMimeTypes() const
{
@@ -357,6 +386,9 @@ static void collectParentMimeTypes(const QString &mime, QStringList &allParents)
}
/*!
+ \property QMimeType::allAncestors
+ \brief the names of direct and indirect parent MIME types
+
Return all the parent mimetypes of this mimetype, direct and indirect.
This includes the parent(s) of its parent(s), etc.
@@ -365,6 +397,9 @@ static void collectParentMimeTypes(const QString &mime, QStringList &allParents)
Note that application/octet-stream is the ultimate parent for all types
of files (but not directories).
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QStringList QMimeType::allAncestors() const
{
@@ -374,7 +409,8 @@ QStringList QMimeType::allAncestors() const
}
/*!
- Return the list of aliases of this mimetype.
+ \property QMimeType::aliases
+ \brief the list of aliases of this mimetype
For instance, for text/csv, the returned list would be:
text/x-csv, text/x-comma-separated-values.
@@ -383,6 +419,9 @@ QStringList QMimeType::allAncestors() const
never to aliases directly.
The order of the aliases in the list is undefined.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QStringList QMimeType::aliases() const
{
@@ -390,8 +429,13 @@ QStringList QMimeType::aliases() const
}
/*!
- Returns the known suffixes for the MIME type.
+ \property QMimeType::suffixes
+ \brief the known suffixes for the MIME type
+
No leading dot is included, so for instance this would return "jpg", "jpeg" for image/jpeg.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QStringList QMimeType::suffixes() const
{
@@ -412,9 +456,14 @@ QStringList QMimeType::suffixes() const
}
/*!
- Returns the preferred suffix for the MIME type.
+ \property QMimeType::preferredSuffix
+ \brief the preferred suffix for the MIME type
+
No leading dot is included, so for instance this would return "pdf" for application/pdf.
The return value can be empty, for mime types which do not have any suffixes associated.
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QString QMimeType::preferredSuffix() const
{
@@ -423,8 +472,11 @@ QString QMimeType::preferredSuffix() const
}
/*!
- \fn QString QMimeType::filterString() const;
- Returns a filter string usable for a file dialog.
+ \property QMimeType::filterString
+ \brief a filter string usable for a file dialog
+
+ While this property was introduced in 5.10, the
+ corresponding accessor method has always been there.
*/
QString QMimeType::filterString() const
{
@@ -449,6 +501,8 @@ QString QMimeType::filterString() const
Returns \c true if this mimetype is \a mimeTypeName,
or inherits \a mimeTypeName (see parentMimeTypes()),
or \a mimeTypeName is an alias for this mimetype.
+
+ This method has been made invokable from QML since 5.10.
*/
bool QMimeType::inherits(const QString &mimeTypeName) const
{
diff --git a/src/corelib/mimetypes/qmimetype.h b/src/corelib/mimetypes/qmimetype.h
index e9ff9ace84..def4034f8a 100644
--- a/src/corelib/mimetypes/qmimetype.h
+++ b/src/corelib/mimetypes/qmimetype.h
@@ -45,6 +45,7 @@
#ifndef QT_NO_MIMETYPE
+#include <QtCore/qobjectdefs.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qstring.h>
@@ -58,6 +59,21 @@ Q_CORE_EXPORT uint qHash(const QMimeType &key, uint seed = 0) Q_DECL_NOTHROW;
class Q_CORE_EXPORT QMimeType
{
+ Q_GADGET
+ Q_PROPERTY(bool valid READ isValid CONSTANT)
+ Q_PROPERTY(bool isDefault READ isDefault CONSTANT)
+ Q_PROPERTY(QString name READ name CONSTANT)
+ Q_PROPERTY(QString comment READ comment CONSTANT)
+ Q_PROPERTY(QString genericIconName READ genericIconName CONSTANT)
+ Q_PROPERTY(QString iconName READ iconName CONSTANT)
+ Q_PROPERTY(QStringList globPatterns READ globPatterns CONSTANT)
+ Q_PROPERTY(QStringList parentMimeTypes READ parentMimeTypes CONSTANT)
+ Q_PROPERTY(QStringList allAncestors READ allAncestors CONSTANT)
+ Q_PROPERTY(QStringList aliases READ aliases CONSTANT)
+ Q_PROPERTY(QStringList suffixes READ suffixes CONSTANT)
+ Q_PROPERTY(QString preferredSuffix READ preferredSuffix CONSTANT)
+ Q_PROPERTY(QString filterString READ filterString CONSTANT)
+
public:
QMimeType();
QMimeType(const QMimeType &other);
@@ -94,7 +110,7 @@ public:
QStringList suffixes() const;
QString preferredSuffix() const;
- bool inherits(const QString &mimeTypeName) const;
+ Q_INVOKABLE bool inherits(const QString &mimeTypeName) const;
QString filterString() const;
diff --git a/src/corelib/mimetypes/qmimetypeparser.cpp b/src/corelib/mimetypes/qmimetypeparser.cpp
index 20b4461b03..5ecd339908 100644
--- a/src/corelib/mimetypes/qmimetypeparser.cpp
+++ b/src/corelib/mimetypes/qmimetypeparser.cpp
@@ -49,7 +49,6 @@
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QDir>
-#include <QtCore/QPair>
#include <QtCore/QXmlStreamReader>
#include <QtCore/QXmlStreamWriter>
#include <QtCore/QStack>
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 40000e7b24..0cc193c325 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -122,8 +122,8 @@ void QFactoryLoader::update()
//
// ### FIXME find a proper solution
//
- const bool isLoadingDebugAndReleaseCocoa = plugins.contains(QStringLiteral("libqcocoa_debug.dylib"))
- && plugins.contains(QStringLiteral("libqcocoa.dylib"));
+ const bool isLoadingDebugAndReleaseCocoa = plugins.contains(QLatin1String("libqcocoa_debug.dylib"))
+ && plugins.contains(QLatin1String("libqcocoa.dylib"));
#endif
for (int j = 0; j < plugins.count(); ++j) {
QString fileName = QDir::cleanPath(path + QLatin1Char('/') + plugins.at(j));
@@ -131,10 +131,10 @@ void QFactoryLoader::update()
#ifdef Q_OS_MAC
if (isLoadingDebugAndReleaseCocoa) {
#ifdef QT_DEBUG
- if (fileName.contains(QStringLiteral("libqcocoa.dylib")))
+ if (fileName.contains(QLatin1String("libqcocoa.dylib")))
continue; // Skip release plugin in debug mode
#else
- if (fileName.contains(QStringLiteral("libqcocoa_debug.dylib")))
+ if (fileName.contains(QLatin1String("libqcocoa_debug.dylib")))
continue; // Skip debug plugin in release mode
#endif
}
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
index 0afce7fcf0..11ef247531 100644
--- a/src/corelib/plugin/quuid.cpp
+++ b/src/corelib/plugin/quuid.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -39,31 +40,34 @@
#include "quuid.h"
+#include "qcryptographichash.h"
#include "qdatastream.h"
-#include "qendian.h"
#include "qdebug.h"
+#include "qendian.h"
+#include "qrandom.h"
#include "private/qtools_p.h"
-#ifndef QT_BOOTSTRAPPED
-#include "qcryptographichash.h"
-#endif
QT_BEGIN_NAMESPACE
-template <class Char, class Integral>
-void _q_toHex(Char *&dst, Integral value)
+// 16 bytes (a uint, two shorts and a uchar[8]), each represented by two hex
+// digits; plus four dashes and a pair of enclosing brace: 16*2 + 4 + 2 = 38.
+enum { MaxStringUuidLength = 38 };
+
+template <class Integral>
+void _q_toHex(char *&dst, Integral value)
{
value = qToBigEndian(value);
const char* p = reinterpret_cast<const char*>(&value);
for (uint i = 0; i < sizeof(Integral); ++i, dst += 2) {
- dst[0] = Char(QtMiscUtils::toHexLower((p[i] >> 4) & 0xf));
- dst[1] = Char(QtMiscUtils::toHexLower(p[i] & 0xf));
+ dst[0] = QtMiscUtils::toHexLower((p[i] >> 4) & 0xf);
+ dst[1] = QtMiscUtils::toHexLower(p[i] & 0xf);
}
}
-template <class Char, class Integral>
-bool _q_fromHex(const Char *&src, Integral &value)
+template <class Integral>
+bool _q_fromHex(const char *&src, Integral &value)
{
value = 0;
@@ -79,48 +83,64 @@ bool _q_fromHex(const Char *&src, Integral &value)
return true;
}
-template <class Char>
-void _q_uuidToHex(Char *&dst, const uint &d1, const ushort &d2, const ushort &d3, const uchar (&d4)[8])
+static char *_q_uuidToHex(const QUuid &uuid, char *dst)
{
- *dst++ = Char('{');
- _q_toHex(dst, d1);
- *dst++ = Char('-');
- _q_toHex(dst, d2);
- *dst++ = Char('-');
- _q_toHex(dst, d3);
- *dst++ = Char('-');
+ *dst++ = '{';
+ _q_toHex(dst, uuid.data1);
+ *dst++ = '-';
+ _q_toHex(dst, uuid.data2);
+ *dst++ = '-';
+ _q_toHex(dst, uuid.data3);
+ *dst++ = '-';
for (int i = 0; i < 2; i++)
- _q_toHex(dst, d4[i]);
- *dst++ = Char('-');
+ _q_toHex(dst, uuid.data4[i]);
+ *dst++ = '-';
for (int i = 2; i < 8; i++)
- _q_toHex(dst, d4[i]);
- *dst = Char('}');
+ _q_toHex(dst, uuid.data4[i]);
+ *dst++ = '}';
+ return dst;
}
-template <class Char>
-bool _q_uuidFromHex(const Char *&src, uint &d1, ushort &d2, ushort &d3, uchar (&d4)[8])
+/*!
+ \internal
+
+ Parses the string representation of a UUID (with optional surrounding "{}")
+ by reading at most MaxStringUuidLength (38) characters from \a src, which
+ may be \c nullptr. Stops at the first invalid character (which includes a
+ premature NUL).
+
+ Returns the successfully parsed QUuid, or a null QUuid in case of failure.
+*/
+Q_NEVER_INLINE
+static QUuid _q_uuidFromHex(const char *src)
{
- if (*src == Char('{'))
- src++;
- if (!_q_fromHex(src, d1)
- || *src++ != Char('-')
- || !_q_fromHex(src, d2)
- || *src++ != Char('-')
- || !_q_fromHex(src, d3)
- || *src++ != Char('-')
- || !_q_fromHex(src, d4[0])
- || !_q_fromHex(src, d4[1])
- || *src++ != Char('-')
- || !_q_fromHex(src, d4[2])
- || !_q_fromHex(src, d4[3])
- || !_q_fromHex(src, d4[4])
- || !_q_fromHex(src, d4[5])
- || !_q_fromHex(src, d4[6])
- || !_q_fromHex(src, d4[7])) {
- return false;
+ uint d1;
+ ushort d2, d3;
+ uchar d4[8];
+
+ if (src) {
+ if (*src == '{')
+ src++;
+ if (Q_LIKELY( _q_fromHex(src, d1)
+ && *src++ == '-'
+ && _q_fromHex(src, d2)
+ && *src++ == '-'
+ && _q_fromHex(src, d3)
+ && *src++ == '-'
+ && _q_fromHex(src, d4[0])
+ && _q_fromHex(src, d4[1])
+ && *src++ == '-'
+ && _q_fromHex(src, d4[2])
+ && _q_fromHex(src, d4[3])
+ && _q_fromHex(src, d4[4])
+ && _q_fromHex(src, d4[5])
+ && _q_fromHex(src, d4[6])
+ && _q_fromHex(src, d4[7]))) {
+ return QUuid(d1, d2, d3, d4[0], d4[1], d4[2], d4[3], d4[4], d4[5], d4[6], d4[7]);
+ }
}
- return true;
+ return QUuid();
}
#ifndef QT_BOOTSTRAPPED
@@ -331,7 +351,7 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
/*!
Creates a QUuid object from the string \a text, which must be
formatted as five hex fields separated by '-', e.g.,
- "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where 'x' is a hex
+ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
digit. The curly braces shown here are optional, but it is normal to
include them. If the conversion fails, a null UUID is created. See
toString() for an explanation of how the five hex fields map to the
@@ -340,45 +360,76 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto
\sa toString(), QUuid()
*/
QUuid::QUuid(const QString &text)
+ : QUuid(fromString(text))
{
- if (text.length() < 36) {
- *this = QUuid();
- return;
- }
+}
- const ushort *data = reinterpret_cast<const ushort *>(text.unicode());
+/*!
+ \since 5.10
- if (*data == '{' && text.length() < 37) {
- *this = QUuid();
- return;
- }
+ Creates a QUuid object from the string \a text, which must be
+ formatted as five hex fields separated by '-', e.g.,
+ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
+ digit. The curly braces shown here are optional, but it is normal to
+ include them. If the conversion fails, a null UUID is returned. See
+ toString() for an explanation of how the five hex fields map to the
+ public data members in QUuid.
+
+ \sa toString(), QUuid()
+*/
+QUuid QUuid::fromString(QStringView text) Q_DECL_NOTHROW
+{
+ if (text.size() > MaxStringUuidLength)
+ text = text.left(MaxStringUuidLength); // text.truncate(MaxStringUuidLength);
+
+ char latin1[MaxStringUuidLength + 1];
+ char *dst = latin1;
- if (!_q_uuidFromHex(data, data1, data2, data3, data4)) {
- *this = QUuid();
- return;
+ for (QChar ch : text)
+ *dst++ = ch.toLatin1();
+
+ *dst++ = '\0'; // don't read garbage as potentially valid data
+
+ return _q_uuidFromHex(latin1);
+}
+
+/*!
+ \since 5.10
+ \overload
+
+ Creates a QUuid object from the string \a text, which must be
+ formatted as five hex fields separated by '-', e.g.,
+ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
+ digit. The curly braces shown here are optional, but it is normal to
+ include them. If the conversion fails, a null UUID is returned. See
+ toString() for an explanation of how the five hex fields map to the
+ public data members in QUuid.
+
+ \sa toString(), QUuid()
+*/
+QUuid QUuid::fromString(QLatin1String text) Q_DECL_NOTHROW
+{
+ if (Q_UNLIKELY(text.size() < MaxStringUuidLength - 2
+ || (text.front() == QLatin1Char('{') && text.size() < MaxStringUuidLength - 1))) {
+ // Too short. Don't call _q_uuidFromHex(); QL1Ss need not be NUL-terminated,
+ // and we don't want to read trailing garbage as potentially valid data.
+ text = QLatin1String();
}
+ return _q_uuidFromHex(text.data());
}
/*!
\internal
*/
QUuid::QUuid(const char *text)
+ : QUuid(_q_uuidFromHex(text))
{
- if (!text) {
- *this = QUuid();
- return;
- }
-
- if (!_q_uuidFromHex(text, data1, data2, data3, data4)) {
- *this = QUuid();
- return;
- }
}
/*!
Creates a QUuid object from the QByteArray \a text, which must be
formatted as five hex fields separated by '-', e.g.,
- "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where 'x' is a hex
+ "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}" where each 'x' is a hex
digit. The curly braces shown here are optional, but it is normal to
include them. If the conversion fails, a null UUID is created. See
toByteArray() for an explanation of how the five hex fields map to the
@@ -389,23 +440,8 @@ QUuid::QUuid(const char *text)
\sa toByteArray(), QUuid()
*/
QUuid::QUuid(const QByteArray &text)
+ : QUuid(fromString(QLatin1String(text.data(), text.size())))
{
- if (text.length() < 36) {
- *this = QUuid();
- return;
- }
-
- const char *data = text.constData();
-
- if (*data == '{' && text.length() < 37) {
- *this = QUuid();
- return;
- }
-
- if (!_q_uuidFromHex(data, data1, data2, data3, data4)) {
- *this = QUuid();
- return;
- }
}
/*!
@@ -548,12 +584,11 @@ QUuid QUuid::fromRfc4122(const QByteArray &bytes)
*/
QString QUuid::toString() const
{
- QString result(38, Qt::Uninitialized);
- ushort *data = (ushort *)result.data();
-
- _q_uuidToHex(data, data1, data2, data3, data4);
-
- return result;
+ char latin1[MaxStringUuidLength];
+ const auto end = _q_uuidToHex(*this, latin1);
+ Q_ASSERT(end - latin1 == MaxStringUuidLength);
+ Q_UNUSED(end);
+ return QString::fromLatin1(latin1, MaxStringUuidLength);
}
/*!
@@ -594,11 +629,10 @@ QString QUuid::toString() const
*/
QByteArray QUuid::toByteArray() const
{
- QByteArray result(38, Qt::Uninitialized);
- char *data = result.data();
-
- _q_uuidToHex(data, data1, data2, data3, data4);
-
+ QByteArray result(MaxStringUuidLength, Qt::Uninitialized);
+ const auto end = _q_uuidToHex(*this, const_cast<char*>(result.constData()));
+ Q_ASSERT(end - result.constData() == MaxStringUuidLength);
+ Q_UNUSED(end);
return result;
}
@@ -883,17 +917,10 @@ bool QUuid::operator>(const QUuid &other) const Q_DECL_NOTHROW
/*!
\fn QUuid QUuid::createUuid()
- On any platform other than Windows, this function returns a new
- UUID with variant QUuid::DCE and version QUuid::Random. If
- the /dev/urandom device exists, then the numbers used to construct
- the UUID will be of cryptographic quality, which will make the UUID
- unique. Otherwise, the numbers of the UUID will be obtained from
- the local pseudo-random number generator (qrand(), which is seeded
- by qsrand()) which is usually not of cryptograhic quality, which
- means that the UUID can't be guaranteed to be unique.
-
- On a Windows platform, a GUID is generated, which almost certainly
- \e{will} be unique, on this or any other system, networked or not.
+ On any platform other than Windows, this function returns a new UUID with
+ variant QUuid::DCE and version QUuid::Random. On Windows, a GUID is
+ generated using the Windows API and will be of the type that the API
+ decides to create.
\sa variant(), version()
*/
@@ -913,82 +940,12 @@ QUuid QUuid::createUuid()
#else // Q_OS_WIN
-QT_BEGIN_INCLUDE_NAMESPACE
-#include "qdatetime.h"
-#include "qfile.h"
-#include "qthreadstorage.h"
-#include <stdlib.h> // for RAND_MAX
-QT_END_INCLUDE_NAMESPACE
-
-#if !defined(QT_BOOTSTRAPPED) && defined(Q_OS_UNIX)
-Q_GLOBAL_STATIC(QThreadStorage<QFile *>, devUrandomStorage);
-#endif
-
QUuid QUuid::createUuid()
{
- QUuid result;
+ QUuid result(Qt::Uninitialized);
uint *data = &(result.data1);
-
-#if defined(Q_OS_UNIX)
- QFile *devUrandom;
-# if !defined(QT_BOOTSTRAPPED)
- devUrandom = devUrandomStorage()->localData();
- if (!devUrandom) {
- devUrandom = new QFile(QLatin1String("/dev/urandom"));
- devUrandom->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
- devUrandomStorage()->setLocalData(devUrandom);
- }
-# else
- QFile file(QLatin1String("/dev/urandom"));
- devUrandom = &file;
- devUrandom->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
-# endif
- enum { AmountToRead = 4 * sizeof(uint) };
- if (devUrandom->isOpen()
- && devUrandom->read((char *) data, AmountToRead) == AmountToRead) {
- // we got what we wanted, nothing more to do
- ;
- } else
-#endif
- {
- static const int intbits = sizeof(int)*8;
- static int randbits = 0;
- if (!randbits) {
- int r = 0;
- int max = RAND_MAX;
- do { ++r; } while ((max=max>>1));
- randbits = r;
- }
-
- // Seed the PRNG once per thread with a combination of current time, a
- // stack address and a serial counter (since thread stack addresses are
- // re-used).
-#ifndef QT_BOOTSTRAPPED
- static QThreadStorage<int *> uuidseed;
- if (!uuidseed.hasLocalData())
- {
- int *pseed = new int;
- static QBasicAtomicInt serial = Q_BASIC_ATOMIC_INITIALIZER(0);
- qsrand(*pseed = QDateTime::currentSecsSinceEpoch()
- + quintptr(&pseed)
- + 2 + serial.fetchAndAddRelaxed(1));
- uuidseed.setLocalData(pseed);
- }
-#else
- static bool seeded = false;
- if (!seeded)
- qsrand(QDateTime::currentSecsSinceEpoch()
- + quintptr(&seeded));
-#endif
-
- int chunks = 16 / sizeof(uint);
- while (chunks--) {
- uint randNumber = 0;
- for (int filled = 0; filled < intbits; filled += randbits)
- randNumber |= qrand()<<filled;
- *(data+chunks) = randNumber;
- }
- }
+ enum { AmountToRead = 4 };
+ QRandomGenerator::fillRange(data, AmountToRead);
result.data4[0] = (result.data4[0] & 0x3F) | 0x80; // UV_DCE
result.data3 = (result.data3 & 0x0FFF) | 0x4000; // UV_Random
diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h
index 264f572993..9e1a35f492 100644
--- a/src/corelib/plugin/quuid.h
+++ b/src/corelib/plugin/quuid.h
@@ -65,6 +65,7 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QUuid
{
+ QUuid(Qt::Initialization) {}
public:
enum Variant {
VarUnknown =-1,
@@ -116,6 +117,8 @@ public:
#endif
QUuid(const QString &);
+ static QUuid fromString(QStringView string) Q_DECL_NOTHROW;
+ static QUuid fromString(QLatin1String string) Q_DECL_NOTHROW;
QUuid(const char *);
QString toString() const;
QUuid(const QByteArray &);
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 7e3610f0b3..3e7033451e 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -642,7 +642,7 @@ const int FreeListConstants::Sizes[FreeListConstants::BlockCount] = {
16,
128,
1024,
- FreeListConstants::MaxIndex - (16-128-1024)
+ FreeListConstants::MaxIndex - (16 + 128 + 1024)
};
typedef QFreeList<QMutexPrivate, FreeListConstants> FreeList;
diff --git a/src/corelib/thread/qresultstore.h b/src/corelib/thread/qresultstore.h
index be9f632557..6c814ef854 100644
--- a/src/corelib/thread/qresultstore.h
+++ b/src/corelib/thread/qresultstore.h
@@ -196,6 +196,8 @@ public:
} // namespace QtPrivate
+Q_DECLARE_TYPEINFO(QtPrivate::ResultItem, Q_PRIMITIVE_TYPE);
+
#endif //Q_QDOC
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp
index ce0c1c91df..96c031eec6 100644
--- a/src/corelib/thread/qsemaphore.cpp
+++ b/src/corelib/thread/qsemaphore.cpp
@@ -94,7 +94,7 @@ QT_BEGIN_NAMESPACE
seated (taking the available seats to 5, making the party of 10
people wait longer).
- \sa QMutex, QWaitCondition, QThread, {Semaphores Example}
+ \sa QSemaphoreReleaser, QMutex, QWaitCondition, QThread, {Semaphores Example}
*/
class QSemaphorePrivate {
@@ -152,7 +152,10 @@ void QSemaphore::acquire(int n)
\snippet code/src_corelib_thread_qsemaphore.cpp 1
- \sa acquire(), available()
+ QSemaphoreReleaser is a \l{http://en.cppreference.com/w/cpp/language/raii}{RAII}
+ wrapper around this function.
+
+ \sa acquire(), available(), QSemaphoreReleaser
*/
void QSemaphore::release(int n)
{
@@ -233,6 +236,152 @@ bool QSemaphore::tryAcquire(int n, int timeout)
}
+/*!
+ \class QSemaphoreReleaser
+ \brief The QSemaphoreReleaser class provides exception-safe deferral of a QSemaphore::release() call
+ \since 5.10
+ \ingroup thread
+ \inmodule QtCore
+
+ \reentrant
+
+ QSemaphoreReleaser can be used wherever you would otherwise use
+ QSemaphore::release(). Constructing a QSemaphoreReleaser defers the
+ release() call on the semaphore until the QSemaphoreReleaser is
+ destroyed (see
+ \l{http://en.cppreference.com/w/cpp/language/raii}{RAII pattern}).
+
+ You can use this to reliably release a semaphore to avoid dead-lock
+ in the face of exceptions or early returns:
+
+ \code
+ // ... do something that may throw or return early
+ sem.release();
+ \endcode
+
+ If an early return is taken or an exception is thrown before the
+ \c{sem.release()} call is reached, the semaphore is not released,
+ possibly preventing the thread waiting in the corresponding
+ \c{sem.acquire()} call from ever continuing execution.
+
+ When using RAII instead:
+
+ \code
+ const QSemaphoreReleaser releaser(sem);
+ // ... do something that may throw or early return
+ // implicitly calls sem.release() here and at every other return in between
+ \endcode
+
+ this can no longer happen, because the compiler will make sure that
+ the QSemaphoreReleaser destructor is always called, and therefore
+ the semaphore is always released.
+
+ QSemaphoreReleaser is move-enabled and can therefore be returned
+ from functions to transfer responsibility for releasing a semaphore
+ out of a function or a scope:
+
+ \code
+ { // some scope
+ QSemaphoreReleaser releaser; // does nothing
+ // ...
+ if (someCondition) {
+ releaser = QSemaphoreReleaser(sem);
+ // ...
+ }
+ // ...
+ } // conditionally calls sem.release(), depending on someCondition
+ \endcode
+
+ A QSemaphoreReleaser can be canceled by a call to cancel(). A canceled
+ semaphore releaser will no longer call QSemaphore::release() in its
+ destructor.
+
+ \sa QMutexLocker
+*/
+
+/*!
+ \fn QSemaphoreReleaser::QSemaphoreReleaser()
+
+ Default constructor. Creates a QSemaphoreReleaser that does nothing.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::QSemaphoreReleaser(QSemaphore &sem, int n)
+
+ Constructor. Stores the arguments and calls \a{sem}.release(\a{n})
+ in the destructor.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::QSemaphoreReleaser(QSemaphore *sem, int n)
+
+ Constructor. Stores the arguments and calls \a{sem}->release(\a{n})
+ in the destructor.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::QSemaphoreReleaser(QSemaphoreReleaser &&other)
+
+ Move constructor. Takes over responsibility to call QSemaphore::release()
+ from \a other, which in turn is canceled.
+
+ \sa cancel()
+*/
+
+/*!
+ \fn QSemaphoreReleaser::operator=(QSemaphoreReleaser &&other)
+
+ Move assignment operator. Takes over responsibility to call QSemaphore::release()
+ from \a other, which in turn is canceled.
+
+ If this semaphore releaser had the responsibility to call some QSemaphore::release()
+ itself, it performs the call before taking over from \a other.
+
+ \sa cancel()
+*/
+
+/*!
+ \fn QSemaphoreReleaser::~QSemaphoreReleaser()
+
+ Unless canceled, calls QSemaphore::release() with the arguments provided
+ to the constructor, or by the last move assignment.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::swap(QSemaphoreReleaser &other)
+
+ Exchanges the responsibilites of \c{*this} and \a other.
+
+ Unlike move assignment, neither of the two objects ever releases its
+ semaphore, if any, as a consequence of swapping.
+
+ Therefore this function is very fast and never fails.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::semaphore() const
+
+ Returns a pointer to the QSemaphore object provided to the constructor,
+ or by the last move assignment, if any. Otherwise, returns \c nullptr.
+*/
+
+/*!
+ \fn QSemaphoreReleaser::cancel()
+
+ Cancels this QSemaphoreReleaser such that the destructor will no longer
+ call \c{semaphore()->release()}. Returns the value of semaphore()
+ before this call. After this call, semaphore() will return \c nullptr.
+
+ To enable again, assign a new QSemaphoreReleaser:
+
+ \code
+ releaser.cancel(); // avoid releasing old semaphore()
+ releaser = QSemaphoreReleaser(sem, 42);
+ // now will call sem.release(42) when 'releaser' is destroyed
+ \endcode
+*/
+
+
QT_END_NAMESPACE
#endif // QT_NO_THREAD
diff --git a/src/corelib/thread/qsemaphore.h b/src/corelib/thread/qsemaphore.h
index adb9d73e50..a92740c8ce 100644
--- a/src/corelib/thread/qsemaphore.h
+++ b/src/corelib/thread/qsemaphore.h
@@ -69,6 +69,45 @@ private:
QSemaphorePrivate *d;
};
+class QSemaphoreReleaser
+{
+ QSemaphore *m_sem = nullptr;
+ int m_n;
+public:
+ QSemaphoreReleaser() = default;
+ explicit QSemaphoreReleaser(QSemaphore &sem, int n = 1) Q_DECL_NOTHROW
+ : m_sem(&sem), m_n(n) {}
+ explicit QSemaphoreReleaser(QSemaphore *sem, int n = 1) Q_DECL_NOTHROW
+ : m_sem(sem), m_n(n) {}
+ QSemaphoreReleaser(QSemaphoreReleaser &&other) Q_DECL_NOTHROW
+ : m_sem(other.m_sem), m_n(other.m_n)
+ { other.m_sem = nullptr; }
+ QSemaphoreReleaser &operator=(QSemaphoreReleaser &&other) Q_DECL_NOTHROW
+ { QSemaphoreReleaser moved(std::move(other)); swap(moved); return *this; }
+
+ ~QSemaphoreReleaser()
+ {
+ if (m_sem)
+ m_sem->release(m_n);
+ }
+
+ void swap(QSemaphoreReleaser &other) Q_DECL_NOTHROW
+ {
+ qSwap(m_sem, other.m_sem);
+ qSwap(m_n, other.m_n);
+ }
+
+ QSemaphore *semaphore() const Q_DECL_NOTHROW
+ { return m_sem; }
+
+ QSemaphore *cancel() Q_DECL_NOTHROW
+ {
+ QSemaphore *old = m_sem;
+ m_sem = nullptr;
+ return old;
+ }
+};
+
#endif // QT_NO_THREAD
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index 996a1df9a0..1ec626a53b 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -291,7 +291,7 @@ QThreadPrivate::~QThreadPrivate()
\fn int QThread::idealThreadCount()
Returns the ideal number of threads that can be run on the system. This is done querying
- the number of processor cores, both real and logical, in the system. This function returns -1
+ the number of processor cores, both real and logical, in the system. This function returns 1
if the number of processor cores could not be detected.
*/
@@ -880,6 +880,51 @@ bool QThread::isInterruptionRequested() const
return d->interruptionRequested;
}
+/*
+ \fn template <typename Function, typename Args...> static QThread *QThread::create(Function &&f, Args &&... args)
+ \since 5.10
+
+ Creates a new QThread object that will execute the function \a f with the
+ arguments \a args.
+
+ The new thread is not started -- it must be started by an explicit call
+ to start(). This allows you to connect to its signals, move QObjects
+ to the thread, choose the new thread's priority and so on. The function
+ \a f will be called in the new thread.
+
+ Returns the newly created QThread instance.
+
+ \note the caller acquires ownership of the returned QThread instance.
+
+ \note this function is only available when using C++17.
+
+ \warning do not call start() on the returned QThread instance more than once;
+ doing so will result in undefined behavior.
+
+ \sa start()
+*/
+
+/*
+ \fn template <typename Function> static QThread *QThread::create(Function &&f)
+ \since 5.10
+
+ Creates a new QThread object that will execute the function \a f.
+
+ The new thread is not started -- it must be started by an explicit call
+ to start(). This allows you to connect to its signals, move QObjects
+ to the thread, choose the new thread's priority and so on. The function
+ \a f will be called in the new thread.
+
+ Returns the newly created QThread instance.
+
+ \note the caller acquires ownership of the returned QThread instance.
+
+ \warning do not call start() on the returned QThread instance more than once;
+ doing so will result in undefined behavior.
+
+ \sa start()
+*/
+
/*!
\class QDaemonThread
\since 5.5
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index 45786537e2..5e6f216219 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -42,6 +42,27 @@
#include <QtCore/qobject.h>
+// The implementation of QThread::create uses various C++14/C++17 facilities;
+// we must check for their presence. Specifically for glibcxx bundled in MinGW
+// with win32 threads, we check the condition found in its <future> header
+// since _GLIBCXX_HAS_GTHREADS might then not be defined.
+// For std::async (used in all codepaths)
+// there is no SG10 feature macro; just test for the header presence.
+// For the C++17 codepath do some more throughout checks for std::invoke and
+// C++14 lambdas availability.
+#if QT_HAS_INCLUDE(<future>) \
+ && (!defined(__GLIBCXX__) || (defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)))
+# define QTHREAD_HAS_CREATE
+# include <future> // for std::async
+# include <functional> // for std::invoke; no guard needed as it's a C++98 header
+
+# if defined(__cpp_lib_invoke) && __cpp_lib_invoke >= 201411 \
+ && defined(__cpp_init_captures) && __cpp_init_captures >= 201304 \
+ && defined(__cpp_generic_lambdas) && __cpp_generic_lambdas >= 201304
+# define QTHREAD_HAS_VARIADIC_CREATE
+# endif
+#endif
+
#include <limits.h>
QT_BEGIN_NAMESPACE
@@ -98,6 +119,16 @@ public:
bool event(QEvent *event) Q_DECL_OVERRIDE;
int loopLevel() const;
+#ifdef QTHREAD_HAS_CREATE
+#ifdef QTHREAD_HAS_VARIADIC_CREATE
+ template <typename Function, typename... Args>
+ static QThread *create(Function &&f, Args &&... args);
+#else
+ template <typename Function>
+ static QThread *create(Function &&f);
+#endif
+#endif
+
public Q_SLOTS:
void start(Priority = InheritPriority);
void terminate();
@@ -131,6 +162,99 @@ private:
friend class QThreadData;
};
+#ifdef QTHREAD_HAS_CREATE
+namespace QtPrivate {
+
+class QThreadCreateThread : public QThread
+{
+public:
+#if defined(QTHREAD_HAS_VARIADIC_CREATE)
+ // C++17: std::thread's constructor complying call
+ template <typename Function, typename... Args>
+ explicit QThreadCreateThread(Function &&f, Args &&... args)
+ : m_future(std::async(std::launch::deferred,
+ [f = static_cast<typename std::decay<Function>::type>(std::forward<Function>(f))](auto &&... largs) mutable -> void
+ {
+ (void)std::invoke(std::move(f), std::forward<decltype(largs)>(largs)...);
+ }, std::forward<Args>(args)...))
+ {
+ }
+#elif defined(__cpp_init_captures) && __cpp_init_captures >= 201304
+ // C++14: implementation for just one callable
+ template <typename Function>
+ explicit QThreadCreateThread(Function &&f)
+ : m_future(std::async(std::launch::deferred,
+ [f = static_cast<typename std::decay<Function>::type>(std::forward<Function>(f))]() mutable -> void
+ {
+ (void)f();
+ }))
+ {
+ }
+#else
+private:
+ // C++11: same as C++14, but with a workaround for not having generalized lambda captures
+ template <typename Function>
+ struct Callable
+ {
+ explicit Callable(Function &&f)
+ : m_function(std::forward<Function>(f))
+ {
+ }
+
+#if defined(Q_COMPILER_DEFAULT_MEMBERS) && defined(Q_COMPILER_DELETE_MEMBERS)
+ // Apply the same semantics of a lambda closure type w.r.t. the special
+ // member functions, if possible: delete the copy assignment operator,
+ // bring back all the others as per the RO5 (cf. §8.1.5.1/11 [expr.prim.lambda.closure])
+ ~Callable() = default;
+ Callable(const Callable &) = default;
+ Callable(Callable &&) = default;
+ Callable &operator=(const Callable &) = delete;
+ Callable &operator=(Callable &&) = default;
+#endif
+
+ void operator()()
+ {
+ (void)m_function();
+ }
+
+ typename std::decay<Function>::type m_function;
+ };
+
+public:
+ template <typename Function>
+ explicit QThreadCreateThread(Function &&f)
+ : m_future(std::async(std::launch::deferred, Callable<Function>(std::forward<Function>(f))))
+ {
+ }
+#endif // QTHREAD_HAS_VARIADIC_CREATE
+
+private:
+ void run() override
+ {
+ m_future.get();
+ }
+
+ std::future<void> m_future;
+};
+
+} // namespace QtPrivate
+
+#ifdef QTHREAD_HAS_VARIADIC_CREATE
+template <typename Function, typename... Args>
+QThread *QThread::create(Function &&f, Args &&... args)
+{
+ return new QtPrivate::QThreadCreateThread(std::forward<Function>(f), std::forward<Args>(args)...);
+}
+#else
+template <typename Function>
+QThread *QThread::create(Function &&f)
+{
+ return new QtPrivate::QThreadCreateThread(std::forward<Function>(f));
+}
+#endif // QTHREAD_HAS_VARIADIC_CREATE
+
+#endif // QTHREAD_HAS_CREATE
+
#else // QT_NO_THREAD
class Q_CORE_EXPORT QThread : public QObject
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index 885b4c0c1e..f3d4750177 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -184,8 +184,8 @@ public:
#endif // Q_OS_UNIX
#ifdef Q_OS_WIN
- static unsigned int __stdcall start(void *);
- static void finish(void *, bool lockAnyway=true);
+ static unsigned int __stdcall start(void *) Q_DECL_NOEXCEPT;
+ static void finish(void *, bool lockAnyway=true) Q_DECL_NOEXCEPT;
Qt::HANDLE handle;
unsigned int id;
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index f359d25a73..cddc4053b1 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -61,6 +61,10 @@
#include "qdebug.h"
+#ifdef __GLIBCXX__
+#include <cxxabi.h>
+#endif
+
#include <sched.h>
#include <errno.h>
@@ -324,49 +328,70 @@ void *QThreadPrivate::start(void *arg)
#endif
pthread_cleanup_push(QThreadPrivate::finish, arg);
- QThread *thr = reinterpret_cast<QThread *>(arg);
- QThreadData *data = QThreadData::get2(thr);
-
+#ifndef QT_NO_EXCEPTIONS
+ try
+#endif
{
- QMutexLocker locker(&thr->d_func()->mutex);
+ QThread *thr = reinterpret_cast<QThread *>(arg);
+ QThreadData *data = QThreadData::get2(thr);
- // do we need to reset the thread priority?
- if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) {
- thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
- }
-
- data->threadId.store(to_HANDLE(pthread_self()));
- set_thread_data(data);
+ {
+ QMutexLocker locker(&thr->d_func()->mutex);
- data->ref();
- data->quitNow = thr->d_func()->exited;
- }
+ // do we need to reset the thread priority?
+ if (int(thr->d_func()->priority) & ThreadPriorityResetFlag) {
+ thr->d_func()->setPriority(QThread::Priority(thr->d_func()->priority & ~ThreadPriorityResetFlag));
+ }
- if (data->eventDispatcher.load()) // custom event dispatcher set?
- data->eventDispatcher.load()->startingUp();
- else
- createEventDispatcher(data);
+ data->threadId.store(to_HANDLE(pthread_self()));
+ set_thread_data(data);
-#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
- {
- // sets the name of the current thread.
- QString objectName = thr->objectName();
+ data->ref();
+ data->quitNow = thr->d_func()->exited;
+ }
- pthread_t thread_id = from_HANDLE<pthread_t>(data->threadId.load());
- if (Q_LIKELY(objectName.isEmpty()))
- setCurrentThreadName(thread_id, thr->metaObject()->className());
+ if (data->eventDispatcher.load()) // custom event dispatcher set?
+ data->eventDispatcher.load()->startingUp();
else
- setCurrentThreadName(thread_id, objectName.toLocal8Bit());
- }
+ createEventDispatcher(data);
+
+#if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX))
+ {
+ // sets the name of the current thread.
+ QString objectName = thr->objectName();
+
+ pthread_t thread_id = from_HANDLE<pthread_t>(data->threadId.load());
+ if (Q_LIKELY(objectName.isEmpty()))
+ setCurrentThreadName(thread_id, thr->metaObject()->className());
+ else
+ setCurrentThreadName(thread_id, objectName.toLocal8Bit());
+ }
#endif
- emit thr->started(QThread::QPrivateSignal());
+ emit thr->started(QThread::QPrivateSignal());
#if !defined(Q_OS_ANDROID)
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- pthread_testcancel();
+ pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+ pthread_testcancel();
#endif
- thr->run();
+ thr->run();
+ }
+#ifndef QT_NO_EXCEPTIONS
+#ifdef __GLIBCXX__
+ // POSIX thread cancellation under glibc is implemented by throwing an exception
+ // of this type. Do what libstdc++ is doing and handle it specially in order not to
+ // abort the application if user's code calls a cancellation function.
+ catch (const abi::__forced_unwind &) {
+ throw;
+ }
+#endif // __GLIBCXX__
+ catch (...) {
+ qTerminate();
+ }
+#endif // QT_NO_EXCEPTIONS
+ // This pop runs finish() below. It's outside the try/catch (and has its
+ // own try/catch) to prevent finish() to be run in case an exception is
+ // thrown.
pthread_cleanup_pop(1);
return 0;
@@ -374,35 +399,53 @@ void *QThreadPrivate::start(void *arg)
void QThreadPrivate::finish(void *arg)
{
- QThread *thr = reinterpret_cast<QThread *>(arg);
- QThreadPrivate *d = thr->d_func();
+#ifndef QT_NO_EXCEPTIONS
+ try
+#endif
+ {
+ QThread *thr = reinterpret_cast<QThread *>(arg);
+ QThreadPrivate *d = thr->d_func();
- QMutexLocker locker(&d->mutex);
+ QMutexLocker locker(&d->mutex);
- d->isInFinish = true;
- d->priority = QThread::InheritPriority;
- void *data = &d->data->tls;
- locker.unlock();
- emit thr->finished(QThread::QPrivateSignal());
- QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
- QThreadStorageData::finish((void **)data);
- locker.relock();
-
- QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load();
- if (eventDispatcher) {
- d->data->eventDispatcher = 0;
+ d->isInFinish = true;
+ d->priority = QThread::InheritPriority;
+ void *data = &d->data->tls;
locker.unlock();
- eventDispatcher->closingDown();
- delete eventDispatcher;
+ emit thr->finished(QThread::QPrivateSignal());
+ QCoreApplication::sendPostedEvents(0, QEvent::DeferredDelete);
+ QThreadStorageData::finish((void **)data);
locker.relock();
- }
- d->running = false;
- d->finished = true;
- d->interruptionRequested = false;
+ QAbstractEventDispatcher *eventDispatcher = d->data->eventDispatcher.load();
+ if (eventDispatcher) {
+ d->data->eventDispatcher = 0;
+ locker.unlock();
+ eventDispatcher->closingDown();
+ delete eventDispatcher;
+ locker.relock();
+ }
+
+ d->running = false;
+ d->finished = true;
+ d->interruptionRequested = false;
- d->isInFinish = false;
- d->thread_done.wakeAll();
+ d->isInFinish = false;
+ d->thread_done.wakeAll();
+ }
+#ifndef QT_NO_EXCEPTIONS
+#ifdef __GLIBCXX__
+ // POSIX thread cancellation under glibc is implemented by throwing an exception
+ // of this type. Do what libstdc++ is doing and handle it specially in order not to
+ // abort the application if user's code calls a cancellation function.
+ catch (const abi::__forced_unwind &) {
+ throw;
+ }
+#endif // __GLIBCXX__
+ catch (...) {
+ qTerminate();
+ }
+#endif // QT_NO_EXCEPTIONS
}
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index ef7bfc511d..24d3ca2d7d 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -344,7 +344,7 @@ void QThreadPrivate::createEventDispatcher(QThreadData *data)
#ifndef QT_NO_THREAD
-unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg)
+unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(void *arg) Q_DECL_NOEXCEPT
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadData *data = QThreadData::get2(thr);
@@ -381,7 +381,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
return 0;
}
-void QThreadPrivate::finish(void *arg, bool lockAnyway)
+void QThreadPrivate::finish(void *arg, bool lockAnyway) Q_DECL_NOEXCEPT
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadPrivate *d = thr->d_func();
diff --git a/src/corelib/thread/qthreadpool.cpp b/src/corelib/thread/qthreadpool.cpp
index f3ce1f258f..9937201619 100644
--- a/src/corelib/thread/qthreadpool.cpp
+++ b/src/corelib/thread/qthreadpool.cpp
@@ -74,7 +74,9 @@ public:
*/
QThreadPoolThread::QThreadPoolThread(QThreadPoolPrivate *manager)
:manager(manager), runnable(0)
-{ }
+{
+ setStackSize(manager->stackSize);
+}
/*
\internal
@@ -154,11 +156,6 @@ void QThreadPoolThread::registerThreadInactive()
\internal
*/
QThreadPoolPrivate:: QThreadPoolPrivate()
- : isExiting(false),
- expiryTimeout(30000),
- maxThreadCount(qAbs(QThread::idealThreadCount())),
- reservedThreads(0),
- activeThreads(0)
{ }
bool QThreadPoolPrivate::tryStart(QRunnable *task)
@@ -609,6 +606,30 @@ void QThreadPool::reserveThread()
++d->reservedThreads;
}
+/*! \property QThreadPool::stacksize
+
+ This property contains the stack size for the thread pool worker
+ threads.
+
+ The value of the property is uses when the thread pool creates
+ new threads only. Changing it has no effect for already created
+ or running threads.
+
+ The default value is 0, which makes QThread use the operating
+ system default stack stize.
+*/
+void QThreadPool::setStackSize(uint stackSize)
+{
+ Q_D(QThreadPool);
+ d->stackSize = stackSize;
+}
+
+uint QThreadPool::stackSize() const
+{
+ Q_D(const QThreadPool);
+ return d->stackSize;
+}
+
/*!
Releases a thread previously reserved by a call to reserveThread().
diff --git a/src/corelib/thread/qthreadpool.h b/src/corelib/thread/qthreadpool.h
index 09b7f96f48..a65eacc996 100644
--- a/src/corelib/thread/qthreadpool.h
+++ b/src/corelib/thread/qthreadpool.h
@@ -58,6 +58,7 @@ class Q_CORE_EXPORT QThreadPool : public QObject
Q_PROPERTY(int expiryTimeout READ expiryTimeout WRITE setExpiryTimeout)
Q_PROPERTY(int maxThreadCount READ maxThreadCount WRITE setMaxThreadCount)
Q_PROPERTY(int activeThreadCount READ activeThreadCount)
+ Q_PROPERTY(uint stackSize READ stackSize WRITE setStackSize)
friend class QFutureInterfaceBase;
public:
@@ -77,6 +78,9 @@ public:
int activeThreadCount() const;
+ void setStackSize(uint stackSize);
+ uint stackSize() const;
+
void reserveThread();
void releaseThread();
diff --git a/src/corelib/thread/qthreadpool_p.h b/src/corelib/thread/qthreadpool_p.h
index 4a9f9e5cfa..8b6a8cc476 100644
--- a/src/corelib/thread/qthreadpool_p.h
+++ b/src/corelib/thread/qthreadpool_p.h
@@ -53,6 +53,7 @@
//
#include "QtCore/qmutex.h"
+#include "QtCore/qthread.h"
#include "QtCore/qwaitcondition.h"
#include "QtCore/qset.h"
#include "QtCore/qqueue.h"
@@ -91,11 +92,12 @@ public:
QVector<QPair<QRunnable *, int> > queue;
QWaitCondition noActiveThreads;
- bool isExiting;
- int expiryTimeout;
- int maxThreadCount;
- int reservedThreads;
- int activeThreads;
+ int expiryTimeout = 30000;
+ int maxThreadCount = QThread::idealThreadCount();
+ int reservedThreads = 0;
+ int activeThreads = 0;
+ uint stackSize = 0;
+ bool isExiting = false;
};
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index 0e7365c32b..9b648adb06 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -686,14 +686,6 @@ QByteArray qCompress(const uchar* data, int nbytes, int compressionLevel)
\sa qCompress()
*/
-/*! \relates QByteArray
-
- \overload
-
- Uncompresses the first \a nbytes of \a data and returns a new byte
- array with the uncompressed data.
-*/
-
#ifndef QT_NO_COMPRESS
namespace {
struct QByteArrayDataDeleter
@@ -709,6 +701,13 @@ static QByteArray invalidCompressedData()
return QByteArray();
}
+/*! \relates QByteArray
+
+ \overload
+
+ Uncompresses the first \a nbytes of \a data and returns a new byte
+ array with the uncompressed data.
+*/
QByteArray qUncompress(const uchar* data, int nbytes)
{
if (!data) {
@@ -1134,6 +1133,13 @@ static inline char qToLower(char c)
Same as prepend(\a ch).
*/
+/*! \fn void QByteArray::shrink_to_fit()
+ \since 5.10
+
+ This function is provided for STL compatibility. It is equivalent to
+ squeeze().
+*/
+
/*! \fn QByteArray::QByteArray(const QByteArray &other)
Constructs a copy of \a other.
@@ -1446,6 +1452,66 @@ QByteArray &QByteArray::operator=(const char *str)
\overload
*/
+/*!
+ \fn char QByteArray::front() const
+ \since 5.10
+
+ Returns the first character in the byte array.
+ Same as \c{at(0)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty byte array constitutes
+ undefined behavior.
+
+ \sa back(), at(), operator[]()
+*/
+
+/*!
+ \fn char QByteArray::back() const
+ \since 5.10
+
+ Returns the last character in the byte array.
+ Same as \c{at(size() - 1)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty byte array constitutes
+ undefined behavior.
+
+ \sa front(), at(), operator[]()
+*/
+
+/*!
+ \fn QByteRef QByteArray::front()
+ \since 5.10
+
+ Returns a reference to the first character in the byte array.
+ Same as \c{operator[](0)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty byte array constitutes
+ undefined behavior.
+
+ \sa back(), at(), operator[]()
+*/
+
+/*!
+ \fn QByteRef QByteArray::back()
+ \since 5.10
+
+ Returns a reference to the last character in the byte array.
+ Same as \c{operator[](size() - 1)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty byte array constitutes
+ undefined behavior.
+
+ \sa front(), at(), operator[]()
+*/
+
/*! \fn bool QByteArray::contains(const QByteArray &ba) const
Returns \c true if the byte array contains an occurrence of the byte
@@ -2905,7 +2971,7 @@ bool QByteArray::endsWith(char ch) const
Example:
\snippet code/src_corelib_tools_qbytearray.cpp 27
- \sa right(), mid(), startsWith(), truncate()
+ \sa startsWith(), right(), mid(), chopped(), chop(), truncate()
*/
QByteArray QByteArray::left(int len) const
@@ -2927,7 +2993,7 @@ QByteArray QByteArray::left(int len) const
Example:
\snippet code/src_corelib_tools_qbytearray.cpp 28
- \sa endsWith(), left(), mid()
+ \sa endsWith(), left(), mid(), chopped(), chop(), truncate()
*/
QByteArray QByteArray::right(int len) const
@@ -2950,7 +3016,7 @@ QByteArray QByteArray::right(int len) const
Example:
\snippet code/src_corelib_tools_qbytearray.cpp 29
- \sa left(), right()
+ \sa left(), right(), chopped(), chop(), truncate()
*/
QByteArray QByteArray::mid(int pos, int len) const
@@ -2974,6 +3040,18 @@ QByteArray QByteArray::mid(int pos, int len) const
}
/*!
+ \fn QByteArray::chopped(int len) const
+ \since 5.10
+
+ Returns a byte array that contains the leftmost size() - \a len bytes of
+ this byte array.
+
+ \note The behavior is undefined if \a len is negative or greater than size().
+
+ \sa endsWith(), left(), right(), mid(), chop(), truncate()
+*/
+
+/*!
\fn QByteArray QByteArray::toLower() const
Returns a lowercase copy of the byte array. The bytearray is
diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h
index 432ef922f6..9a600ca366 100644
--- a/src/corelib/tools/qbytearray.h
+++ b/src/corelib/tools/qbytearray.h
@@ -186,32 +186,36 @@ public:
{ qSwap(d, other.d); }
inline int size() const;
- bool isEmpty() const;
+ inline bool isEmpty() const;
void resize(int size);
QByteArray &fill(char c, int size = -1);
- int capacity() const;
- void reserve(int size);
- void squeeze();
+ inline int capacity() const;
+ inline void reserve(int size);
+ inline void squeeze();
#ifndef QT_NO_CAST_FROM_BYTEARRAY
- operator const char *() const;
- operator const void *() const;
+ inline operator const char *() const;
+ inline operator const void *() const;
#endif
- char *data();
- const char *data() const;
+ inline char *data();
+ inline const char *data() const;
inline const char *constData() const;
inline void detach();
- bool isDetached() const;
+ inline bool isDetached() const;
inline bool isSharedWith(const QByteArray &other) const { return d == other.d; }
void clear();
- char at(int i) const;
- char operator[](int i) const;
- char operator[](uint i) const;
- QByteRef operator[](int i);
- QByteRef operator[](uint i);
+ inline char at(int i) const;
+ inline char operator[](int i) const;
+ inline char operator[](uint i) const;
+ inline QByteRef operator[](int i);
+ inline QByteRef operator[](uint i);
+ Q_REQUIRED_RESULT char front() const { return at(0); }
+ Q_REQUIRED_RESULT inline QByteRef front();
+ Q_REQUIRED_RESULT char back() const { return at(size() - 1); }
+ Q_REQUIRED_RESULT inline QByteRef back();
int indexOf(char c, int from = 0) const;
int indexOf(const char *c, int from = 0) const;
@@ -220,9 +224,9 @@ public:
int lastIndexOf(const char *c, int from = -1) const;
int lastIndexOf(const QByteArray &a, int from = -1) const;
- bool contains(char c) const;
- bool contains(const char *a) const;
- bool contains(const QByteArray &a) const;
+ inline bool contains(char c) const;
+ inline bool contains(const char *a) const;
+ inline bool contains(const QByteArray &a) const;
int count(char c) const;
int count(const char *a) const;
int count(const QByteArray &a) const;
@@ -230,6 +234,8 @@ public:
Q_REQUIRED_RESULT QByteArray left(int len) const;
Q_REQUIRED_RESULT QByteArray right(int len) const;
Q_REQUIRED_RESULT QByteArray mid(int index, int len = -1) const;
+ Q_REQUIRED_RESULT QByteArray chopped(int len) const
+ { Q_ASSERT(len >= 0); Q_ASSERT(len <= size()); return left(size() - len); }
bool startsWith(const QByteArray &a) const;
bool startsWith(char c) const;
@@ -280,12 +286,12 @@ public:
Q_REQUIRED_RESULT QByteArray rightJustified(int width, char fill = ' ', bool truncate = false) const;
QByteArray &prepend(char c);
- QByteArray &prepend(int count, char c);
+ inline QByteArray &prepend(int count, char c);
QByteArray &prepend(const char *s);
QByteArray &prepend(const char *s, int len);
QByteArray &prepend(const QByteArray &a);
QByteArray &append(char c);
- QByteArray &append(int count, char c);
+ inline QByteArray &append(int count, char c);
QByteArray &append(const char *s);
QByteArray &append(const char *s, int len);
QByteArray &append(const QByteArray &a);
@@ -298,17 +304,17 @@ public:
QByteArray &replace(int index, int len, const char *s);
QByteArray &replace(int index, int len, const char *s, int alen);
QByteArray &replace(int index, int len, const QByteArray &s);
- QByteArray &replace(char before, const char *after);
+ inline QByteArray &replace(char before, const char *after);
QByteArray &replace(char before, const QByteArray &after);
- QByteArray &replace(const char *before, const char *after);
+ inline QByteArray &replace(const char *before, const char *after);
QByteArray &replace(const char *before, int bsize, const char *after, int asize);
QByteArray &replace(const QByteArray &before, const QByteArray &after);
- QByteArray &replace(const QByteArray &before, const char *after);
+ inline QByteArray &replace(const QByteArray &before, const char *after);
QByteArray &replace(const char *before, const QByteArray &after);
QByteArray &replace(char before, char after);
- QByteArray &operator+=(char c);
- QByteArray &operator+=(const char *s);
- QByteArray &operator+=(const QByteArray &a);
+ inline QByteArray &operator+=(char c);
+ inline QByteArray &operator+=(const char *s);
+ inline QByteArray &operator+=(const QByteArray &a);
QList<QByteArray> split(char sep) const;
@@ -352,13 +358,13 @@ public:
const QByteArray &include = QByteArray(),
char percent = '%') const;
- QByteArray &setNum(short, int base = 10);
- QByteArray &setNum(ushort, int base = 10);
- QByteArray &setNum(int, int base = 10);
- QByteArray &setNum(uint, int base = 10);
+ inline QByteArray &setNum(short, int base = 10);
+ inline QByteArray &setNum(ushort, int base = 10);
+ inline QByteArray &setNum(int, int base = 10);
+ inline QByteArray &setNum(uint, int base = 10);
QByteArray &setNum(qlonglong, int base = 10);
QByteArray &setNum(qulonglong, int base = 10);
- QByteArray &setNum(float, char f = 'g', int prec = 6);
+ inline QByteArray &setNum(float, char f = 'g', int prec = 6);
QByteArray &setNum(double, char f = 'g', int prec = 6);
QByteArray &setRawData(const char *a, uint n); // ### Qt 6: use an int
@@ -413,12 +419,13 @@ public:
typedef char *pointer;
typedef const char *const_pointer;
typedef char value_type;
- void push_back(char c);
- void push_back(const char *c);
- void push_back(const QByteArray &a);
- void push_front(char c);
- void push_front(const char *c);
- void push_front(const QByteArray &a);
+ inline void push_back(char c);
+ inline void push_back(const char *c);
+ inline void push_back(const QByteArray &a);
+ inline void push_front(char c);
+ inline void push_front(const char *c);
+ inline void push_front(const QByteArray &a);
+ void shrink_to_fit() { squeeze(); }
static inline QByteArray fromStdString(const std::string &s);
inline std::string toStdString() const;
@@ -549,6 +556,8 @@ inline QByteRef QByteArray::operator[](int i)
{ Q_ASSERT(i >= 0); return QByteRef(*this, i); }
inline QByteRef QByteArray::operator[](uint i)
{ return QByteRef(*this, i); }
+inline QByteRef QByteArray::front() { return operator[](0); }
+inline QByteRef QByteArray::back() { return operator[](size() - 1); }
inline QByteArray::iterator QByteArray::begin()
{ detach(); return d->data(); }
inline QByteArray::const_iterator QByteArray::begin() const
@@ -683,8 +692,4 @@ Q_DECLARE_SHARED(QByteArray)
QT_END_NAMESPACE
-#ifdef QT_USE_QSTRINGBUILDER
-#include <QtCore/qstring.h>
-#endif
-
#endif // QBYTEARRAY_H
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index 1d3293e85e..5c887f47cd 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -608,6 +608,24 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \fn QChar::QChar(char16_t ch)
+ \since 5.10
+
+ Constructs a QChar corresponding to the UTF-16 character \a ch.
+
+ \note This constructor is not available on MSVC 2013.
+*/
+
+/*!
+ \fn QChar::QChar(wchar_t ch)
+ \since 5.10
+
+ Constructs a QChar corresponding to the wide character \a ch.
+
+ \note This constructor is only available on Windows.
+*/
+
+/*!
\fn QChar::QChar(char ch)
Constructs a QChar corresponding to ASCII/Latin-1 character \a ch.
@@ -1532,6 +1550,11 @@ static inline ushort foldCase(ushort ch) Q_DECL_NOTHROW
return convertCase_helper<QUnicodeTables::CasefoldTraits>(ch);
}
+static inline QChar foldCase(QChar ch) Q_DECL_NOTHROW
+{
+ return QChar(foldCase(ch.unicode()));
+}
+
/*!
\fn QChar QChar::toCaseFolded() const
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
index 81ef67d116..53cb8993fb 100644
--- a/src/corelib/tools/qchar.h
+++ b/src/corelib/tools/qchar.h
@@ -86,6 +86,13 @@ public:
Q_DECL_CONSTEXPR QChar(int rc) Q_DECL_NOTHROW : ucs(ushort(rc & 0xffff)) {}
Q_DECL_CONSTEXPR QChar(SpecialCharacter s) Q_DECL_NOTHROW : ucs(ushort(s)) {} // implicit
Q_DECL_CONSTEXPR QChar(QLatin1Char ch) Q_DECL_NOTHROW : ucs(ch.unicode()) {} // implicit
+#if defined(Q_COMPILER_UNICODE_STRINGS)
+ Q_DECL_CONSTEXPR QChar(char16_t ch) Q_DECL_NOTHROW : ucs(ushort(ch)) {} // implicit
+#endif
+#if defined(Q_OS_WIN)
+ Q_STATIC_ASSERT(sizeof(wchar_t) == sizeof(ushort));
+ Q_DECL_CONSTEXPR QChar(wchar_t ch) Q_DECL_NOTHROW : ucs(ushort(ch)) {} // implicit
+#endif
#ifndef QT_NO_CAST_FROM_ASCII
QT_ASCII_CAST_WARN Q_DECL_CONSTEXPR explicit QChar(char c) Q_DECL_NOTHROW : ucs(uchar(c)) { }
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 11c023f762..d8d79dfeba 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -160,8 +160,7 @@ static ParsedDate getDateFromJulianDay(qint64 julianDay)
if (year <= 0)
--year ;
- const ParsedDate result = { year, month, day };
- return result;
+ return { year, month, day };
}
/*****************************************************************************
@@ -212,7 +211,7 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s)
{
ParsedRfcDateTime result;
- // Matches "Wdy, DD Mon YYYY HH:mm:ss ±hhmm" (Wdy, being optional)
+ // Matches "Wdy, dd Mon yyyy HH:mm:ss ±hhmm" (Wdy, being optional)
QRegExp rex(QStringLiteral("^(?:[A-Z][a-z]+,)?[ \\t]*(\\d{1,2})[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d)(?::(\\d\\d))?)?[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?"));
if (s.indexOf(rex) == 0) {
const QStringList cap = rex.capturedTexts();
@@ -224,7 +223,7 @@ static ParsedRfcDateTime rfcDateImpl(const QString &s)
const int minOffset = cap[9].toInt();
result.utcOffset = ((hourOffset * 60 + minOffset) * (positiveOffset ? 60 : -60));
} else {
- // Matches "Wdy Mon DD HH:mm:ss YYYY"
+ // Matches "Wdy Mon dd HH:mm:ss yyyy"
QRegExp rex(QStringLiteral("^[A-Z][a-z]+[ \\t]+([A-Z][a-z]+)[ \\t]+(\\d\\d)(?:[ \\t]+(\\d\\d):(\\d\\d):(\\d\\d))?[ \\t]+(\\d\\d\\d\\d)[ \\t]*(?:([+-])(\\d\\d)(\\d\\d))?"));
if (s.indexOf(rex) == 0) {
const QStringList cap = rex.capturedTexts();
@@ -646,13 +645,11 @@ int QDate::weekNumber(int *yearNumber) const
QString QDate::shortMonthName(int month, QDate::MonthNameType type)
{
- if (month >= 1 || month <= 12) {
- switch (type) {
- case QDate::DateFormat:
- return QLocale::system().monthName(month, QLocale::ShortFormat);
- case QDate::StandaloneFormat:
- return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat);
- }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().monthName(month, QLocale::ShortFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneMonthName(month, QLocale::ShortFormat);
}
return QString();
}
@@ -690,13 +687,11 @@ QString QDate::shortMonthName(int month, QDate::MonthNameType type)
QString QDate::longMonthName(int month, MonthNameType type)
{
- if (month >= 1 && month <= 12) {
- switch (type) {
- case QDate::DateFormat:
- return QLocale::system().monthName(month, QLocale::LongFormat);
- case QDate::StandaloneFormat:
- return QLocale::system().standaloneMonthName(month, QLocale::LongFormat);
- }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().monthName(month, QLocale::LongFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneMonthName(month, QLocale::LongFormat);
}
return QString();
}
@@ -729,13 +724,11 @@ QString QDate::longMonthName(int month, MonthNameType type)
QString QDate::shortDayName(int weekday, MonthNameType type)
{
- if (weekday >= 1 && weekday <= 7) {
- switch (type) {
- case QDate::DateFormat:
- return QLocale::system().dayName(weekday, QLocale::ShortFormat);
- case QDate::StandaloneFormat:
- return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
- }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().dayName(weekday, QLocale::ShortFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneDayName(weekday, QLocale::ShortFormat);
}
return QString();
}
@@ -768,13 +761,11 @@ QString QDate::shortDayName(int weekday, MonthNameType type)
QString QDate::longDayName(int weekday, MonthNameType type)
{
- if (weekday >= 1 && weekday <= 7) {
- switch (type) {
- case QDate::DateFormat:
- return QLocale::system().dayName(weekday, QLocale::LongFormat);
- case QDate::StandaloneFormat:
- return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
- }
+ switch (type) {
+ case QDate::DateFormat:
+ return QLocale::system().dayName(weekday, QLocale::LongFormat);
+ case QDate::StandaloneFormat:
+ return QLocale::system().standaloneDayName(weekday, QLocale::LongFormat);
}
return QString();
}
@@ -819,8 +810,8 @@ static QString toStringIsoDate(qint64 jd)
If the \a format is Qt::ISODate, the string format corresponds
to the ISO 8601 extended specification for representations of
- dates and times, taking the form YYYY-MM-DD, where YYYY is the
- year, MM is the month of the year (between 01 and 12), and DD is
+ dates and times, taking the form yyyy-MM-dd, where yyyy is the
+ year, MM is the month of the year (between 01 and 12), and dd is
the day of the month between 01 and 31.
If the \a format is Qt::SystemLocaleShortDate or
@@ -866,7 +857,7 @@ QString QDate::toString(Qt::DateFormat format) const
case Qt::DefaultLocaleLongDate:
return QLocale().toString(*this, QLocale::LongFormat);
case Qt::RFC2822Date:
- return QLocale::c().toString(*this, QStringLiteral("dd MMM yyyy"));
+ return QLocale::c().toString(*this, QStringViewLiteral("dd MMM yyyy"));
default:
#ifndef QT_NO_TEXTDATE
case Qt::TextDate:
@@ -879,6 +870,9 @@ QString QDate::toString(Qt::DateFormat format) const
}
/*!
+ \fn QString QDate::toString(const QString &format) const
+ \fn QString QDate::toString(QStringView format) const
+
Returns the date as a string. The \a format parameter determines
the format of the result string.
@@ -927,10 +921,18 @@ QString QDate::toString(Qt::DateFormat format) const
\sa fromString(), QDateTime::toString(), QTime::toString(), QLocale::toString()
*/
-QString QDate::toString(const QString& format) const
+QString QDate::toString(QStringView format) const
{
return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
}
+
+#if QT_STRINGVIEW_LEVEL < 2
+QString QDate::toString(const QString &format) const
+{
+ return toString(qToStringViewIgnoringNull(format));
+}
+#endif
+
#endif //QT_NO_DATESTRING
/*!
@@ -1625,6 +1627,9 @@ QString QTime::toString(Qt::DateFormat format) const
}
/*!
+ \fn QString QTime::toString(const QString &format) const
+ \fn QString QTime::toString(QStringView format) const
+
Returns the time as a string. The \a format parameter determines
the format of the result string.
@@ -1679,11 +1684,20 @@ QString QTime::toString(Qt::DateFormat format) const
\sa fromString(), QDate::toString(), QDateTime::toString(), QLocale::toString()
*/
-QString QTime::toString(const QString& format) const
+QString QTime::toString(QStringView format) const
{
return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
}
+
+#if QT_STRINGVIEW_VERSION < 2
+QString QTime::toString(const QString &format) const
+{
+ return toString(qToStringViewIgnoringNull(format));
+}
+#endif
+
#endif //QT_NO_DATESTRING
+
/*!
Sets the time to hour \a h, minute \a m, seconds \a s and
milliseconds \a ms.
@@ -2207,6 +2221,26 @@ static QString qt_tzname(QDateTimePrivate::DaylightStatus daylightStatus)
#endif // Q_OS_WIN
}
+#ifndef QT_BOOTSTRAPPED
+/*
+ \internal
+ Implemented here to share qt_tzname()
+*/
+int QDateTimeParser::startsWithLocalTimeZone(const QStringRef name)
+{
+ QDateTimePrivate::DaylightStatus zones[2] = {
+ QDateTimePrivate::StandardTime,
+ QDateTimePrivate::DaylightTime
+ };
+ for (const auto z : zones) {
+ QString zone(qt_tzname(z));
+ if (name.startsWith(zone))
+ return zone.size();
+ }
+ return 0;
+}
+#endif // QT_BOOTSTRAPPED
+
// Calls the platform variant of mktime for the given date, time and daylightStatus,
// and updates the date, time, daylightStatus and abbreviation with the returned values
// If the date falls outside the 1970 to 2037 range supported by mktime / time_t
@@ -3751,13 +3785,13 @@ void QDateTime::setTime_t(uint secsSince1Jan1970UTC)
If the \a format is Qt::ISODate, the string format corresponds
to the ISO 8601 extended specification for representations of
- dates and times, taking the form YYYY-MM-DDTHH:mm:ss[Z|[+|-]HH:mm],
+ dates and times, taking the form yyyy-MM-ddTHH:mm:ss[Z|[+|-]HH:mm],
depending on the timeSpec() of the QDateTime. If the timeSpec()
is Qt::UTC, Z will be appended to the string; if the timeSpec() is
Qt::OffsetFromUTC, the offset in hours and minutes from UTC will
be appended to the string. To include milliseconds in the ISO 8601
date, use the \a format Qt::ISODateWithMs, which corresponds to
- YYYY-MM-DDTHH:mm:ss.zzz[Z|[+|-]HH:mm].
+ yyyy-MM-ddTHH:mm:ss.zzz[Z|[+|-]HH:mm].
If the \a format is Qt::SystemLocaleShortDate or
Qt::SystemLocaleLongDate, the string format depends on the locale
@@ -3804,7 +3838,7 @@ QString QDateTime::toString(Qt::DateFormat format) const
case Qt::DefaultLocaleLongDate:
return QLocale().toString(*this, QLocale::LongFormat);
case Qt::RFC2822Date: {
- buf = QLocale::c().toString(*this, QStringLiteral("dd MMM yyyy hh:mm:ss "));
+ buf = QLocale::c().toString(*this, QStringViewLiteral("dd MMM yyyy hh:mm:ss "));
buf += toOffsetString(Qt::TextDate, offsetFromUtc());
return buf;
}
@@ -3862,6 +3896,9 @@ QString QDateTime::toString(Qt::DateFormat format) const
}
/*!
+ \fn QString QDateTime::toString(const QString &format) const
+ \fn QString QDateTime::toString(QStringView format) const
+
Returns the datetime as a string. The \a format parameter
determines the format of the result string.
@@ -3939,10 +3976,18 @@ QString QDateTime::toString(Qt::DateFormat format) const
\sa fromString(), QDate::toString(), QTime::toString(), QLocale::toString()
*/
-QString QDateTime::toString(const QString& format) const
+QString QDateTime::toString(QStringView format) const
{
return QLocale::system().toString(*this, format); // QLocale::c() ### Qt6
}
+
+#if QT_STRINGVIEW_LEVEL < 2
+QString QDateTime::toString(const QString &format) const
+{
+ return toString(qToStringViewIgnoringNull(format));
+}
+#endif
+
#endif //QT_NO_DATESTRING
static inline void massageAdjustedDateTime(const QDateTimeData &d, QDate *date, QTime *time)
@@ -4718,25 +4763,35 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
if (size < 10)
return QDateTime();
- QStringRef isoString(&string);
- Qt::TimeSpec spec = Qt::LocalTime;
-
QDate date = QDate::fromString(string.left(10), Qt::ISODate);
if (!date.isValid())
return QDateTime();
if (size == 10)
return QDateTime(date);
- isoString = isoString.right(isoString.length() - 11);
+ Qt::TimeSpec spec = Qt::LocalTime;
+ QStringRef isoString(&string);
+ isoString = isoString.mid(10); // trim "yyyy-MM-dd"
+
+ // Must be left with T and at least one digit for the hour:
+ if (isoString.size() < 2
+ || !(isoString.startsWith(QLatin1Char('T'))
+ // FIXME: QSql relies on QVariant::toDateTime() accepting a space here:
+ || isoString.startsWith(QLatin1Char(' ')))) {
+ return QDateTime();
+ }
+ isoString = isoString.mid(1); // trim 'T' (or space)
+
int offset = 0;
// Check end of string for Time Zone definition, either Z for UTC or [+-]HH:mm for Offset
if (isoString.endsWith(QLatin1Char('Z'))) {
spec = Qt::UTC;
- isoString = isoString.left(isoString.size() - 1);
+ isoString.chop(1); // trim 'Z'
} else {
// the loop below is faster but functionally equal to:
// const int signIndex = isoString.indexOf(QRegExp(QStringLiteral("[+-]")));
int signIndex = isoString.size() - 1;
+ Q_ASSERT(signIndex >= 0);
bool found = false;
{
const QChar plus = QLatin1Char('+');
@@ -4744,8 +4799,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
do {
QChar character(isoString.at(signIndex));
found = character == plus || character == minus;
- } while (--signIndex >= 0 && !found);
- ++signIndex;
+ } while (!found && --signIndex >= 0);
}
if (found) {
@@ -5275,39 +5329,53 @@ QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
QDebug operator<<(QDebug dbg, const QDate &date)
{
QDebugStateSaver saver(dbg);
- dbg.nospace() << "QDate(" << date.toString(Qt::ISODate) << ')';
+ dbg.nospace() << "QDate(";
+ if (date.isValid())
+ dbg.nospace() << date.toString(Qt::ISODate);
+ else
+ dbg.nospace() << "Invalid";
+ dbg.nospace() << ')';
return dbg;
}
QDebug operator<<(QDebug dbg, const QTime &time)
{
QDebugStateSaver saver(dbg);
- dbg.nospace() << "QTime(" << time.toString(QStringLiteral("HH:mm:ss.zzz")) << ')';
+ dbg.nospace() << "QTime(";
+ if (time.isValid())
+ dbg.nospace() << time.toString(QStringViewLiteral("HH:mm:ss.zzz"));
+ else
+ dbg.nospace() << "Invalid";
+ dbg.nospace() << ')';
return dbg;
}
QDebug operator<<(QDebug dbg, const QDateTime &date)
{
QDebugStateSaver saver(dbg);
- const Qt::TimeSpec ts = date.timeSpec();
dbg.nospace() << "QDateTime(";
- dbg.noquote() << date.toString(QStringLiteral("yyyy-MM-dd HH:mm:ss.zzz t"))
- << ' ' << ts;
- switch (ts) {
- case Qt::UTC:
- break;
- case Qt::OffsetFromUTC:
- dbg << ' ' << date.offsetFromUtc() << 's';
- break;
- case Qt::TimeZone:
+ if (date.isValid()) {
+ const Qt::TimeSpec ts = date.timeSpec();
+ dbg.noquote() << date.toString(QStringViewLiteral("yyyy-MM-dd HH:mm:ss.zzz t"))
+ << ' ' << ts;
+ switch (ts) {
+ case Qt::UTC:
+ break;
+ case Qt::OffsetFromUTC:
+ dbg.space() << date.offsetFromUtc() << 's';
+ break;
+ case Qt::TimeZone:
#if QT_CONFIG(timezone)
- dbg << ' ' << date.timeZone().id();
+ dbg.space() << date.timeZone().id();
#endif // timezone
- break;
- case Qt::LocalTime:
- break;
+ break;
+ case Qt::LocalTime:
+ break;
+ }
+ } else {
+ dbg.nospace() << "Invalid";
}
- return dbg << ')';
+ return dbg.nospace() << ')';
}
#endif
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
index 2518dc7301..815fa12b23 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/tools/qdatetime.h
@@ -89,8 +89,11 @@ public:
#endif // QT_NO_TEXTDATE
#ifndef QT_NO_DATESTRING
QString toString(Qt::DateFormat f = Qt::TextDate) const;
+#if QT_STRINGVIEW_LEVEL < 2
QString toString(const QString &format) const;
#endif
+ QString toString(QStringView format) const;
+#endif
#if QT_DEPRECATED_SINCE(5,0)
QT_DEPRECATED inline bool setYMD(int y, int m, int d)
{ if (uint(y) <= 99) y += 1900; return setDate(y, m, d); }
@@ -162,8 +165,11 @@ public:
int msec() const;
#ifndef QT_NO_DATESTRING
QString toString(Qt::DateFormat f = Qt::TextDate) const;
+#if QT_STRINGVIEW_LEVEL < 2
QString toString(const QString &format) const;
#endif
+ QString toString(QStringView format) const;
+#endif
bool setHMS(int h, int m, int s, int ms = 0);
Q_REQUIRED_RESULT QTime addSecs(int secs) const;
@@ -295,8 +301,11 @@ public:
#ifndef QT_NO_DATESTRING
QString toString(Qt::DateFormat f = Qt::TextDate) const;
+#if QT_STRINGVIEW_LEVEL < 2
QString toString(const QString &format) const;
#endif
+ QString toString(QStringView format) const;
+#endif
Q_REQUIRED_RESULT QDateTime addDays(qint64 days) const;
Q_REQUIRED_RESULT QDateTime addMonths(int months) const;
Q_REQUIRED_RESULT QDateTime addYears(int years) const;
diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp
index 62dd25e072..3908e6710e 100644
--- a/src/corelib/tools/qdatetimeparser.cpp
+++ b/src/corelib/tools/qdatetimeparser.cpp
@@ -44,6 +44,7 @@
#include "qset.h"
#include "qlocale.h"
#include "qdatetime.h"
+#include "qtimezone.h"
#include "qregexp.h"
#include "qdebug.h"
@@ -86,6 +87,7 @@ int QDateTimeParser::getDigit(const QDateTime &t, int index) const
}
const SectionNode &node = sectionNodes.at(index);
switch (node.type) {
+ case TimeZoneSection: return t.offsetFromUtc();
case Hour24Section: case Hour12Section: return t.time().hour();
case MinuteSection: return t.time().minute();
case SecondSection: return t.time().second();
@@ -144,6 +146,9 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
int minute = time.minute();
int second = time.second();
int msec = time.msec();
+ Qt::TimeSpec tspec = v.timeSpec();
+ // Only offset from UTC is amenable to setting an int value:
+ int offset = tspec == Qt::OffsetFromUTC ? v.offsetFromUtc() : 0;
switch (node.type) {
case Hour24Section: case Hour12Section: hour = newVal; break;
@@ -164,6 +169,12 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
}
day = newVal;
break;
+ case TimeZoneSection:
+ if (newVal < absoluteMin(index) || newVal > absoluteMax(index))
+ return false;
+ tspec = Qt::OffsetFromUTC;
+ offset = newVal;
+ break;
case AmPmSection: hour = (newVal == 0 ? hour % 12 : (hour % 12) + 12); break;
default:
qWarning("QDateTimeParser::setDigit() Internal error (%s)",
@@ -179,17 +190,23 @@ bool QDateTimeParser::setDigit(QDateTime &v, int index, int newVal) const
day = max;
}
}
- if (QDate::isValid(year, month, day) && QTime::isValid(hour, minute, second, msec)) {
- v = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
- return true;
- }
- return false;
+
+ const QDate newDate(year, month, day);
+ const QTime newTime(hour, minute, second, msec);
+ if (!newDate.isValid() || !newTime.isValid())
+ return false;
+
+ // Preserve zone:
+ v = (tspec == Qt::TimeZone
+ ? QDateTime(newDate, newTime, v.timeZone())
+ : QDateTime(newDate, newTime, tspec, offset));
+ return true;
}
/*!
- \
+ \internal
Returns the absolute maximum for a section
*/
@@ -198,6 +215,7 @@ int QDateTimeParser::absoluteMax(int s, const QDateTime &cur) const
{
const SectionNode &sn = sectionNode(s);
switch (sn.type) {
+ case TimeZoneSection: return QTimeZone::MaxUtcOffsetSecs;
case Hour24Section:
case Hour12Section: return 23; // this is special-cased in
// parseSection. We want it to be
@@ -232,6 +250,7 @@ int QDateTimeParser::absoluteMin(int s) const
{
const SectionNode &sn = sectionNode(s);
switch (sn.type) {
+ case TimeZoneSection: return QTimeZone::MinUtcOffsetSecs;
case Hour24Section:
case Hour12Section:
case MinuteSection:
@@ -492,7 +511,16 @@ bool QDateTimeParser::parseFormat(const QString &newFormat)
newDisplay |= sn.type;
}
break;
-
+ case 't':
+ if (parserType != QVariant::Time) {
+ const SectionNode sn = { TimeZoneSection, i - add, countRepeat(newFormat, i, 4), 0 };
+ newSectionNodes.append(sn);
+ appendSeparator(&newSeparators, newFormat, index, i - index, lastQuote);
+ i += sn.count - 1;
+ index = i + 1;
+ newDisplay |= TimeZoneSection;
+ }
+ break;
default:
break;
}
@@ -631,6 +659,8 @@ int QDateTimeParser::sectionMaxSize(Section s, int count) const
case MSecSection: return 3;
case YearSection: return 4;
case YearSection2Digits: return 2;
+ // Arbitrarily many tokens (each up to 14 bytes) joined with / separators:
+ case TimeZoneSection: return std::numeric_limits<int>::max();
case CalendarPopupSection:
case Internal:
@@ -689,89 +719,79 @@ QString QDateTimeParser::sectionText(int sectionIndex) const
}
-#ifndef QT_NO_TEXTDATE
-/*!
- \internal:skipToNextSection
-
- Parses the part of \a text that corresponds to \a s and returns
- the value of that field. Sets *stateptr to the right state if
- stateptr != 0.
-*/
+#ifndef QT_NO_DATESTRING
-int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
- QString &text, int &cursorPosition, int index,
- State &state, int *usedptr) const
+QDateTimeParser::ParsedSection
+QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionIndex,
+ int offset, QString *text) const
{
- state = Invalid;
- int num = 0;
+ ParsedSection result; // initially Invalid
const SectionNode &sn = sectionNode(sectionIndex);
- if ((sn.type & Internal) == Internal) {
+ if (sn.type & Internal) {
qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
qPrintable(sn.name()), sectionIndex);
- return -1;
+ return result;
}
const int sectionmaxsize = sectionMaxSize(sectionIndex);
- QStringRef sectionTextRef = text.midRef(index, sectionmaxsize);
- int sectiontextSize = sectionTextRef.size();
+ QStringRef sectionTextRef = text->midRef(offset, sectionmaxsize);
QDTPDEBUG << "sectionValue for" << sn.name()
- << "with text" << text << "and st" << sectionTextRef
- << text.midRef(index, sectionmaxsize)
- << index;
+ << "with text" << *text << "and (at" << offset
+ << ") st:" << sectionTextRef;
- int used = 0;
switch (sn.type) {
case AmPmSection: {
QString sectiontext = sectionTextRef.toString();
+ int used;
const int ampm = findAmPm(sectiontext, sectionIndex, &used);
switch (ampm) {
case AM: // sectiontext == AM
case PM: // sectiontext == PM
- num = ampm;
- state = Acceptable;
+ result = ParsedSection(Acceptable, ampm, used);
break;
case PossibleAM: // sectiontext => AM
case PossiblePM: // sectiontext => PM
- num = ampm - 2;
- state = Intermediate;
+ result = ParsedSection(Intermediate, ampm - 2, used);
break;
case PossibleBoth: // sectiontext => AM|PM
- num = 0;
- state = Intermediate;
+ result = ParsedSection(Intermediate, 0, used);
break;
case Neither:
- state = Invalid;
QDTPDEBUG << "invalid because findAmPm(" << sectiontext << ") returned -1";
break;
default:
QDTPDEBUGN("This should never happen (findAmPm returned %d)", ampm);
break;
}
- if (state != Invalid)
- text.replace(index, used, sectiontext.constData(), used);
+ if (result.state != Invalid)
+ text->replace(offset, used, sectiontext.constData(), used);
break; }
+ case TimeZoneSection:
+ result = findTimeZone(sectionTextRef, currentValue,
+ absoluteMax(sectionIndex),
+ absoluteMin(sectionIndex));
+ break;
case MonthSection:
case DayOfWeekSectionShort:
case DayOfWeekSectionLong:
if (sn.count >= 3) {
QString sectiontext = sectionTextRef.toString();
+ int num = 0, used = 0;
if (sn.type == MonthSection) {
- int min = 1;
const QDate minDate = getMinimum().date();
- if (currentValue.date().year() == minDate.year()) {
- min = minDate.month();
- }
+ const int min = (currentValue.date().year() == minDate.year())
+ ? minDate.month() : 1;
num = findMonth(sectiontext.toLower(), min, sectionIndex, &sectiontext, &used);
} else {
num = findDay(sectiontext.toLower(), 1, sectionIndex, &sectiontext, &used);
}
+ result = ParsedSection(Intermediate, num, used);
if (num != -1) {
- state = (used == sectiontext.size() ? Acceptable : Intermediate);
- text.replace(index, used, sectiontext.constData(), used);
- } else {
- state = Intermediate;
+ text->replace(offset, used, sectiontext.constData(), used);
+ if (used == sectiontext.size())
+ result = ParsedSection(Acceptable, num, used);
}
break;
}
@@ -784,26 +804,22 @@ int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionInde
case MinuteSection:
case SecondSection:
case MSecSection: {
+ int sectiontextSize = sectionTextRef.size();
if (sectiontextSize == 0) {
- num = 0;
- used = 0;
- state = Intermediate;
+ result = ParsedSection(Intermediate);
} else {
+ for (int i = 0; i < sectiontextSize; ++i) {
+ if (sectionTextRef.at(i).isSpace())
+ sectiontextSize = i; // which exits the loop
+ }
+
const int absMax = absoluteMax(sectionIndex);
QLocale loc;
bool ok = true;
- int last = -1;
- used = -1;
-
- QStringRef digitsStr = sectionTextRef;
- for (int i = 0; i < sectiontextSize; ++i) {
- if (digitsStr.at(i).isSpace()) {
- sectiontextSize = i;
- break;
- }
- }
+ int last = -1, used = -1;
const int max = qMin(sectionmaxsize, sectiontextSize);
+ QStringRef digitsStr = sectionTextRef.left(max);
for (int digits = max; digits >= 1; --digits) {
digitsStr.truncate(digits);
int tmp = (int)loc.toUInt(digitsStr, &ok);
@@ -825,42 +841,36 @@ int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionInde
if (last == -1) {
QChar first(sectionTextRef.at(0));
- if (separators.at(sectionIndex + 1).startsWith(first)) {
- used = 0;
- state = Intermediate;
- } else {
- state = Invalid;
+ if (separators.at(sectionIndex + 1).startsWith(first))
+ result = ParsedSection(Intermediate, 0, used);
+ else
QDTPDEBUG << "invalid because" << sectionTextRef << "can't become a uint" << last << ok;
- }
} else {
- num += last;
const FieldInfo fi = fieldInfo(sectionIndex);
const bool done = (used == sectionmaxsize);
if (!done && fi & Fraction) { // typing 2 in a zzz field should be .200, not .002
- for (int i=used; i<sectionmaxsize; ++i) {
- num *= 10;
- }
+ for (int i = used; i < sectionmaxsize; ++i)
+ last *= 10;
}
const int absMin = absoluteMin(sectionIndex);
- if (num < absMin) {
- state = done ? Invalid : Intermediate;
- if (done)
- QDTPDEBUG << "invalid because" << num << "is less than absoluteMin" << absMin;
- } else if (num > absMax) {
- state = Intermediate;
+ if (last < absMin) {
+ if (!done) // reversed test to dodge QDTPDEBUG ugliness !
+ result = ParsedSection(Intermediate, last, used);
+ else
+ QDTPDEBUG << "invalid because" << last << "is less than absoluteMin" << absMin;
+ } else if (last > absMax) {
+ result = ParsedSection(Intermediate, last, used);
} else if (!done && (fi & (FixedWidth|Numeric)) == (FixedWidth|Numeric)) {
if (skipToNextSection(sectionIndex, currentValue, digitsStr)) {
- state = Acceptable;
const int missingZeroes = sectionmaxsize - digitsStr.size();
- text.insert(index, QString(missingZeroes, QLatin1Char('0')));
- used = sectionmaxsize;
- cursorPosition += missingZeroes;
+ result = ParsedSection(Acceptable, last, sectionmaxsize, missingZeroes);
+ text->insert(offset, QString(missingZeroes, QLatin1Char('0')));
++(const_cast<QDateTimeParser*>(this)->sectionNodes[sectionIndex].zeroesAdded);
} else {
- state = Intermediate;;
+ result = ParsedSection(Intermediate, last, used);;
}
} else {
- state = Acceptable;
+ result = ParsedSection(Acceptable, last, used);
}
}
}
@@ -868,277 +878,506 @@ int QDateTimeParser::parseSection(const QDateTime &currentValue, int sectionInde
default:
qWarning("QDateTimeParser::parseSection Internal error (%s %d)",
qPrintable(sn.name()), sectionIndex);
- return -1;
+ return result;
+ }
+ Q_ASSERT(result.state != Invalid || result.value == -1);
+
+ return result;
+}
+
+/*!
+ \internal
+
+ Returns a date consistent with the given data on parts specified by known,
+ while staying as close to the given data as it can. Returns an invalid date
+ when on valid date is consistent with the data.
+*/
+
+static QDate actualDate(QDateTimeParser::Sections known, int year, int year2digits,
+ int month, int day, int dayofweek)
+{
+ QDate actual(year, month, day);
+ if (actual.isValid() && year % 100 == year2digits && actual.dayOfWeek() == dayofweek)
+ return actual; // The obvious candidate is fine :-)
+
+ if (dayofweek < 1 || dayofweek > 7) // Invalid: ignore
+ known &= ~QDateTimeParser::DayOfWeekSectionMask;
+
+ // Assuming year > 0 ...
+ if (year % 100 != year2digits) {
+ if (known & QDateTimeParser::YearSection2Digits) {
+ // Over-ride year, even if specified:
+ year += year2digits - year % 100;
+ known &= ~QDateTimeParser::YearSection;
+ } else {
+ year2digits = year % 100;
+ }
+ }
+ Q_ASSERT(year % 100 == year2digits);
+
+ if (month < 1) { // If invalid, clip to nearest valid and ignore in known.
+ month = 1;
+ known &= ~QDateTimeParser::MonthSection;
+ } else if (month > 12) {
+ month = 12;
+ known &= ~QDateTimeParser::MonthSection;
+ }
+
+ QDate first(year, month, 1);
+ int last = known & QDateTimeParser::YearSection && known & QDateTimeParser::MonthSection
+ ? first.daysInMonth() : 0;
+ // If we also know day-of-week, tweak last to the last in the month that matches it:
+ if (last && known & QDateTimeParser::DayOfWeekSectionMask) {
+ int diff = (dayofweek - first.dayOfWeek() - last) % 7;
+ Q_ASSERT(diff <= 0); // C++11 specifies (-ve) % (+ve) to be <= 0.
+ last += diff;
+ }
+ if (day < 1) {
+ if (known & QDateTimeParser::DayOfWeekSectionMask && last) {
+ day = 1 + dayofweek - first.dayOfWeek();
+ if (day < 1)
+ day += 7;
+ } else {
+ day = 1;
+ }
+ known &= ~QDateTimeParser::DaySection;
+ } else if (day > 31) {
+ day = last;
+ known &= ~QDateTimeParser::DaySection;
+ } else if (last && day > last && (known & QDateTimeParser::DaySection) == 0) {
+ day = last;
+ }
+
+ actual = QDate(year, month, day);
+ if (!actual.isValid() // We can't do better than we have, in this case
+ || (known & QDateTimeParser::DaySection
+ && known & QDateTimeParser::MonthSection
+ && known & QDateTimeParser::YearSection) // ditto
+ || actual.dayOfWeek() == dayofweek // Good enough, use it.
+ || (known & QDateTimeParser::DayOfWeekSectionMask) == 0) { // No contradiction, use it.
+ return actual;
+ }
+
+ /*
+ Now it gets trickier.
+
+ We have some inconsistency in our data; we've been told day of week, but
+ it doesn't fit with our year, month and day. At least one of these is
+ unknown, though: so we can fix day of week by tweaking it.
+ */
+
+ if ((known & QDateTimeParser::DaySection) == 0) {
+ // Relatively easy to fix.
+ day += dayofweek - actual.dayOfWeek();
+ if (day < 1)
+ day += 7;
+ else if (day > actual.daysInMonth())
+ day -= 7;
+ actual = QDate(year, month, day);
+ return actual;
+ }
+
+ if ((known & QDateTimeParser::MonthSection) == 0) {
+ /*
+ Try possible month-offsets, m, preferring small; at least one (present
+ month doesn't work) and at most 11 (max month, 12, minus min, 1); try
+ in both directions, ignoring any offset that takes us out of range.
+ */
+ for (int m = 1; m < 12; m++) {
+ if (m < month) {
+ actual = QDate(year, month - m, day);
+ if (actual.dayOfWeek() == dayofweek)
+ return actual;
+ }
+ if (m + month <= 12) {
+ actual = QDate(year, month + m, day);
+ if (actual.dayOfWeek() == dayofweek)
+ return actual;
+ }
+ }
+ // Should only get here in corner cases; e.g. day == 31
+ actual = QDate(year, month, day); // Restore from trial values.
}
- if (usedptr)
- *usedptr = used;
+ if ((known & QDateTimeParser::YearSection) == 0) {
+ if (known & QDateTimeParser::YearSection2Digits) {
+ /*
+ Two-digit year and month are specified; choice of century can only
+ fix this if diff is in one of {1, 2, 5} or {2, 4, 6}; but not if
+ diff is in the other. It's also only reasonable to consider
+ adjacent century, e.g. if year thinks it's 2012 and two-digit year
+ is '97, it makes sense to consider 1997. If either adjacent
+ century does work, the other won't.
+ */
+ actual = QDate(year + 100, month, day);
+ if (actual.dayOfWeek() == dayofweek)
+ return actual;
+ actual = QDate(year - 100, month, day);
+ if (actual.dayOfWeek() == dayofweek)
+ return actual;
+ } else {
+ // Offset by 7 is usually enough, but rare cases may need more:
+ for (int y = 1; y < 12; y++) {
+ actual = QDate(year - y, month, day);
+ if (actual.dayOfWeek() == dayofweek)
+ return actual;
+ actual = QDate(year + y, month, day);
+ if (actual.dayOfWeek() == dayofweek)
+ return actual;
+ }
+ }
+ actual = QDate(year, month, day); // Restore from trial values.
+ }
- return (state != Invalid ? num : -1);
+ return actual; // It'll just have to do :-(
}
-#endif // QT_NO_TEXTDATE
-#ifndef QT_NO_DATESTRING
/*!
\internal
*/
-QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPosition,
- const QDateTime &currentValue, bool fixup) const
+static QTime actualTime(QDateTimeParser::Sections known,
+ int hour, int hour12, int ampm,
+ int minute, int second, int msec)
{
- const QDateTime minimum = getMinimum();
- const QDateTime maximum = getMaximum();
+ // If we have no conflict, or don't know enough to diagonose one, use this:
+ QTime actual(hour, minute, second, msec);
+ if (hour12 < 0 || hour12 > 12) { // ignore bogus value
+ known &= ~QDateTimeParser::Hour12Section;
+ hour12 = hour % 12;
+ }
- State state = Acceptable;
+ if (ampm == -1 || (known & QDateTimeParser::AmPmSection) == 0) {
+ if ((known & QDateTimeParser::Hour12Section) == 0 || hour % 12 == hour12)
+ return actual;
- QDateTime newCurrentValue;
+ if ((known & QDateTimeParser::Hour24Section) == 0)
+ hour = hour12 + (hour > 12 ? 12 : 0);
+ } else {
+ Q_ASSERT(ampm == 0 || ampm == 1);
+ if (hour - hour12 == ampm * 12)
+ return actual;
+
+ if ((known & QDateTimeParser::Hour24Section) == 0
+ && known & QDateTimeParser::Hour12Section) {
+ hour = hour12 + ampm * 12;
+ }
+ }
+ actual = QTime(hour, minute, second, msec);
+ return actual;
+}
+
+/*!
+ \internal
+*/
+QDateTimeParser::StateNode
+QDateTimeParser::scanString(const QDateTime &defaultValue,
+ bool fixup, QString *input) const
+{
+ State state = Acceptable;
bool conflicts = false;
const int sectionNodesCount = sectionNodes.size();
+ int padding = 0;
+ int pos = 0;
+ int year, month, day;
+ const QDate defaultDate = defaultValue.date();
+ const QTime defaultTime = defaultValue.time();
+ defaultDate.getDate(&year, &month, &day);
+ int year2digits = year % 100;
+ int hour = defaultTime.hour();
+ int hour12 = -1;
+ int minute = defaultTime.minute();
+ int second = defaultTime.second();
+ int msec = defaultTime.msec();
+ int dayofweek = defaultDate.dayOfWeek();
+ Qt::TimeSpec tspec = defaultValue.timeSpec();
+ int zoneOffset = 0; // In seconds; local - UTC
+ QString zoneName;
+ QTimeZone timeZone;
+ switch (tspec) {
+ case Qt::OffsetFromUTC: // timeZone is ignored
+ zoneOffset = defaultValue.offsetFromUtc();
+ break;
+ case Qt::TimeZone:
+ timeZone = defaultValue.timeZone();
+ if (timeZone.isValid())
+ zoneOffset = timeZone.offsetFromUtc(defaultValue);
+ // else: is there anything we can do about this ?
+ break;
+ default: // zoneOffset and timeZone are ignored
+ break;
+ }
- QDTPDEBUG << "parse" << input;
- {
- int pos = 0;
- int year, month, day;
- const QDate currentDate = currentValue.date();
- const QTime currentTime = currentValue.time();
- currentDate.getDate(&year, &month, &day);
- int year2digits = year % 100;
- int hour = currentTime.hour();
- int hour12 = -1;
- int minute = currentTime.minute();
- int second = currentTime.second();
- int msec = currentTime.msec();
- int dayofweek = currentDate.dayOfWeek();
-
- int ampm = -1;
- Sections isSet = NoSection;
- int num;
- State tmpstate;
-
- for (int index=0; state != Invalid && index<sectionNodesCount; ++index) {
- if (QStringRef(&input, pos, separators.at(index).size()) != separators.at(index)) {
- QDTPDEBUG << "invalid because" << input.midRef(pos, separators.at(index).size())
- << "!=" << separators.at(index)
- << index << pos << currentSectionIndex;
- state = Invalid;
- goto end;
- }
- pos += separators.at(index).size();
- sectionNodes[index].pos = pos;
- int *current = 0;
- const SectionNode sn = sectionNodes.at(index);
- int used;
-
- num = parseSection(currentValue, index, input, cursorPosition, pos, tmpstate, &used);
- QDTPDEBUG << "sectionValue" << sn.name() << input
- << "pos" << pos << "used" << used << stateName(tmpstate);
- if (fixup && tmpstate == Intermediate && used < sn.count) {
- const FieldInfo fi = fieldInfo(index);
- if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
- const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0'));
- input.replace(pos, used, newText);
- used = sn.count;
- }
- }
- pos += qMax(0, used);
+ int ampm = -1;
+ Sections isSet = NoSection;
- state = qMin<State>(state, tmpstate);
- if (state == Intermediate && context == FromString) {
- state = Invalid;
- break;
+ for (int index = 0; index < sectionNodesCount; ++index) {
+ Q_ASSERT(state != Invalid);
+ if (QStringRef(input, pos, separators.at(index).size()) != separators.at(index)) {
+ QDTPDEBUG << "invalid because" << input->midRef(pos, separators.at(index).size())
+ << "!=" << separators.at(index)
+ << index << pos << currentSectionIndex;
+ return StateNode();
+ }
+ pos += separators.at(index).size();
+ sectionNodes[index].pos = pos;
+ int *current = 0;
+ const SectionNode sn = sectionNodes.at(index);
+ ParsedSection sect;
+
+ {
+ const QDate date = actualDate(isSet, year, year2digits, month, day, dayofweek);
+ const QTime time = actualTime(isSet, hour, hour12, ampm, minute, second, msec);
+ sect = parseSection(tspec == Qt::TimeZone
+ ? QDateTime(date, time, timeZone)
+ : QDateTime(date, time, tspec, zoneOffset),
+ index, pos, input);
+ }
+
+ QDTPDEBUG << "sectionValue" << sn.name() << *input
+ << "pos" << pos << "used" << sect.used << stateName(sect.state);
+
+ padding += sect.zeroes;
+ if (fixup && sect.state == Intermediate && sect.used < sn.count) {
+ const FieldInfo fi = fieldInfo(index);
+ if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
+ const QString newText = QString::fromLatin1("%1").arg(sect.value, sn.count, 10, QLatin1Char('0'));
+ input->replace(pos, sect.used, newText);
+ sect.used = sn.count;
}
+ }
- QDTPDEBUG << index << sn.name() << "is set to"
- << pos << "state is" << stateName(state);
-
-
- if (state != Invalid) {
- switch (sn.type) {
- case Hour24Section: current = &hour; break;
- case Hour12Section: current = &hour12; break;
- case MinuteSection: current = &minute; break;
- case SecondSection: current = &second; break;
- case MSecSection: current = &msec; break;
- case YearSection: current = &year; break;
- case YearSection2Digits: current = &year2digits; break;
- case MonthSection: current = &month; break;
- case DayOfWeekSectionShort:
- case DayOfWeekSectionLong: current = &dayofweek; break;
- case DaySection: current = &day; num = qMax<int>(1, num); break;
- case AmPmSection: current = &ampm; break;
- default:
- qWarning("QDateTimeParser::parse Internal error (%s)",
- qPrintable(sn.name()));
- break;
- }
- if (!current) {
- qWarning("QDateTimeParser::parse Internal error 2");
- return StateNode();
- }
- if (isSet & sn.type && *current != num) {
- QDTPDEBUG << "CONFLICT " << sn.name() << *current << num;
- conflicts = true;
- if (index != currentSectionIndex || num == -1) {
- continue;
- }
- }
- if (num != -1)
- *current = num;
- isSet |= sn.type;
+ state = qMin<State>(state, sect.state);
+ if (state == Invalid || (state == Intermediate && context == FromString))
+ return StateNode();
+
+ switch (sn.type) {
+ case TimeZoneSection:
+ current = &zoneOffset;
+ if (sect.used > 0) {
+ // Synchronize with what findTimeZone() found:
+ QStringRef zoneName = input->midRef(pos, sect.used);
+ Q_ASSERT(!zoneName.isEmpty()); // sect.used > 0
+ const QByteArray latinZone(zoneName.toLatin1());
+ timeZone = QTimeZone(latinZone);
+ tspec = timeZone.isValid()
+ ? (QTimeZone::isTimeZoneIdAvailable(latinZone)
+ ? Qt::TimeZone
+ : Qt::OffsetFromUTC)
+ : (Q_ASSERT(startsWithLocalTimeZone(zoneName)), Qt::LocalTime);
}
+ break;
+ case Hour24Section: current = &hour; break;
+ case Hour12Section: current = &hour12; break;
+ case MinuteSection: current = &minute; break;
+ case SecondSection: current = &second; break;
+ case MSecSection: current = &msec; break;
+ case YearSection: current = &year; break;
+ case YearSection2Digits: current = &year2digits; break;
+ case MonthSection: current = &month; break;
+ case DayOfWeekSectionShort:
+ case DayOfWeekSectionLong: current = &dayofweek; break;
+ case DaySection: current = &day; sect.value = qMax<int>(1, sect.value); break;
+ case AmPmSection: current = &ampm; break;
+ default:
+ qWarning("QDateTimeParser::parse Internal error (%s)",
+ qPrintable(sn.name()));
+ break;
}
- if (state != Invalid && QStringRef(&input, pos, input.size() - pos) != separators.last()) {
- QDTPDEBUG << "invalid because" << input.midRef(pos)
- << "!=" << separators.last() << pos;
- state = Invalid;
+ if (sect.used > 0)
+ pos += sect.used;
+ QDTPDEBUG << index << sn.name() << "is set to"
+ << pos << "state is" << stateName(state);
+
+ if (!current) {
+ qWarning("QDateTimeParser::parse Internal error 2");
+ return StateNode();
+ }
+ if (isSet & sn.type && *current != sect.value) {
+ QDTPDEBUG << "CONFLICT " << sn.name() << *current << sect.value;
+ conflicts = true;
+ if (index != currentSectionIndex || sect.state == Invalid) {
+ continue;
+ }
}
+ if (sect.state != Invalid)
+ *current = sect.value;
- if (state != Invalid) {
- if (parserType != QVariant::Time) {
- if (year % 100 != year2digits && (isSet & YearSection2Digits)) {
- if (!(isSet & YearSection)) {
- year = (year / 100) * 100;
- year += year2digits;
- } else {
- conflicts = true;
- const SectionNode &sn = sectionNode(currentSectionIndex);
- if (sn.type == YearSection2Digits) {
- year = (year / 100) * 100;
- year += year2digits;
- }
- }
- }
+ // Record the present section:
+ isSet |= sn.type;
+ }
- const QDate date(year, month, day);
- const int diff = dayofweek - date.dayOfWeek();
- if (diff != 0 && state == Acceptable && isSet & DayOfWeekSectionMask) {
- if (isSet & DaySection)
- conflicts = true;
- const SectionNode &sn = sectionNode(currentSectionIndex);
- if (sn.type & DayOfWeekSectionMask || currentSectionIndex == -1) {
- // dayofweek should be preferred
- day += diff;
- if (day <= 0) {
- day += 7;
- } else if (day > date.daysInMonth()) {
- day -= 7;
- }
- QDTPDEBUG << year << month << day << dayofweek
- << diff << QDate(year, month, day).dayOfWeek();
- }
- }
+ if (QStringRef(input, pos, input->size() - pos) != separators.last()) {
+ QDTPDEBUG << "invalid because" << input->midRef(pos)
+ << "!=" << separators.last() << pos;
+ return StateNode();
+ }
- bool needfixday = false;
- if (sectionType(currentSectionIndex) & DaySectionMask) {
- cachedDay = day;
- } else if (cachedDay > day) {
- day = cachedDay;
- needfixday = true;
+ if (parserType != QVariant::Time) {
+ if (year % 100 != year2digits && (isSet & YearSection2Digits)) {
+ if (!(isSet & YearSection)) {
+ year = (year / 100) * 100;
+ year += year2digits;
+ } else {
+ conflicts = true;
+ const SectionNode &sn = sectionNode(currentSectionIndex);
+ if (sn.type == YearSection2Digits) {
+ year = (year / 100) * 100;
+ year += year2digits;
}
+ }
+ }
- if (!QDate::isValid(year, month, day)) {
- if (day < 32) {
- cachedDay = day;
- }
- if (day > 28 && QDate::isValid(year, month, 1)) {
- needfixday = true;
- }
- }
- if (needfixday) {
- if (context == FromString) {
- state = Invalid;
- goto end;
- }
- if (state == Acceptable && fixday) {
- day = qMin<int>(day, QDate(year, month, 1).daysInMonth());
-
- const QLocale loc = locale();
- for (int i=0; i<sectionNodesCount; ++i) {
- const SectionNode sn = sectionNode(i);
- if (sn.type & DaySection) {
- input.replace(sectionPos(sn), sectionSize(i), loc.toString(day));
- } else if (sn.type & DayOfWeekSectionMask) {
- const int dayOfWeek = QDate(year, month, day).dayOfWeek();
- const QLocale::FormatType dayFormat =
- (sn.type == DayOfWeekSectionShort
- ? QLocale::ShortFormat : QLocale::LongFormat);
- const QString dayName(loc.dayName(dayOfWeek, dayFormat));
- input.replace(sectionPos(sn), sectionSize(i), dayName);
- }
- }
- } else {
- state = qMin(Intermediate, state);
- }
+ const QDate date(year, month, day);
+ const int diff = dayofweek - date.dayOfWeek();
+ if (diff != 0 && state == Acceptable && isSet & DayOfWeekSectionMask) {
+ if (isSet & DaySection)
+ conflicts = true;
+ const SectionNode &sn = sectionNode(currentSectionIndex);
+ if (sn.type & DayOfWeekSectionMask || currentSectionIndex == -1) {
+ // dayofweek should be preferred
+ day += diff;
+ if (day <= 0) {
+ day += 7;
+ } else if (day > date.daysInMonth()) {
+ day -= 7;
}
+ QDTPDEBUG << year << month << day << dayofweek
+ << diff << QDate(year, month, day).dayOfWeek();
}
+ }
- if (parserType != QVariant::Date) {
- if (isSet & Hour12Section) {
- const bool hasHour = isSet & Hour24Section;
- if (ampm == -1) {
- if (hasHour) {
- ampm = (hour < 12 ? 0 : 1);
- } else {
- ampm = 0; // no way to tell if this is am or pm so I assume am
- }
- }
- hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
- if (!hasHour) {
- hour = hour12;
- } else if (hour != hour12) {
- conflicts = true;
- }
- } else if (ampm != -1) {
- if (!(isSet & (Hour24Section))) {
- hour = (12 * ampm); // special case. Only ap section
- } else if ((ampm == 0) != (hour < 12)) {
- conflicts = true;
+ bool needfixday = false;
+ if (sectionType(currentSectionIndex) & DaySectionMask) {
+ cachedDay = day;
+ } else if (cachedDay > day) {
+ day = cachedDay;
+ needfixday = true;
+ }
+
+ if (!QDate::isValid(year, month, day)) {
+ if (day < 32) {
+ cachedDay = day;
+ }
+ if (day > 28 && QDate::isValid(year, month, 1)) {
+ needfixday = true;
+ }
+ }
+ if (needfixday) {
+ if (context == FromString) {
+ return StateNode();
+ }
+ if (state == Acceptable && fixday) {
+ day = qMin<int>(day, QDate(year, month, 1).daysInMonth());
+
+ const QLocale loc = locale();
+ for (int i=0; i<sectionNodesCount; ++i) {
+ const SectionNode sn = sectionNode(i);
+ if (sn.type & DaySection) {
+ input->replace(sectionPos(sn), sectionSize(i), loc.toString(day));
+ } else if (sn.type & DayOfWeekSectionMask) {
+ const int dayOfWeek = QDate(year, month, day).dayOfWeek();
+ const QLocale::FormatType dayFormat =
+ (sn.type == DayOfWeekSectionShort
+ ? QLocale::ShortFormat : QLocale::LongFormat);
+ const QString dayName(loc.dayName(dayOfWeek, dayFormat));
+ input->replace(sectionPos(sn), sectionSize(i), dayName);
}
}
-
+ } else if (state > Intermediate) {
+ state = Intermediate;
}
+ }
+ }
- newCurrentValue = QDateTime(QDate(year, month, day), QTime(hour, minute, second, msec), spec);
- QDTPDEBUG << year << month << day << hour << minute << second << msec;
+ if (parserType != QVariant::Date) {
+ if (isSet & Hour12Section) {
+ const bool hasHour = isSet & Hour24Section;
+ if (ampm == -1) {
+ if (hasHour) {
+ ampm = (hour < 12 ? 0 : 1);
+ } else {
+ ampm = 0; // no way to tell if this is am or pm so I assume am
+ }
+ }
+ hour12 = (ampm == 0 ? hour12 % 12 : (hour12 % 12) + 12);
+ if (!hasHour) {
+ hour = hour12;
+ } else if (hour != hour12) {
+ conflicts = true;
+ }
+ } else if (ampm != -1) {
+ if (!(isSet & (Hour24Section))) {
+ hour = (12 * ampm); // special case. Only ap section
+ } else if ((ampm == 0) != (hour < 12)) {
+ conflicts = true;
+ }
}
- QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
- newCurrentValue.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
- stateName(state).toLatin1().constData());
+
}
-end:
- if (newCurrentValue.isValid()) {
- if (context != FromString && state != Invalid && newCurrentValue < minimum) {
+
+ QDTPDEBUG << year << month << day << hour << minute << second << msec;
+ Q_ASSERT(state != Invalid);
+
+ const QDate date(year, month, day);
+ const QTime time(hour, minute, second, msec);
+ return StateNode(tspec == Qt::TimeZone
+ ? QDateTime(date, time, timeZone)
+ : QDateTime(date, time, tspec, zoneOffset),
+ state, padding, conflicts);
+}
+
+/*!
+ \internal
+*/
+
+QDateTimeParser::StateNode
+QDateTimeParser::parse(QString input, int position, const QDateTime &defaultValue, bool fixup) const
+{
+ const QDateTime minimum = getMinimum();
+ const QDateTime maximum = getMaximum();
+
+ QDTPDEBUG << "parse" << input;
+ StateNode scan = scanString(defaultValue, fixup, &input);
+ QDTPDEBUGN("'%s' => '%s'(%s)", input.toLatin1().constData(),
+ scan.value.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz")).toLatin1().constData(),
+ stateName(scan.state).toLatin1().constData());
+
+ if (scan.value.isValid() && scan.state != Invalid) {
+ if (context != FromString && scan.value < minimum) {
const QLatin1Char space(' ');
- if (newCurrentValue >= minimum)
+ if (scan.value >= minimum)
qWarning("QDateTimeParser::parse Internal error 3 (%s %s)",
- qPrintable(newCurrentValue.toString()), qPrintable(minimum.toString()));
+ qPrintable(scan.value.toString()), qPrintable(minimum.toString()));
bool done = false;
- state = Invalid;
+ scan.state = Invalid;
+ const int sectionNodesCount = sectionNodes.size();
for (int i=0; i<sectionNodesCount && !done; ++i) {
const SectionNode &sn = sectionNodes.at(i);
QString t = sectionText(input, i, sn.pos).toLower();
- if ((t.size() < sectionMaxSize(i) && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
+ if ((t.size() < sectionMaxSize(i)
+ && (((int)fieldInfo(i) & (FixedWidth|Numeric)) != Numeric))
|| t.contains(space)) {
switch (sn.type) {
case AmPmSection:
switch (findAmPm(t, i)) {
case AM:
case PM:
- state = Acceptable;
+ scan.state = Acceptable;
done = true;
break;
case Neither:
- state = Invalid;
+ scan.state = Invalid;
done = true;
break;
case PossibleAM:
case PossiblePM:
case PossibleBoth: {
- const QDateTime copy(newCurrentValue.addSecs(12 * 60 * 60));
+ const QDateTime copy(scan.value.addSecs(12 * 60 * 60));
if (copy >= minimum && copy <= maximum) {
- state = Intermediate;
+ scan.state = Intermediate;
done = true;
}
break; }
@@ -1146,19 +1385,18 @@ end:
Q_FALLTHROUGH();
case MonthSection:
if (sn.count >= 3) {
- const int currentMonth = newCurrentValue.date().month();
- int tmp = currentMonth;
+ const int finalMonth = scan.value.date().month();
+ int tmp = finalMonth;
// I know the first possible month makes the date too early
while ((tmp = findMonth(t, tmp + 1, i)) != -1) {
- const QDateTime copy(newCurrentValue.addMonths(tmp - currentMonth));
+ const QDateTime copy(scan.value.addMonths(tmp - finalMonth));
if (copy >= minimum && copy <= maximum)
break; // break out of while
}
- if (tmp == -1) {
- break;
+ if (tmp != -1) {
+ scan.state = Intermediate;
+ done = true;
}
- state = Intermediate;
- done = true;
break;
}
Q_FALLTHROUGH();
@@ -1167,25 +1405,24 @@ end:
int toMax;
if (sn.type & TimeSectionMask) {
- if (newCurrentValue.daysTo(minimum) != 0) {
+ if (scan.value.daysTo(minimum) != 0) {
break;
}
- const QTime time = newCurrentValue.time();
+ const QTime time = scan.value.time();
toMin = time.msecsTo(minimum.time());
- if (newCurrentValue.daysTo(maximum) > 0) {
+ if (scan.value.daysTo(maximum) > 0)
toMax = -1; // can't get to max
- } else {
+ else
toMax = time.msecsTo(maximum.time());
- }
} else {
- toMin = newCurrentValue.daysTo(minimum);
- toMax = newCurrentValue.daysTo(maximum);
+ toMin = scan.value.daysTo(minimum);
+ toMax = scan.value.daysTo(maximum);
}
const int maxChange = sn.maxChange();
if (toMin > maxChange) {
QDTPDEBUG << "invalid because toMin > maxChange" << toMin
- << maxChange << t << newCurrentValue << minimum;
- state = Invalid;
+ << maxChange << t << scan.value << minimum;
+ scan.state = Invalid;
done = true;
break;
} else if (toMax > maxChange) {
@@ -1196,23 +1433,23 @@ end:
if (min == -1) {
qWarning("QDateTimeParser::parse Internal error 4 (%s)",
qPrintable(sn.name()));
- state = Invalid;
+ scan.state = Invalid;
done = true;
break;
}
- int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, newCurrentValue);
- int pos = cursorPosition - sn.pos;
+ int max = toMax != -1 ? getDigit(maximum, i) : absoluteMax(i, scan.value);
+ int pos = position + scan.padded - sn.pos;
if (pos < 0 || pos >= t.size())
pos = -1;
- if (!potentialValue(t.simplified(), min, max, i, newCurrentValue, pos)) {
+ if (!potentialValue(t.simplified(), min, max, i, scan.value, pos)) {
QDTPDEBUG << "invalid because potentialValue(" << t.simplified() << min << max
<< sn.name() << "returned" << toMax << toMin << pos;
- state = Invalid;
+ scan.state = Invalid;
done = true;
break;
}
- state = Intermediate;
+ scan.state = Intermediate;
done = true;
break; }
}
@@ -1222,27 +1459,21 @@ end:
if (context == FromString) {
// optimization
Q_ASSERT(maximum.date().toJulianDay() == 4642999);
- if (newCurrentValue.date().toJulianDay() > 4642999)
- state = Invalid;
+ if (scan.value.date().toJulianDay() > 4642999)
+ scan.state = Invalid;
} else {
- if (newCurrentValue > maximum)
- state = Invalid;
+ if (scan.value > maximum)
+ scan.state = Invalid;
}
- QDTPDEBUG << "not checking intermediate because newCurrentValue is" << newCurrentValue << minimum << maximum;
+ QDTPDEBUG << "not checking intermediate because scanned value is" << scan.value << minimum << maximum;
}
}
- StateNode node;
- node.input = input;
- node.state = state;
- node.conflicts = conflicts;
- node.value = newCurrentValue.toTimeSpec(spec);
- text = input;
- return node;
+ text = scan.input = input;
+ // Set spec *after* all checking, so validity is a property of the string:
+ scan.value = scan.value.toTimeSpec(spec);
+ return scan;
}
-#endif // QT_NO_DATESTRING
-
-#ifndef QT_NO_TEXTDATE
/*
\internal
@@ -1330,7 +1561,57 @@ int QDateTimeParser::findDay(const QString &str1, int startDay, int sectionIndex
const int index = findTextEntry(str1, daysOfWeek, usedDay, used);
return index < 0 ? index : index + startDay;
}
-#endif // QT_NO_TEXTDATE
+
+/*!
+ \internal
+
+ Return's .value is zone's offset, zone time - UTC time, in seconds.
+ See QTimeZonePrivate::isValidId() for the format of zone names.
+ */
+QDateTimeParser::ParsedSection
+QDateTimeParser::findTimeZone(QStringRef str, const QDateTime &when,
+ int maxVal, int minVal) const
+{
+ int index = startsWithLocalTimeZone(str);
+ int offset;
+
+ if (index > 0) {
+ // We won't actually use this, but we need a valid return:
+ offset = QDateTime(when.date(), when.time(), Qt::LocalTime).offsetFromUtc();
+ } else {
+ int size = str.length();
+ offset = std::numeric_limits<int>::max(); // deliberately out of range
+ Q_ASSERT(offset > QTimeZone::MaxUtcOffsetSecs); // cf. absoluteMax()
+
+ // Collect up plausibly-valid characters; let QTimeZone work out what's truly valid.
+ while (index < size) {
+ QChar here = str[index];
+ if (here < 127
+ && (here.isLetterOrNumber()
+ || here == '/' || here == '-'
+ || here == '_' || here == '.'
+ || here == '+' || here == ':'))
+ index++;
+ else
+ break;
+ }
+
+ while (index > 0) {
+ str.truncate(index);
+ QTimeZone zone(str.toLatin1());
+ if (zone.isValid()) {
+ offset = zone.offsetFromUtc(when);
+ break;
+ }
+ index--; // maybe we collected too much ...
+ }
+ }
+
+ if (index > 0 && maxVal >= offset && offset >= minVal)
+ return ParsedSection(Acceptable, offset, index);
+
+ return ParsedSection();
+}
/*!
\internal
@@ -1419,6 +1700,7 @@ QDateTimeParser::AmPmFinder QDateTimeParser::findAmPm(QString &str, int sectionI
return PossibleBoth;
return (!broken[amindex] ? PossibleAM : PossiblePM);
}
+#endif // QT_NO_DATESTRING
/*!
\internal
@@ -1461,15 +1743,13 @@ QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
case MinuteSection:
case Hour24Section:
case Hour12Section:
- case YearSection:
case YearSection2Digits:
+ ret |= AllowPartial;
+ Q_FALLTHROUGH();
+ case YearSection:
ret |= Numeric;
- if (sn.type != YearSection) {
- ret |= AllowPartial;
- }
- if (sn.count != 1) {
+ if (sn.count != 1)
ret |= FixedWidth;
- }
break;
case MonthSection:
case DaySection:
@@ -1490,6 +1770,8 @@ QDateTimeParser::FieldInfo QDateTimeParser::fieldInfo(int index) const
case AmPmSection:
ret |= FixedWidth;
break;
+ case TimeZoneSection:
+ break;
default:
qWarning("QDateTimeParser::fieldInfo Internal error 2 (%d %s %d)",
index, qPrintable(sn.name()), sn.count);
@@ -1571,39 +1853,39 @@ bool QDateTimeParser::potentialValue(const QStringRef &str, int min, int max, in
return false;
}
+/*!
+ \internal
+*/
bool QDateTimeParser::skipToNextSection(int index, const QDateTime &current, const QStringRef &text) const
{
- const SectionNode &node = sectionNode(index);
Q_ASSERT(text.size() < sectionMaxSize(index));
-
- const QDateTime maximum = getMaximum();
- const QDateTime minimum = getMinimum();
- Q_ASSERT(current >= minimum && current <= maximum);
-
- QDateTime tmp = current;
+ const SectionNode &node = sectionNode(index);
int min = absoluteMin(index);
- setDigit(tmp, index, min);
- if (tmp < minimum) {
- min = getDigit(minimum, index);
- }
-
int max = absoluteMax(index, current);
- setDigit(tmp, index, max);
- if (tmp > maximum) {
- max = getDigit(maximum, index);
+ // Time-zone field is only numeric if given as offset from UTC:
+ if (node.type != TimeZoneSection || current.timeSpec() == Qt::OffsetFromUTC) {
+ const QDateTime maximum = getMaximum();
+ const QDateTime minimum = getMinimum();
+ Q_ASSERT(current >= minimum && current <= maximum);
+
+ QDateTime tmp = current;
+ if (!setDigit(tmp, index, min) || tmp < minimum)
+ min = getDigit(minimum, index);
+
+ if (!setDigit(tmp, index, max) || tmp > maximum)
+ max = getDigit(maximum, index);
}
int pos = cursorPosition() - node.pos;
if (pos < 0 || pos >= text.size())
pos = -1;
- const bool potential = potentialValue(text, min, max, index, current, pos);
- return !potential;
-
- /* If the value potentially can become another valid entry we
- * don't want to skip to the next. E.g. In a M field (month
- * without leading 0 if you type 1 we don't want to autoskip but
- * if you type 3 we do
+ /*
+ If the value potentially can become another valid entry we don't want to
+ skip to the next. E.g. In a M field (month without leading 0) if you type
+ 1 we don't want to autoskip (there might be [012] following) but if you
+ type 3 we do.
*/
+ return !potentialValue(text, min, max, index, current, pos);
}
/*!
@@ -1624,6 +1906,7 @@ QString QDateTimeParser::SectionNode::name(QDateTimeParser::Section s)
case QDateTimeParser::MinuteSection: return QLatin1String("MinuteSection");
case QDateTimeParser::MonthSection: return QLatin1String("MonthSection");
case QDateTimeParser::SecondSection: return QLatin1String("SecondSection");
+ case QDateTimeParser::TimeZoneSection: return QLatin1String("TimeZoneSection");
case QDateTimeParser::YearSection: return QLatin1String("YearSection");
case QDateTimeParser::YearSection2Digits: return QLatin1String("YearSection2Digits");
case QDateTimeParser::NoSection: return QLatin1String("NoSection");
@@ -1652,9 +1935,7 @@ QString QDateTimeParser::stateName(State s) const
bool QDateTimeParser::fromString(const QString &t, QDate *date, QTime *time) const
{
QDateTime val(QDate(1900, 1, 1), QDATETIMEEDIT_TIME_MIN);
- QString text = t;
- int copy = -1;
- const StateNode tmp = parse(text, copy, val, false);
+ const StateNode tmp = parse(t, -1, val, false);
if (tmp.state != Acceptable || tmp.conflicts) {
return false;
}
diff --git a/src/corelib/tools/qdatetimeparser_p.h b/src/corelib/tools/qdatetimeparser_p.h
index b50c88b4c1..f6f9ed5e24 100644
--- a/src/corelib/tools/qdatetimeparser_p.h
+++ b/src/corelib/tools/qdatetimeparser_p.h
@@ -113,9 +113,10 @@ public:
MinuteSection = 0x00008,
Hour12Section = 0x00010,
Hour24Section = 0x00020,
+ TimeZoneSection = 0x00040,
HourSectionMask = (Hour12Section | Hour24Section),
TimeSectionMask = (MSecSection | SecondSection | MinuteSection |
- HourSectionMask | AmPmSection),
+ HourSectionMask | AmPmSection | TimeZoneSection),
DaySection = 0x00100,
MonthSection = 0x00200,
@@ -159,11 +160,14 @@ public:
};
struct StateNode {
- StateNode() : state(Invalid), conflicts(false) {}
+ StateNode() : state(Invalid), padded(0), conflicts(false) {}
+ StateNode(const QDateTime &val, State ok=Acceptable, int pad=0, bool bad=false)
+ : value(val), state(ok), padded(pad), conflicts(bad) {}
QString input;
+ QDateTime value;
State state;
+ int padded;
bool conflicts;
- QDateTime value;
};
enum AmPm {
@@ -177,12 +181,10 @@ public:
};
#ifndef QT_NO_DATESTRING
- StateNode parse(QString &input, int &cursorPosition, const QDateTime &currentValue, bool fixup) const;
-#endif
- bool parseFormat(const QString &format);
-#ifndef QT_NO_DATESTRING
+ StateNode parse(QString input, int position, const QDateTime &defaultValue, bool fixup) const;
bool fromString(const QString &text, QDate *date, QTime *time) const;
#endif
+ bool parseFormat(const QString &format);
enum FieldInfoFlag {
Numeric = 0x01,
@@ -200,14 +202,28 @@ public:
private:
int sectionMaxSize(Section s, int count) const;
QString sectionText(const QString &text, int sectionIndex, int index) const;
- int parseSection(const QDateTime &currentValue, int sectionIndex, QString &txt, int &cursorPosition,
- int index, QDateTimeParser::State &state, int *used = 0) const;
-#ifndef QT_NO_TEXTDATE
+#ifndef QT_NO_DATESTRING
+ StateNode scanString(const QDateTime &defaultValue,
+ bool fixup, QString *input) const;
+ struct ParsedSection {
+ int value;
+ int used;
+ int zeroes;
+ State state;
+ Q_DECL_CONSTEXPR ParsedSection(State ok = Invalid,
+ int val = 0, int read = 0, int zs = 0)
+ : value(ok == Invalid ? -1 : val), used(read), zeroes(zs), state(ok)
+ {}
+ };
+ ParsedSection parseSection(const QDateTime &currentValue, int sectionIndex,
+ int offset, QString *text) const;
int findMonth(const QString &str1, int monthstart, int sectionIndex,
QString *monthName = 0, int *used = 0) const;
int findDay(const QString &str1, int intDaystart, int sectionIndex,
QString *dayName = 0, int *used = 0) const;
-#endif
+ ParsedSection findTimeZone(QStringRef str, const QDateTime &when,
+ int maxVal, int minVal) const;
+ static int startsWithLocalTimeZone(const QStringRef name); // implemented in qdatetime.cpp
enum AmPmFinder {
Neither = -1,
@@ -218,6 +234,8 @@ private:
PossibleBoth = 4
};
AmPmFinder findAmPm(QString &str, int index, int *used = 0) const;
+#endif // QT_NO_DATESTRING
+
bool potentialValue(const QStringRef &str, int min, int max, int index,
const QDateTime &currentValue, int insert) const;
bool potentialValue(const QString &str, int min, int max, int index,
diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp
index 1f9c05c0b7..9d8c276cff 100644
--- a/src/corelib/tools/qhash.cpp
+++ b/src/corelib/tools/qhash.cpp
@@ -63,13 +63,9 @@
#ifndef QT_BOOTSTRAPPED
#include <qcoreapplication.h>
+#include <qrandom.h>
#endif // QT_BOOTSTRAPPED
-#ifdef Q_OS_UNIX
-#include <stdio.h>
-#include "private/qcore_unix_p.h"
-#endif // Q_OS_UNIX
-
#include <limits.h>
QT_BEGIN_NAMESPACE
@@ -203,7 +199,7 @@ static inline uint hash(const uchar *p, size_t len, uint seed) Q_DECL_NOTHROW
{
uint h = seed;
- if (hasFastCrc32())
+ if (seed && hasFastCrc32())
return crc32(p, len, h);
for (size_t i = 0; i < len; ++i)
@@ -221,7 +217,7 @@ static inline uint hash(const QChar *p, size_t len, uint seed) Q_DECL_NOTHROW
{
uint h = seed;
- if (hasFastCrc32())
+ if (seed && hasFastCrc32())
return crc32(p, len, h);
for (size_t i = 0; i < len; ++i)
@@ -235,6 +231,7 @@ uint qHash(const QByteArray &key, uint seed) Q_DECL_NOTHROW
return hash(reinterpret_cast<const uchar *>(key.constData()), size_t(key.size()), seed);
}
+#if QT_STRINGVIEW_LEVEL < 2
uint qHash(const QString &key, uint seed) Q_DECL_NOTHROW
{
return hash(key.unicode(), size_t(key.size()), seed);
@@ -244,6 +241,12 @@ uint qHash(const QStringRef &key, uint seed) Q_DECL_NOTHROW
{
return hash(key.unicode(), size_t(key.size()), seed);
}
+#endif
+
+uint qHash(QStringView key, uint seed) Q_DECL_NOTHROW
+{
+ return hash(key.data(), key.size(), seed);
+}
uint qHash(const QBitArray &bitArray, uint seed) Q_DECL_NOTHROW
{
@@ -281,42 +284,17 @@ static uint qt_create_qhash_seed()
#ifndef QT_BOOTSTRAPPED
QByteArray envSeed = qgetenv("QT_HASH_SEED");
- if (!envSeed.isNull())
- return envSeed.toUInt();
-
-#ifdef Q_OS_UNIX
- int randomfd = qt_safe_open("/dev/urandom", O_RDONLY);
- if (randomfd == -1)
- randomfd = qt_safe_open("/dev/random", O_RDONLY | O_NONBLOCK);
- if (randomfd != -1) {
- if (qt_safe_read(randomfd, reinterpret_cast<char *>(&seed), sizeof(seed)) == sizeof(seed)) {
- qt_safe_close(randomfd);
- return seed;
+ if (!envSeed.isNull()) {
+ uint seed = envSeed.toUInt();
+ if (seed) {
+ // can't use qWarning here (reentrancy)
+ fprintf(stderr, "QT_HASH_SEED: forced seed value is not 0, cannot guarantee that the "
+ "hashing functions will produce a stable value.");
}
- qt_safe_close(randomfd);
- }
-#endif // Q_OS_UNIX
-
-#if defined(Q_OS_WIN32) && !defined(Q_CC_GNU)
- errno_t err;
- err = rand_s(&seed);
- if (err == 0)
return seed;
-#endif // Q_OS_WIN32
-
- // general fallback: initialize from the current timestamp, pid,
- // and address of a stack-local variable
- quint64 timestamp = QDateTime::currentMSecsSinceEpoch();
- seed ^= timestamp;
- seed ^= (timestamp >> 32);
-
- quint64 pid = QCoreApplication::applicationPid();
- seed ^= pid;
- seed ^= (pid >> 32);
+ }
- quintptr seedPtr = reinterpret_cast<quintptr>(&seed);
- seed ^= seedPtr;
- seed ^= (qulonglong(seedPtr) >> 32); // no-op on 32-bit platforms
+ seed = QRandomGenerator::get32();
#endif // QT_BOOTSTRAPPED
return seed;
@@ -372,14 +350,17 @@ int qGlobalQHashSeed()
is needed. We discourage to do it in production code as it can make your
application susceptible to \l{algorithmic complexity attacks}.
+ From Qt 5.10 and onwards, the only allowed values are 0 and -1. Passing the
+ value -1 will reinitialize the global QHash seed to a random value, while
+ the value of 0 is used to request a stable algorithm for C++ primitive
+ types types (like \c int) and string types (QString, QByteArray).
+
The seed is set in any newly created QHash. See \l{qHash} about how this seed
is being used by QHash.
If the environment variable \c QT_HASH_SEED is set, calling this function will
result in a no-op.
- Passing the value -1 will reinitialize the global QHash seed to a random value.
-
\sa qGlobalQHashSeed
*/
void qSetGlobalQHashSeed(int newSeed)
@@ -390,6 +371,11 @@ void qSetGlobalQHashSeed(int newSeed)
int x(qt_create_qhash_seed() & INT_MAX);
qt_qhash_seed.store(x);
} else {
+ if (newSeed) {
+ // can't use qWarning here (reentrancy)
+ fprintf(stderr, "qSetGlobalQHashSeed: forced seed value is not 0, cannot guarantee that the "
+ "hashing functions will produce a stable value.");
+ }
qt_qhash_seed.store(newSeed & INT_MAX);
}
}
@@ -405,37 +391,25 @@ void qSetGlobalQHashSeed(int newSeed)
results.
The qt_hash functions must *never* change their results.
+
+ This function can hash discontiguous memory by invoking it on each chunk,
+ passing the previous's result in the next call's \a chained argument.
*/
-static uint qt_hash(const QChar *p, int n) Q_DECL_NOTHROW
+uint qt_hash(QStringView key, uint chained) Q_DECL_NOTHROW
{
- uint h = 0;
+ auto n = key.size();
+ auto p = key.utf16();
+
+ uint h = chained;
while (n--) {
- h = (h << 4) + (*p++).unicode();
+ h = (h << 4) + *p++;
h ^= (h & 0xf0000000) >> 23;
h &= 0x0fffffff;
}
return h;
}
-/*!
- \internal
- \overload
-*/
-uint qt_hash(const QString &key) Q_DECL_NOTHROW
-{
- return qt_hash(key.unicode(), key.size());
-}
-
-/*!
- \internal
- \overload
-*/
-uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW
-{
- return qt_hash(key.unicode(), key.size());
-}
-
/*
The prime_deltas array contains the difference between a power
of two and the next prime number:
@@ -1033,6 +1007,13 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
Returns the hash value for the \a key, using \a seed to seed the calculation.
*/
+/*! \fn uint qHash(QStringView key, uint seed = 0)
+ \relates QStringView
+ \since 5.10
+
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+*/
+
/*! \fn uint qHash(QLatin1String key, uint seed = 0)
\relates QHash
\since 5.0
@@ -1252,9 +1233,8 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
should never depend on a particular QHash ordering, there may be situations
where you temporarily need deterministic behavior, for example for debugging or
regression testing. To disable the randomization, define the environment
- variable \c QT_HASH_SEED. The contents of that variable, interpreted as a
- decimal value, will be used as the seed for qHash(). Alternatively, you can
- call the qSetGlobalQHashSeed() function.
+ variable \c QT_HASH_SEED to have the value 0. Alternatively, you can call
+ the qSetGlobalQHashSeed() function with the value 0.
\sa QHashIterator, QMutableHashIterator, QMap, QSet
*/
@@ -1706,6 +1686,60 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
\sa keyBegin()
*/
+/*! \fn QHash::key_value_iterator QHash::keyValueBegin()
+ \since 5.10
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the hash.
+
+ \sa keyValueEnd()
+*/
+
+/*! \fn QHash::key_value_iterator QHash::keyValueEnd()
+ \since 5.10
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the hash.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn QHash::const_key_value_iterator QHash::keyValueBegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the hash.
+
+ \sa keyValueEnd()
+*/
+
+/*! \fn QHash::const_key_value_iterator QHash::constKeyValueBegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the hash.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn QHash::const_key_value_iterator QHash::keyValueEnd() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the hash.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn QHash::const_key_value_iterator QHash::constKeyValueEnd() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the hash.
+
+ \sa constKeyValueBegin()
+*/
+
/*! \fn QHash::iterator QHash::erase(const_iterator pos)
\since 5.7
@@ -2441,6 +2475,18 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW
Returns the underlying const_iterator this key_iterator is based on.
*/
+/*! \typedef QHash::key_value_iterator
+ \inmodule QtCore
+ \since 5.10
+ \brief The QMap::key_value_iterator typedef provides an STL-style iterator for QHash and QMultiHash.
+
+ QHash::key_value_iterator is essentially the same as QHash::iterator
+ with the difference that operator*() returns a key/value pair instead of a
+ value.
+
+ \sa QKeyValueIterator
+*/
+
/*! \fn QDataStream &operator<<(QDataStream &out, const QHash<Key, T>& hash)
\relates QHash
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 703066857d..715acc77ce 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -449,6 +449,9 @@ public:
const_iterator base() const { return i; }
};
+ typedef QKeyValueIterator<const Key&, const T&, const_iterator> const_key_value_iterator;
+ typedef QKeyValueIterator<const Key&, T&, iterator> key_value_iterator;
+
// STL style
inline iterator begin() { detach(); return iterator(d->firstNode()); }
inline const_iterator begin() const { return const_iterator(d->firstNode()); }
@@ -460,6 +463,12 @@ public:
inline const_iterator constEnd() const { return const_iterator(e); }
inline key_iterator keyBegin() const { return key_iterator(begin()); }
inline key_iterator keyEnd() const { return key_iterator(end()); }
+ inline key_value_iterator keyValueBegin() { return key_value_iterator(begin()); }
+ inline key_value_iterator keyValueEnd() { return key_value_iterator(end()); }
+ inline const_key_value_iterator keyValueBegin() const { return const_key_value_iterator(begin()); }
+ inline const_key_value_iterator constKeyValueBegin() const { return const_key_value_iterator(begin()); }
+ inline const_key_value_iterator keyValueEnd() const { return const_key_value_iterator(end()); }
+ inline const_key_value_iterator constKeyValueEnd() const { return const_key_value_iterator(end()); }
QPair<iterator, iterator> equal_range(const Key &key);
QPair<const_iterator, const_iterator> equal_range(const Key &key) const Q_DECL_NOTHROW;
@@ -816,7 +825,7 @@ Q_OUTOFLINE_TEMPLATE T QHash<Key, T>::take(const Key &akey)
Node **node = findNode(akey);
if (*node != e) {
- T t = (*node)->value;
+ T t = std::move((*node)->value);
Node *next = (*node)->next;
deleteNode(*node);
*node = next;
diff --git a/src/corelib/tools/qhashfunctions.h b/src/corelib/tools/qhashfunctions.h
index 0eb6c1b5ce..f75b310e4e 100644
--- a/src/corelib/tools/qhashfunctions.h
+++ b/src/corelib/tools/qhashfunctions.h
@@ -41,7 +41,7 @@
#ifndef QHASHFUNCTIONS_H
#define QHASHFUNCTIONS_H
-#include <QtCore/qchar.h>
+#include <QtCore/qstring.h>
#include <QtCore/qpair.h>
#include <numeric> // for std::accumulate
@@ -95,12 +95,14 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION uint qHash(long double key, uint seed = 0) Q
#endif
Q_DECL_CONST_FUNCTION Q_DECL_CONSTEXPR inline uint qHash(const QChar key, uint seed = 0) Q_DECL_NOTHROW { return qHash(key.unicode(), seed); }
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QByteArray &key, uint seed = 0) Q_DECL_NOTHROW;
+#if QT_STRINGVIEW_LEVEL < 2
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QString &key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QStringRef &key, uint seed = 0) Q_DECL_NOTHROW;
+#endif
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QStringView key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(const QBitArray &key, uint seed = 0) Q_DECL_NOTHROW;
Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qHash(QLatin1String key, uint seed = 0) Q_DECL_NOTHROW;
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QString &key) Q_DECL_NOTHROW;
-Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(const QStringRef &key) Q_DECL_NOTHROW;
+Q_CORE_EXPORT Q_DECL_PURE_FUNCTION uint qt_hash(QStringView key, uint chained = 0) Q_DECL_NOTHROW;
template <class T> inline uint qHash(const T *key, uint seed = 0) Q_DECL_NOTHROW
{
diff --git a/src/corelib/tools/qiterator.h b/src/corelib/tools/qiterator.h
index 3953005242..918b124d5c 100644
--- a/src/corelib/tools/qiterator.h
+++ b/src/corelib/tools/qiterator.h
@@ -179,6 +179,157 @@ public: \
n = c->end(); return false; } \
};
+template<typename Key, typename T, class Iterator>
+class QKeyValueIterator
+{
+public:
+ typedef typename Iterator::iterator_category iterator_category;
+ typedef typename Iterator::difference_type difference_type;
+ typedef std::pair<Key, T> value_type;
+ typedef const value_type *pointer;
+ typedef const value_type &reference;
+
+ QKeyValueIterator() = default;
+ Q_DECL_CONSTEXPR explicit QKeyValueIterator(Iterator o) Q_DECL_NOEXCEPT_EXPR(std::is_nothrow_move_constructible<Iterator>::value)
+ : i(std::move(o)) {}
+
+ std::pair<Key, T> operator*() const {
+ return std::pair<Key, T>(i.key(), i.value());
+ }
+
+ friend bool operator==(QKeyValueIterator lhs, QKeyValueIterator rhs) Q_DECL_NOEXCEPT { return lhs.i == rhs.i; }
+ friend bool operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) Q_DECL_NOEXCEPT { return lhs.i != rhs.i; }
+
+ inline QKeyValueIterator &operator++() { ++i; return *this; }
+ inline QKeyValueIterator operator++(int) { return QKeyValueIterator(i++);}
+ inline QKeyValueIterator &operator--() { --i; return *this; }
+ inline QKeyValueIterator operator--(int) { return QKeyValueIterator(i--); }
+ Iterator base() const { return i; }
+
+private:
+ Iterator i;
+};
+
+/*! \class QKeyValueIterator
+ \inmodule QtCore
+ \since 5.10
+
+ \brief Iterator over the key/value pairs of an associative container.
+
+ The QKeyValueIterator class provides an STL-style iterator for returning
+ key/value pairs from associative containers like QHash and QMap. It
+ supports the same API as the STL associative containers, i.e. getting a
+ key/value pair when iterating through the container.
+
+ This will allow for better interoperability between QMap, QHash and friends
+ and STL-style algorithms.
+
+ \warning Iterators on implicitly shared containers do not work
+ exactly like STL-iterators. You should avoid copying a container
+ while iterators are active on that container. For more information,
+ read \l{Implicit sharing iterator problem}.
+*/
+
+/*! \typedef QKeyValueIterator::iterator_category
+ \internal
+*/
+
+/*! \typedef QKeyValueIterator::difference_type
+ \internal
+*/
+
+/*! \typedef QKeyValueIterator::value_type
+ \internal
+*/
+
+/*! \typedef QKeyValueIterator::pointer
+ \internal
+*/
+
+/*! \typedef QKeyValueIterator::reference
+ \internal
+*/
+
+/*! \fn QKeyValueIterator()
+
+ Constructs a default QKeyValueIterator.
+*/
+
+/*! \fn QKeyValueIterator(Iterator o)
+
+ Constructs a QKeyValueIterator on top of \a o.
+*/
+
+/*! \fn const T &QKeyValueIterator::operator*() const
+
+ Returns the current entry as a pair.
+*/
+
+/*! \fn bool QKeyValueIterator::operator==(QKeyValueIterator lhs, QKeyValueIterator rhs)
+
+ Returns \c true if \a rhs points to the same item as \a lhs otherwise returns
+ \c false.
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QKeyValueIterator::operator!=(QKeyValueIterator lhs, QKeyValueIterator rhs) const
+
+ Returns \c true if \a rhs points to a different item than \a lhs otherwise
+ returns \c false.
+
+ \sa operator==()
+*/
+
+/*!
+ \fn QKeyValueIterator &QKeyValueIterator::operator++()
+
+ The prefix ++ operator (\c{++i}) advances the iterator to the
+ next item in the container and returns the iterator.
+
+ \note Advancing the iterator past its container's end() constitutes
+ undefined behavior.
+
+ \sa operator--()
+*/
+
+/*! \fn QKeyValueIterator QKeyValueIterator::operator++(int)
+
+ \overload
+
+ The postfix ++ operator (\c{i++}) advances the iterator to the
+ next item in the container and returns the iterator's prior value.
+
+ \note Advancing the iterator past its container's end() constitutes
+ undefined behavior.
+*/
+
+/*! \fn QKeyValueIterator &QKeyValueIterator::operator--()
+
+ The prefix -- operator (\c{--i}) backs the iterator up to the previous item
+ in the container and returns the iterator.
+
+ \note Backing up an iterator to before its container's begin() constitutes
+ undefined behavior.
+
+ \sa operator++()
+*/
+
+/*! \fn QKeyValueIterator QKeyValueIterator::operator--(int)
+
+ \overload
+
+ The postfix -- operator (\c{i--}) backs the iterator up to the previous item
+ in the container and returns the iterator's prior value.
+
+ \note Backing up an iterator to before its container's begin() constitutes
+ undefined behavior.
+*/
+
+/*! \fn Iterator QKeyValueIterator::base() const
+ Returns the underlying iterator this QKeyValueIterator is based on.
+*/
+
QT_END_NAMESPACE
#endif // QITERATOR_H
diff --git a/src/corelib/tools/qlinkedlist.h b/src/corelib/tools/qlinkedlist.h
index 249f76dafd..9f54ba7825 100644
--- a/src/corelib/tools/qlinkedlist.h
+++ b/src/corelib/tools/qlinkedlist.h
@@ -448,7 +448,7 @@ bool QLinkedList<T>::removeOne(const T &_t)
template <typename T>
inline T QLinkedList<T>::takeFirst()
{
- T t = first();
+ T t = std::move(first());
removeFirst();
return t;
}
@@ -456,7 +456,7 @@ inline T QLinkedList<T>::takeFirst()
template <typename T>
inline T QLinkedList<T>::takeLast()
{
- T t = last();
+ T t = std::move(last());
removeLast();
return t;
}
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index e2706de9ee..1042c29460 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -555,14 +555,14 @@ inline void QList<T>::removeAt(int i)
template <typename T>
inline T QList<T>::takeAt(int i)
{ Q_ASSERT_X(i >= 0 && i < p.size(), "QList<T>::take", "index out of range");
- detach(); Node *n = reinterpret_cast<Node *>(p.at(i)); T t = n->t(); node_destruct(n);
+ detach(); Node *n = reinterpret_cast<Node *>(p.at(i)); T t = std::move(n->t()); node_destruct(n);
p.remove(i); return t; }
template <typename T>
inline T QList<T>::takeFirst()
-{ T t = first(); removeFirst(); return t; }
+{ T t = std::move(first()); removeFirst(); return t; }
template <typename T>
inline T QList<T>::takeLast()
-{ T t = last(); removeLast(); return t; }
+{ T t = std::move(last()); removeLast(); return t; }
template <typename T>
Q_OUTOFLINE_TEMPLATE void QList<T>::reserve(int alloc)
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 63219b5bab..5db181885c 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -61,6 +61,7 @@
#include "qvariant.h"
#include "qstringbuilder.h"
#include "private/qnumeric_p.h"
+#include <cmath>
#ifdef Q_OS_WIN
# include <qt_windows.h>
# include <time.h>
@@ -89,8 +90,9 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qlocale_data_p.h"
QT_END_INCLUDE_NAMESPACE
-QLocale::Language QLocalePrivate::codeToLanguage(const QChar *code, int len) Q_DECL_NOTHROW
+QLocale::Language QLocalePrivate::codeToLanguage(QStringView code) Q_DECL_NOTHROW
{
+ const auto len = code.size();
if (len != 2 && len != 3)
return QLocale::C;
ushort uc1 = code[0].toLower().unicode();
@@ -131,8 +133,9 @@ QLocale::Language QLocalePrivate::codeToLanguage(const QChar *code, int len) Q_D
return QLocale::C;
}
-QLocale::Script QLocalePrivate::codeToScript(const QChar *code, int len) Q_DECL_NOTHROW
+QLocale::Script QLocalePrivate::codeToScript(QStringView code) Q_DECL_NOTHROW
{
+ const auto len = code.size();
if (len != 4)
return QLocale::AnyScript;
@@ -150,10 +153,12 @@ QLocale::Script QLocalePrivate::codeToScript(const QChar *code, int len) Q_DECL_
return QLocale::AnyScript;
}
-QLocale::Country QLocalePrivate::codeToCountry(const QChar *code, int len) Q_DECL_NOTHROW
+QLocale::Country QLocalePrivate::codeToCountry(QStringView code) Q_DECL_NOTHROW
{
+ const auto len = code.size();
if (len != 2 && len != 3)
return QLocale::AnyCountry;
+
ushort uc1 = code[0].toUpper().unicode();
ushort uc2 = code[1].toUpper().unicode();
ushort uc3 = len > 2 ? code[2].toUpper().unicode() : 0;
@@ -167,48 +172,35 @@ QLocale::Country QLocalePrivate::codeToCountry(const QChar *code, int len) Q_DEC
return QLocale::AnyCountry;
}
-QString QLocalePrivate::languageToCode(QLocale::Language language)
+QLatin1String QLocalePrivate::languageToCode(QLocale::Language language)
{
if (language == QLocale::AnyLanguage)
- return QString();
+ return QLatin1String();
if (language == QLocale::C)
return QLatin1String("C");
const unsigned char *c = language_code_list + 3*(uint(language));
- QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized);
+ return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3);
- code[0] = ushort(c[0]);
- code[1] = ushort(c[1]);
- if (c[2] != 0)
- code[2] = ushort(c[2]);
-
- return code;
}
-QString QLocalePrivate::scriptToCode(QLocale::Script script)
+QLatin1String QLocalePrivate::scriptToCode(QLocale::Script script)
{
if (script == QLocale::AnyScript || script > QLocale::LastScript)
- return QString();
+ return QLatin1String();
const unsigned char *c = script_code_list + 4*(uint(script));
- return QString::fromLatin1((const char *)c, 4);
+ return QLatin1String(reinterpret_cast<const char *>(c), 4);
}
-QString QLocalePrivate::countryToCode(QLocale::Country country)
+QLatin1String QLocalePrivate::countryToCode(QLocale::Country country)
{
if (country == QLocale::AnyCountry)
- return QString();
+ return QLatin1String();
const unsigned char *c = country_code_list + 3*(uint(country));
- QString code(c[2] == 0 ? 2 : 3, Qt::Uninitialized);
-
- code[0] = ushort(c[0]);
- code[1] = ushort(c[1]);
- if (c[2] != 0)
- code[2] = ushort(c[2]);
-
- return code;
+ return QLatin1String(reinterpret_cast<const char*>(c), c[2] == 0 ? 2 : 3);
}
// http://www.unicode.org/reports/tr35/#Likely_Subtags
@@ -527,7 +519,7 @@ static const QLocaleData *findLocaleData(const QString &name)
return QLocaleData::findLocaleData(lang, script, cntry);
}
-QString qt_readEscapedFormatString(const QString &format, int *idx)
+QString qt_readEscapedFormatString(QStringView format, int *idx)
{
int &i = *idx;
@@ -561,13 +553,31 @@ QString qt_readEscapedFormatString(const QString &format, int *idx)
return result;
}
-int qt_repeatCount(const QString &s, int i)
+/*!
+ \internal
+
+ Counts the number of identical leading characters in \a s.
+
+ If \a s is empty, returns 0.
+
+ Otherwise, returns the number of consecutive \c{s.front()}
+ characters at the start of \a s.
+
+ \code
+ qt_repeatCount(u"a"); // == 1
+ qt_repeatCount(u"ab"); // == 1
+ qt_repeatCount(u"aab"); // == 2
+ \endcode
+*/
+int qt_repeatCount(QStringView s)
{
- QChar c = s.at(i);
- int j = i + 1;
+ if (s.isEmpty())
+ return 0;
+ const QChar c = s.front();
+ qssize_t j = 1;
while (j < s.size() && s.at(j) == c)
++j;
- return j - i;
+ return int(j);
}
static const QLocaleData *default_data = 0;
@@ -1122,27 +1132,27 @@ QString QLocale::name() const
return d->languageCode() + QLatin1Char('_') + d->countryCode();
}
-static qlonglong toIntegral_helper(const QLocaleData *d, const QChar *data, int len, bool *ok,
+static qlonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool *ok,
QLocale::NumberOptions mode, qlonglong)
{
- return d->stringToLongLong(data, len, 10, ok, mode);
+ return d->stringToLongLong(str, 10, ok, mode);
}
-static qulonglong toIntegral_helper(const QLocaleData *d, const QChar *data, int len, bool *ok,
+static qulonglong toIntegral_helper(const QLocaleData *d, QStringView str, bool *ok,
QLocale::NumberOptions mode, qulonglong)
{
- return d->stringToUnsLongLong(data, len, 10, ok, mode);
+ return d->stringToUnsLongLong(str, 10, ok, mode);
}
template <typename T> static inline
-T toIntegral_helper(const QLocalePrivate *d, const QChar *data, int len, bool *ok)
+T toIntegral_helper(const QLocalePrivate *d, QStringView str, bool *ok)
{
// ### Qt6: use std::conditional<std::is_unsigned<T>::value, qulonglong, qlonglong>::type
const bool isUnsigned = T(0) < T(-1);
typedef typename QtPrivate::QConditional<isUnsigned, qulonglong, qlonglong>::Type Int64;
// we select the right overload by the last, unused parameter
- Int64 val = toIntegral_helper(d->m_data, data, len, ok, d->m_numberOptions, Int64());
+ Int64 val = toIntegral_helper(d->m_data, str, ok, d->m_numberOptions, Int64());
if (T(val) != val) {
if (ok)
*ok = false;
@@ -1211,6 +1221,7 @@ QString QLocale::scriptToString(QLocale::Script script)
return QLatin1String(script_name_list + script_name_index[script]);
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns the short int represented by the localized string \a s.
@@ -1226,7 +1237,7 @@ QString QLocale::scriptToString(QLocale::Script script)
short QLocale::toShort(const QString &s, bool *ok) const
{
- return toIntegral_helper<short>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<short>(d, s, ok);
}
/*!
@@ -1244,7 +1255,7 @@ short QLocale::toShort(const QString &s, bool *ok) const
ushort QLocale::toUShort(const QString &s, bool *ok) const
{
- return toIntegral_helper<ushort>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<ushort>(d, s, ok);
}
/*!
@@ -1262,7 +1273,7 @@ ushort QLocale::toUShort(const QString &s, bool *ok) const
int QLocale::toInt(const QString &s, bool *ok) const
{
- return toIntegral_helper<int>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<int>(d, s, ok);
}
/*!
@@ -1280,7 +1291,7 @@ int QLocale::toInt(const QString &s, bool *ok) const
uint QLocale::toUInt(const QString &s, bool *ok) const
{
- return toIntegral_helper<uint>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<uint>(d, s, ok);
}
/*!
@@ -1299,7 +1310,7 @@ uint QLocale::toUInt(const QString &s, bool *ok) const
qlonglong QLocale::toLongLong(const QString &s, bool *ok) const
{
- return toIntegral_helper<qlonglong>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<qlonglong>(d, s, ok);
}
/*!
@@ -1318,7 +1329,7 @@ qlonglong QLocale::toLongLong(const QString &s, bool *ok) const
qulonglong QLocale::toULongLong(const QString &s, bool *ok) const
{
- return toIntegral_helper<qulonglong>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<qulonglong>(d, s, ok);
}
/*!
@@ -1361,7 +1372,7 @@ float QLocale::toFloat(const QString &s, bool *ok) const
double QLocale::toDouble(const QString &s, bool *ok) const
{
- return d->m_data->stringToDouble(s.constData(), s.size(), ok, d->m_numberOptions);
+ return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
}
/*!
@@ -1381,7 +1392,7 @@ double QLocale::toDouble(const QString &s, bool *ok) const
short QLocale::toShort(const QStringRef &s, bool *ok) const
{
- return toIntegral_helper<short>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<short>(d, s, ok);
}
/*!
@@ -1401,7 +1412,7 @@ short QLocale::toShort(const QStringRef &s, bool *ok) const
ushort QLocale::toUShort(const QStringRef &s, bool *ok) const
{
- return toIntegral_helper<ushort>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<ushort>(d, s, ok);
}
/*!
@@ -1421,7 +1432,7 @@ ushort QLocale::toUShort(const QStringRef &s, bool *ok) const
int QLocale::toInt(const QStringRef &s, bool *ok) const
{
- return toIntegral_helper<int>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<int>(d, s, ok);
}
/*!
@@ -1441,7 +1452,7 @@ int QLocale::toInt(const QStringRef &s, bool *ok) const
uint QLocale::toUInt(const QStringRef &s, bool *ok) const
{
- return toIntegral_helper<uint>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<uint>(d, s, ok);
}
/*!
@@ -1462,7 +1473,7 @@ uint QLocale::toUInt(const QStringRef &s, bool *ok) const
qlonglong QLocale::toLongLong(const QStringRef &s, bool *ok) const
{
- return toIntegral_helper<qlonglong>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<qlonglong>(d, s, ok);
}
/*!
@@ -1483,7 +1494,7 @@ qlonglong QLocale::toLongLong(const QStringRef &s, bool *ok) const
qulonglong QLocale::toULongLong(const QStringRef &s, bool *ok) const
{
- return toIntegral_helper<qulonglong>(d, s.constData(), s.size(), ok);
+ return toIntegral_helper<qulonglong>(d, s, ok);
}
/*!
@@ -1530,9 +1541,178 @@ float QLocale::toFloat(const QStringRef &s, bool *ok) const
double QLocale::toDouble(const QStringRef &s, bool *ok) const
{
- return d->m_data->stringToDouble(s.constData(), s.size(), ok, d->m_numberOptions);
+ return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
+}
+#endif // QT_STRINGVIEW_LEVEL < 2
+
+/*!
+ Returns the short int represented by the localized string \a s.
+
+ If the conversion fails, the function returns 0.
+
+ If \a ok is not null, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toUShort(), toString()
+
+ \since 5.10
+*/
+
+short QLocale::toShort(QStringView s, bool *ok) const
+{
+ return toIntegral_helper<short>(d, s, ok);
+}
+
+/*!
+ Returns the unsigned short int represented by the localized string \a s.
+
+ If the conversion fails, the function returns 0.
+
+ If \a ok is not null, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toShort(), toString()
+
+ \since 5.10
+*/
+
+ushort QLocale::toUShort(QStringView s, bool *ok) const
+{
+ return toIntegral_helper<ushort>(d, s, ok);
+}
+
+/*!
+ Returns the int represented by the localized string \a s.
+
+ If the conversion fails, the function returns 0.
+
+ If \a ok is not null, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toUInt(), toString()
+
+ \since 5.10
+*/
+
+int QLocale::toInt(QStringView s, bool *ok) const
+{
+ return toIntegral_helper<int>(d, s, ok);
+}
+
+/*!
+ Returns the unsigned int represented by the localized string \a s.
+
+ If the conversion fails, the function returns 0.
+
+ If \a ok is not null, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toInt(), toString()
+
+ \since 5.10
+*/
+
+uint QLocale::toUInt(QStringView s, bool *ok) const
+{
+ return toIntegral_helper<uint>(d, s, ok);
+}
+
+/*!
+ Returns the long long int represented by the localized string \a s.
+
+ If the conversion fails, the function returns 0.
+
+ If \a ok is not null, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toInt(), toULongLong(), toDouble(), toString()
+
+ \since 5.10
+*/
+
+
+qlonglong QLocale::toLongLong(QStringView s, bool *ok) const
+{
+ return toIntegral_helper<qlonglong>(d, s, ok);
+}
+
+/*!
+ Returns the unsigned long long int represented by the localized
+ string \a s.
+
+ If the conversion fails, the function returns 0.
+
+ If \a ok is not null, failure is reported by setting *ok to false, and
+ success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toLongLong(), toInt(), toDouble(), toString()
+
+ \since 5.10
+*/
+
+qulonglong QLocale::toULongLong(QStringView s, bool *ok) const
+{
+ return toIntegral_helper<qulonglong>(d, s, ok);
+}
+
+/*!
+ Returns the float represented by the localized string \a s, or 0.0
+ if the conversion failed.
+
+ If \a ok is not null, reports failure by setting
+ *ok to false and success by setting *ok to true.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toDouble(), toInt(), toString()
+
+ \since 5.10
+*/
+
+float QLocale::toFloat(QStringView s, bool *ok) const
+{
+ return QLocaleData::convertDoubleToFloat(toDouble(s, ok), ok);
}
+/*!
+ Returns the double represented by the localized string \a s, or
+ 0.0 if the conversion failed.
+
+ If \a ok is not null, reports failure by setting
+ *ok to false and success by setting *ok to true.
+
+ Unlike QString::toDouble(), this function does not fall back to
+ the "C" locale if the string cannot be interpreted in this
+ locale.
+
+ \snippet code/src_corelib_tools_qlocale.cpp 3-qstringview
+
+ Notice that the last conversion returns 1234.0, because '.' is the
+ thousands group separator in the German locale.
+
+ This function ignores leading and trailing whitespace.
+
+ \sa toFloat(), toInt(), toString()
+
+ \since 5.10
+*/
+
+double QLocale::toDouble(QStringView s, bool *ok) const
+{
+ return d->m_data->stringToDouble(s, ok, d->m_numberOptions);
+}
/*!
Returns a localized string representation of \a i.
@@ -1564,6 +1744,7 @@ QString QLocale::toString(qulonglong i) const
return d->m_data->unsLongLongToString(i, -1, 10, -1, flags);
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a localized string representation of the given \a date in the
specified \a format.
@@ -1574,6 +1755,19 @@ QString QLocale::toString(const QDate &date, const QString &format) const
{
return d->dateTimeToString(format, QDateTime(), date, QTime(), this);
}
+#endif
+
+/*!
+ \since 5.10
+
+ Returns a localized string representation of the given \a date in the
+ specified \a format.
+ If \a format is an empty string, an empty string is returned.
+*/
+QString QLocale::toString(const QDate &date, QStringView format) const
+{
+ return d->dateTimeToString(format, QDateTime(), date, QTime(), this);
+}
/*!
Returns a localized string representation of the given \a date according
@@ -1599,7 +1793,7 @@ QString QLocale::toString(const QDate &date, FormatType format) const
return toString(date, format_str);
}
-static bool timeFormatContainsAP(const QString &format)
+static bool timeFormatContainsAP(QStringView format)
{
int i = 0;
while (i < format.size()) {
@@ -1616,6 +1810,7 @@ static bool timeFormatContainsAP(const QString &format)
return false;
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a localized string representation of the given \a time according
to the specified \a format.
@@ -1625,7 +1820,21 @@ QString QLocale::toString(const QTime &time, const QString &format) const
{
return d->dateTimeToString(format, QDateTime(), QDate(), time, this);
}
+#endif
+
+/*!
+ \since 5.10
+
+ Returns a localized string representation of the given \a time according
+ to the specified \a format.
+ If \a format is an empty string, an empty string is returned.
+*/
+QString QLocale::toString(const QTime &time, QStringView format) const
+{
+ return d->dateTimeToString(format, QDateTime(), QDate(), time, this);
+}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\since 4.4
@@ -1638,6 +1847,19 @@ QString QLocale::toString(const QDateTime &dateTime, const QString &format) cons
{
return d->dateTimeToString(format, dateTime, QDate(), QTime(), this);
}
+#endif
+
+/*!
+ \since 5.10
+
+ Returns a localized string representation of the given \a dateTime according
+ to the specified \a format.
+ If \a format is an empty string, an empty string is returned.
+*/
+QString QLocale::toString(const QDateTime &dateTime, QStringView format) const
+{
+ return d->dateTimeToString(format, dateTime, QDate(), QTime(), this);
+}
/*!
\since 4.4
@@ -2549,7 +2771,7 @@ QString QLocale::pmText() const
}
-QString QLocalePrivate::dateTimeToString(const QString &format, const QDateTime &datetime,
+QString QLocalePrivate::dateTimeToString(QStringView format, const QDateTime &datetime,
const QDate &dateOnly, const QTime &timeOnly,
const QLocale *q) const
{
@@ -2582,7 +2804,7 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDateTime
}
const QChar c = format.at(i);
- int repeat = qt_repeatCount(format, i);
+ int repeat = qt_repeatCount(format.mid(i));
bool used = false;
if (formatDate) {
switch (c.unicode()) {
@@ -2717,7 +2939,7 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDateTime
case 'a':
used = true;
- if (i + 1 < format.length() && format.at(i + 1).unicode() == 'p') {
+ if (i + 1 < format.size() && format.at(i + 1).unicode() == 'p') {
repeat = 2;
} else {
repeat = 1;
@@ -2727,7 +2949,7 @@ QString QLocalePrivate::dateTimeToString(const QString &format, const QDateTime
case 'A':
used = true;
- if (i + 1 < format.length() && format.at(i + 1).unicode() == 'P') {
+ if (i + 1 < format.size() && format.at(i + 1).unicode() == 'P') {
repeat = 2;
} else {
repeat = 1;
@@ -3082,12 +3304,12 @@ QString QLocaleData::unsLongLongToString(const QChar zero, const QChar group,
number. We can't detect junk here, since we don't even know the base
of the number.
*/
-bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOptions number_options,
+bool QLocaleData::numberToCLocale(QStringView s, QLocale::NumberOptions number_options,
CharBuff *result) const
{
- const QChar *uc = str;
- int l = len;
- int idx = 0;
+ const QChar *uc = s.data();
+ auto l = s.size();
+ decltype(l) idx = 0;
// Skip whitespace
while (idx < l && uc[idx].isSpace())
@@ -3205,7 +3427,7 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len, QLocale::NumberOpti
return idx == l;
}
-bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArray *buff,
+bool QLocaleData::validateChars(QStringView str, NumberMode numMode, QByteArray *buff,
int decDigits, QLocale::NumberOptions number_options) const
{
buff->clear();
@@ -3219,7 +3441,7 @@ bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArr
bool dec = false;
int decDigitCnt = 0;
- for (int i = 0; i < str.length(); ++i) {
+ for (qssize_t i = 0; i < str.size(); ++i) {
char c = digitToCLocale(str.at(i));
if (c >= '0' && c <= '9') {
@@ -3306,11 +3528,11 @@ bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArr
return true;
}
-double QLocaleData::stringToDouble(const QChar *begin, int len, bool *ok,
+double QLocaleData::stringToDouble(QStringView str, bool *ok,
QLocale::NumberOptions number_options) const
{
CharBuff buff;
- if (!numberToCLocale(begin, len, number_options, &buff)) {
+ if (!numberToCLocale(str, number_options, &buff)) {
if (ok != 0)
*ok = false;
return 0.0;
@@ -3323,11 +3545,11 @@ double QLocaleData::stringToDouble(const QChar *begin, int len, bool *ok,
return d;
}
-qlonglong QLocaleData::stringToLongLong(const QChar *begin, int len, int base, bool *ok,
+qlonglong QLocaleData::stringToLongLong(QStringView str, int base, bool *ok,
QLocale::NumberOptions number_options) const
{
CharBuff buff;
- if (!numberToCLocale(begin, len, number_options, &buff)) {
+ if (!numberToCLocale(str, number_options, &buff)) {
if (ok != 0)
*ok = false;
return 0;
@@ -3336,11 +3558,11 @@ qlonglong QLocaleData::stringToLongLong(const QChar *begin, int len, int base, b
return bytearrayToLongLong(buff.constData(), base, ok);
}
-qulonglong QLocaleData::stringToUnsLongLong(const QChar *begin, int len, int base, bool *ok,
+qulonglong QLocaleData::stringToUnsLongLong(QStringView str, int base, bool *ok,
QLocale::NumberOptions number_options) const
{
CharBuff buff;
- if (!numberToCLocale(begin, len, number_options, &buff)) {
+ if (!numberToCLocale(str, number_options, &buff)) {
if (ok != 0)
*ok = false;
return 0;
@@ -3349,7 +3571,7 @@ qulonglong QLocaleData::stringToUnsLongLong(const QChar *begin, int len, int bas
return bytearrayToUnsLongLong(buff.constData(), base, ok);
}
-double QLocaleData::bytearrayToDouble(const char *num, bool *ok, bool *overflow)
+double QLocaleData::bytearrayToDouble(const char *num, bool *ok)
{
bool nonNullOk = false;
int len = static_cast<int>(strlen(num));
@@ -3358,12 +3580,10 @@ double QLocaleData::bytearrayToDouble(const char *num, bool *ok, bool *overflow)
double d = asciiToDouble(num, len, nonNullOk, processed);
if (ok)
*ok = nonNullOk;
- if (overflow)
- *overflow = processed < len;
return d;
}
-qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow)
+qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok)
{
bool _ok;
const char *endptr;
@@ -3371,8 +3591,6 @@ qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok,
if (*num == '\0') {
if (ok != 0)
*ok = false;
- if (overflow != 0)
- *overflow = false;
return 0;
}
@@ -3381,11 +3599,6 @@ qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok,
if (!_ok) {
if (ok != 0)
*ok = false;
- if (overflow != 0) {
- // the only way qstrtoll can fail with *endptr != '\0' on a non-empty
- // input string is overflow
- *overflow = *endptr != '\0';
- }
return 0;
}
@@ -3393,15 +3606,11 @@ qlonglong QLocaleData::bytearrayToLongLong(const char *num, int base, bool *ok,
// we stopped at a non-digit character after converting some digits
if (ok != 0)
*ok = false;
- if (overflow != 0)
- *overflow = false;
return 0;
}
if (ok != 0)
*ok = true;
- if (overflow != 0)
- *overflow = false;
return l;
}
@@ -3576,6 +3785,76 @@ QString QLocale::toCurrencyString(double value, const QString &symbol, int preci
}
/*!
+ \since 5.10
+
+ \enum QLocale::DataSizeFormat
+
+ Specifies the format for representation of data quantities.
+
+ \omitvalue DataSizeBase1000
+ \omitvalue DataSizeSIQuantifiers
+ \value DataSizeIecFormat format using base 1024 and IEC prefixes: KiB, MiB, GiB, ...
+ \value DataSizeTraditionalFormat format using base 1024 and SI prefixes: kB, MB, GB, ...
+ \value DataSizeSIFormat format using base 1000 and SI prefixes: kB, MB, GB, ...
+
+ \sa formattedDataSize()
+*/
+
+/*!
+ \since 5.10
+
+ Converts a size in bytes to a human-readable localized string, expressed in
+ a unit for which the numeric portion is at least 1 but as low as
+ possible. For example if \a bytes is 16384, \a precision is 2, and \a format
+ is \c DataSizeIecFormat (the default), this function returns "16.00 KiB";
+ for 1330409069609 bytes it returns "1.21 GiB"; and so on. If \a format is \c
+ DataSizeIecFormat or \c DataSizeTraditionalFormat, the given number of bytes
+ is divided by a power of 1024, with result less than 1024; for \c
+ DataSizeSIFormat, it is divided by a power of 1000, with result less than
+ 1000. DataSizeIecFormat uses the new IEC standard quantifiers Ki, Mi and so
+ on, whereas DataSizeSIFormat uses and DataSizeTraditionalFormat abuses the
+ older SI quantifiers k, M, etc.
+
+ \sa refresh(), caching()
+*/
+QString QLocale::formattedDataSize(qint64 bytes, int precision, DataSizeFormats format)
+{
+ int power, base = 1000;
+ if (!bytes) {
+ power = 0;
+ } else if (format & DataSizeBase1000) {
+ power = int(std::log10(qAbs(bytes)) / 3);
+ } else { // Compute log2(bytes) / 10:
+ power = int((63 - qCountLeadingZeroBits(quint64(qAbs(bytes)))) / 10);
+ base = 1024;
+ }
+ // Only go to doubles if we'll be using a quantifier:
+ const QString number = power
+ ? toString(bytes / std::pow(double(base), power), 'f', qMin(precision, 3 * power))
+ : toString(bytes);
+
+ // We don't support sizes in units larger than exbibytes because
+ // the number of bytes would not fit into qint64.
+ Q_ASSERT(power <= 6 && power >= 0);
+ QString unit;
+ if (power > 0) {
+ quint16 index, size;
+ if (format & DataSizeSIQuantifiers) {
+ index = d->m_data->m_byte_si_quantified_idx;
+ size = d->m_data->m_byte_si_quantified_size;
+ } else {
+ index = d->m_data->m_byte_iec_quantified_idx;
+ size = d->m_data->m_byte_iec_quantified_size;
+ }
+ unit = getLocaleListData(byte_unit_data + index, size, power - 1);
+ } else {
+ unit = getLocaleData(byte_unit_data + d->m_data->m_byte_idx, d->m_data->m_byte_size);
+ }
+
+ return number + QLatin1Char(' ') + unit;
+}
+
+/*!
\since 4.8
Returns an ordered list of locale names for translation purposes in
diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h
index bd89e48234..54b1a32946 100644
--- a/src/corelib/tools/qlocale.h
+++ b/src/corelib/tools/qlocale.h
@@ -913,6 +913,19 @@ public:
CurrencyDisplayName
};
+ enum DataSizeFormat {
+ // Single-bit values, for internal use.
+ DataSizeBase1000 = 1, // use factors of 1000 instead of IEC's 1024;
+ DataSizeSIQuantifiers = 2, // use SI quantifiers instead of IEC ones.
+
+ // Flags values for use in API:
+ DataSizeIecFormat = 0, // base 1024, KiB, MiB, GiB, ...
+ DataSizeTraditionalFormat = DataSizeSIQuantifiers, // base 1024, kB, MB, GB, ...
+ DataSizeSIFormat = DataSizeBase1000 | DataSizeSIQuantifiers // base 1000, kB, MB, GB, ...
+ };
+ Q_DECLARE_FLAGS(DataSizeFormats, DataSizeFormat)
+ Q_FLAG(DataSizeFormats)
+
QLocale();
QLocale(const QString &name);
QLocale(Language language, Country country = AnyCountry);
@@ -935,6 +948,7 @@ public:
QString nativeLanguageName() const;
QString nativeCountryName() const;
+#if QT_STRINGVIEW_LEVEL < 2
short toShort(const QString &s, bool *ok = Q_NULLPTR) const;
ushort toUShort(const QString &s, bool *ok = Q_NULLPTR) const;
int toInt(const QString &s, bool *ok = Q_NULLPTR) const;
@@ -952,6 +966,16 @@ public:
qulonglong toULongLong(const QStringRef &s, bool *ok = Q_NULLPTR) const;
float toFloat(const QStringRef &s, bool *ok = Q_NULLPTR) const;
double toDouble(const QStringRef &s, bool *ok = Q_NULLPTR) const;
+#endif
+
+ short toShort(QStringView s, bool *ok = nullptr) const;
+ ushort toUShort(QStringView s, bool *ok = nullptr) const;
+ int toInt(QStringView s, bool *ok = nullptr) const;
+ uint toUInt(QStringView s, bool *ok = nullptr) const;
+ qlonglong toLongLong(QStringView s, bool *ok = nullptr) const;
+ qulonglong toULongLong(QStringView s, bool *ok = nullptr) const;
+ float toFloat(QStringView s, bool *ok = nullptr) const;
+ double toDouble(QStringView s, bool *ok = nullptr) const;
QString toString(qlonglong i) const;
QString toString(qulonglong i) const;
@@ -961,12 +985,18 @@ public:
inline QString toString(uint i) const;
QString toString(double i, char f = 'g', int prec = 6) const;
inline QString toString(float i, char f = 'g', int prec = 6) const;
+
+#if QT_STRINGVIEW_LEVEL < 2
QString toString(const QDate &date, const QString &formatStr) const;
- QString toString(const QDate &date, FormatType format = LongFormat) const;
QString toString(const QTime &time, const QString &formatStr) const;
+ QString toString(const QDateTime &dateTime, const QString &format) const;
+#endif
+ QString toString(const QDate &date, QStringView formatStr) const;
+ QString toString(const QTime &time, QStringView formatStr) const;
+ QString toString(const QDateTime &dateTime, QStringView format) const;
+ QString toString(const QDate &date, FormatType format = LongFormat) const;
QString toString(const QTime &time, FormatType format = LongFormat) const;
QString toString(const QDateTime &dateTime, FormatType format = LongFormat) const;
- QString toString(const QDateTime &dateTime, const QString &format) const;
QString dateFormat(FormatType format = LongFormat) const;
QString timeFormat(FormatType format = LongFormat) const;
@@ -1028,6 +1058,8 @@ public:
{ return toCurrencyString(double(i), symbol, precision); }
#endif
+ QString formattedDataSize(qint64 bytes, int precision = 2, DataSizeFormats format = DataSizeIecFormat);
+
QStringList uiLanguages() const;
bool operator==(const QLocale &other) const;
diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc
index d419172356..ed3eb93313 100644
--- a/src/corelib/tools/qlocale.qdoc
+++ b/src/corelib/tools/qlocale.qdoc
@@ -92,7 +92,7 @@
\note For the current keyboard input locale take a look at
QInputMethod::locale().
- QLocale's data is based on Common Locale Data Repository v29.
+ QLocale's data is based on Common Locale Data Repository v31.0.1.
\sa QString::arg(), QString::toInt(), QString::toDouble(),
QInputMethod::locale()
diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/tools/qlocale_data_p.h
index 869153942e..cf210454d4 100644
--- a/src/corelib/tools/qlocale_data_p.h
+++ b/src/corelib/tools/qlocale_data_p.h
@@ -77,16 +77,16 @@ static const int ImperialMeasurementSystemsCount =
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2016-03-19 from the
- Common Locale Data Repository v29
+ This part of the file was generated on 2017-06-07 from the
+ Common Locale Data Repository v31.0.1
http://www.unicode.org/cldr/
- Do not change it, instead edit CLDR data and regenerate this file using
- cldr2qlocalexml.py and qlocalexml2cpp.py.
+ Do not edit this section: instead regenerate it using
+ cldr2qlocalexml.py and qlocalexml2cpp.py on updated (or
+ edited) CLDR data; see qtbase/util/local_database/.
*/
-
static const QLocaleId likely_subtags[] = {
{ 4, 0, 0 }, { 4, 7, 69 }, // aa -> aa_Latn_ET
{ 2, 0, 0 }, { 2, 2, 81 }, // ab -> ab_Cyrl_GE
@@ -138,8 +138,7 @@ static const QLocaleId likely_subtags[] = {
{ 152, 0, 0 }, { 152, 14, 67 }, // byn -> byn_Ethi_ER
{ 24, 0, 0 }, { 24, 7, 197 }, // ca -> ca_Latn_ES
{ 156, 0, 0 }, { 156, 7, 157 }, // cch -> cch_Latn_NG
- { 272, 0, 0 }, { 272, 11, 100 }, // ccp -> ccp_Beng_IN
- { 272, 46, 0 }, { 272, 46, 18 }, // ccp_Cakm -> ccp_Cakm_BD
+ { 272, 0, 0 }, { 272, 46, 18 }, // ccp -> ccp_Cakm_BD
{ 218, 0, 0 }, { 218, 2, 178 }, // ce -> ce_Cyrl_RU
{ 211, 0, 0 }, { 211, 7, 221 }, // cgg -> cgg_Latn_UG
{ 217, 0, 0 }, { 217, 7, 89 }, // ch -> ch_Latn_GU
@@ -744,7 +743,6 @@ static const QLocaleId likely_subtags[] = {
{ 0, 2, 81 }, { 2, 2, 81 }, // und_Cyrl_GE -> ab_Cyrl_GE
{ 0, 2, 85 }, { 74, 2, 85 }, // und_Cyrl_GR -> mk_Cyrl_GR
{ 0, 2, 141 }, { 129, 2, 141 }, // und_Cyrl_MD -> uk_Cyrl_MD
- { 0, 2, 172 }, { 22, 2, 172 }, // und_Cyrl_PL -> be_Cyrl_PL
{ 0, 2, 177 }, { 20, 2, 177 }, // und_Cyrl_RO -> bg_Cyrl_RO
{ 0, 2, 191 }, { 129, 2, 191 }, // und_Cyrl_SK -> uk_Cyrl_SK
{ 0, 2, 257 }, { 100, 2, 257 }, // und_Cyrl_XK -> sr_Cyrl_XK
@@ -932,184 +930,184 @@ static const quint16 locale_index[] = {
231, // Galician
232, // Georgian
233, // German
- 239, // Greek
- 241, // Greenlandic
- 242, // Guarani
- 243, // Gujarati
- 244, // Hausa
- 248, // Hebrew
- 249, // Hindi
- 250, // Hungarian
- 251, // Icelandic
- 252, // Indonesian
- 253, // Interlingua
+ 240, // Greek
+ 242, // Greenlandic
+ 243, // Guarani
+ 244, // Gujarati
+ 245, // Hausa
+ 249, // Hebrew
+ 250, // Hindi
+ 251, // Hungarian
+ 252, // Icelandic
+ 253, // Indonesian
+ 254, // Interlingua
0, // Interlingue
- 254, // Inuktitut
+ 255, // Inuktitut
0, // Inupiak
- 256, // Irish
- 257, // Italian
- 260, // Japanese
- 261, // Javanese
- 262, // Kannada
- 263, // Kashmiri
- 264, // Kazakh
- 265, // Kinyarwanda
- 266, // Kirghiz
- 267, // Korean
- 269, // Kurdish
- 270, // Rundi
- 271, // Lao
+ 257, // Irish
+ 258, // Italian
+ 262, // Japanese
+ 263, // Javanese
+ 264, // Kannada
+ 265, // Kashmiri
+ 266, // Kazakh
+ 267, // Kinyarwanda
+ 268, // Kirghiz
+ 269, // Korean
+ 271, // Kurdish
+ 272, // Rundi
+ 273, // Lao
0, // Latin
- 272, // Latvian
- 273, // Lingala
- 277, // Lithuanian
- 278, // Macedonian
- 279, // Malagasy
- 280, // Malay
- 284, // Malayalam
- 285, // Maltese
- 286, // Maori
- 287, // Marathi
+ 274, // Latvian
+ 275, // Lingala
+ 279, // Lithuanian
+ 280, // Macedonian
+ 281, // Malagasy
+ 282, // Malay
+ 286, // Malayalam
+ 287, // Maltese
+ 288, // Maori
+ 289, // Marathi
0, // Marshallese
- 288, // Mongolian
+ 290, // Mongolian
0, // Nauru
- 290, // Nepali
- 292, // NorwegianBokmal
- 294, // Occitan
- 295, // Oriya
- 296, // Pashto
- 297, // Persian
- 299, // Polish
- 300, // Portuguese
- 312, // Punjabi
- 314, // Quechua
- 317, // Romansh
- 318, // Romanian
- 320, // Russian
+ 292, // Nepali
+ 294, // NorwegianBokmal
+ 296, // Occitan
+ 297, // Oriya
+ 298, // Pashto
+ 299, // Persian
+ 301, // Polish
+ 302, // Portuguese
+ 314, // Punjabi
+ 316, // Quechua
+ 319, // Romansh
+ 320, // Romanian
+ 322, // Russian
0, // Samoan
- 326, // Sango
- 327, // Sanskrit
- 328, // Serbian
- 336, // Ossetic
- 338, // Southern Sotho
- 339, // Tswana
- 340, // Shona
- 341, // Sindhi
- 342, // Sinhala
- 343, // Swati
- 344, // Slovak
- 345, // Slovenian
- 346, // Somali
- 350, // Spanish
+ 328, // Sango
+ 329, // Sanskrit
+ 330, // Serbian
+ 338, // Ossetic
+ 340, // Southern Sotho
+ 341, // Tswana
+ 342, // Shona
+ 343, // Sindhi
+ 344, // Sinhala
+ 345, // Swati
+ 346, // Slovak
+ 347, // Slovenian
+ 348, // Somali
+ 352, // Spanish
0, // Sundanese
- 377, // Swahili
- 381, // Swedish
+ 380, // Swahili
+ 384, // Swedish
0, // Sardinian
- 384, // Tajik
- 385, // Tamil
- 389, // Tatar
- 390, // Telugu
- 391, // Thai
- 392, // Tibetan
- 394, // Tigrinya
- 396, // Tongan
- 397, // Tsonga
- 398, // Turkish
- 400, // Turkmen
+ 387, // Tajik
+ 388, // Tamil
+ 392, // Tatar
+ 393, // Telugu
+ 394, // Thai
+ 395, // Tibetan
+ 397, // Tigrinya
+ 399, // Tongan
+ 400, // Tsonga
+ 401, // Turkish
+ 403, // Turkmen
0, // Tahitian
- 401, // Uighur
- 402, // Ukrainian
- 403, // Urdu
- 405, // Uzbek
- 408, // Vietnamese
+ 404, // Uighur
+ 405, // Ukrainian
+ 406, // Urdu
+ 408, // Uzbek
+ 411, // Vietnamese
0, // Volapuk
- 409, // Welsh
- 410, // Wolof
- 411, // Xhosa
+ 412, // Welsh
+ 413, // Wolof
+ 414, // Xhosa
0, // Yiddish
- 412, // Yoruba
+ 415, // Yoruba
0, // Zhuang
- 414, // Zulu
- 415, // NorwegianNynorsk
- 416, // Bosnian
- 418, // Divehi
- 419, // Manx
- 420, // Cornish
- 421, // Akan
- 422, // Konkani
- 423, // Ga
- 424, // Igbo
- 425, // Kamba
- 426, // Syriac
- 427, // Blin
- 428, // Geez
+ 417, // Zulu
+ 418, // NorwegianNynorsk
+ 419, // Bosnian
+ 421, // Divehi
+ 422, // Manx
+ 423, // Cornish
+ 424, // Akan
+ 425, // Konkani
+ 426, // Ga
+ 427, // Igbo
+ 428, // Kamba
+ 429, // Syriac
+ 430, // Blin
+ 431, // Geez
0, // Koro
- 429, // Sidamo
- 430, // Atsam
- 431, // Tigre
- 432, // Jju
- 433, // Friulian
- 434, // Venda
- 435, // Ewe
- 437, // Walamo
- 438, // Hawaiian
- 439, // Tyap
- 440, // Nyanja
- 441, // Filipino
- 442, // Swiss German
- 445, // Sichuan Yi
- 446, // Kpelle
- 447, // Low German
- 448, // South Ndebele
- 449, // Northern Sotho
- 450, // Northern Sami
- 453, // Taroko
- 454, // Gusii
- 455, // Taita
- 456, // Fulah
- 460, // Kikuyu
- 461, // Samburu
- 462, // Sena
- 463, // North Ndebele
- 464, // Rombo
- 465, // Tachelhit
- 467, // Kabyle
- 468, // Nyankole
- 469, // Bena
- 470, // Vunjo
- 471, // Bambara
- 473, // Embu
- 474, // Cherokee
- 475, // Morisyen
- 476, // Makonde
- 477, // Langi
- 478, // Ganda
- 479, // Bemba
- 480, // Kabuverdianu
- 481, // Meru
- 482, // Kalenjin
- 483, // Nama
- 484, // Machame
- 485, // Colognian
- 486, // Masai
- 488, // Soga
- 489, // Luyia
- 490, // Asu
- 491, // Teso
- 493, // Saho
- 494, // Koyra Chiini
- 495, // Rwa
- 496, // Luo
- 497, // Chiga
- 498, // Central Morocco Tamazight
- 499, // Koyraboro Senni
- 500, // Shambala
- 501, // Bodo
+ 432, // Sidamo
+ 433, // Atsam
+ 434, // Tigre
+ 435, // Jju
+ 436, // Friulian
+ 437, // Venda
+ 438, // Ewe
+ 440, // Walamo
+ 441, // Hawaiian
+ 442, // Tyap
+ 443, // Nyanja
+ 444, // Filipino
+ 445, // Swiss German
+ 448, // Sichuan Yi
+ 449, // Kpelle
+ 450, // Low German
+ 452, // South Ndebele
+ 453, // Northern Sotho
+ 454, // Northern Sami
+ 457, // Taroko
+ 458, // Gusii
+ 459, // Taita
+ 460, // Fulah
+ 464, // Kikuyu
+ 465, // Samburu
+ 466, // Sena
+ 467, // North Ndebele
+ 468, // Rombo
+ 469, // Tachelhit
+ 471, // Kabyle
+ 472, // Nyankole
+ 473, // Bena
+ 474, // Vunjo
+ 475, // Bambara
+ 477, // Embu
+ 478, // Cherokee
+ 479, // Morisyen
+ 480, // Makonde
+ 481, // Langi
+ 482, // Ganda
+ 483, // Bemba
+ 484, // Kabuverdianu
+ 485, // Meru
+ 486, // Kalenjin
+ 487, // Nama
+ 488, // Machame
+ 489, // Colognian
+ 490, // Masai
+ 492, // Soga
+ 493, // Luyia
+ 494, // Asu
+ 495, // Teso
+ 497, // Saho
+ 498, // Koyra Chiini
+ 499, // Rwa
+ 500, // Luo
+ 501, // Chiga
+ 502, // Central Morocco Tamazight
+ 503, // Koyraboro Senni
+ 504, // Shambala
+ 505, // Bodo
0, // Avaric
0, // Chamorro
- 502, // Chechen
- 503, // Church
- 504, // Chuvash
+ 506, // Chechen
+ 507, // Church
+ 508, // Chuvash
0, // Cree
0, // Haitian
0, // Herero
@@ -1119,37 +1117,37 @@ static const quint16 locale_index[] = {
0, // Kongo
0, // Kwanyama
0, // Limburgish
- 505, // LubaKatanga
- 506, // Luxembourgish
+ 509, // LubaKatanga
+ 510, // Luxembourgish
0, // Navaho
0, // Ndonga
0, // Ojibwa
0, // Pali
- 507, // Walloon
- 508, // Aghem
- 509, // Basaa
- 510, // Zarma
- 511, // Duala
- 512, // JolaFonyi
- 513, // Ewondo
- 514, // Bafia
- 515, // MakhuwaMeetto
- 516, // Mundang
- 517, // Kwasio
- 518, // Nuer
- 519, // Sakha
- 520, // Sangu
+ 511, // Walloon
+ 512, // Aghem
+ 513, // Basaa
+ 514, // Zarma
+ 515, // Duala
+ 516, // JolaFonyi
+ 517, // Ewondo
+ 518, // Bafia
+ 519, // MakhuwaMeetto
+ 520, // Mundang
+ 521, // Kwasio
+ 522, // Nuer
+ 523, // Sakha
+ 524, // Sangu
0, // Congo Swahili
- 521, // Tasawaq
- 522, // Vai
- 524, // Walser
- 525, // Yangben
+ 525, // Tasawaq
+ 526, // Vai
+ 528, // Walser
+ 529, // Yangben
0, // Avestan
- 526, // Asturian
- 527, // Ngomba
- 528, // Kako
- 529, // Meta
- 530, // Ngiemboon
+ 530, // Asturian
+ 531, // Ngomba
+ 532, // Kako
+ 533, // Meta
+ 534, // Ngiemboon
0, // Aragonese
0, // Akkadian
0, // AncientEgyptian
@@ -1161,7 +1159,7 @@ static const quint16 locale_index[] = {
0, // Buginese
0, // Buhid
0, // Carian
- 0, // Chakma
+ 535, // Chakma
0, // ClassicalMandaic
0, // Coptic
0, // Dogri
@@ -1179,7 +1177,7 @@ static const quint16 locale_index[] = {
0, // Lycian
0, // Lydian
0, // Mandingo
- 0, // Manipuri
+ 536, // Manipuri
0, // Meroitic
0, // NorthernThai
0, // OldIrish
@@ -1198,26 +1196,26 @@ static const quint16 locale_index[] = {
0, // Sora
0, // Sylheti
0, // Tagbanwa
- 0, // TaiDam
+ 537, // TaiDam
0, // TaiNua
0, // Ugaritic
- 531, // Akoose
- 532, // Lakota
- 533, // Standard Moroccan Tamazight
- 534, // Mapuche
- 535, // Central Kurdish
- 537, // LowerSorbian
- 538, // UpperSorbian
- 539, // Kenyang
- 540, // Mohawk
- 541, // Nko
+ 538, // Akoose
+ 539, // Lakota
+ 540, // Standard Moroccan Tamazight
+ 541, // Mapuche
+ 542, // Central Kurdish
+ 544, // LowerSorbian
+ 545, // UpperSorbian
+ 546, // Kenyang
+ 547, // Mohawk
+ 548, // Nko
0, // Prussian
- 542, // Kiche
- 543, // Southern Sami
- 544, // Lule Sami
- 545, // Inari Sami
- 546, // Skolt Sami
- 547, // Warlpiri
+ 549, // Kiche
+ 550, // Southern Sami
+ 551, // Lule Sami
+ 552, // Inari Sami
+ 553, // Skolt Sami
+ 554, // Warlpiri
0, // Manichaean Middle Persian
0, // Mende
0, // Ancient North Arabian
@@ -1235,10 +1233,10 @@ static const quint16 locale_index[] = {
0, // Bhojpuri
0, // Hieroglyphic Luwian
0, // Literary Chinese
- 548, // Mazanderani
+ 555, // Mazanderani
0, // Mru
0, // Newari
- 549, // Northern Luri
+ 556, // Northern Luri
0, // Palauan
0, // Papiamento
0, // Saraiki
@@ -1246,567 +1244,574 @@ static const quint16 locale_index[] = {
0, // Tok Pisin
0, // Tuvalu
0, // UncodedLanguages
- 551, // Cantonese
+ 558, // Cantonese
0, // Osage
0, // Tangut
0 // trailing 0
};
static const QLocaleData locale_data[] = {
-// lang script terr dec group list prcnt zero minus plus exp quotStart quotEnd altQuotStart altQuotEnd lpStart lpMid lpEnd lpTwo sDtFmt lDtFmt sTmFmt lTmFmt ssMonth slMonth sMonth lMonth sDays lDays am,len pm,len
- { 1, 0, 0, 46, 44, 59, 37, 48, 45, 43, 101, 34, 34, 39, 39, 0,6 , 0,6 , 0,6 , 0,6 , 0,10 , 10,17 , 0,8 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 158,27 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 99,14 , 0,2 , 0,2 , {0,0,0}, 0,0 , 0,7 , 0,4 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // C/AnyScript/AnyCountry
- { 3, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 35,18 , 18,7 , 25,12 , 185,48 , 233,111 , 134,24 , 185,48 , 233,111 , 134,24 , 113,28 , 141,55 , 85,14 , 113,28 , 141,55 , 85,14 , 2,2 , 2,2 , {69,84,66}, 0,2 , 7,24 , 4,4 , 4,0 , 0,6 , 6,10 , 2, 1, 7, 6, 7 }, // Oromo/Latin/Ethiopia
- { 3, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 35,18 , 37,5 , 8,10 , 185,48 , 233,111 , 134,24 , 185,48 , 233,111 , 134,24 , 113,28 , 141,55 , 85,14 , 113,28 , 141,55 , 85,14 , 2,2 , 2,2 , {75,69,83}, 2,3 , 0,7 , 4,4 , 4,0 , 0,6 , 16,8 , 2, 1, 7, 6, 7 }, // Oromo/Latin/Kenya
- { 4, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Afar/Latin/Ethiopia
- { 5, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 80,18 , 18,7 , 25,12 , 392,59 , 451,92 , 134,24 , 392,59 , 451,92 , 134,24 , 196,28 , 224,58 , 282,14 , 196,28 , 224,58 , 282,14 , 4,3 , 4,3 , {90,65,82}, 5,1 , 31,67 , 4,4 , 4,0 , 24,9 , 33,11 , 2, 1, 7, 6, 7 }, // Afrikaans/Latin/SouthAfrica
- { 5, 7, 148, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 98,16 , 18,7 , 25,12 , 392,59 , 451,92 , 134,24 , 392,59 , 451,92 , 134,24 , 196,28 , 224,58 , 282,14 , 196,28 , 224,58 , 282,14 , 4,3 , 4,3 , {78,65,68}, 6,1 , 98,55 , 4,4 , 4,0 , 24,9 , 44,7 , 2, 1, 1, 6, 7 }, // Afrikaans/Latin/Namibia
- { 6, 7, 2, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 18,7 , 42,13 , 543,48 , 591,78 , 669,24 , 543,48 , 693,78 , 669,24 , 296,28 , 324,58 , 382,14 , 296,28 , 396,58 , 382,14 , 7,11 , 7,10 , {65,76,76}, 7,4 , 153,45 , 13,5 , 4,0 , 51,5 , 56,8 , 0, 0, 1, 6, 7 }, // Albanian/Latin/Albania
- { 6, 7, 127, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 37,5 , 8,10 , 543,48 , 591,78 , 669,24 , 543,48 , 693,78 , 669,24 , 296,28 , 324,58 , 382,14 , 296,28 , 396,58 , 382,14 , 7,11 , 7,10 , {77,75,68}, 11,3 , 198,54 , 13,5 , 4,0 , 51,5 , 64,8 , 2, 1, 1, 6, 7 }, // Albanian/Latin/Macedonia
- { 6, 7, 257, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 37,5 , 8,10 , 543,48 , 591,78 , 669,24 , 543,48 , 693,78 , 669,24 , 296,28 , 324,58 , 382,14 , 296,28 , 396,58 , 382,14 , 7,11 , 7,10 , {69,85,82}, 14,1 , 252,21 , 13,5 , 4,0 , 51,5 , 72,6 , 2, 1, 1, 6, 7 }, // Albanian/Latin/Kosovo
- { 7, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 23,6 , 23,6 , 29,9 , 38,8 , 120,10 , 130,17 , 18,7 , 25,12 , 771,46 , 817,61 , 878,24 , 771,46 , 817,61 , 878,24 , 454,27 , 481,28 , 509,14 , 454,27 , 481,28 , 509,14 , 18,3 , 17,4 , {69,84,66}, 15,2 , 273,34 , 4,4 , 4,0 , 78,4 , 82,5 , 2, 1, 7, 6, 7 }, // Amharic/Ethiopic/Ethiopia
- { 8, 1, 64, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {69,71,80}, 17,5 , 307,81 , 8,5 , 4,0 , 87,7 , 94,3 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Egypt
- { 8, 1, 3, 44, 46, 59, 1642, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1001,71 , 1001,71 , 1072,24 , 1001,71 , 1001,71 , 1072,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {68,90,68}, 22,5 , 388,102 , 8,5 , 4,0 , 87,7 , 97,7 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Algeria
- { 8, 1, 17, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {66,72,68}, 27,5 , 490,98 , 8,5 , 4,0 , 87,7 , 104,7 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Bahrain
- { 8, 1, 42, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {88,65,70}, 32,4 , 588,112 , 8,5 , 4,0 , 87,7 , 111,4 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Chad
- { 8, 1, 48, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 37,5 , 8,10 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {75,77,70}, 36,7 , 700,105 , 8,5 , 4,0 , 87,7 , 115,9 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Comoros
- { 8, 1, 59, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {68,74,70}, 43,3 , 805,84 , 8,5 , 4,0 , 87,7 , 124,6 , 0, 0, 6, 6, 7 }, // Arabic/Arabic/Djibouti
- { 8, 1, 67, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {69,82,78}, 46,3 , 889,91 , 8,5 , 4,0 , 87,7 , 130,7 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Eritrea
- { 8, 1, 103, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1096,92 , 1096,92 , 1188,24 , 1212,92 , 1096,92 , 1188,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {73,81,68}, 49,5 , 980,91 , 8,5 , 4,0 , 87,7 , 137,6 , 0, 0, 6, 5, 6 }, // Arabic/Arabic/Iraq
- { 8, 1, 105, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 55,4 , 59,9 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {73,76,83}, 54,1 , 1071,133 , 8,5 , 4,0 , 87,7 , 143,7 , 2, 1, 7, 5, 6 }, // Arabic/Arabic/Israel
- { 8, 1, 109, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1096,92 , 1096,92 , 1188,24 , 1096,92 , 1096,92 , 1188,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {74,79,68}, 55,5 , 1204,91 , 8,5 , 4,0 , 87,7 , 150,6 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Jordan
- { 8, 1, 115, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {75,87,68}, 60,5 , 1295,91 , 8,5 , 4,0 , 87,7 , 156,6 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Kuwait
- { 8, 1, 119, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1096,92 , 1096,92 , 1188,24 , 1096,92 , 1096,92 , 1188,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {76,66,80}, 65,5 , 1386,84 , 8,5 , 4,0 , 87,7 , 162,5 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Lebanon
- { 8, 1, 122, 44, 46, 59, 1642, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {76,89,68}, 70,5 , 1470,88 , 8,5 , 4,0 , 87,7 , 167,5 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Libya
- { 8, 1, 136, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1304,72 , 1304,72 , 1376,24 , 1304,72 , 1304,72 , 1376,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {77,82,79}, 75,5 , 1558,112 , 8,5 , 4,0 , 87,7 , 172,9 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Mauritania
- { 8, 1, 145, 44, 46, 59, 1642, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 37,5 , 8,10 , 1400,70 , 1400,70 , 1470,24 , 1400,70 , 1400,70 , 1470,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {77,65,68}, 80,5 , 1670,87 , 8,5 , 4,0 , 87,7 , 181,6 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Morocco
- { 8, 1, 162, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {79,77,82}, 85,5 , 1757,84 , 8,5 , 4,0 , 87,7 , 187,5 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Oman
- { 8, 1, 165, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1096,92 , 1096,92 , 1188,24 , 1096,92 , 1096,92 , 1188,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {73,76,83}, 54,1 , 1071,133 , 8,5 , 4,0 , 87,7 , 192,18 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/PalestinianTerritories
- { 8, 1, 175, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {81,65,82}, 90,5 , 1841,77 , 8,5 , 4,0 , 87,7 , 210,3 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Qatar
- { 8, 1, 186, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {83,65,82}, 95,5 , 1918,84 , 8,5 , 4,0 , 87,7 , 213,24 , 2, 1, 7, 5, 6 }, // Arabic/Arabic/SaudiArabia
- { 8, 1, 194, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {83,79,83}, 100,1 , 2002,77 , 8,5 , 4,0 , 87,7 , 237,7 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Somalia
- { 8, 1, 201, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {83,68,71}, 101,4 , 2079,91 , 8,5 , 4,0 , 87,7 , 244,7 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Sudan
- { 8, 1, 207, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1096,92 , 1096,92 , 1188,24 , 1096,92 , 1096,92 , 1188,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {83,89,80}, 105,5 , 2170,78 , 8,5 , 4,0 , 87,7 , 251,5 , 0, 0, 6, 5, 6 }, // Arabic/Arabic/Syria
- { 8, 1, 216, 44, 46, 59, 1642, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1001,71 , 1001,71 , 1072,24 , 1001,71 , 1001,71 , 1072,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {84,78,68}, 110,5 , 2248,95 , 8,5 , 4,0 , 87,7 , 256,4 , 3, 0, 7, 5, 6 }, // Arabic/Arabic/Tunisia
- { 8, 1, 223, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {65,69,68}, 115,5 , 2343,97 , 8,5 , 4,0 , 87,7 , 260,24 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/UnitedArabEmirates
- { 8, 1, 236, 46, 44, 59, 1642, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {77,65,68}, 80,5 , 1670,87 , 8,5 , 4,0 , 87,7 , 284,15 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/WesternSahara
- { 8, 1, 237, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {89,69,82}, 120,5 , 2440,77 , 8,5 , 4,0 , 87,7 , 299,5 , 0, 0, 7, 5, 6 }, // Arabic/Arabic/Yemen
- { 8, 1, 254, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 902,75 , 902,75 , 977,24 , 902,75 , 902,75 , 977,24 , 523,52 , 523,52 , 575,14 , 523,52 , 523,52 , 575,14 , 21,1 , 21,1 , {83,83,80}, 125,1 , 2517,132 , 8,5 , 4,0 , 87,7 , 304,12 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/SouthSudan
- { 9, 10, 11, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 65,7 , 65,7 , 175,8 , 183,19 , 55,4 , 68,10 , 1494,48 , 1542,94 , 1636,24 , 1494,48 , 1660,106 , 1636,24 , 589,28 , 617,62 , 679,21 , 589,28 , 617,62 , 700,15 , 0,2 , 0,2 , {65,77,68}, 126,1 , 2649,46 , 8,5 , 4,0 , 316,7 , 323,8 , 0, 0, 1, 6, 7 }, // Armenian/Armenian/Armenia
- { 10, 11, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 202,8 , 210,18 , 78,8 , 86,12 , 1766,62 , 1828,88 , 158,27 , 1766,62 , 1828,88 , 158,27 , 715,37 , 752,58 , 85,14 , 715,37 , 752,58 , 85,14 , 22,9 , 22,7 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 331,7 , 338,4 , 2, 1, 7, 7, 7 }, // Assamese/Bengali/India
- { 12, 7, 15, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 72,8 , 72,8 , 175,8 , 228,17 , 37,5 , 8,10 , 1916,48 , 1964,77 , 158,27 , 1916,48 , 2041,77 , 158,27 , 810,27 , 837,67 , 99,14 , 810,27 , 837,67 , 99,14 , 0,2 , 0,2 , {65,90,78}, 128,1 , 2695,58 , 8,5 , 4,0 , 342,15 , 357,10 , 2, 1, 1, 6, 7 }, // Azerbaijani/Latin/Azerbaijan
- { 12, 1, 102, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 6, 5, 5 }, // Azerbaijani/Arabic/Iran
- { 12, 2, 15, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 175,8 , 245,19 , 37,5 , 8,10 , 2118,77 , 2118,77 , 158,27 , 2118,77 , 2118,77 , 158,27 , 904,67 , 904,67 , 99,14 , 904,67 , 904,67 , 99,14 , 0,2 , 0,2 , {65,90,78}, 128,1 , 2753,12 , 8,5 , 4,0 , 367,15 , 382,10 , 2, 1, 1, 6, 7 }, // Azerbaijani/Cyrillic/Azerbaijan
- { 13, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {82,85,66}, 129,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Bashkir/Cyrillic/Russia
- { 14, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8220, 8221, 0,6 , 0,6 , 80,9 , 80,9 , 264,10 , 274,26 , 37,5 , 98,12 , 2195,60 , 2255,93 , 2348,24 , 2372,60 , 2432,105 , 2348,24 , 971,28 , 999,68 , 1067,14 , 1081,28 , 1109,68 , 1067,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 2765,20 , 13,5 , 4,0 , 392,7 , 399,8 , 2, 1, 1, 6, 7 }, // Basque/Latin/Spain
- { 15, 11, 18, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 89,10 , 99,9 , 300,6 , 210,18 , 18,7 , 25,12 , 2537,90 , 2537,90 , 2627,33 , 2537,90 , 2537,90 , 2627,33 , 1177,37 , 1214,58 , 1272,18 , 1177,37 , 1290,58 , 1272,18 , 31,9 , 29,7 , {66,68,84}, 130,1 , 2785,49 , 0,4 , 4,0 , 407,5 , 412,8 , 2, 1, 5, 6, 7 }, // Bengali/Bengali/Bangladesh
- { 15, 11, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 89,10 , 99,9 , 300,6 , 210,18 , 18,7 , 25,12 , 2537,90 , 2537,90 , 2627,33 , 2537,90 , 2537,90 , 2627,33 , 1177,37 , 1214,58 , 1272,18 , 1177,37 , 1290,58 , 1272,18 , 31,9 , 29,7 , {73,78,82}, 127,1 , 2834,43 , 0,4 , 4,0 , 407,5 , 420,4 , 2, 1, 7, 7, 7 }, // Bengali/Bengali/India
- { 16, 31, 25, 46, 44, 59, 37, 3872, 45, 43, 101, 8220, 8221, 8216, 8217, 108,9 , 108,9 , 108,9 , 108,9 , 53,10 , 306,30 , 110,22 , 132,27 , 2660,63 , 2723,191 , 2914,27 , 2941,27 , 2968,132 , 3100,27 , 1348,34 , 1382,79 , 1461,27 , 1348,34 , 1382,79 , 1461,27 , 40,5 , 36,6 , {66,84,78}, 131,3 , 2877,15 , 4,4 , 4,0 , 424,6 , 430,5 , 2, 1, 7, 6, 7 }, // Dzongkha/Tibetan/Bhutan
- { 19, 7, 74, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 3127,63 , 3190,78 , 3268,36 , 3304,63 , 3190,78 , 3268,36 , 1488,33 , 1521,43 , 1564,18 , 1488,33 , 1521,43 , 1564,18 , 45,4 , 42,4 , {69,85,82}, 14,1 , 2892,36 , 13,5 , 4,0 , 435,9 , 444,5 , 2, 1, 1, 6, 7 }, // Breton/Latin/France
- { 20, 2, 33, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 117,7 , 117,7 , 336,12 , 348,22 , 55,4 , 59,9 , 3367,49 , 3416,82 , 3498,24 , 3367,49 , 3416,82 , 3498,24 , 1582,21 , 1603,55 , 1658,14 , 1582,21 , 1603,55 , 1658,14 , 49,6 , 46,6 , {66,71,78}, 134,3 , 2928,47 , 13,5 , 4,0 , 449,9 , 458,8 , 2, 1, 1, 6, 7 }, // Bulgarian/Cyrillic/Bulgaria
- { 21, 25, 147, 46, 44, 4170, 37, 4160, 45, 43, 101, 8220, 8221, 8216, 8217, 124,6 , 124,6 , 130,11 , 141,9 , 370,8 , 378,18 , 37,5 , 8,10 , 3522,46 , 3568,88 , 3656,24 , 3522,46 , 3568,88 , 3656,24 , 1672,54 , 1672,54 , 1726,14 , 1672,54 , 1672,54 , 1726,14 , 55,5 , 52,3 , {77,77,75}, 137,1 , 2975,27 , 8,5 , 4,0 , 466,3 , 469,6 , 0, 0, 7, 6, 7 }, // Burmese/Myanmar/Myanmar
- { 22, 2, 20, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 150,7 , 150,7 , 114,6 , 10,17 , 159,5 , 164,10 , 3680,48 , 3728,95 , 3823,24 , 3847,48 , 3895,98 , 3823,24 , 1740,21 , 1761,56 , 1817,14 , 1740,21 , 1761,56 , 1817,14 , 60,9 , 55,12 , {66,89,82}, 138,2 , 3002,89 , 13,5 , 4,0 , 475,10 , 485,8 , 0, 0, 1, 6, 7 }, // Belarusian/Cyrillic/Belarus
- { 23, 20, 36, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 157,9 , 166,9 , 300,6 , 98,16 , 18,7 , 25,12 , 3993,71 , 3993,71 , 158,27 , 3993,71 , 3993,71 , 158,27 , 1831,47 , 1831,47 , 1878,19 , 1831,47 , 1831,47 , 1878,19 , 69,5 , 67,5 , {75,72,82}, 140,1 , 3091,29 , 4,4 , 4,0 , 493,5 , 498,7 , 2, 1, 7, 6, 7 }, // Khmer/Khmer/Cambodia
- { 24, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 175,7 , 175,7 , 300,6 , 396,22 , 55,4 , 59,9 , 4064,60 , 4124,82 , 4206,36 , 4064,60 , 4242,115 , 4206,36 , 1897,28 , 1925,60 , 1985,21 , 1897,28 , 1925,60 , 1985,21 , 74,5 , 72,5 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 505,6 , 511,7 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Spain
- { 24, 7, 5, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 175,7 , 175,7 , 300,6 , 396,22 , 55,4 , 59,9 , 4064,60 , 4124,82 , 4206,36 , 4064,60 , 4242,115 , 4206,36 , 1897,28 , 1925,60 , 1985,21 , 1897,28 , 1925,60 , 1985,21 , 74,5 , 72,5 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 505,6 , 518,7 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Andorra
- { 24, 7, 74, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 175,7 , 175,7 , 300,6 , 396,22 , 55,4 , 59,9 , 4064,60 , 4124,82 , 4206,36 , 4064,60 , 4242,115 , 4206,36 , 1897,28 , 1925,60 , 1985,21 , 1897,28 , 1925,60 , 1985,21 , 74,5 , 72,5 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 505,6 , 525,6 , 2, 1, 1, 6, 7 }, // Catalan/Latin/France
- { 24, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 175,7 , 175,7 , 300,6 , 396,22 , 55,4 , 59,9 , 4064,60 , 4124,82 , 4206,36 , 4064,60 , 4242,115 , 4206,36 , 1897,28 , 1925,60 , 1985,21 , 1897,28 , 1925,60 , 1985,21 , 74,5 , 72,5 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 505,6 , 531,6 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Italy
- { 25, 5, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 182,5 , 182,5 , 187,5 , 187,5 , 418,8 , 426,13 , 174,6 , 180,11 , 4357,39 , 4396,38 , 158,27 , 4357,39 , 4396,38 , 158,27 , 2006,21 , 2027,28 , 2055,14 , 2006,21 , 2027,28 , 2055,14 , 79,2 , 77,2 , {67,78,89}, 141,1 , 3140,13 , 4,4 , 4,0 , 537,4 , 541,2 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/China
- { 25, 5, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 182,5 , 182,5 , 187,5 , 187,5 , 300,6 , 426,13 , 174,6 , 180,11 , 4357,39 , 4396,38 , 158,27 , 4357,39 , 4396,38 , 158,27 , 2006,21 , 2027,28 , 2055,14 , 2006,21 , 2027,28 , 2055,14 , 79,2 , 77,2 , {72,75,68}, 142,3 , 3153,11 , 4,4 , 4,0 , 537,4 , 543,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/HongKong
- { 25, 5, 126, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 182,5 , 182,5 , 187,5 , 187,5 , 300,6 , 426,13 , 174,6 , 180,11 , 4357,39 , 4396,38 , 158,27 , 4357,39 , 4396,38 , 158,27 , 2006,21 , 2027,28 , 2055,14 , 2006,21 , 2027,28 , 2055,14 , 79,2 , 77,2 , {77,79,80}, 145,4 , 3164,13 , 4,4 , 4,0 , 537,4 , 552,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Macau
- { 25, 5, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 182,5 , 182,5 , 187,5 , 187,5 , 27,8 , 426,13 , 174,6 , 180,11 , 4357,39 , 4396,38 , 158,27 , 4357,39 , 4396,38 , 158,27 , 2006,21 , 2027,28 , 2055,14 , 2006,21 , 2027,28 , 2055,14 , 79,2 , 77,2 , {83,71,68}, 6,1 , 3177,15 , 4,4 , 4,0 , 537,4 , 561,3 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Singapore
- { 25, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 182,5 , 182,5 , 192,5 , 192,5 , 439,8 , 426,13 , 174,6 , 191,13 , 4357,39 , 4357,39 , 158,27 , 4357,39 , 4357,39 , 158,27 , 2069,21 , 2027,28 , 2055,14 , 2069,21 , 2027,28 , 2055,14 , 79,2 , 77,2 , {72,75,68}, 142,3 , 3153,11 , 18,5 , 4,0 , 564,4 , 568,14 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/HongKong
- { 25, 6, 126, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 182,5 , 182,5 , 192,5 , 192,5 , 439,8 , 426,13 , 174,6 , 191,13 , 4357,39 , 4357,39 , 158,27 , 4357,39 , 4357,39 , 158,27 , 2069,21 , 2027,28 , 2055,14 , 2069,21 , 2027,28 , 2055,14 , 79,2 , 77,2 , {77,79,80}, 145,4 , 3192,13 , 18,5 , 4,0 , 564,4 , 582,14 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Macau
- { 25, 6, 208, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 182,5 , 182,5 , 187,5 , 187,5 , 418,8 , 447,14 , 174,6 , 191,13 , 4357,39 , 4357,39 , 158,27 , 4357,39 , 4357,39 , 158,27 , 2069,21 , 2027,28 , 2055,14 , 2069,21 , 2027,28 , 2055,14 , 79,2 , 77,2 , {84,87,68}, 6,1 , 3205,13 , 4,4 , 4,0 , 564,4 , 596,2 , 2, 0, 7, 6, 7 }, // Chinese/Traditional Han/Taiwan
- { 26, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Corsican/Latin/France
- { 27, 7, 54, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 175,7 , 175,7 , 461,11 , 472,19 , 37,5 , 8,10 , 4434,49 , 4483,94 , 4577,39 , 4434,49 , 4616,98 , 4577,39 , 2090,28 , 2118,58 , 2176,14 , 2090,28 , 2118,58 , 2190,14 , 0,2 , 0,2 , {72,82,75}, 149,3 , 3218,60 , 13,5 , 4,0 , 598,8 , 606,8 , 2, 1, 1, 6, 7 }, // Croatian/Latin/Croatia
- { 27, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 175,7 , 175,7 , 461,11 , 472,19 , 37,5 , 8,10 , 4434,49 , 4483,94 , 4577,39 , 4434,49 , 4616,98 , 4577,39 , 2090,28 , 2118,58 , 2176,14 , 2090,28 , 2118,58 , 2190,14 , 0,2 , 0,2 , {66,65,77}, 152,2 , 3278,85 , 13,5 , 4,0 , 598,8 , 614,19 , 2, 1, 1, 6, 7 }, // Croatian/Latin/BosniaAndHerzegowina
- { 28, 7, 57, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 197,7 , 197,7 , 175,8 , 491,17 , 55,4 , 59,9 , 4714,48 , 4762,82 , 158,27 , 4714,48 , 4844,84 , 158,27 , 2204,21 , 2225,49 , 2274,14 , 2204,21 , 2225,49 , 2274,14 , 81,4 , 79,4 , {67,90,75}, 154,2 , 3363,68 , 13,5 , 4,0 , 633,7 , 640,15 , 2, 0, 1, 6, 7 }, // Czech/Latin/CzechRepublic
- { 29, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 204,8 , 204,8 , 120,10 , 508,23 , 159,5 , 164,10 , 4928,48 , 4976,84 , 134,24 , 5060,59 , 4976,84 , 134,24 , 2288,28 , 2316,51 , 2367,14 , 2381,35 , 2316,51 , 2367,14 , 0,2 , 0,2 , {68,75,75}, 156,3 , 3431,42 , 13,5 , 4,0 , 655,5 , 660,7 , 2, 1, 1, 6, 7 }, // Danish/Latin/Denmark
- { 29, 7, 86, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 204,8 , 204,8 , 120,10 , 508,23 , 204,7 , 86,12 , 4928,48 , 4976,84 , 134,24 , 5060,59 , 4976,84 , 134,24 , 2288,28 , 2316,51 , 2367,14 , 2381,35 , 2316,51 , 2367,14 , 0,2 , 0,2 , {68,75,75}, 156,3 , 3431,42 , 13,5 , 4,0 , 655,5 , 667,8 , 2, 1, 1, 6, 7 }, // Danish/Latin/Greenland
- { 30, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 370,8 , 98,16 , 37,5 , 8,10 , 5119,59 , 5178,88 , 134,24 , 5119,59 , 5178,88 , 134,24 , 2416,21 , 2437,59 , 2496,14 , 2416,21 , 2437,59 , 2496,14 , 85,4 , 83,4 , {69,85,82}, 14,1 , 3473,19 , 8,5 , 23,6 , 675,10 , 685,9 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Netherlands
- { 30, 7, 12, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 370,8 , 98,16 , 37,5 , 8,10 , 5119,59 , 5178,88 , 134,24 , 5119,59 , 5178,88 , 134,24 , 2416,21 , 2437,59 , 2496,14 , 2416,21 , 2437,59 , 2496,14 , 85,4 , 83,4 , {65,87,71}, 159,4 , 3492,55 , 8,5 , 23,6 , 675,10 , 694,5 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Aruba
- { 30, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 531,7 , 98,16 , 37,5 , 8,10 , 5119,59 , 5178,88 , 134,24 , 5119,59 , 5178,88 , 134,24 , 2416,21 , 2437,59 , 2496,14 , 2416,21 , 2437,59 , 2496,14 , 85,4 , 83,4 , {69,85,82}, 14,1 , 3473,19 , 13,5 , 4,0 , 699,6 , 705,6 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Belgium
- { 30, 7, 152, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 370,8 , 98,16 , 37,5 , 8,10 , 5119,59 , 5178,88 , 134,24 , 5119,59 , 5178,88 , 134,24 , 2416,21 , 2437,59 , 2496,14 , 2416,21 , 2437,59 , 2496,14 , 85,4 , 83,4 , {65,78,71}, 163,4 , 3547,97 , 8,5 , 23,6 , 675,10 , 711,7 , 2, 1, 1, 6, 7 }, // Dutch/Latin/CuraSao
- { 30, 7, 202, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 370,8 , 98,16 , 37,5 , 8,10 , 5119,59 , 5178,88 , 134,24 , 5119,59 , 5178,88 , 134,24 , 2416,21 , 2437,59 , 2496,14 , 2416,21 , 2437,59 , 2496,14 , 85,4 , 83,4 , {83,82,68}, 6,1 , 3644,58 , 8,5 , 23,6 , 675,10 , 718,8 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Suriname
- { 30, 7, 255, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 370,8 , 98,16 , 37,5 , 8,10 , 5119,59 , 5178,88 , 134,24 , 5119,59 , 5178,88 , 134,24 , 2416,21 , 2437,59 , 2496,14 , 2416,21 , 2437,59 , 2496,14 , 85,4 , 83,4 , {85,83,68}, 6,1 , 3702,61 , 8,5 , 23,6 , 675,10 , 726,19 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Bonaire
- { 30, 7, 256, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 370,8 , 98,16 , 37,5 , 8,10 , 5119,59 , 5178,88 , 134,24 , 5119,59 , 5178,88 , 134,24 , 2416,21 , 2437,59 , 2496,14 , 2416,21 , 2437,59 , 2496,14 , 85,4 , 83,4 , {65,78,71}, 163,4 , 3547,97 , 8,5 , 23,6 , 675,10 , 745,12 , 2, 1, 1, 6, 7 }, // Dutch/Latin/SintMaarten
- { 31, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 538,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 3763,35 , 4,4 , 4,0 , 757,16 , 773,13 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStates
- { 31, 3, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {85,83,68}, 167,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // English/Deseret/UnitedStates
- { 31, 7, 4, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 538,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 3763,35 , 4,4 , 4,0 , 786,7 , 793,14 , 2, 1, 7, 6, 7 }, // English/Latin/AmericanSamoa
- { 31, 7, 7, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {88,67,68}, 6,1 , 3798,71 , 4,4 , 4,0 , 786,7 , 807,8 , 2, 1, 1, 6, 7 }, // English/Latin/Anguilla
- { 31, 7, 9, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {88,67,68}, 6,1 , 3798,71 , 4,4 , 4,0 , 786,7 , 815,17 , 2, 1, 7, 6, 7 }, // English/Latin/AntiguaAndBarbuda
- { 31, 7, 13, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 222,9 , 222,9 , 300,6 , 10,17 , 18,7 , 25,12 , 5266,59 , 48,86 , 5266,59 , 5266,59 , 48,86 , 5266,59 , 2510,35 , 28,57 , 2545,25 , 2510,35 , 28,57 , 2545,25 , 89,2 , 87,2 , {65,85,68}, 6,1 , 3869,59 , 4,4 , 4,0 , 832,18 , 850,9 , 2, 1, 7, 6, 7 }, // English/Latin/Australia
- { 31, 7, 14, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3928,20 , 8,5 , 4,0 , 786,7 , 859,7 , 2, 1, 1, 6, 7 }, // English/Latin/Austria
- { 31, 7, 16, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {66,83,68}, 6,1 , 3948,53 , 4,4 , 4,0 , 786,7 , 866,7 , 2, 1, 7, 6, 7 }, // English/Latin/Bahamas
- { 31, 7, 19, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {66,66,68}, 6,1 , 4001,56 , 4,4 , 4,0 , 786,7 , 873,8 , 2, 1, 1, 6, 7 }, // English/Latin/Barbados
- { 31, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 27,8 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3928,20 , 13,5 , 4,0 , 786,7 , 881,7 , 2, 1, 1, 6, 7 }, // English/Latin/Belgium
- { 31, 7, 22, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 27,8 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {66,90,68}, 6,1 , 4057,47 , 4,4 , 4,0 , 786,7 , 888,6 , 2, 1, 7, 6, 7 }, // English/Latin/Belize
- { 31, 7, 24, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {66,77,68}, 6,1 , 4104,53 , 4,4 , 4,0 , 786,7 , 894,7 , 2, 1, 1, 6, 7 }, // English/Latin/Bermuda
- { 31, 7, 28, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 27,8 , 80,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {66,87,80}, 170,1 , 4157,50 , 4,4 , 4,0 , 786,7 , 901,8 , 2, 1, 7, 6, 7 }, // English/Latin/Botswana
- { 31, 7, 31, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 167,3 , 3763,35 , 4,4 , 4,0 , 786,7 , 909,30 , 2, 1, 1, 6, 7 }, // English/Latin/BritishIndianOceanTerritory
- { 31, 7, 35, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 538,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {66,73,70}, 171,3 , 4207,53 , 4,4 , 4,0 , 786,7 , 939,7 , 0, 0, 1, 6, 7 }, // English/Latin/Burundi
- { 31, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {88,65,70}, 32,4 , 4260,83 , 4,4 , 4,0 , 786,7 , 946,8 , 0, 0, 1, 6, 7 }, // English/Latin/Cameroon
- { 31, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 53,10 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {67,65,68}, 6,1 , 4343,53 , 4,4 , 4,0 , 954,16 , 970,6 , 2, 0, 7, 6, 7 }, // English/Latin/Canada
- { 31, 7, 40, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {75,89,68}, 6,1 , 4396,71 , 4,4 , 4,0 , 786,7 , 976,14 , 2, 1, 1, 6, 7 }, // English/Latin/CaymanIslands
- { 31, 7, 45, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {65,85,68}, 6,1 , 3869,59 , 4,4 , 4,0 , 786,7 , 990,16 , 2, 1, 1, 6, 7 }, // English/Latin/ChristmasIsland
- { 31, 7, 46, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {65,85,68}, 6,1 , 3869,59 , 4,4 , 4,0 , 786,7 , 1006,23 , 2, 1, 1, 6, 7 }, // English/Latin/CocosIslands
- { 31, 7, 51, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {78,90,68}, 6,1 , 4467,62 , 4,4 , 4,0 , 786,7 , 1029,12 , 2, 1, 1, 6, 7 }, // English/Latin/CookIslands
- { 31, 7, 56, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3928,20 , 4,4 , 4,0 , 786,7 , 1041,6 , 2, 1, 1, 6, 7 }, // English/Latin/Cyprus
- { 31, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 159,5 , 164,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {68,75,75}, 156,3 , 4529,44 , 13,5 , 4,0 , 786,7 , 1047,7 , 2, 1, 1, 6, 7 }, // English/Latin/Denmark
- { 31, 7, 60, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {88,67,68}, 6,1 , 3798,71 , 4,4 , 4,0 , 786,7 , 1054,8 , 2, 1, 7, 6, 7 }, // English/Latin/Dominica
- { 31, 7, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,82,78}, 46,3 , 4573,50 , 4,4 , 4,0 , 786,7 , 1062,7 , 2, 1, 1, 6, 7 }, // English/Latin/Eritrea
- { 31, 7, 70, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {70,75,80}, 125,1 , 4623,74 , 4,4 , 4,0 , 786,7 , 1069,16 , 2, 1, 1, 6, 7 }, // English/Latin/FalklandIslands
- { 31, 7, 72, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {70,74,68}, 6,1 , 4697,47 , 4,4 , 4,0 , 786,7 , 1085,4 , 2, 1, 1, 6, 7 }, // English/Latin/Fiji
- { 31, 7, 73, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 211,4 , 215,9 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3928,20 , 13,5 , 4,0 , 786,7 , 1089,7 , 2, 1, 1, 6, 7 }, // English/Latin/Finland
- { 31, 7, 75, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {71,66,80}, 125,1 , 4744,32 , 4,4 , 4,0 , 786,7 , 1096,8 , 2, 1, 1, 6, 7 }, // English/Latin/Guernsey
- { 31, 7, 80, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {71,77,68}, 174,1 , 4776,50 , 4,4 , 4,0 , 786,7 , 1104,6 , 2, 1, 1, 6, 7 }, // English/Latin/Gambia
- { 31, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3928,20 , 13,5 , 4,0 , 786,7 , 1110,7 , 2, 1, 1, 6, 7 }, // English/Latin/Germany
- { 31, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {71,72,83}, 175,3 , 4826,47 , 4,4 , 4,0 , 786,7 , 1117,5 , 2, 1, 1, 6, 7 }, // English/Latin/Ghana
- { 31, 7, 84, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {71,73,80}, 125,1 , 4873,53 , 4,4 , 4,0 , 786,7 , 1122,9 , 2, 1, 1, 6, 7 }, // English/Latin/Gibraltar
- { 31, 7, 87, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {88,67,68}, 6,1 , 3798,71 , 4,4 , 4,0 , 786,7 , 1131,7 , 2, 1, 1, 6, 7 }, // English/Latin/Grenada
- { 31, 7, 89, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 538,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 3763,35 , 4,4 , 4,0 , 786,7 , 1138,4 , 2, 1, 7, 6, 7 }, // English/Latin/Guam
- { 31, 7, 93, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {71,89,68}, 6,1 , 4926,56 , 4,4 , 4,0 , 786,7 , 1142,6 , 0, 0, 1, 6, 7 }, // English/Latin/Guyana
- { 31, 7, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 439,8 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {72,75,68}, 142,3 , 4982,56 , 4,4 , 4,0 , 786,7 , 1148,19 , 2, 1, 7, 6, 7 }, // English/Latin/HongKong
- { 31, 7, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 27,8 , 98,16 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {73,78,82}, 127,1 , 5038,44 , 8,5 , 4,0 , 786,7 , 1167,5 , 2, 1, 7, 7, 7 }, // English/Latin/India
- { 31, 7, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 98,16 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 85,4 , 83,4 , {69,85,82}, 14,1 , 3928,20 , 4,4 , 4,0 , 786,7 , 1172,7 , 2, 1, 7, 6, 7 }, // English/Latin/Ireland
- { 31, 7, 105, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 55,4 , 59,9 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {73,76,83}, 54,1 , 5082,62 , 4,4 , 4,0 , 786,7 , 1179,6 , 2, 1, 7, 5, 6 }, // English/Latin/Israel
- { 31, 7, 107, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 300,6 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {74,77,68}, 6,1 , 5144,53 , 4,4 , 4,0 , 786,7 , 1185,7 , 2, 1, 7, 6, 7 }, // English/Latin/Jamaica
- { 31, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {75,69,83}, 2,3 , 5197,53 , 4,4 , 4,0 , 786,7 , 1192,5 , 2, 1, 7, 6, 7 }, // English/Latin/Kenya
- { 31, 7, 112, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {65,85,68}, 6,1 , 3869,59 , 4,4 , 4,0 , 786,7 , 1197,8 , 2, 1, 1, 6, 7 }, // English/Latin/Kiribati
- { 31, 7, 120, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 5250,61 , 4,4 , 4,0 , 786,7 , 1205,7 , 2, 1, 1, 6, 7 }, // English/Latin/Lesotho
- { 31, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {76,82,68}, 6,1 , 5311,53 , 4,4 , 4,0 , 786,7 , 1212,7 , 2, 1, 1, 6, 7 }, // English/Latin/Liberia
- { 31, 7, 126, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {77,79,80}, 145,4 , 5364,53 , 4,4 , 4,0 , 786,7 , 1219,15 , 2, 1, 7, 6, 7 }, // English/Latin/Macau
- { 31, 7, 128, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {77,71,65}, 178,2 , 5417,54 , 4,4 , 4,0 , 786,7 , 1234,10 , 0, 0, 1, 6, 7 }, // English/Latin/Madagascar
- { 31, 7, 129, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {77,87,75}, 180,2 , 5471,53 , 4,4 , 4,0 , 786,7 , 1244,6 , 2, 1, 1, 6, 7 }, // English/Latin/Malawi
- { 31, 7, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {77,89,82}, 182,2 , 5524,59 , 4,4 , 4,0 , 786,7 , 1250,8 , 2, 1, 1, 6, 7 }, // English/Latin/Malaysia
- { 31, 7, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3928,20 , 4,4 , 4,0 , 786,7 , 1258,5 , 2, 1, 7, 6, 7 }, // English/Latin/Malta
- { 31, 7, 134, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 538,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 3763,35 , 4,4 , 4,0 , 786,7 , 1263,16 , 2, 1, 7, 6, 7 }, // English/Latin/MarshallIslands
- { 31, 7, 137, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {77,85,82}, 184,2 , 5583,53 , 4,4 , 4,0 , 786,7 , 1279,9 , 0, 0, 1, 6, 7 }, // English/Latin/Mauritius
- { 31, 7, 140, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 167,3 , 3763,35 , 4,4 , 4,0 , 786,7 , 1288,10 , 2, 1, 1, 6, 7 }, // English/Latin/Micronesia
- { 31, 7, 144, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {88,67,68}, 6,1 , 3798,71 , 4,4 , 4,0 , 786,7 , 1298,10 , 2, 1, 1, 6, 7 }, // English/Latin/Montserrat
- { 31, 7, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {78,65,68}, 6,1 , 5636,53 , 4,4 , 4,0 , 786,7 , 1308,7 , 2, 1, 1, 6, 7 }, // English/Latin/Namibia
- { 31, 7, 149, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {65,85,68}, 6,1 , 3869,59 , 4,4 , 4,0 , 786,7 , 1315,5 , 2, 1, 1, 6, 7 }, // English/Latin/Nauru
- { 31, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3928,20 , 8,5 , 23,6 , 786,7 , 1320,11 , 2, 1, 1, 6, 7 }, // English/Latin/Netherlands
- { 31, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 531,7 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {78,90,68}, 6,1 , 4467,62 , 4,4 , 4,0 , 786,7 , 1331,11 , 2, 1, 7, 6, 7 }, // English/Latin/NewZealand
- { 31, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {78,71,78}, 186,1 , 5689,50 , 4,4 , 4,0 , 786,7 , 1342,7 , 2, 1, 1, 6, 7 }, // English/Latin/Nigeria
- { 31, 7, 158, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {78,90,68}, 6,1 , 4467,62 , 4,4 , 4,0 , 786,7 , 1349,4 , 2, 1, 1, 6, 7 }, // English/Latin/Niue
- { 31, 7, 159, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {65,85,68}, 6,1 , 3869,59 , 4,4 , 4,0 , 786,7 , 1353,14 , 2, 1, 1, 6, 7 }, // English/Latin/NorfolkIsland
- { 31, 7, 160, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 538,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 3763,35 , 4,4 , 4,0 , 786,7 , 1367,24 , 2, 1, 1, 6, 7 }, // English/Latin/NorthernMarianaIslands
- { 31, 7, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {80,75,82}, 184,2 , 5739,53 , 4,4 , 4,0 , 786,7 , 1391,8 , 0, 0, 7, 6, 7 }, // English/Latin/Pakistan
- { 31, 7, 164, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 167,3 , 3763,35 , 4,4 , 4,0 , 786,7 , 1399,5 , 2, 1, 1, 6, 7 }, // English/Latin/Palau
- { 31, 7, 167, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {80,71,75}, 137,1 , 5792,73 , 4,4 , 4,0 , 786,7 , 1404,16 , 2, 1, 1, 6, 7 }, // English/Latin/PapuaNewGuinea
- { 31, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {80,72,80}, 187,1 , 5865,53 , 4,4 , 4,0 , 786,7 , 1420,11 , 2, 1, 7, 6, 7 }, // English/Latin/Philippines
- { 31, 7, 171, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {78,90,68}, 6,1 , 4467,62 , 4,4 , 4,0 , 786,7 , 1431,16 , 2, 1, 1, 6, 7 }, // English/Latin/Pitcairn
- { 31, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 538,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 3763,35 , 4,4 , 4,0 , 786,7 , 1447,11 , 2, 1, 7, 6, 7 }, // English/Latin/PuertoRico
- { 31, 7, 179, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {82,87,70}, 188,2 , 5918,47 , 4,4 , 4,0 , 786,7 , 1458,6 , 0, 0, 1, 6, 7 }, // English/Latin/Rwanda
- { 31, 7, 180, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {88,67,68}, 6,1 , 3798,71 , 4,4 , 4,0 , 786,7 , 1464,17 , 2, 1, 1, 6, 7 }, // English/Latin/SaintKittsAndNevis
- { 31, 7, 181, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {88,67,68}, 6,1 , 3798,71 , 4,4 , 4,0 , 786,7 , 1481,9 , 2, 1, 1, 6, 7 }, // English/Latin/SaintLucia
- { 31, 7, 182, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {88,67,68}, 6,1 , 3798,71 , 4,4 , 4,0 , 786,7 , 1490,24 , 2, 1, 1, 6, 7 }, // English/Latin/SaintVincentAndTheGrenadines
- { 31, 7, 183, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {87,83,84}, 190,3 , 5965,40 , 4,4 , 4,0 , 786,7 , 1514,5 , 2, 1, 7, 6, 7 }, // English/Latin/Samoa
- { 31, 7, 188, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {83,67,82}, 193,2 , 6005,59 , 4,4 , 4,0 , 786,7 , 1519,10 , 2, 1, 1, 6, 7 }, // English/Latin/Seychelles
- { 31, 7, 189, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {83,76,76}, 195,2 , 6064,68 , 4,4 , 4,0 , 786,7 , 1529,12 , 0, 0, 1, 6, 7 }, // English/Latin/SierraLeone
- { 31, 7, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 300,6 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {83,71,68}, 6,1 , 6132,56 , 4,4 , 4,0 , 786,7 , 1541,9 , 2, 1, 7, 6, 7 }, // English/Latin/Singapore
- { 31, 7, 192, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3928,20 , 13,5 , 29,7 , 786,7 , 1550,8 , 2, 1, 1, 6, 7 }, // English/Latin/Slovenia
- { 31, 7, 193, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {83,66,68}, 6,1 , 6188,74 , 4,4 , 4,0 , 786,7 , 1558,15 , 2, 1, 1, 6, 7 }, // English/Latin/SolomonIslands
- { 31, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 264,10 , 80,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 5250,61 , 4,4 , 4,0 , 786,7 , 1573,12 , 2, 1, 7, 6, 7 }, // English/Latin/SouthAfrica
- { 31, 7, 199, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {83,72,80}, 125,1 , 6262,56 , 4,4 , 4,0 , 786,7 , 1585,10 , 2, 1, 1, 6, 7 }, // English/Latin/SaintHelena
- { 31, 7, 201, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {83,68,71}, 0,0 , 6318,50 , 4,4 , 4,0 , 786,7 , 1595,5 , 2, 1, 6, 5, 6 }, // English/Latin/Sudan
- { 31, 7, 204, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {83,90,76}, 197,1 , 6368,53 , 4,4 , 4,0 , 786,7 , 1600,9 , 2, 1, 1, 6, 7 }, // English/Latin/Swaziland
- { 31, 7, 205, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 53,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {83,69,75}, 198,2 , 6421,47 , 13,5 , 4,0 , 786,7 , 1609,6 , 2, 1, 1, 6, 7 }, // English/Latin/Sweden
- { 31, 7, 206, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {67,72,70}, 0,0 , 6468,41 , 8,5 , 36,5 , 786,7 , 1615,11 , 2, 0, 1, 6, 7 }, // English/Latin/Switzerland
- { 31, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {84,90,83}, 200,3 , 6509,62 , 4,4 , 4,0 , 786,7 , 1626,8 , 0, 0, 1, 6, 7 }, // English/Latin/Tanzania
- { 31, 7, 213, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {78,90,68}, 6,1 , 4467,62 , 4,4 , 4,0 , 786,7 , 1634,7 , 2, 1, 1, 6, 7 }, // English/Latin/Tokelau
- { 31, 7, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {84,79,80}, 203,2 , 6571,49 , 4,4 , 4,0 , 786,7 , 1641,5 , 2, 1, 1, 6, 7 }, // English/Latin/Tonga
- { 31, 7, 215, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {84,84,68}, 6,1 , 6620,80 , 4,4 , 4,0 , 786,7 , 1646,17 , 2, 1, 7, 6, 7 }, // English/Latin/TrinidadAndTobago
- { 31, 7, 219, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 167,3 , 3763,35 , 4,4 , 4,0 , 786,7 , 1663,22 , 2, 1, 1, 6, 7 }, // English/Latin/TurksAndCaicosIslands
- { 31, 7, 220, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {65,85,68}, 6,1 , 3869,59 , 4,4 , 4,0 , 786,7 , 1685,6 , 2, 1, 1, 6, 7 }, // English/Latin/Tuvalu
- { 31, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,71,88}, 205,3 , 6700,56 , 4,4 , 4,0 , 786,7 , 1691,6 , 0, 0, 1, 6, 7 }, // English/Latin/Uganda
- { 31, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 222,9 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 89,2 , 87,2 , {71,66,80}, 125,1 , 6756,47 , 4,4 , 4,0 , 1697,15 , 1712,14 , 2, 1, 1, 6, 7 }, // English/Latin/UnitedKingdom
- { 31, 7, 226, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 538,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 3763,35 , 4,4 , 4,0 , 786,7 , 1726,21 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStatesMinorOutlyingIslands
- { 31, 7, 229, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {86,85,86}, 208,2 , 6803,44 , 4,4 , 4,0 , 786,7 , 1747,7 , 0, 0, 1, 6, 7 }, // English/Latin/Vanuatu
- { 31, 7, 233, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 167,3 , 3763,35 , 4,4 , 4,0 , 786,7 , 1754,22 , 2, 1, 1, 6, 7 }, // English/Latin/BritishVirginIslands
- { 31, 7, 234, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 538,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 3763,35 , 4,4 , 4,0 , 786,7 , 1776,19 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStatesVirginIslands
- { 31, 7, 239, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {90,77,87}, 137,1 , 6847,50 , 4,4 , 4,0 , 786,7 , 1795,6 , 2, 1, 1, 6, 7 }, // English/Latin/Zambia
- { 31, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 439,8 , 80,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 167,3 , 3763,35 , 4,4 , 4,0 , 786,7 , 1801,8 , 2, 1, 7, 6, 7 }, // English/Latin/Zimbabwe
- { 31, 7, 249, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 167,3 , 3763,35 , 4,4 , 4,0 , 786,7 , 1809,12 , 2, 1, 1, 6, 7 }, // English/Latin/DiegoGarcia
- { 31, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {71,66,80}, 125,1 , 4744,32 , 4,4 , 4,0 , 786,7 , 1821,11 , 2, 1, 1, 6, 7 }, // English/Latin/IsleOfMan
- { 31, 7, 252, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {71,66,80}, 125,1 , 4744,32 , 4,4 , 4,0 , 786,7 , 1832,6 , 2, 1, 1, 6, 7 }, // English/Latin/Jersey
- { 31, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {83,83,80}, 125,1 , 6897,68 , 4,4 , 4,0 , 786,7 , 1838,11 , 2, 1, 1, 6, 7 }, // English/Latin/SouthSudan
- { 31, 7, 256, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 212,10 , 222,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , {65,78,71}, 163,4 , 6965,95 , 4,4 , 4,0 , 786,7 , 1849,12 , 2, 1, 1, 6, 7 }, // English/Latin/SintMaarten
- { 33, 7, 68, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 231,8 , 231,8 , 175,8 , 544,18 , 55,4 , 224,9 , 5325,59 , 5384,91 , 5475,24 , 5325,59 , 5384,91 , 5475,24 , 2570,14 , 2584,63 , 2570,14 , 2570,14 , 2584,63 , 2570,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 7060,20 , 13,5 , 4,0 , 1861,5 , 1866,5 , 2, 1, 1, 6, 7 }, // Estonian/Latin/Estonia
- { 34, 7, 71, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 204,8 , 204,8 , 175,8 , 544,18 , 37,5 , 8,10 , 5499,48 , 5547,83 , 134,24 , 5630,59 , 5547,83 , 134,24 , 2647,28 , 2675,74 , 2749,14 , 2763,35 , 2675,74 , 2749,14 , 0,2 , 0,2 , {68,75,75}, 198,2 , 7080,43 , 13,5 , 4,0 , 1871,8 , 1879,7 , 2, 1, 1, 6, 7 }, // Faroese/Latin/FaroeIslands
- { 34, 7, 58, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 204,8 , 204,8 , 175,8 , 544,18 , 37,5 , 8,10 , 5499,48 , 5547,83 , 134,24 , 5630,59 , 5547,83 , 134,24 , 2647,28 , 2675,74 , 2749,14 , 2763,35 , 2675,74 , 2749,14 , 0,2 , 0,2 , {68,75,75}, 156,3 , 7080,43 , 13,5 , 4,0 , 1871,8 , 660,7 , 2, 1, 1, 6, 7 }, // Faroese/Latin/Denmark
- { 36, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 231,8 , 231,8 , 562,8 , 491,17 , 211,4 , 215,9 , 5689,69 , 5758,105 , 5863,24 , 5887,129 , 5887,129 , 5863,24 , 2798,21 , 2819,67 , 2886,14 , 2798,21 , 2900,81 , 2886,14 , 91,3 , 89,3 , {69,85,82}, 14,1 , 7123,20 , 13,5 , 4,0 , 1886,5 , 1891,5 , 2, 1, 1, 6, 7 }, // Finnish/Latin/Finland
- { 37, 7, 74, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 1904,6 , 2, 1, 1, 6, 7 }, // French/Latin/France
- { 37, 7, 3, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {68,90,68}, 210,2 , 7143,51 , 13,5 , 4,0 , 1896,8 , 1910,7 , 2, 1, 6, 5, 6 }, // French/Latin/Algeria
- { 37, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 531,7 , 98,16 , 37,5 , 233,23 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 1917,8 , 2, 1, 1, 6, 7 }, // French/Latin/Belgium
- { 37, 7, 23, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 7194,59 , 13,5 , 4,0 , 1896,8 , 1925,5 , 0, 0, 1, 6, 7 }, // French/Latin/Benin
- { 37, 7, 34, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 7194,59 , 13,5 , 4,0 , 1896,8 , 1930,12 , 0, 0, 1, 6, 7 }, // French/Latin/BurkinaFaso
- { 37, 7, 35, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {66,73,70}, 171,3 , 7253,53 , 13,5 , 4,0 , 1896,8 , 939,7 , 0, 0, 1, 6, 7 }, // French/Latin/Burundi
- { 37, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,65,70}, 32,4 , 7306,56 , 13,5 , 4,0 , 1896,8 , 1942,8 , 0, 0, 1, 6, 7 }, // French/Latin/Cameroon
- { 37, 7, 38, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 570,8 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {67,65,68}, 6,1 , 7362,54 , 41,8 , 4,0 , 1950,17 , 970,6 , 2, 0, 7, 6, 7 }, // French/Latin/Canada
- { 37, 7, 41, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,65,70}, 32,4 , 7306,56 , 13,5 , 4,0 , 1896,8 , 1967,25 , 0, 0, 1, 6, 7 }, // French/Latin/CentralAfricanRepublic
- { 37, 7, 42, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,65,70}, 32,4 , 7306,56 , 13,5 , 4,0 , 1896,8 , 1992,5 , 0, 0, 1, 6, 7 }, // French/Latin/Chad
- { 37, 7, 48, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {75,77,70}, 215,2 , 7416,51 , 13,5 , 4,0 , 1896,8 , 1997,7 , 0, 0, 1, 6, 7 }, // French/Latin/Comoros
- { 37, 7, 49, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {67,68,70}, 217,2 , 7467,53 , 13,5 , 4,0 , 1896,8 , 2004,14 , 2, 1, 1, 6, 7 }, // French/Latin/CongoKinshasa
- { 37, 7, 50, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,65,70}, 32,4 , 7306,56 , 13,5 , 4,0 , 1896,8 , 2018,17 , 0, 0, 1, 6, 7 }, // French/Latin/CongoBrazzaville
- { 37, 7, 53, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 7194,59 , 13,5 , 4,0 , 1896,8 , 2035,13 , 0, 0, 1, 6, 7 }, // French/Latin/IvoryCoast
- { 37, 7, 59, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {68,74,70}, 43,3 , 7520,57 , 13,5 , 4,0 , 1896,8 , 2048,8 , 0, 0, 6, 6, 7 }, // French/Latin/Djibouti
- { 37, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,65,70}, 32,4 , 7306,56 , 13,5 , 4,0 , 1896,8 , 2056,18 , 0, 0, 1, 6, 7 }, // French/Latin/EquatorialGuinea
- { 37, 7, 76, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 2074,16 , 2, 1, 1, 6, 7 }, // French/Latin/FrenchGuiana
- { 37, 7, 77, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,80,70}, 219,4 , 7577,35 , 13,5 , 4,0 , 1896,8 , 2090,19 , 0, 0, 1, 6, 7 }, // French/Latin/FrenchPolynesia
- { 37, 7, 79, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,65,70}, 32,4 , 7306,56 , 13,5 , 4,0 , 1896,8 , 2109,5 , 0, 0, 1, 6, 7 }, // French/Latin/Gabon
- { 37, 7, 88, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 2114,10 , 2, 1, 1, 6, 7 }, // French/Latin/Guadeloupe
- { 37, 7, 91, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {71,78,70}, 223,2 , 7612,48 , 13,5 , 4,0 , 1896,8 , 2124,6 , 0, 0, 1, 6, 7 }, // French/Latin/Guinea
- { 37, 7, 94, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {72,84,71}, 225,1 , 7660,57 , 13,5 , 4,0 , 1896,8 , 2130,5 , 2, 1, 1, 6, 7 }, // French/Latin/Haiti
- { 37, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 2135,10 , 2, 1, 1, 6, 7 }, // French/Latin/Luxembourg
- { 37, 7, 128, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {77,71,65}, 178,2 , 7717,54 , 13,5 , 4,0 , 1896,8 , 1234,10 , 0, 0, 1, 6, 7 }, // French/Latin/Madagascar
- { 37, 7, 132, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 7194,59 , 13,5 , 4,0 , 1896,8 , 2145,4 , 0, 0, 1, 6, 7 }, // French/Latin/Mali
- { 37, 7, 135, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 2149,10 , 2, 1, 1, 6, 7 }, // French/Latin/Martinique
- { 37, 7, 136, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {77,82,79}, 226,2 , 7771,66 , 13,5 , 4,0 , 1896,8 , 2159,10 , 0, 0, 1, 6, 7 }, // French/Latin/Mauritania
- { 37, 7, 137, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {77,85,82}, 184,2 , 7837,63 , 13,5 , 4,0 , 1896,8 , 2169,7 , 0, 0, 1, 6, 7 }, // French/Latin/Mauritius
- { 37, 7, 138, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 2176,7 , 2, 1, 1, 6, 7 }, // French/Latin/Mayotte
- { 37, 7, 142, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 2183,6 , 2, 1, 1, 6, 7 }, // French/Latin/Monaco
- { 37, 7, 145, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6164,61 , 6079,85 , 134,24 , 6164,61 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 85,4 , 83,4 , {77,65,68}, 228,3 , 7900,54 , 13,5 , 4,0 , 1896,8 , 2189,5 , 2, 1, 6, 5, 6 }, // French/Latin/Morocco
- { 37, 7, 153, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,80,70}, 219,4 , 7577,35 , 13,5 , 4,0 , 1896,8 , 2194,18 , 0, 0, 1, 6, 7 }, // French/Latin/NewCaledonia
- { 37, 7, 156, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 7194,59 , 13,5 , 4,0 , 1896,8 , 2212,5 , 0, 0, 1, 6, 7 }, // French/Latin/Niger
- { 37, 7, 176, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 2217,10 , 2, 1, 1, 6, 7 }, // French/Latin/Reunion
- { 37, 7, 179, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {82,87,70}, 188,2 , 7954,50 , 13,5 , 4,0 , 1896,8 , 1458,6 , 0, 0, 1, 6, 7 }, // French/Latin/Rwanda
- { 37, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 7194,59 , 13,5 , 4,0 , 1896,8 , 2227,7 , 0, 0, 1, 6, 7 }, // French/Latin/Senegal
- { 37, 7, 188, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {83,67,82}, 193,2 , 8004,71 , 13,5 , 4,0 , 1896,8 , 1519,10 , 2, 1, 1, 6, 7 }, // French/Latin/Seychelles
- { 37, 7, 200, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 2234,24 , 2, 1, 1, 6, 7 }, // French/Latin/SaintPierreAndMiquelon
- { 37, 7, 206, 46, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 239,8 , 239,8 , 175,8 , 10,17 , 37,5 , 256,14 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {67,72,70}, 231,3 , 8075,45 , 8,5 , 36,5 , 2258,15 , 2273,6 , 2, 0, 1, 6, 7 }, // French/Latin/Switzerland
- { 37, 7, 207, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {83,89,80}, 234,2 , 8120,51 , 13,5 , 4,0 , 1896,8 , 2279,5 , 0, 0, 6, 5, 6 }, // French/Latin/Syria
- { 37, 7, 212, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 7194,59 , 13,5 , 4,0 , 1896,8 , 2284,4 , 0, 0, 1, 6, 7 }, // French/Latin/Togo
- { 37, 7, 216, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {84,78,68}, 236,2 , 8171,51 , 13,5 , 4,0 , 1896,8 , 2288,7 , 3, 0, 7, 5, 6 }, // French/Latin/Tunisia
- { 37, 7, 229, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {86,85,86}, 208,2 , 8222,51 , 13,5 , 4,0 , 1896,8 , 1747,7 , 0, 0, 1, 6, 7 }, // French/Latin/Vanuatu
- { 37, 7, 235, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {88,80,70}, 219,4 , 7577,35 , 13,5 , 4,0 , 1896,8 , 2295,16 , 0, 0, 1, 6, 7 }, // French/Latin/WallisAndFutunaIslands
- { 37, 7, 244, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 2311,16 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Barthelemy
- { 37, 7, 245, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 239,8 , 239,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6016,63 , 6079,85 , 134,24 , 6016,63 , 6079,85 , 134,24 , 2981,35 , 3016,52 , 3068,14 , 2981,35 , 3016,52 , 3068,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 1896,8 , 2327,12 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Martin
- { 38, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 370,8 , 98,16 , 37,5 , 8,10 , 6225,48 , 6273,95 , 134,24 , 6368,60 , 6273,95 , 134,24 , 3082,21 , 3103,54 , 2496,14 , 3082,21 , 3103,54 , 2496,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 3473,19 , 8,5 , 49,6 , 2339,10 , 2349,8 , 2, 1, 1, 6, 7 }, // Western Frisian/Latin/Netherlands
- { 39, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 247,10 , 247,10 , 120,10 , 578,21 , 37,5 , 8,10 , 6428,61 , 6489,142 , 6631,24 , 6428,61 , 6655,167 , 6631,24 , 3157,28 , 3185,69 , 3254,14 , 3157,28 , 3185,69 , 3254,14 , 94,1 , 92,1 , {71,66,80}, 125,1 , 8273,86 , 4,4 , 4,0 , 2357,8 , 2365,22 , 2, 1, 1, 6, 7 }, // Gaelic/Latin/UnitedKingdom
- { 40, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 599,17 , 37,5 , 8,10 , 6822,48 , 6870,87 , 6957,24 , 6981,48 , 7029,87 , 6957,24 , 3268,28 , 3296,49 , 3345,14 , 3359,29 , 3388,49 , 3345,14 , 85,4 , 83,4 , {69,85,82}, 14,1 , 3928,20 , 13,5 , 4,0 , 2387,6 , 2393,6 , 2, 1, 1, 6, 7 }, // Galician/Latin/Spain
- { 41, 15, 81, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 171, 187, 0,6 , 0,6 , 264,8 , 264,8 , 175,8 , 616,19 , 37,5 , 8,10 , 7116,48 , 7164,99 , 7263,24 , 7116,48 , 7164,99 , 7263,24 , 3437,28 , 3465,62 , 3527,14 , 3437,28 , 3465,62 , 3527,14 , 0,2 , 0,2 , {71,69,76}, 238,1 , 8359,43 , 13,5 , 4,0 , 2399,7 , 2406,10 , 2, 1, 1, 6, 7 }, // Georgian/Georgian/Georgia
- { 42, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 272,9 , 272,9 , 175,8 , 544,18 , 37,5 , 8,10 , 7287,48 , 7335,83 , 134,24 , 7418,59 , 7335,83 , 134,24 , 3541,21 , 3562,60 , 3622,14 , 3636,28 , 3562,60 , 3622,14 , 95,5 , 93,6 , {69,85,82}, 14,1 , 8402,19 , 13,5 , 4,0 , 2416,7 , 2423,11 , 2, 1, 1, 6, 7 }, // German/Latin/Germany
- { 42, 7, 14, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 272,9 , 272,9 , 175,8 , 544,18 , 37,5 , 8,10 , 7477,48 , 7525,83 , 134,24 , 7608,59 , 7525,83 , 134,24 , 3541,21 , 3562,60 , 3622,14 , 3636,28 , 3562,60 , 3622,14 , 95,5 , 93,6 , {69,85,82}, 14,1 , 8402,19 , 8,5 , 4,0 , 2434,24 , 2458,10 , 2, 1, 1, 6, 7 }, // German/Latin/Austria
- { 42, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 272,9 , 272,9 , 175,8 , 544,18 , 37,5 , 8,10 , 7287,48 , 7335,83 , 134,24 , 7418,59 , 7335,83 , 134,24 , 3541,21 , 3562,60 , 3622,14 , 3636,28 , 3562,60 , 3622,14 , 95,5 , 93,6 , {69,85,82}, 14,1 , 8402,19 , 13,5 , 4,0 , 2416,7 , 2468,7 , 2, 1, 1, 6, 7 }, // German/Latin/Belgium
- { 42, 7, 123, 46, 39, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 272,9 , 272,9 , 175,8 , 544,18 , 37,5 , 8,10 , 7287,48 , 7335,83 , 134,24 , 7418,59 , 7335,83 , 134,24 , 3541,21 , 3562,60 , 3622,14 , 3636,28 , 3562,60 , 3622,14 , 95,5 , 93,6 , {67,72,70}, 231,3 , 8421,58 , 8,5 , 4,0 , 2416,7 , 2475,13 , 2, 0, 1, 6, 7 }, // German/Latin/Liechtenstein
- { 42, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 272,9 , 272,9 , 175,8 , 544,18 , 37,5 , 8,10 , 7287,48 , 7335,83 , 134,24 , 7418,59 , 7335,83 , 134,24 , 3541,21 , 3562,60 , 3622,14 , 3636,28 , 3562,60 , 3622,14 , 95,5 , 93,6 , {69,85,82}, 14,1 , 8402,19 , 13,5 , 4,0 , 2416,7 , 2488,9 , 2, 1, 1, 6, 7 }, // German/Latin/Luxembourg
- { 42, 7, 206, 46, 39, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 272,9 , 272,9 , 175,8 , 544,18 , 37,5 , 8,10 , 7287,48 , 7335,83 , 134,24 , 7418,59 , 7335,83 , 134,24 , 3541,21 , 3562,60 , 3622,14 , 3636,28 , 3562,60 , 3622,14 , 95,5 , 93,6 , {67,72,70}, 231,3 , 8421,58 , 8,5 , 36,5 , 2497,21 , 2518,7 , 2, 0, 1, 6, 7 }, // German/Latin/Switzerland
- { 43, 16, 85, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 281,9 , 281,9 , 300,6 , 10,17 , 18,7 , 25,12 , 7667,50 , 7717,115 , 7832,24 , 7856,50 , 7906,115 , 7832,24 , 3664,28 , 3692,55 , 3747,14 , 3664,28 , 3692,55 , 3747,14 , 100,4 , 99,4 , {69,85,82}, 14,1 , 8479,19 , 13,5 , 4,0 , 2525,8 , 2533,6 , 2, 1, 1, 6, 7 }, // Greek/Greek/Greece
- { 43, 16, 56, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 281,9 , 281,9 , 300,6 , 10,17 , 18,7 , 25,12 , 7667,50 , 7717,115 , 7832,24 , 7856,50 , 7906,115 , 7832,24 , 3664,28 , 3692,55 , 3747,14 , 3664,28 , 3692,55 , 3747,14 , 100,4 , 99,4 , {69,85,82}, 14,1 , 8479,19 , 13,5 , 4,0 , 2525,8 , 2539,6 , 2, 1, 1, 6, 7 }, // Greek/Greek/Cyprus
- { 44, 7, 86, 44, 46, 59, 37, 48, 45, 43, 101, 187, 171, 8250, 8249, 0,6 , 0,6 , 290,11 , 290,11 , 53,10 , 599,17 , 18,7 , 25,12 , 4928,48 , 8021,96 , 134,24 , 4928,48 , 8021,96 , 134,24 , 3761,28 , 3789,98 , 3887,14 , 3761,28 , 3789,98 , 3887,14 , 0,2 , 0,2 , {68,75,75}, 156,3 , 8498,62 , 4,4 , 36,5 , 2545,11 , 2556,16 , 2, 1, 1, 6, 7 }, // Greenlandic/Latin/Greenland
- { 45, 7, 168, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {80,89,71}, 239,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Guarani/Latin/Paraguay
- { 46, 17, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 301,9 , 301,9 , 300,6 , 210,18 , 270,8 , 278,13 , 8117,67 , 8184,87 , 8271,31 , 8117,67 , 8184,87 , 8271,31 , 3901,32 , 3933,53 , 3986,19 , 3901,32 , 3933,53 , 3986,19 , 0,2 , 0,2 , {73,78,82}, 127,1 , 8560,46 , 4,4 , 4,0 , 2572,7 , 2579,4 , 2, 1, 7, 7, 7 }, // Gujarati/Gujarati/India
- { 47, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 300,6 , 210,18 , 18,7 , 25,12 , 8302,48 , 8350,85 , 8435,24 , 8302,48 , 8350,85 , 8435,24 , 4005,21 , 4026,52 , 4078,14 , 4005,21 , 4026,52 , 4078,14 , 0,2 , 0,2 , {78,71,78}, 186,1 , 8606,12 , 8,5 , 4,0 , 2583,5 , 2588,8 , 2, 1, 1, 6, 7 }, // Hausa/Latin/Nigeria
- { 47, 1, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {78,71,78}, 186,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Hausa/Arabic/Nigeria
- { 47, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 300,6 , 210,18 , 18,7 , 25,12 , 8302,48 , 8350,85 , 8435,24 , 8302,48 , 8350,85 , 8435,24 , 4005,21 , 4026,52 , 4078,14 , 4005,21 , 4026,52 , 4078,14 , 0,2 , 0,2 , {71,72,83}, 175,3 , 0,7 , 8,5 , 4,0 , 2583,5 , 2596,4 , 2, 1, 1, 6, 7 }, // Hausa/Latin/Ghana
- { 47, 7, 156, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 300,6 , 210,18 , 37,5 , 8,10 , 8302,48 , 8350,85 , 8435,24 , 8302,48 , 8350,85 , 8435,24 , 4005,21 , 4026,52 , 4078,14 , 4005,21 , 4026,52 , 4078,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 8618,36 , 8,5 , 4,0 , 2583,5 , 2600,5 , 0, 0, 1, 6, 7 }, // Hausa/Latin/Niger
- { 48, 18, 105, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 310,6 , 310,6 , 562,8 , 635,18 , 55,4 , 59,9 , 8459,58 , 8517,72 , 158,27 , 8459,58 , 8517,72 , 158,27 , 4092,46 , 4138,65 , 4203,21 , 4092,46 , 4138,65 , 4203,21 , 104,6 , 103,5 , {73,76,83}, 54,1 , 8654,54 , 13,5 , 4,0 , 2605,5 , 2610,5 , 2, 1, 7, 5, 6 }, // Hebrew/Hebrew/Israel
- { 49, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 316,9 , 325,8 , 300,6 , 10,17 , 18,7 , 25,12 , 8589,59 , 8648,73 , 8721,30 , 8589,59 , 8648,73 , 8721,30 , 4224,32 , 4256,53 , 4309,19 , 4224,32 , 4256,53 , 4309,19 , 110,9 , 108,7 , {73,78,82}, 127,1 , 8708,42 , 4,4 , 4,0 , 2615,6 , 2621,4 , 2, 1, 7, 7, 7 }, // Hindi/Devanagari/India
- { 50, 7, 98, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 187, 171, 0,6 , 0,6 , 333,8 , 333,8 , 653,13 , 666,19 , 55,4 , 59,9 , 8751,64 , 8815,98 , 8913,25 , 8751,64 , 8815,98 , 8913,25 , 4328,19 , 4347,52 , 4399,17 , 4328,19 , 4347,52 , 4399,17 , 119,3 , 115,3 , {72,85,70}, 240,2 , 8750,46 , 13,5 , 4,0 , 2625,6 , 2631,12 , 2, 0, 1, 6, 7 }, // Hungarian/Latin/Hungary
- { 51, 7, 99, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 204,8 , 204,8 , 562,8 , 544,18 , 37,5 , 8,10 , 8938,59 , 8997,82 , 9079,24 , 8938,59 , 8997,82 , 9079,24 , 4416,35 , 4451,81 , 4532,14 , 4416,35 , 4451,81 , 4532,14 , 122,4 , 118,4 , {73,83,75}, 242,3 , 8796,49 , 13,5 , 4,0 , 2643,8 , 2651,6 , 0, 0, 1, 6, 7 }, // Icelandic/Latin/Iceland
- { 52, 7, 101, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 341,10 , 351,9 , 27,8 , 80,18 , 159,5 , 164,10 , 9103,48 , 9151,87 , 134,24 , 9103,48 , 9151,87 , 134,24 , 4546,28 , 4574,43 , 4617,14 , 4546,28 , 4574,43 , 4617,14 , 0,2 , 0,2 , {73,68,82}, 245,2 , 8845,39 , 4,4 , 4,0 , 2657,9 , 2657,9 , 0, 0, 7, 6, 7 }, // Indonesian/Latin/Indonesia
- { 53, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Interlingua/Latin/France
- { 55, 44, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {67,65,68}, 247,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/CanadianAboriginal/Canada
- { 55, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {67,65,68}, 247,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/Latin/Canada
- { 57, 7, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 360,11 , 247,10 , 120,10 , 98,16 , 37,5 , 8,10 , 9238,62 , 9300,107 , 9407,24 , 9238,62 , 9300,107 , 9407,24 , 4631,37 , 4668,75 , 4743,14 , 4631,37 , 4668,75 , 4743,14 , 85,4 , 83,4 , {69,85,82}, 14,1 , 8884,31 , 4,4 , 4,0 , 2666,7 , 2673,4 , 2, 1, 7, 6, 7 }, // Irish/Latin/Ireland
- { 58, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 98,16 , 37,5 , 8,10 , 9431,48 , 9479,94 , 9573,24 , 9431,48 , 9597,94 , 9573,24 , 4757,28 , 4785,57 , 4842,14 , 4757,28 , 4856,57 , 4842,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 8915,19 , 13,5 , 4,0 , 2677,8 , 2685,6 , 2, 1, 1, 6, 7 }, // Italian/Latin/Italy
- { 58, 7, 184, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 98,16 , 37,5 , 8,10 , 9431,48 , 9479,94 , 9573,24 , 9431,48 , 9597,94 , 9573,24 , 4757,28 , 4785,57 , 4842,14 , 4757,28 , 4856,57 , 4842,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 8915,19 , 13,5 , 4,0 , 2677,8 , 2691,10 , 2, 1, 1, 6, 7 }, // Italian/Latin/SanMarino
- { 58, 7, 206, 46, 39, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 257,7 , 257,7 , 175,8 , 10,17 , 37,5 , 8,10 , 9431,48 , 9597,94 , 9573,24 , 9431,48 , 9597,94 , 9573,24 , 4757,28 , 4785,57 , 4842,14 , 4757,28 , 4856,57 , 4842,14 , 0,2 , 0,2 , {67,72,70}, 231,3 , 8934,53 , 8,5 , 36,5 , 2677,8 , 2701,8 , 2, 0, 1, 6, 7 }, // Italian/Latin/Switzerland
- { 59, 19, 108, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 182,5 , 182,5 , 182,5 , 182,5 , 264,10 , 426,13 , 55,4 , 291,10 , 4357,39 , 4357,39 , 158,27 , 4357,39 , 4357,39 , 158,27 , 4913,14 , 4927,28 , 4913,14 , 4913,14 , 4927,28 , 4913,14 , 126,2 , 122,2 , {74,80,89}, 141,1 , 8987,11 , 4,4 , 4,0 , 2709,3 , 2712,2 , 0, 0, 7, 6, 7 }, // Japanese/Japanese/Japan
- { 60, 7, 101, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {73,68,82}, 245,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Javanese/Latin/Indonesia
- { 61, 21, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 371,12 , 383,11 , 300,6 , 35,18 , 270,8 , 278,13 , 9691,63 , 9754,87 , 9841,31 , 9691,63 , 9754,87 , 9841,31 , 4955,33 , 4988,54 , 5042,20 , 4955,33 , 4988,54 , 5042,20 , 128,9 , 124,7 , {73,78,82}, 127,1 , 8998,49 , 4,4 , 4,0 , 2714,5 , 2719,4 , 2, 1, 7, 7, 7 }, // Kannada/Kannada/India
- { 62, 1, 100, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 538,6 , 35,18 , 18,7 , 25,12 , 9872,72 , 9872,72 , 9944,24 , 9872,72 , 9872,72 , 9944,24 , 5062,54 , 5116,56 , 5172,14 , 5062,54 , 5116,56 , 5172,14 , 0,2 , 0,2 , {73,78,82}, 127,1 , 9047,23 , 8,5 , 4,0 , 2723,5 , 2728,10 , 2, 1, 7, 7, 7 }, // Kashmiri/Arabic/India
- { 63, 2, 110, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 394,10 , 175,8 , 685,22 , 37,5 , 8,10 , 9968,60 , 10028,83 , 10111,24 , 10135,60 , 10195,83 , 10111,24 , 5186,21 , 5207,56 , 5263,14 , 5186,21 , 5277,56 , 5263,14 , 137,5 , 131,11 , {75,90,84}, 250,1 , 9070,58 , 13,5 , 4,0 , 2738,10 , 2748,9 , 2, 1, 1, 6, 7 }, // Kazakh/Cyrillic/Kazakhstan
- { 64, 7, 179, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 707,8 , 715,18 , 37,5 , 8,10 , 10278,60 , 10338,101 , 158,27 , 10278,60 , 10338,101 , 158,27 , 5333,35 , 5368,84 , 85,14 , 5333,35 , 5368,84 , 85,14 , 0,2 , 0,2 , {82,87,70}, 188,2 , 0,7 , 55,6 , 4,0 , 2757,11 , 1458,6 , 0, 0, 1, 6, 7 }, // Kinyarwanda/Latin/Rwanda
- { 65, 2, 116, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 404,10 , 404,10 , 175,8 , 733,23 , 37,5 , 8,10 , 10439,48 , 10487,80 , 10567,24 , 10591,59 , 10650,80 , 10567,24 , 5452,38 , 5490,57 , 5547,14 , 5452,38 , 5490,57 , 5547,14 , 142,5 , 142,14 , {75,71,83}, 251,3 , 9128,52 , 13,5 , 4,0 , 2768,8 , 2776,10 , 2, 1, 1, 6, 7 }, // Kirghiz/Cyrillic/Kyrgyzstan
- { 66, 22, 114, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 414,7 , 414,7 , 756,9 , 765,16 , 301,7 , 308,13 , 10730,39 , 10730,39 , 10730,39 , 10730,39 , 10730,39 , 10730,39 , 5561,14 , 5575,28 , 5561,14 , 5561,14 , 5575,28 , 5561,14 , 147,2 , 156,2 , {75,82,87}, 254,1 , 9180,19 , 4,4 , 4,0 , 2786,3 , 2789,4 , 0, 0, 7, 6, 7 }, // Korean/Korean/SouthKorea
- { 66, 22, 113, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 414,7 , 414,7 , 756,9 , 765,16 , 301,7 , 308,13 , 10730,39 , 10730,39 , 10730,39 , 10730,39 , 10730,39 , 10730,39 , 5561,14 , 5575,28 , 5561,14 , 5561,14 , 5575,28 , 5561,14 , 147,2 , 156,2 , {75,80,87}, 255,3 , 9199,39 , 4,4 , 4,0 , 2786,3 , 2793,11 , 0, 0, 1, 6, 7 }, // Korean/Korean/NorthKorea
- { 67, 7, 217, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {84,82,89}, 258,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Kurdish/Latin/Turkey
- { 68, 7, 35, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 10769,60 , 10829,106 , 158,27 , 10769,60 , 10829,106 , 158,27 , 5603,34 , 5637,89 , 85,14 , 5603,34 , 5637,89 , 85,14 , 149,5 , 158,5 , {66,73,70}, 171,3 , 9238,27 , 0,4 , 4,0 , 2804,8 , 2812,8 , 0, 0, 1, 6, 7 }, // Rundi/Latin/Burundi
- { 69, 23, 117, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 421,9 , 439,8 , 781,19 , 55,4 , 321,24 , 10935,61 , 10996,75 , 158,27 , 10935,61 , 10996,75 , 158,27 , 5726,36 , 5762,57 , 5819,16 , 5762,57 , 5762,57 , 5835,14 , 154,8 , 163,8 , {76,65,75}, 259,1 , 9265,21 , 4,4 , 36,5 , 2820,3 , 2820,3 , 0, 0, 7, 6, 7 }, // Lao/Lao/Laos
- { 71, 7, 118, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 430,8 , 430,8 , 175,8 , 800,26 , 37,5 , 8,10 , 11071,65 , 11136,101 , 134,24 , 11237,65 , 11302,101 , 134,24 , 5849,21 , 5870,72 , 5942,14 , 5849,21 , 5956,72 , 5942,14 , 162,14 , 171,11 , {69,85,82}, 14,1 , 9286,23 , 13,5 , 4,0 , 2823,8 , 2831,7 , 2, 1, 1, 6, 7 }, // Latvian/Latin/Latvia
- { 72, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 438,9 , 438,9 , 439,8 , 98,16 , 37,5 , 8,10 , 11403,48 , 11451,203 , 11654,24 , 11403,48 , 11451,203 , 11654,24 , 6028,28 , 6056,100 , 6156,14 , 6028,28 , 6056,100 , 6156,14 , 176,8 , 182,6 , {67,68,70}, 217,2 , 9309,23 , 13,5 , 4,0 , 2838,7 , 2845,29 , 2, 1, 1, 6, 7 }, // Lingala/Latin/CongoKinshasa
- { 72, 7, 6, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 438,9 , 438,9 , 439,8 , 98,16 , 37,5 , 8,10 , 11403,48 , 11451,203 , 11654,24 , 11403,48 , 11451,203 , 11654,24 , 6028,28 , 6056,100 , 6156,14 , 6028,28 , 6056,100 , 6156,14 , 176,8 , 182,6 , {65,79,65}, 260,2 , 9332,23 , 13,5 , 4,0 , 2838,7 , 2874,6 , 2, 1, 1, 6, 7 }, // Lingala/Latin/Angola
- { 72, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 438,9 , 438,9 , 439,8 , 98,16 , 37,5 , 8,10 , 11403,48 , 11451,203 , 11654,24 , 11403,48 , 11451,203 , 11654,24 , 6028,28 , 6056,100 , 6156,14 , 6028,28 , 6056,100 , 6156,14 , 176,8 , 182,6 , {88,65,70}, 32,4 , 9355,23 , 13,5 , 4,0 , 2838,7 , 2880,26 , 0, 0, 1, 6, 7 }, // Lingala/Latin/CentralAfricanRepublic
- { 72, 7, 50, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 438,9 , 438,9 , 439,8 , 98,16 , 37,5 , 8,10 , 11403,48 , 11451,203 , 11654,24 , 11403,48 , 11451,203 , 11654,24 , 6028,28 , 6056,100 , 6156,14 , 6028,28 , 6056,100 , 6156,14 , 176,8 , 182,6 , {88,65,70}, 32,4 , 9355,23 , 13,5 , 4,0 , 2838,7 , 2906,5 , 0, 0, 1, 6, 7 }, // Lingala/Latin/CongoBrazzaville
- { 73, 7, 124, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 447,8 , 447,8 , 53,10 , 826,27 , 37,5 , 8,10 , 11678,70 , 11748,96 , 11844,24 , 11678,70 , 11868,98 , 11844,24 , 6170,21 , 6191,89 , 6280,14 , 6170,21 , 6191,89 , 6280,14 , 184,9 , 188,6 , {69,85,82}, 14,1 , 9378,30 , 13,5 , 4,0 , 2911,8 , 2919,7 , 2, 1, 1, 6, 7 }, // Lithuanian/Latin/Lithuania
- { 74, 2, 127, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 117,7 , 0,6 , 853,7 , 80,18 , 37,5 , 8,10 , 11966,61 , 12027,85 , 12112,24 , 11966,61 , 12027,85 , 12112,24 , 6294,34 , 6328,54 , 1658,14 , 6294,34 , 6328,54 , 1658,14 , 193,10 , 194,8 , {77,75,68}, 262,3 , 9408,56 , 8,5 , 4,0 , 2926,10 , 2936,10 , 2, 1, 1, 6, 7 }, // Macedonian/Cyrillic/Macedonia
- { 75, 7, 128, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 12136,48 , 12184,92 , 134,24 , 12136,48 , 12184,92 , 134,24 , 6382,34 , 6416,60 , 6476,14 , 6382,34 , 6416,60 , 6476,14 , 0,2 , 0,2 , {77,71,65}, 178,2 , 9464,13 , 4,4 , 4,0 , 2946,8 , 2954,12 , 0, 0, 1, 6, 7 }, // Malagasy/Latin/Madagascar
- { 76, 7, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 351,9 , 351,9 , 531,7 , 10,17 , 18,7 , 25,12 , 12276,48 , 12324,82 , 12406,24 , 12276,48 , 12324,82 , 12406,24 , 6490,28 , 6518,43 , 6561,14 , 6490,28 , 6518,43 , 6561,14 , 203,2 , 202,3 , {77,89,82}, 182,2 , 9477,39 , 4,4 , 4,0 , 2966,13 , 1250,8 , 2, 1, 1, 6, 7 }, // Malay/Latin/Malaysia
- { 76, 1, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {77,89,82}, 182,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Malay/Arabic/Malaysia
- { 76, 7, 32, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 351,9 , 351,9 , 531,7 , 860,12 , 18,7 , 25,12 , 12276,48 , 12324,82 , 12406,24 , 12276,48 , 12324,82 , 12406,24 , 6490,28 , 6518,43 , 6561,14 , 6490,28 , 6518,43 , 6561,14 , 203,2 , 202,3 , {66,78,68}, 6,1 , 9516,31 , 8,5 , 4,0 , 2966,13 , 2979,6 , 2, 1, 1, 6, 7 }, // Malay/Latin/Brunei
- { 76, 7, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 351,9 , 351,9 , 531,7 , 10,17 , 18,7 , 25,12 , 12276,48 , 12324,82 , 12406,24 , 12276,48 , 12324,82 , 12406,24 , 6490,28 , 6518,43 , 6561,14 , 6490,28 , 6518,43 , 6561,14 , 203,2 , 202,3 , {83,71,68}, 6,1 , 9547,37 , 4,4 , 4,0 , 2966,13 , 2985,9 , 2, 1, 7, 6, 7 }, // Malay/Latin/Singapore
- { 77, 24, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 455,13 , 468,12 , 300,6 , 872,18 , 18,7 , 25,12 , 12430,62 , 12492,88 , 12580,31 , 12430,62 , 12492,88 , 12611,29 , 6575,41 , 6616,77 , 6693,22 , 6575,41 , 6715,76 , 6791,21 , 0,2 , 0,2 , {73,78,82}, 127,1 , 9584,40 , 4,4 , 4,0 , 2994,6 , 3000,6 , 2, 1, 7, 7, 7 }, // Malayalam/Malayalam/India
- { 78, 7, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 480,8 , 488,7 , 120,10 , 890,23 , 37,5 , 8,10 , 12640,48 , 12688,86 , 12774,36 , 12640,48 , 12688,86 , 12810,24 , 6812,28 , 6840,63 , 6903,21 , 6812,28 , 6840,63 , 6924,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 9624,27 , 4,4 , 4,0 , 3006,5 , 1258,5 , 2, 1, 7, 6, 7 }, // Maltese/Latin/Malta
- { 79, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {78,90,68}, 265,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Maori/Latin/NewZealand
- { 80, 13, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 495,9 , 495,9 , 300,6 , 210,18 , 18,7 , 25,12 , 12834,66 , 12900,86 , 12986,32 , 12834,66 , 12900,86 , 12986,32 , 6938,32 , 6970,53 , 4309,19 , 6938,32 , 6970,53 , 4309,19 , 205,5 , 205,4 , {73,78,82}, 127,1 , 9651,43 , 4,4 , 4,0 , 3011,5 , 2621,4 , 2, 1, 7, 7, 7 }, // Marathi/Devanagari/India
- { 82, 2, 143, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 913,29 , 37,5 , 8,10 , 13018,99 , 13117,189 , 158,27 , 13018,99 , 13117,189 , 158,27 , 7023,21 , 7044,43 , 5835,14 , 7023,21 , 7044,43 , 5835,14 , 210,2 , 209,2 , {77,78,84}, 268,1 , 9694,25 , 8,5 , 4,0 , 3016,6 , 3022,6 , 0, 0, 1, 6, 7 }, // Mongolian/Cyrillic/Mongolia
- { 82, 8, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {67,78,89}, 269,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Mongolian/Mongolian/China
- { 84, 13, 150, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 504,7 , 0,6 , 504,7 , 504,7 , 53,10 , 63,17 , 37,5 , 8,10 , 13306,85 , 13306,85 , 13391,27 , 13306,85 , 13418,85 , 13391,27 , 7087,33 , 7120,54 , 7174,18 , 7087,33 , 7120,54 , 7174,18 , 110,9 , 108,7 , {78,80,82}, 272,4 , 9719,49 , 8,5 , 4,0 , 3028,6 , 3034,5 , 2, 1, 7, 6, 7 }, // Nepali/Devanagari/Nepal
- { 84, 13, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 504,7 , 0,6 , 504,7 , 504,7 , 53,10 , 63,17 , 18,7 , 25,12 , 13306,85 , 13306,85 , 13391,27 , 13306,85 , 13418,85 , 13391,27 , 7087,33 , 7120,54 , 7174,18 , 7087,33 , 7120,54 , 7174,18 , 110,9 , 108,7 , {73,78,82}, 127,1 , 9768,49 , 8,5 , 4,0 , 3028,6 , 2621,4 , 2, 1, 7, 7, 7 }, // Nepali/Devanagari/India
- { 85, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 204,8 , 204,8 , 942,10 , 491,17 , 159,5 , 164,10 , 5499,48 , 13503,83 , 134,24 , 5630,59 , 13503,83 , 134,24 , 2381,35 , 2316,51 , 2367,14 , 2381,35 , 2316,51 , 2367,14 , 85,4 , 83,4 , {78,79,75}, 198,2 , 9817,44 , 8,5 , 4,0 , 3039,12 , 3051,5 , 2, 1, 1, 6, 7 }, // NorwegianBokmal/Latin/Norway
- { 85, 7, 203, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 204,8 , 204,8 , 942,10 , 491,17 , 159,5 , 164,10 , 5499,48 , 13503,83 , 134,24 , 5630,59 , 13503,83 , 134,24 , 2381,35 , 2316,51 , 2367,14 , 2381,35 , 2316,51 , 2367,14 , 85,4 , 83,4 , {78,79,75}, 198,2 , 9817,44 , 8,5 , 4,0 , 3039,12 , 3056,21 , 2, 1, 1, 6, 7 }, // NorwegianBokmal/Latin/SvalbardAndJanMayenIslands
- { 86, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Occitan/Latin/France
- { 87, 26, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 952,6 , 10,17 , 18,7 , 25,12 , 13586,86 , 13586,86 , 13672,32 , 13586,86 , 13586,86 , 13672,32 , 7192,33 , 7225,54 , 7279,18 , 7192,33 , 7225,54 , 7279,18 , 89,2 , 87,2 , {73,78,82}, 127,1 , 9861,11 , 8,5 , 4,0 , 3077,5 , 3082,4 , 2, 1, 7, 7, 7 }, // Oriya/Oriya/India
- { 88, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 418,8 , 958,20 , 55,4 , 345,11 , 13704,68 , 13704,68 , 158,27 , 13704,68 , 13704,68 , 158,27 , 7297,49 , 7297,49 , 85,14 , 7297,49 , 7297,49 , 85,14 , 212,4 , 211,4 , {65,70,78}, 276,1 , 9872,13 , 13,5 , 4,0 , 3086,4 , 3090,9 , 0, 0, 6, 4, 5 }, // Pashto/Arabic/Afghanistan
- { 89, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 171, 187, 8249, 8250, 511,7 , 511,7 , 518,8 , 526,7 , 418,8 , 98,16 , 55,4 , 345,11 , 13772,70 , 13772,70 , 13842,24 , 13866,74 , 13866,74 , 13842,24 , 7297,49 , 7297,49 , 7346,14 , 7297,49 , 7297,49 , 7346,14 , 216,9 , 215,8 , {73,82,82}, 277,4 , 9885,37 , 61,5 , 4,0 , 3099,5 , 3104,5 , 0, 0, 6, 5, 5 }, // Persian/Arabic/Iran
- { 89, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 171, 187, 8249, 8250, 511,7 , 511,7 , 518,8 , 526,7 , 418,8 , 98,16 , 55,4 , 345,11 , 13772,70 , 13772,70 , 13940,24 , 13964,62 , 14026,68 , 13842,24 , 7297,49 , 7297,49 , 7346,14 , 7297,49 , 7297,49 , 7346,14 , 216,9 , 215,8 , {65,70,78}, 276,1 , 9922,55 , 61,5 , 4,0 , 3109,3 , 3090,9 , 0, 0, 6, 4, 5 }, // Persian/Arabic/Afghanistan
- { 90, 7, 172, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 175,7 , 175,7 , 942,10 , 10,17 , 37,5 , 8,10 , 14094,48 , 14142,97 , 14239,24 , 14094,48 , 14263,99 , 14239,24 , 7360,34 , 7394,59 , 7453,14 , 7360,34 , 7394,59 , 7453,14 , 0,2 , 0,2 , {80,76,78}, 281,2 , 9977,77 , 13,5 , 4,0 , 3112,6 , 3118,6 , 2, 1, 1, 6, 7 }, // Polish/Latin/Poland
- { 91, 7, 30, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7467,28 , 7495,79 , 7574,14 , 7467,28 , 7495,79 , 7574,14 , 0,2 , 0,2 , {66,82,76}, 283,2 , 10054,54 , 4,4 , 4,0 , 3124,19 , 3143,6 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Brazil
- { 91, 7, 6, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {65,79,65}, 260,2 , 10108,54 , 13,5 , 4,0 , 3149,9 , 3158,6 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Angola
- { 91, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {67,86,69}, 285,1 , 10162,69 , 13,5 , 4,0 , 3149,9 , 3164,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/CapeVerde
- { 91, 7, 62, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {85,83,68}, 167,3 , 10231,81 , 13,5 , 4,0 , 3149,9 , 3174,11 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/EastTimor
- { 91, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {88,65,70}, 32,4 , 10312,59 , 13,5 , 4,0 , 3149,9 , 3185,16 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/EquatorialGuinea
- { 91, 7, 92, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {88,79,70}, 212,3 , 10371,62 , 13,5 , 4,0 , 3149,9 , 3201,12 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/GuineaBissau
- { 91, 7, 125, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {69,85,82}, 14,1 , 10433,20 , 13,5 , 4,0 , 3149,9 , 3213,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Luxembourg
- { 91, 7, 126, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 18,7 , 25,12 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {77,79,80}, 145,4 , 10453,53 , 13,5 , 4,0 , 3149,9 , 3223,19 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Macau
- { 91, 7, 146, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {77,90,78}, 286,3 , 10506,72 , 13,5 , 4,0 , 3149,9 , 3242,10 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Mozambique
- { 91, 7, 173, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {69,85,82}, 14,1 , 10433,20 , 13,5 , 4,0 , 3252,17 , 3269,8 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Portugal
- { 91, 7, 185, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {83,84,68}, 289,2 , 10578,92 , 13,5 , 4,0 , 3149,9 , 3277,19 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/SaoTomeAndPrincipe
- { 91, 7, 206, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 978,27 , 37,5 , 8,10 , 14362,48 , 14410,89 , 134,24 , 14362,48 , 14410,89 , 134,24 , 7588,49 , 7495,79 , 7574,14 , 7588,49 , 7495,79 , 7574,14 , 225,8 , 223,8 , {67,72,70}, 231,3 , 10670,45 , 13,5 , 4,0 , 3149,9 , 3296,5 , 2, 0, 1, 6, 7 }, // Portuguese/Latin/Switzerland
- { 92, 4, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 533,9 , 533,9 , 300,6 , 10,17 , 18,7 , 25,12 , 14499,50 , 14549,68 , 14617,28 , 14499,50 , 14549,68 , 14617,28 , 7637,36 , 7673,57 , 7730,23 , 7637,36 , 7673,57 , 7730,23 , 233,6 , 231,6 , {73,78,82}, 127,1 , 10715,39 , 4,4 , 4,0 , 3301,6 , 3307,4 , 2, 1, 7, 7, 7 }, // Punjabi/Gurmukhi/India
- { 92, 1, 163, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 80,18 , 18,7 , 25,12 , 14645,67 , 14645,67 , 158,27 , 14645,67 , 14645,67 , 158,27 , 7753,37 , 7753,37 , 85,14 , 7753,37 , 7753,37 , 85,14 , 0,2 , 0,2 , {80,75,82}, 291,1 , 10754,13 , 55,6 , 4,0 , 3311,6 , 3317,6 , 0, 0, 7, 6, 7 }, // Punjabi/Arabic/Pakistan
- { 93, 7, 169, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 210,18 , 37,5 , 8,10 , 14712,48 , 14760,128 , 158,27 , 14712,48 , 14760,128 , 158,27 , 7790,28 , 7818,53 , 7871,14 , 7790,28 , 7818,53 , 7871,14 , 85,4 , 83,4 , {80,69,78}, 292,3 , 0,7 , 8,5 , 4,0 , 3323,8 , 3331,4 , 2, 1, 7, 6, 7 }, // Quechua/Latin/Peru
- { 93, 7, 26, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 210,18 , 37,5 , 8,10 , 14712,48 , 14760,128 , 158,27 , 14712,48 , 14760,128 , 158,27 , 7790,28 , 7818,53 , 7871,14 , 7790,28 , 7818,53 , 7871,14 , 85,4 , 83,4 , {66,79,66}, 295,2 , 0,7 , 8,5 , 4,0 , 3323,8 , 3335,7 , 2, 1, 1, 6, 7 }, // Quechua/Latin/Bolivia
- { 93, 7, 63, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 210,18 , 37,5 , 8,10 , 14712,48 , 14760,128 , 158,27 , 14712,48 , 14760,128 , 158,27 , 7790,28 , 7818,53 , 7871,14 , 7790,28 , 7818,53 , 7871,14 , 85,4 , 83,4 , {85,83,68}, 6,1 , 0,7 , 8,5 , 4,0 , 3323,8 , 3342,7 , 2, 1, 1, 6, 7 }, // Quechua/Latin/Ecuador
- { 94, 7, 206, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 370,8 , 1005,28 , 37,5 , 8,10 , 14888,67 , 14955,92 , 15047,24 , 14888,67 , 14955,92 , 15047,24 , 7885,23 , 7908,56 , 7964,14 , 7885,23 , 7908,56 , 7964,14 , 89,2 , 237,2 , {67,72,70}, 231,3 , 10767,46 , 13,5 , 4,0 , 3349,9 , 3358,6 , 2, 0, 1, 6, 7 }, // Romansh/Latin/Switzerland
- { 95, 7, 177, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 542,8 , 542,8 , 942,10 , 10,17 , 37,5 , 8,10 , 15071,60 , 15131,98 , 15229,24 , 15071,60 , 15131,98 , 15229,24 , 7978,34 , 8012,48 , 3068,14 , 7978,34 , 8012,48 , 3068,14 , 85,4 , 83,4 , {82,79,78}, 297,3 , 10813,57 , 13,5 , 4,0 , 3364,6 , 3370,7 , 2, 1, 1, 6, 7 }, // Romanian/Latin/Romania
- { 95, 7, 141, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 542,8 , 542,8 , 942,10 , 10,17 , 37,5 , 8,10 , 15071,60 , 15131,98 , 15229,24 , 15071,60 , 15131,98 , 15229,24 , 8060,28 , 8012,48 , 8088,16 , 8060,28 , 8012,48 , 8088,16 , 85,4 , 83,4 , {77,68,76}, 300,1 , 10870,69 , 13,5 , 4,0 , 3377,13 , 3390,17 , 2, 1, 1, 6, 7 }, // Romanian/Latin/Moldova
- { 96, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 117,7 , 117,7 , 175,8 , 348,22 , 55,4 , 59,9 , 15253,62 , 10650,80 , 10567,24 , 15315,62 , 15377,82 , 10567,24 , 8104,21 , 8125,62 , 8187,14 , 8104,21 , 8125,62 , 8104,21 , 239,2 , 239,2 , {82,85,66}, 129,1 , 10939,89 , 13,5 , 4,0 , 3407,7 , 3414,6 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Russia
- { 96, 2, 20, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 117,7 , 117,7 , 175,8 , 348,22 , 55,4 , 59,9 , 15253,62 , 10650,80 , 10567,24 , 15315,62 , 15377,82 , 10567,24 , 8104,21 , 8125,62 , 8187,14 , 8104,21 , 8125,62 , 8104,21 , 239,2 , 239,2 , {66,89,82}, 138,2 , 11028,94 , 13,5 , 4,0 , 3407,7 , 485,8 , 0, 0, 1, 6, 7 }, // Russian/Cyrillic/Belarus
- { 96, 2, 110, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 117,7 , 117,7 , 175,8 , 348,22 , 55,4 , 59,9 , 15253,62 , 10650,80 , 10567,24 , 15315,62 , 15377,82 , 10567,24 , 8104,21 , 8125,62 , 8187,14 , 8104,21 , 8125,62 , 8104,21 , 239,2 , 239,2 , {75,90,84}, 250,1 , 11122,83 , 13,5 , 4,0 , 3407,7 , 3420,9 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kazakhstan
- { 96, 2, 116, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 117,7 , 117,7 , 175,8 , 348,22 , 55,4 , 59,9 , 15253,62 , 10650,80 , 10567,24 , 15315,62 , 15377,82 , 10567,24 , 8104,21 , 8125,62 , 8187,14 , 8104,21 , 8125,62 , 8104,21 , 239,2 , 239,2 , {75,71,83}, 251,3 , 11205,81 , 13,5 , 4,0 , 3407,7 , 3429,8 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kyrgyzstan
- { 96, 2, 141, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 117,7 , 117,7 , 175,8 , 348,22 , 55,4 , 59,9 , 15253,62 , 10650,80 , 10567,24 , 15315,62 , 15377,82 , 10567,24 , 8104,21 , 8125,62 , 8187,14 , 8104,21 , 8125,62 , 8104,21 , 239,2 , 239,2 , {77,68,76}, 300,1 , 11286,79 , 13,5 , 4,0 , 3407,7 , 3437,7 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Moldova
- { 96, 2, 222, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 117,7 , 117,7 , 175,8 , 348,22 , 37,5 , 8,10 , 15253,62 , 10650,80 , 10567,24 , 15315,62 , 15377,82 , 10567,24 , 8104,21 , 8125,62 , 8187,14 , 8104,21 , 8125,62 , 8104,21 , 239,2 , 239,2 , {85,65,72}, 301,1 , 11365,92 , 13,5 , 4,0 , 3407,7 , 3444,7 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Ukraine
- { 98, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 15459,48 , 15507,91 , 15598,24 , 15459,48 , 15507,91 , 15598,24 , 8201,28 , 8229,66 , 8295,14 , 8201,28 , 8229,66 , 8295,14 , 241,2 , 241,2 , {88,65,70}, 32,4 , 11457,25 , 4,4 , 36,5 , 3451,5 , 3456,22 , 0, 0, 1, 6, 7 }, // Sango/Latin/CentralAfricanRepublic
- { 99, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 7, 7 }, // Sanskrit/Devanagari/India
- { 100, 2, 243, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 117,7 , 117,7 , 1033,7 , 1040,20 , 159,5 , 164,10 , 15622,48 , 15670,81 , 12112,24 , 15622,48 , 15670,81 , 12112,24 , 8309,28 , 8337,52 , 8389,14 , 8309,28 , 8337,52 , 8389,14 , 243,9 , 243,8 , {82,83,68}, 302,3 , 11482,58 , 13,5 , 4,0 , 3478,6 , 3484,6 , 0, 0, 1, 6, 7 }, // Serbian/Cyrillic/Serbia
- { 100, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 175,7 , 175,7 , 1033,7 , 1040,20 , 37,5 , 8,10 , 15751,48 , 15799,81 , 15880,24 , 15751,48 , 15799,81 , 15880,24 , 8403,28 , 8431,54 , 2176,14 , 8403,28 , 8431,54 , 2176,14 , 252,9 , 251,8 , {66,65,77}, 152,2 , 11540,174 , 13,5 , 4,0 , 3490,6 , 614,19 , 2, 1, 1, 6, 7 }, // Serbian/Latin/BosniaAndHerzegowina
- { 100, 7, 242, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 175,7 , 175,7 , 1033,7 , 1040,20 , 159,5 , 164,10 , 15751,48 , 15799,81 , 15880,24 , 15751,48 , 15799,81 , 15880,24 , 8403,28 , 8431,54 , 2176,14 , 8403,28 , 8431,54 , 2176,14 , 252,9 , 251,8 , {69,85,82}, 14,1 , 11714,23 , 13,5 , 4,0 , 3490,6 , 3496,9 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Montenegro
- { 100, 7, 243, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 175,7 , 175,7 , 1033,7 , 1040,20 , 159,5 , 164,10 , 15751,48 , 15799,81 , 15880,24 , 15751,48 , 15799,81 , 15880,24 , 8403,28 , 8431,54 , 2176,14 , 8403,28 , 8431,54 , 2176,14 , 252,9 , 251,8 , {82,83,68}, 302,3 , 11737,58 , 13,5 , 4,0 , 3490,6 , 3505,6 , 0, 0, 1, 6, 7 }, // Serbian/Latin/Serbia
- { 100, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 117,7 , 117,7 , 1033,7 , 1040,20 , 37,5 , 8,10 , 15622,48 , 15670,81 , 12112,24 , 15622,48 , 15670,81 , 12112,24 , 8309,28 , 8337,52 , 8389,14 , 8309,28 , 8337,52 , 8389,14 , 243,9 , 243,8 , {66,65,77}, 305,2 , 11795,174 , 13,5 , 4,0 , 3478,6 , 3511,19 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/BosniaAndHerzegowina
- { 100, 2, 242, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 117,7 , 117,7 , 1033,7 , 1040,20 , 159,5 , 164,10 , 15622,48 , 15670,81 , 12112,24 , 15622,48 , 15670,81 , 12112,24 , 8309,28 , 8337,52 , 8389,14 , 8309,28 , 8337,52 , 8389,14 , 243,9 , 243,8 , {69,85,82}, 14,1 , 11969,23 , 13,5 , 4,0 , 3478,6 , 3530,9 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Montenegro
- { 100, 2, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 117,7 , 117,7 , 1033,7 , 1040,20 , 159,5 , 164,10 , 15622,48 , 15670,81 , 12112,24 , 15622,48 , 15670,81 , 12112,24 , 8309,28 , 8337,52 , 8389,14 , 8309,28 , 8337,52 , 8389,14 , 243,9 , 243,8 , {69,85,82}, 14,1 , 11969,23 , 13,5 , 4,0 , 3478,6 , 3539,6 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Kosovo
- { 100, 7, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 175,7 , 175,7 , 1033,7 , 1040,20 , 159,5 , 164,10 , 15751,48 , 15799,81 , 15880,24 , 15751,48 , 15799,81 , 15880,24 , 8403,28 , 8431,54 , 2176,14 , 8403,28 , 8431,54 , 2176,14 , 252,9 , 251,8 , {69,85,82}, 14,1 , 11714,23 , 13,5 , 4,0 , 3490,6 , 3545,6 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Kosovo
- { 101, 2, 81, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 550,9 , 550,9 , 175,8 , 1060,23 , 37,5 , 8,10 , 15904,63 , 15967,82 , 10567,24 , 16049,60 , 16109,86 , 10567,24 , 8485,28 , 8513,61 , 8574,14 , 8588,28 , 8616,61 , 8574,14 , 261,15 , 259,15 , {71,69,76}, 238,1 , 11992,17 , 8,5 , 4,0 , 3551,4 , 3555,11 , 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Georgia
- { 101, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 550,9 , 550,9 , 175,8 , 1060,23 , 37,5 , 8,10 , 15904,63 , 15967,82 , 10567,24 , 16049,60 , 16109,86 , 10567,24 , 8485,28 , 8513,61 , 8574,14 , 8588,28 , 8616,61 , 8574,14 , 261,15 , 259,15 , {82,85,66}, 129,1 , 12009,17 , 8,5 , 4,0 , 3551,4 , 3566,6 , 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Russia
- { 102, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Southern Sotho/Latin/SouthAfrica
- { 103, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tswana/Latin/SouthAfrica
- { 104, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 16195,47 , 16242,100 , 16342,24 , 16195,47 , 16242,100 , 16342,24 , 8677,32 , 8709,55 , 8764,14 , 8677,32 , 8709,55 , 8764,14 , 0,2 , 0,2 , {85,83,68}, 167,3 , 12026,22 , 4,4 , 4,0 , 3572,8 , 1801,8 , 2, 1, 7, 6, 7 }, // Shona/Latin/Zimbabwe
- { 105, 1, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {80,75,82}, 184,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Sindhi/Arabic/Pakistan
- { 106, 32, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 559,9 , 568,8 , 53,10 , 63,17 , 159,5 , 164,10 , 16366,59 , 16425,96 , 16521,32 , 16553,61 , 16425,96 , 16521,32 , 8778,39 , 8817,62 , 8879,19 , 8778,39 , 8817,62 , 8879,19 , 276,5 , 274,4 , {76,75,82}, 307,3 , 12048,58 , 4,4 , 4,0 , 3580,5 , 3585,11 , 2, 1, 1, 6, 7 }, // Sinhala/Sinhala/SriLanka
- { 107, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Swati/Latin/SouthAfrica
- { 108, 7, 191, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 197,7 , 576,7 , 114,6 , 544,18 , 55,4 , 59,9 , 16614,48 , 16662,82 , 15880,24 , 16614,48 , 16744,89 , 15880,24 , 8898,21 , 8919,52 , 8971,14 , 8898,21 , 8919,52 , 8971,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 12106,26 , 13,5 , 4,0 , 3596,10 , 3606,9 , 2, 1, 1, 6, 7 }, // Slovak/Latin/Slovakia
- { 109, 7, 192, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 583,8 , 583,8 , 1083,9 , 1092,19 , 37,5 , 8,10 , 15751,48 , 16833,86 , 15880,24 , 16919,59 , 16833,86 , 15880,24 , 8985,28 , 9013,52 , 9065,14 , 9079,35 , 9013,52 , 9065,14 , 81,4 , 278,4 , {69,85,82}, 14,1 , 12132,28 , 13,5 , 4,0 , 3615,11 , 3626,9 , 2, 1, 1, 6, 7 }, // Slovenian/Latin/Slovenia
- { 110, 7, 194, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1111,19 , 18,7 , 25,12 , 16978,48 , 17026,189 , 17215,24 , 16978,48 , 17026,189 , 17215,24 , 9114,28 , 9142,47 , 9189,14 , 9114,28 , 9142,47 , 9189,14 , 281,3 , 282,3 , {83,79,83}, 100,1 , 12160,22 , 4,4 , 4,0 , 3635,8 , 3643,10 , 0, 0, 1, 6, 7 }, // Somali/Latin/Somalia
- { 110, 7, 59, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1111,19 , 18,7 , 25,12 , 16978,48 , 17026,189 , 17215,24 , 16978,48 , 17026,189 , 17215,24 , 9114,28 , 9142,47 , 9189,14 , 9114,28 , 9142,47 , 9189,14 , 281,3 , 282,3 , {68,74,70}, 43,3 , 12182,21 , 4,4 , 4,0 , 3635,8 , 3653,7 , 0, 0, 6, 6, 7 }, // Somali/Latin/Djibouti
- { 110, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1111,19 , 18,7 , 25,12 , 16978,48 , 17026,189 , 17215,24 , 16978,48 , 17026,189 , 17215,24 , 9114,28 , 9142,47 , 9189,14 , 9114,28 , 9142,47 , 9189,14 , 281,3 , 282,3 , {69,84,66}, 0,2 , 12203,22 , 4,4 , 4,0 , 3635,8 , 3660,8 , 2, 1, 7, 6, 7 }, // Somali/Latin/Ethiopia
- { 110, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1111,19 , 37,5 , 8,10 , 16978,48 , 17026,189 , 17215,24 , 16978,48 , 17026,189 , 17215,24 , 9114,28 , 9142,47 , 9189,14 , 9114,28 , 9142,47 , 9189,14 , 281,3 , 282,3 , {75,69,83}, 2,3 , 0,7 , 4,4 , 4,0 , 3635,8 , 3668,7 , 2, 1, 7, 6, 7 }, // Somali/Latin/Kenya
- { 111, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 55,4 , 345,11 , 17239,61 , 17300,89 , 17389,24 , 17239,61 , 17300,89 , 17389,24 , 9203,35 , 9238,53 , 7871,14 , 9203,35 , 9238,53 , 7871,14 , 74,5 , 72,5 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 3675,17 , 2393,6 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Spain
- { 111, 7, 10, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {65,82,83}, 6,1 , 12225,51 , 8,5 , 4,0 , 3692,7 , 3699,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Argentina
- { 111, 7, 26, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {66,79,66}, 295,2 , 12276,35 , 4,4 , 4,0 , 3692,7 , 3335,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Bolivia
- { 111, 7, 30, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {66,82,76}, 283,2 , 12311,52 , 4,4 , 4,0 , 3692,7 , 3143,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Brazil
- { 111, 7, 43, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 370,8 , 978,27 , 37,5 , 8,10 , 17239,61 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {67,76,80}, 6,1 , 12363,45 , 4,4 , 36,5 , 3692,7 , 3708,5 , 0, 0, 1, 6, 7 }, // Spanish/Latin/Chile
- { 111, 7, 47, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 531,7 , 978,27 , 18,7 , 25,12 , 17239,61 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 9291,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {67,79,80}, 6,1 , 12408,54 , 8,5 , 4,0 , 3692,7 , 3713,8 , 0, 0, 7, 6, 7 }, // Spanish/Latin/Colombia
- { 111, 7, 52, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {67,82,67}, 310,1 , 12462,67 , 4,4 , 4,0 , 3692,7 , 3721,10 , 0, 0, 1, 6, 7 }, // Spanish/Latin/CostaRica
- { 111, 7, 55, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {67,85,80}, 6,1 , 12529,42 , 4,4 , 4,0 , 3692,7 , 3731,4 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Cuba
- { 111, 7, 61, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 18,7 , 25,12 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {68,79,80}, 311,3 , 12571,54 , 4,4 , 66,6 , 3692,7 , 3735,20 , 2, 1, 7, 6, 7 }, // Spanish/Latin/DominicanRepublic
- { 111, 7, 63, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {85,83,68}, 6,1 , 12625,70 , 4,4 , 36,5 , 3692,7 , 3342,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Ecuador
- { 111, 7, 65, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {85,83,68}, 6,1 , 12625,70 , 4,4 , 4,0 , 3692,7 , 3755,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/ElSalvador
- { 111, 7, 66, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 55,4 , 345,11 , 17239,61 , 17300,89 , 17389,24 , 17239,61 , 17300,89 , 17389,24 , 9203,35 , 9238,53 , 7871,14 , 9203,35 , 9238,53 , 7871,14 , 74,5 , 72,5 , {88,65,70}, 32,4 , 12695,53 , 4,4 , 4,0 , 3692,7 , 3766,17 , 0, 0, 1, 6, 7 }, // Spanish/Latin/EquatorialGuinea
- { 111, 7, 90, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 531,7 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {71,84,81}, 314,1 , 12748,30 , 18,5 , 4,0 , 3692,7 , 3783,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Guatemala
- { 111, 7, 96, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 1130,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {72,78,76}, 300,1 , 12778,60 , 4,4 , 4,0 , 3692,7 , 3792,8 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Honduras
- { 111, 7, 139, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 27,8 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17497,48 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 3068,14 , 85,4 , 83,4 , {77,88,78}, 6,1 , 12838,48 , 4,4 , 4,0 , 3800,17 , 3817,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Mexico
- { 111, 7, 155, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {78,73,79}, 315,2 , 12886,69 , 4,4 , 4,0 , 3692,7 , 3823,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Nicaragua
- { 111, 7, 166, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 1157,8 , 978,27 , 18,7 , 25,12 , 17413,60 , 17300,89 , 17389,24 , 17413,60 , 17300,89 , 17389,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {80,65,66}, 317,3 , 12955,54 , 4,4 , 4,0 , 3692,7 , 3832,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Panama
- { 111, 7, 168, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17239,61 , 17300,89 , 17473,24 , 17239,61 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {80,89,71}, 320,3 , 13009,61 , 8,5 , 23,6 , 3692,7 , 3838,8 , 0, 0, 7, 6, 7 }, // Spanish/Latin/Paraguay
- { 111, 7, 169, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 531,7 , 978,27 , 37,5 , 8,10 , 17545,60 , 17605,88 , 17473,24 , 17693,60 , 17753,88 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {80,69,78}, 292,3 , 13070,62 , 4,4 , 4,0 , 3692,7 , 3331,4 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Peru
- { 111, 7, 170, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 18,7 , 25,12 , 17239,61 , 17300,89 , 17389,24 , 17239,61 , 17300,89 , 17389,24 , 9203,35 , 9238,53 , 7871,14 , 9203,35 , 9238,53 , 7871,14 , 74,5 , 72,5 , {80,72,80}, 187,1 , 13132,48 , 13,5 , 4,0 , 3692,7 , 3846,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Philippines
- { 111, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 1157,8 , 978,27 , 18,7 , 25,12 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {85,83,68}, 6,1 , 12625,70 , 4,4 , 4,0 , 3692,7 , 1447,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/PuertoRico
- { 111, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 18,7 , 25,12 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 12625,70 , 4,4 , 4,0 , 3692,7 , 3855,14 , 2, 1, 7, 6, 7 }, // Spanish/Latin/UnitedStates
- { 111, 7, 227, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17545,60 , 17605,88 , 17473,24 , 17693,60 , 17753,88 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {85,89,85}, 6,1 , 13180,48 , 8,5 , 4,0 , 3692,7 , 3869,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Uruguay
- { 111, 7, 231, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 18,7 , 25,12 , 17239,61 , 17300,89 , 17473,24 , 17239,61 , 17300,89 , 17389,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 74,5 , 72,5 , {86,69,70}, 323,3 , 13228,64 , 4,4 , 36,5 , 3692,7 , 3876,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Venezuela
- { 111, 7, 238, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 55,4 , 345,11 , 17239,61 , 17300,89 , 17389,24 , 17239,61 , 17300,89 , 17389,24 , 9203,35 , 9238,53 , 7871,14 , 9203,35 , 9238,53 , 7871,14 , 74,5 , 72,5 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 3692,7 , 3885,8 , 2, 1, 1, 6, 7 }, // Spanish/Latin/CanaryIslands
- { 111, 7, 246, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 37,5 , 8,10 , 17413,60 , 17300,89 , 17473,24 , 17413,60 , 17300,89 , 17473,24 , 9203,35 , 9238,53 , 3068,14 , 9203,35 , 9238,53 , 9291,14 , 85,4 , 83,4 , {0,0,0}, 0,0 , 13292,0 , 4,4 , 4,0 , 3893,23 , 3916,13 , 2, 1, 1, 6, 7 }, // Spanish/Latin/LatinAmericaAndTheCaribbean
- { 111, 7, 250, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 978,27 , 55,4 , 345,11 , 17239,61 , 17300,89 , 17389,24 , 17239,61 , 17300,89 , 17389,24 , 9203,35 , 9238,53 , 7871,14 , 9203,35 , 9238,53 , 7871,14 , 74,5 , 72,5 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 3692,7 , 3929,15 , 2, 1, 1, 6, 7 }, // Spanish/Latin/CeutaAndMelilla
- { 113, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 598,8 , 598,8 , 120,10 , 10,17 , 37,5 , 8,10 , 17841,48 , 17889,84 , 134,24 , 17841,48 , 17889,84 , 134,24 , 9305,60 , 9305,60 , 85,14 , 9305,60 , 9305,60 , 85,14 , 0,2 , 0,2 , {84,90,83}, 200,3 , 13292,67 , 4,4 , 4,0 , 3944,9 , 1626,8 , 0, 0, 1, 6, 7 }, // Swahili/Latin/Tanzania
- { 113, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 598,8 , 598,8 , 439,8 , 98,16 , 37,5 , 8,10 , 17841,48 , 17889,84 , 17973,24 , 17997,48 , 18045,188 , 134,24 , 9305,60 , 9305,60 , 9365,14 , 9379,28 , 9407,93 , 85,14 , 284,10 , 285,10 , {67,68,70}, 217,2 , 13359,55 , 4,4 , 4,0 , 3953,18 , 3971,32 , 2, 1, 1, 6, 7 }, // Swahili/Latin/CongoKinshasa
- { 113, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 598,8 , 598,8 , 120,10 , 10,17 , 37,5 , 8,10 , 17841,48 , 17889,84 , 134,24 , 17841,48 , 17889,84 , 134,24 , 9305,60 , 9305,60 , 85,14 , 9305,60 , 9305,60 , 85,14 , 0,2 , 0,2 , {75,69,83}, 2,3 , 13414,58 , 4,4 , 4,0 , 3944,9 , 1192,5 , 2, 1, 7, 6, 7 }, // Swahili/Latin/Kenya
- { 113, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 598,8 , 598,8 , 120,10 , 10,17 , 37,5 , 8,10 , 17841,48 , 17889,84 , 134,24 , 17841,48 , 17889,84 , 134,24 , 9305,60 , 9305,60 , 85,14 , 9305,60 , 9305,60 , 85,14 , 0,2 , 0,2 , {85,71,88}, 205,3 , 13472,61 , 4,4 , 4,0 , 3944,9 , 1691,6 , 0, 0, 1, 6, 7 }, // Swahili/Latin/Uganda
- { 114, 7, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 606,9 , 606,9 , 53,10 , 98,16 , 37,5 , 356,16 , 18233,59 , 18292,86 , 134,24 , 18233,59 , 18292,86 , 134,24 , 9500,29 , 9529,50 , 2367,14 , 9500,29 , 9529,50 , 2367,14 , 294,2 , 295,2 , {83,69,75}, 198,2 , 13533,45 , 13,5 , 4,0 , 4003,7 , 4010,7 , 2, 1, 1, 6, 7 }, // Swedish/Latin/Sweden
- { 114, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 606,9 , 606,9 , 1165,10 , 98,16 , 37,5 , 356,16 , 18233,59 , 18292,86 , 134,24 , 18233,59 , 18292,86 , 134,24 , 9500,29 , 9529,50 , 2367,14 , 9500,29 , 9529,50 , 2367,14 , 294,2 , 295,2 , {69,85,82}, 14,1 , 8915,19 , 13,5 , 4,0 , 4003,7 , 1089,7 , 2, 1, 1, 6, 7 }, // Swedish/Latin/Finland
- { 114, 7, 248, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 606,9 , 606,9 , 53,10 , 98,16 , 37,5 , 356,16 , 18233,59 , 18292,86 , 134,24 , 18233,59 , 18292,86 , 134,24 , 9500,29 , 9529,50 , 2367,14 , 9500,29 , 9529,50 , 2367,14 , 294,2 , 295,2 , {69,85,82}, 14,1 , 8915,19 , 13,5 , 4,0 , 4003,7 , 4017,5 , 2, 1, 1, 6, 7 }, // Swedish/Latin/AlandIslands
- { 116, 2, 209, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {84,74,83}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tajik/Cyrillic/Tajikistan
- { 117, 27, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 615,13 , 615,13 , 300,6 , 210,18 , 301,7 , 372,12 , 18378,58 , 18436,86 , 18522,31 , 18378,58 , 18553,86 , 18522,31 , 9579,39 , 9618,49 , 9667,20 , 9579,39 , 9618,49 , 9667,20 , 296,8 , 297,8 , {73,78,82}, 127,1 , 13578,49 , 8,5 , 4,0 , 4022,5 , 4027,7 , 2, 1, 7, 7, 7 }, // Tamil/Tamil/India
- { 117, 27, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 615,13 , 615,13 , 300,6 , 210,18 , 301,7 , 372,12 , 18378,58 , 18436,86 , 18522,31 , 18378,58 , 18553,86 , 18522,31 , 9579,39 , 9618,49 , 9667,20 , 9579,39 , 9618,49 , 9667,20 , 296,8 , 297,8 , {77,89,82}, 182,2 , 13627,61 , 8,5 , 4,0 , 4022,5 , 4034,7 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/Malaysia
- { 117, 27, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 615,13 , 615,13 , 300,6 , 210,18 , 301,7 , 372,12 , 18378,58 , 18436,86 , 18522,31 , 18378,58 , 18553,86 , 18522,31 , 9579,39 , 9618,49 , 9667,20 , 9579,39 , 9618,49 , 9667,20 , 296,8 , 297,8 , {83,71,68}, 6,1 , 13688,61 , 8,5 , 4,0 , 4022,5 , 4041,11 , 2, 1, 7, 6, 7 }, // Tamil/Tamil/Singapore
- { 117, 27, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 615,13 , 615,13 , 300,6 , 210,18 , 37,5 , 8,10 , 18378,58 , 18436,86 , 18522,31 , 18378,58 , 18553,86 , 18522,31 , 9579,39 , 9618,49 , 9667,20 , 9579,39 , 9618,49 , 9667,20 , 296,8 , 297,8 , {76,75,82}, 326,3 , 13749,49 , 8,5 , 4,0 , 4022,5 , 4052,6 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/SriLanka
- { 118, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {82,85,66}, 129,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tatar/Cyrillic/Russia
- { 119, 28, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 628,11 , 628,11 , 370,8 , 1175,18 , 18,7 , 25,12 , 18639,66 , 18705,86 , 18791,31 , 18822,62 , 18705,86 , 18791,31 , 9687,32 , 9719,60 , 9779,18 , 9687,32 , 9719,60 , 9779,18 , 304,4 , 305,4 , {73,78,82}, 127,1 , 13798,26 , 4,4 , 4,0 , 4058,6 , 4064,9 , 2, 1, 7, 7, 7 }, // Telugu/Telugu/India
- { 120, 30, 211, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 639,5 , 639,5 , 644,8 , 652,7 , 300,6 , 1193,19 , 37,5 , 384,28 , 18884,63 , 18947,98 , 18884,63 , 18884,63 , 18947,98 , 18884,63 , 9797,23 , 9820,68 , 9888,16 , 9797,23 , 9820,68 , 9888,16 , 308,10 , 309,10 , {84,72,66}, 329,3 , 13824,19 , 4,4 , 4,0 , 4073,3 , 4073,3 , 2, 1, 7, 6, 7 }, // Thai/Thai/Thailand
- { 121, 31, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1212,23 , 18,7 , 25,12 , 2660,63 , 19045,159 , 158,27 , 2660,63 , 19204,147 , 158,27 , 9904,51 , 9955,79 , 10034,27 , 9904,51 , 9955,79 , 10034,27 , 318,7 , 319,8 , {67,78,89}, 332,1 , 13843,13 , 8,5 , 4,0 , 4076,8 , 4084,6 , 2, 1, 7, 6, 7 }, // Tibetan/Tibetan/China
- { 121, 31, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1212,23 , 18,7 , 25,12 , 2660,63 , 19045,159 , 158,27 , 2660,63 , 19204,147 , 158,27 , 9904,51 , 9955,79 , 10034,27 , 9904,51 , 9955,79 , 10034,27 , 318,7 , 319,8 , {73,78,82}, 127,1 , 13856,19 , 8,5 , 4,0 , 4076,8 , 4090,7 , 2, 1, 7, 7, 7 }, // Tibetan/Tibetan/India
- { 122, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1235,23 , 18,7 , 25,12 , 19351,46 , 19397,62 , 878,24 , 19351,46 , 19397,62 , 878,24 , 10061,29 , 10061,29 , 10090,14 , 10061,29 , 10061,29 , 10090,14 , 325,7 , 327,7 , {69,84,66}, 0,2 , 13875,16 , 4,4 , 4,0 , 4097,4 , 82,5 , 2, 1, 7, 6, 7 }, // Tigrinya/Ethiopic/Ethiopia
- { 122, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1258,23 , 18,7 , 25,12 , 19459,46 , 19505,54 , 878,24 , 19459,46 , 19505,54 , 878,24 , 10104,29 , 10104,29 , 10090,14 , 10104,29 , 10104,29 , 10090,14 , 325,7 , 327,7 , {69,82,78}, 46,3 , 0,7 , 4,4 , 4,0 , 4097,4 , 4101,4 , 2, 1, 1, 6, 7 }, // Tigrinya/Ethiopic/Eritrea
- { 123, 7, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 659,8 , 659,8 , 659,8 , 659,8 , 300,6 , 98,16 , 18,7 , 25,12 , 19559,51 , 19610,87 , 19697,24 , 19559,51 , 19610,87 , 19697,24 , 10133,29 , 10162,60 , 10222,14 , 10133,29 , 10162,60 , 10222,14 , 0,2 , 0,2 , {84,79,80}, 203,2 , 13891,41 , 8,5 , 4,0 , 4105,13 , 1641,5 , 2, 1, 1, 6, 7 }, // Tongan/Latin/Tonga
- { 124, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tsonga/Latin/SouthAfrica
- { 125, 7, 217, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 667,8 , 667,8 , 1281,9 , 1290,16 , 37,5 , 8,10 , 19721,48 , 19769,75 , 19844,24 , 19721,48 , 19769,75 , 19844,24 , 10236,28 , 10264,54 , 10318,14 , 10236,28 , 10264,54 , 10318,14 , 332,2 , 334,2 , {84,82,89}, 258,1 , 13932,40 , 13,5 , 4,0 , 4118,6 , 4124,7 , 2, 1, 1, 6, 7 }, // Turkish/Latin/Turkey
- { 125, 7, 56, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 667,8 , 667,8 , 1281,9 , 1290,16 , 18,7 , 25,12 , 19721,48 , 19769,75 , 19844,24 , 19721,48 , 19769,75 , 19844,24 , 10236,28 , 10264,54 , 10318,14 , 10236,28 , 10264,54 , 10318,14 , 332,2 , 334,2 , {69,85,82}, 14,1 , 8402,19 , 13,5 , 4,0 , 4118,6 , 4131,6 , 2, 1, 1, 6, 7 }, // Turkish/Latin/Cyprus
- { 126, 7, 218, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8220, 8221, 0,6 , 0,6 , 675,8 , 675,8 , 942,10 , 1290,16 , 37,5 , 8,10 , 19868,51 , 19919,77 , 19996,24 , 19868,51 , 19919,77 , 19996,24 , 10332,21 , 10353,54 , 10407,14 , 10332,21 , 10353,54 , 10407,14 , 0,2 , 0,2 , {84,77,84}, 333,3 , 13972,49 , 13,5 , 4,0 , 4137,9 , 4146,12 , 2, 1, 1, 6, 7 }, // Turkmen/Latin/Turkmenistan
- { 128, 1, 44, 46, 44, 59, 37, 48, 45, 43, 101, 187, 171, 8250, 8249, 0,6 , 0,6 , 212,10 , 222,9 , 538,6 , 1306,18 , 18,7 , 25,12 , 20020,84 , 20020,84 , 158,27 , 20020,84 , 20020,84 , 158,27 , 10421,21 , 10442,55 , 10497,14 , 10421,21 , 10442,55 , 10497,14 , 334,12 , 336,12 , {67,78,89}, 141,1 , 14021,40 , 4,4 , 4,0 , 4158,8 , 4166,5 , 2, 1, 7, 6, 7 }, // Uighur/Arabic/China
- { 129, 2, 222, 44, 160, 59, 37, 48, 45, 43, 1077, 171, 187, 8222, 8220, 0,6 , 0,6 , 150,7 , 150,7 , 175,8 , 1324,22 , 37,5 , 8,10 , 20104,48 , 20152,95 , 20247,24 , 20271,67 , 20338,87 , 20247,24 , 10511,21 , 10532,56 , 10588,14 , 10511,21 , 10532,56 , 10588,14 , 346,2 , 348,2 , {85,65,72}, 301,1 , 14061,49 , 13,5 , 4,0 , 4171,10 , 4181,7 , 2, 1, 1, 6, 7 }, // Ukrainian/Cyrillic/Ukraine
- { 130, 1, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 683,10 , 693,9 , 300,6 , 157,18 , 18,7 , 25,12 , 20425,68 , 20425,68 , 134,24 , 20425,68 , 20425,68 , 134,24 , 10602,39 , 10602,39 , 85,14 , 10602,39 , 10602,39 , 85,14 , 348,9 , 350,9 , {80,75,82}, 184,2 , 14110,49 , 8,5 , 4,0 , 4188,4 , 4192,7 , 0, 0, 7, 6, 7 }, // Urdu/Arabic/Pakistan
- { 130, 1, 100, 46, 44, 59, 37, 1776, 45, 43, 1602, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 702,6 , 702,6 , 300,6 , 157,18 , 18,7 , 25,12 , 20425,68 , 20425,68 , 134,24 , 20425,68 , 20425,68 , 134,24 , 10602,39 , 10602,39 , 85,14 , 10602,39 , 10602,39 , 85,14 , 348,9 , 350,9 , {73,78,82}, 127,1 , 14159,42 , 8,5 , 4,0 , 4188,4 , 4199,5 , 2, 1, 7, 7, 7 }, // Urdu/Arabic/India
- { 131, 7, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8217, 8216, 0,6 , 0,6 , 708,8 , 708,8 , 27,8 , 715,18 , 37,5 , 345,11 , 20493,52 , 20545,75 , 20620,24 , 20644,48 , 20692,75 , 20620,24 , 10641,21 , 10662,61 , 10723,14 , 10641,21 , 10662,61 , 10723,14 , 357,2 , 359,2 , {85,90,83}, 336,4 , 14201,58 , 8,5 , 4,0 , 4204,6 , 4210,11 , 0, 0, 1, 6, 7 }, // Uzbek/Latin/Uzbekistan
- { 131, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 418,8 , 1346,33 , 55,4 , 345,11 , 20767,47 , 14026,68 , 158,27 , 20767,47 , 14026,68 , 158,27 , 10737,21 , 7297,49 , 85,14 , 10737,21 , 7297,49 , 85,14 , 0,2 , 0,2 , {65,70,78}, 276,1 , 14259,13 , 13,5 , 4,0 , 4221,6 , 3090,9 , 0, 0, 6, 4, 5 }, // Uzbek/Arabic/Afghanistan
- { 131, 2, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 715,18 , 37,5 , 8,10 , 10439,48 , 20814,71 , 10567,24 , 10439,48 , 20814,71 , 10567,24 , 10758,28 , 10786,53 , 10839,14 , 10758,28 , 10786,53 , 10839,14 , 0,2 , 0,2 , {85,90,83}, 340,3 , 14272,49 , 8,5 , 4,0 , 4227,5 , 4232,10 , 0, 0, 1, 6, 7 }, // Uzbek/Cyrillic/Uzbekistan
- { 132, 7, 232, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 716,8 , 716,8 , 120,10 , 1379,31 , 37,5 , 8,10 , 20885,75 , 20960,99 , 158,27 , 21059,75 , 21134,99 , 158,27 , 10853,33 , 10886,55 , 10941,21 , 10853,33 , 10886,55 , 10941,21 , 359,2 , 361,2 , {86,78,68}, 343,1 , 14321,33 , 8,5 , 4,0 , 4242,10 , 4252,8 , 0, 0, 1, 6, 7 }, // Vietnamese/Latin/Vietnam
- { 134, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 10,17 , 37,5 , 8,10 , 21233,52 , 21285,87 , 21372,26 , 21398,59 , 21285,87 , 21372,26 , 10962,29 , 10991,77 , 11068,15 , 11083,30 , 10991,77 , 11068,15 , 0,2 , 0,2 , {71,66,80}, 125,1 , 14354,92 , 4,4 , 4,0 , 4260,7 , 4267,16 , 2, 1, 1, 6, 7 }, // Welsh/Latin/UnitedKingdom
- { 135, 7, 187, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Wolof/Latin/Senegal
- { 136, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Xhosa/Latin/SouthAfrica
- { 138, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 21457,73 , 21530,121 , 158,27 , 21457,73 , 21530,121 , 158,27 , 11113,44 , 11157,69 , 85,14 , 11113,44 , 11157,69 , 85,14 , 361,5 , 363,5 , {78,71,78}, 186,1 , 14446,34 , 4,4 , 4,0 , 4283,10 , 4293,18 , 2, 1, 1, 6, 7 }, // Yoruba/Latin/Nigeria
- { 138, 7, 23, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 21651,74 , 21725,134 , 158,27 , 21651,74 , 21725,134 , 158,27 , 11226,44 , 11270,69 , 85,14 , 11226,44 , 11270,69 , 85,14 , 366,5 , 368,5 , {88,79,70}, 212,3 , 14480,34 , 4,4 , 4,0 , 4283,10 , 4311,16 , 0, 0, 1, 6, 7 }, // Yoruba/Latin/Benin
- { 140, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 724,9 , 733,10 , 538,6 , 35,18 , 18,7 , 25,12 , 21859,48 , 21907,91 , 134,24 , 21859,48 , 21907,91 , 21998,24 , 11339,28 , 11367,74 , 11441,14 , 11339,28 , 11367,74 , 11441,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 14514,67 , 4,4 , 4,0 , 4327,7 , 4334,14 , 2, 1, 7, 6, 7 }, // Zulu/Latin/SouthAfrica
- { 141, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 204,8 , 204,8 , 942,10 , 491,17 , 159,5 , 412,16 , 5499,48 , 13503,83 , 134,24 , 22022,59 , 13503,83 , 134,24 , 11455,28 , 11483,51 , 2367,14 , 11534,28 , 11483,51 , 2367,14 , 371,9 , 373,11 , {78,79,75}, 198,2 , 14581,42 , 13,5 , 4,0 , 4348,7 , 4355,5 , 2, 1, 1, 6, 7 }, // NorwegianNynorsk/Latin/Norway
- { 142, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8217, 0,6 , 0,6 , 175,7 , 175,7 , 1410,9 , 1040,20 , 37,5 , 8,10 , 4928,48 , 22081,83 , 15880,24 , 4928,48 , 22081,83 , 15880,24 , 2090,28 , 2118,58 , 2176,14 , 2090,28 , 2118,58 , 2190,14 , 380,11 , 384,7 , {66,65,77}, 152,2 , 14623,174 , 13,5 , 4,0 , 4360,8 , 614,19 , 2, 1, 1, 6, 7 }, // Bosnian/Latin/BosniaAndHerzegowina
- { 142, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 117,7 , 117,7 , 1033,7 , 1040,20 , 37,5 , 8,10 , 15622,48 , 22164,83 , 12112,24 , 15622,48 , 22164,83 , 12112,24 , 11562,28 , 11590,54 , 8389,14 , 11562,28 , 11590,54 , 8389,14 , 243,9 , 391,7 , {66,65,77}, 305,2 , 14797,151 , 13,5 , 4,0 , 4368,8 , 3511,19 , 2, 1, 1, 6, 7 }, // Bosnian/Cyrillic/BosniaAndHerzegowina
- { 143, 29, 131, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {77,86,82}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 5, 6, 7 }, // Divehi/Thaana/Maldives
- { 144, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 599,17 , 37,5 , 8,10 , 22247,102 , 22349,140 , 158,27 , 22247,102 , 22349,140 , 158,27 , 11644,30 , 11674,57 , 85,14 , 11644,30 , 11674,57 , 85,14 , 85,4 , 83,4 , {71,66,80}, 125,1 , 0,7 , 4,4 , 4,0 , 4376,5 , 4381,12 , 2, 1, 1, 6, 7 }, // Manx/Latin/IsleOfMan
- { 145, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 98,16 , 37,5 , 8,10 , 22489,46 , 22535,130 , 158,27 , 22489,46 , 22535,130 , 158,27 , 11731,28 , 11759,61 , 85,14 , 11731,28 , 11759,61 , 85,14 , 85,4 , 83,4 , {71,66,80}, 125,1 , 0,7 , 4,4 , 4,0 , 4393,8 , 4401,14 , 2, 1, 1, 6, 7 }, // Cornish/Latin/UnitedKingdom
- { 146, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 707,8 , 715,18 , 18,7 , 25,12 , 22665,48 , 22713,192 , 158,27 , 22665,48 , 22713,192 , 158,27 , 11820,28 , 11848,49 , 11897,14 , 11820,28 , 11848,49 , 11897,14 , 391,2 , 398,2 , {71,72,83}, 175,3 , 14948,17 , 4,4 , 4,0 , 4415,4 , 4419,5 , 2, 1, 1, 6, 7 }, // Akan/Latin/Ghana
- { 147, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 952,6 , 98,16 , 18,7 , 25,12 , 22905,87 , 22905,87 , 158,27 , 22905,87 , 22905,87 , 158,27 , 6938,32 , 11911,55 , 85,14 , 6938,32 , 11911,55 , 85,14 , 205,5 , 400,5 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 4424,6 , 2621,4 , 2, 1, 7, 7, 7 }, // Konkani/Devanagari/India
- { 148, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {71,72,83}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Ga/Latin/Ghana
- { 149, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 22992,48 , 23040,86 , 158,27 , 22992,48 , 23040,86 , 158,27 , 11966,29 , 11995,57 , 85,14 , 11966,29 , 11995,57 , 85,14 , 45,4 , 405,4 , {78,71,78}, 186,1 , 14965,12 , 4,4 , 4,0 , 4430,4 , 1342,7 , 2, 1, 1, 6, 7 }, // Igbo/Latin/Nigeria
- { 150, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 23126,48 , 23174,189 , 23363,24 , 23126,48 , 23174,189 , 23363,24 , 12052,28 , 12080,74 , 12154,14 , 12052,28 , 12080,74 , 12154,14 , 393,9 , 409,7 , {75,69,83}, 2,3 , 14977,23 , 4,4 , 4,0 , 4434,7 , 1192,5 , 2, 1, 7, 6, 7 }, // Kamba/Latin/Kenya
- { 151, 33, 103, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {73,81,68}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 6, 5, 6 }, // Syriac/Syriac/Iraq
- { 152, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,82,78}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Blin/Ethiopic/Eritrea
- { 153, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Geez/Ethiopic/Ethiopia
- { 155, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Sidamo/Latin/Ethiopia
- { 156, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {78,71,78}, 186,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Atsam/Latin/Nigeria
- { 157, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,82,78}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tigre/Ethiopic/Eritrea
- { 158, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {78,71,78}, 186,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Jju/Latin/Nigeria
- { 159, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 257,7 , 257,7 , 27,8 , 1419,27 , 37,5 , 8,10 , 23387,48 , 23435,77 , 23512,24 , 23387,48 , 23435,77 , 23512,24 , 12168,28 , 12196,50 , 3068,14 , 12168,28 , 12196,50 , 3068,14 , 402,2 , 416,2 , {69,85,82}, 14,1 , 3120,20 , 8,5 , 4,0 , 4441,6 , 4447,6 , 2, 1, 1, 6, 7 }, // Friulian/Latin/Italy
- { 160, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Venda/Latin/SouthAfrica
- { 161, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 743,11 , 754,10 , 538,6 , 1446,23 , 428,12 , 440,17 , 23536,48 , 23584,87 , 23671,24 , 23536,48 , 23584,87 , 23671,24 , 12246,28 , 12274,44 , 12318,14 , 12246,28 , 12274,44 , 12318,14 , 404,3 , 418,5 , {71,72,83}, 175,3 , 15000,37 , 4,4 , 4,0 , 4453,6 , 4459,12 , 2, 1, 1, 6, 7 }, // Ewe/Latin/Ghana
- { 161, 7, 212, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 743,11 , 754,10 , 538,6 , 1446,23 , 37,5 , 8,10 , 23536,48 , 23584,87 , 23671,24 , 23536,48 , 23584,87 , 23671,24 , 12246,28 , 12274,44 , 12318,14 , 12246,28 , 12274,44 , 12318,14 , 404,3 , 418,5 , {88,79,70}, 212,3 , 15037,106 , 4,4 , 4,0 , 4453,6 , 4471,11 , 0, 0, 1, 6, 7 }, // Ewe/Latin/Togo
- { 162, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Walamo/Ethiopic/Ethiopia
- { 163, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 300,6 , 10,17 , 18,7 , 25,12 , 23695,59 , 23754,95 , 158,27 , 23695,59 , 23754,95 , 158,27 , 12332,21 , 12353,57 , 85,14 , 12332,21 , 12353,57 , 85,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 0,7 , 4,4 , 4,0 , 4482,14 , 4496,19 , 2, 1, 7, 6, 7 }, // Hawaiian/Latin/UnitedStates
- { 164, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {78,71,78}, 186,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tyap/Latin/Nigeria
- { 165, 7, 129, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {77,87,75}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Nyanja/Latin/Malawi
- { 166, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 764,9 , 773,8 , 538,6 , 35,18 , 18,7 , 25,12 , 23849,48 , 23897,88 , 23985,38 , 23849,48 , 23897,88 , 23849,48 , 12410,28 , 12438,55 , 12410,28 , 12410,28 , 12438,55 , 12410,28 , 0,2 , 0,2 , {80,72,80}, 187,1 , 15143,58 , 4,4 , 4,0 , 4515,8 , 4523,9 , 2, 1, 7, 6, 7 }, // Filipino/Latin/Philippines
- { 167, 7, 206, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 272,9 , 272,9 , 175,8 , 544,18 , 37,5 , 8,10 , 7287,48 , 24023,86 , 134,24 , 7287,48 , 24023,86 , 134,24 , 12493,28 , 12521,63 , 3622,14 , 12493,28 , 12521,63 , 3622,14 , 95,5 , 423,4 , {67,72,70}, 231,3 , 15201,55 , 13,5 , 4,0 , 4532,16 , 4548,7 , 2, 0, 1, 6, 7 }, // Swiss German/Latin/Switzerland
- { 167, 7, 74, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 272,9 , 272,9 , 175,8 , 544,18 , 37,5 , 8,10 , 7287,48 , 24023,86 , 134,24 , 7287,48 , 24023,86 , 134,24 , 12493,28 , 12521,63 , 3622,14 , 12493,28 , 12521,63 , 3622,14 , 95,5 , 423,4 , {69,85,82}, 14,1 , 8402,19 , 13,5 , 4,0 , 4532,16 , 4555,10 , 2, 1, 1, 6, 7 }, // Swiss German/Latin/France
- { 167, 7, 123, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 272,9 , 272,9 , 175,8 , 544,18 , 37,5 , 8,10 , 7287,48 , 24023,86 , 134,24 , 7287,48 , 24023,86 , 134,24 , 12493,28 , 12521,63 , 3622,14 , 12493,28 , 12521,63 , 3622,14 , 95,5 , 423,4 , {67,72,70}, 231,3 , 15201,55 , 13,5 , 4,0 , 4532,16 , 4565,13 , 2, 0, 1, 6, 7 }, // Swiss German/Latin/Liechtenstein
- { 168, 34, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 158,27 , 24109,38 , 158,27 , 158,27 , 24109,38 , 158,27 , 12584,21 , 12605,28 , 12633,14 , 12584,21 , 12605,28 , 12633,14 , 407,2 , 427,2 , {67,78,89}, 332,1 , 0,7 , 55,6 , 4,0 , 4578,3 , 4581,2 , 2, 1, 7, 6, 7 }, // Sichuan Yi/Yi/China
- { 169, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {76,82,68}, 6,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Kpelle/Latin/Liberia
- { 170, 7, 82, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Low German/Latin/Germany
- { 171, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // South Ndebele/Latin/SouthAfrica
- { 172, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Northern Sotho/Latin/SouthAfrica
- { 173, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 231,8 , 231,8 , 53,10 , 63,17 , 37,5 , 8,10 , 24147,59 , 24206,145 , 24351,24 , 24147,59 , 24206,145 , 24351,24 , 12647,33 , 12680,75 , 12755,14 , 12647,33 , 12680,75 , 12755,14 , 409,11 , 429,13 , {78,79,75}, 198,2 , 15256,63 , 13,5 , 4,0 , 4583,15 , 4598,5 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Norway
- { 173, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 231,8 , 231,8 , 53,10 , 63,17 , 37,5 , 8,10 , 24375,85 , 24206,145 , 24351,24 , 24375,85 , 24206,145 , 24351,24 , 12647,33 , 12769,65 , 12834,14 , 12647,33 , 12769,65 , 12834,14 , 409,11 , 429,13 , {69,85,82}, 14,1 , 15319,23 , 13,5 , 4,0 , 4583,15 , 4603,6 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Finland
- { 173, 7, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 231,8 , 231,8 , 53,10 , 63,17 , 37,5 , 8,10 , 24147,59 , 24206,145 , 24351,24 , 24147,59 , 24206,145 , 24351,24 , 12647,33 , 12680,75 , 12755,14 , 12647,33 , 12680,75 , 12755,14 , 409,11 , 429,13 , {83,69,75}, 198,2 , 15342,63 , 13,5 , 4,0 , 4583,15 , 4609,6 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Sweden
- { 174, 7, 208, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {84,87,68}, 344,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Taroko/Latin/Taiwan
- { 175, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 24460,48 , 24508,88 , 24596,24 , 24460,48 , 24508,88 , 24596,24 , 12848,28 , 12876,62 , 12938,14 , 12848,28 , 12876,62 , 12938,14 , 420,6 , 442,3 , {75,69,83}, 2,3 , 15405,24 , 4,4 , 4,0 , 4615,8 , 1192,5 , 2, 1, 7, 6, 7 }, // Gusii/Latin/Kenya
- { 176, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 24620,48 , 24668,221 , 24889,24 , 24620,48 , 24668,221 , 24889,24 , 12952,28 , 12980,105 , 13085,14 , 12952,28 , 12980,105 , 13085,14 , 426,10 , 445,10 , {75,69,83}, 2,3 , 15405,24 , 4,4 , 4,0 , 4623,7 , 1192,5 , 2, 1, 7, 6, 7 }, // Taita/Latin/Kenya
- { 177, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 24913,48 , 24961,77 , 25038,24 , 24913,48 , 24961,77 , 25038,24 , 13099,28 , 13127,59 , 13186,14 , 13099,28 , 13127,59 , 13186,14 , 436,6 , 455,7 , {88,79,70}, 212,3 , 15429,26 , 13,5 , 4,0 , 4630,6 , 4636,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Senegal
- { 177, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 24913,48 , 24961,77 , 25038,24 , 24913,48 , 24961,77 , 25038,24 , 13099,28 , 13127,59 , 13186,14 , 13099,28 , 13127,59 , 13186,14 , 436,6 , 455,7 , {88,65,70}, 32,4 , 15455,25 , 13,5 , 4,0 , 4630,6 , 4644,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Cameroon
- { 177, 7, 91, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 24913,48 , 24961,77 , 25038,24 , 24913,48 , 24961,77 , 25038,24 , 13099,28 , 13127,59 , 13186,14 , 13099,28 , 13127,59 , 13186,14 , 436,6 , 455,7 , {71,78,70}, 223,2 , 0,7 , 13,5 , 4,0 , 4630,6 , 4652,4 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea
- { 177, 7, 136, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 18,7 , 25,12 , 24913,48 , 24961,77 , 25038,24 , 24913,48 , 24961,77 , 25038,24 , 13099,28 , 13127,59 , 13186,14 , 13099,28 , 13127,59 , 13186,14 , 436,6 , 455,7 , {77,82,79}, 226,2 , 15480,22 , 13,5 , 4,0 , 4630,6 , 4656,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Mauritania
- { 178, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 25062,48 , 25110,185 , 25295,24 , 25062,48 , 25110,185 , 25295,24 , 13200,28 , 13228,63 , 13291,14 , 13200,28 , 13228,63 , 13291,14 , 442,6 , 462,8 , {75,69,83}, 2,3 , 15502,23 , 4,4 , 4,0 , 4664,6 , 1192,5 , 2, 1, 7, 6, 7 }, // Kikuyu/Latin/Kenya
- { 179, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 25319,48 , 25367,173 , 25540,24 , 25319,48 , 25367,173 , 25540,24 , 13305,28 , 13333,105 , 13438,14 , 13305,28 , 13333,105 , 13438,14 , 448,7 , 470,5 , {75,69,83}, 2,3 , 15525,25 , 4,4 , 4,0 , 4670,8 , 1192,5 , 2, 1, 7, 6, 7 }, // Samburu/Latin/Kenya
- { 180, 7, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 978,27 , 37,5 , 8,10 , 25564,48 , 25612,88 , 134,24 , 25564,48 , 25612,88 , 134,24 , 13452,28 , 13480,55 , 13535,14 , 13452,28 , 13480,55 , 13535,14 , 0,2 , 0,2 , {77,90,78}, 286,3 , 15550,28 , 0,4 , 4,0 , 4678,4 , 3242,10 , 2, 1, 7, 6, 7 }, // Sena/Latin/Mozambique
- { 181, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 25700,52 , 25752,112 , 25864,24 , 25700,52 , 25752,112 , 25864,24 , 13549,28 , 13577,50 , 13627,14 , 13549,28 , 13577,50 , 13627,14 , 0,2 , 0,2 , {85,83,68}, 167,3 , 15578,24 , 4,4 , 4,0 , 4682,10 , 1801,8 , 2, 1, 7, 6, 7 }, // North Ndebele/Latin/Zimbabwe
- { 182, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 25888,39 , 25927,194 , 26121,24 , 25888,39 , 25927,194 , 26121,24 , 13641,29 , 13670,65 , 13735,14 , 13641,29 , 13670,65 , 13735,14 , 455,8 , 475,7 , {84,90,83}, 200,3 , 15602,25 , 4,4 , 4,0 , 4692,9 , 1626,8 , 0, 0, 1, 6, 7 }, // Rombo/Latin/Tanzania
- { 183, 9, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 26145,48 , 26193,81 , 26274,24 , 26145,48 , 26193,81 , 26274,24 , 13749,30 , 13779,47 , 85,14 , 13749,30 , 13779,47 , 85,14 , 463,6 , 482,8 , {77,65,68}, 0,0 , 15627,21 , 0,4 , 4,0 , 4701,7 , 4708,6 , 2, 1, 6, 5, 6 }, // Tachelhit/Tifinagh/Morocco
- { 183, 7, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 26298,48 , 26346,81 , 26427,24 , 26298,48 , 26346,81 , 26427,24 , 13826,30 , 13856,48 , 85,14 , 13826,30 , 13856,48 , 85,14 , 469,6 , 490,8 , {77,65,68}, 0,0 , 15648,21 , 0,4 , 4,0 , 4714,10 , 4724,6 , 2, 1, 6, 5, 6 }, // Tachelhit/Latin/Morocco
- { 184, 7, 3, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 18,7 , 25,12 , 26451,48 , 26499,84 , 26583,24 , 26451,48 , 26499,84 , 26583,24 , 13904,30 , 13934,51 , 13985,14 , 13904,30 , 13934,51 , 13985,14 , 475,7 , 498,9 , {68,90,68}, 210,2 , 15669,21 , 0,4 , 4,0 , 4730,9 , 4739,8 , 2, 1, 6, 5, 6 }, // Kabyle/Latin/Algeria
- { 185, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26607,48 , 26655,152 , 134,24 , 26607,48 , 26655,152 , 134,24 , 13999,28 , 14027,74 , 14101,14 , 13999,28 , 14027,74 , 14101,14 , 0,2 , 0,2 , {85,71,88}, 205,3 , 15690,26 , 4,4 , 4,0 , 4747,10 , 1691,6 , 0, 0, 1, 6, 7 }, // Nyankole/Latin/Uganda
- { 186, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26807,48 , 26855,254 , 27109,24 , 26807,48 , 26855,254 , 27109,24 , 14115,28 , 14143,82 , 14225,14 , 14115,28 , 14143,82 , 14225,14 , 482,7 , 507,7 , {84,90,83}, 200,3 , 15716,29 , 0,4 , 4,0 , 4757,6 , 4763,10 , 0, 0, 1, 6, 7 }, // Bena/Latin/Tanzania
- { 187, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 17841,48 , 27133,87 , 134,24 , 17841,48 , 27133,87 , 134,24 , 14239,28 , 14267,62 , 14329,14 , 14239,28 , 14267,62 , 14329,14 , 489,5 , 514,9 , {84,90,83}, 200,3 , 15745,27 , 4,4 , 4,0 , 4773,8 , 1626,8 , 0, 0, 1, 6, 7 }, // Vunjo/Latin/Tanzania
- { 188, 7, 132, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 27220,47 , 27267,92 , 27359,24 , 27220,47 , 27267,92 , 27359,24 , 14343,28 , 14371,44 , 14415,14 , 14343,28 , 14371,44 , 14415,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 15772,24 , 4,4 , 4,0 , 4781,9 , 2145,4 , 0, 0, 1, 6, 7 }, // Bambara/Latin/Mali
- { 188, 75, 132, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Bambara/Nko/Mali
- { 189, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 27383,48 , 27431,207 , 27638,24 , 27383,48 , 27431,207 , 27638,24 , 14429,28 , 14457,64 , 14521,14 , 14429,28 , 14457,64 , 14521,14 , 494,2 , 523,2 , {75,69,83}, 2,3 , 15405,24 , 4,4 , 4,0 , 4790,6 , 1192,5 , 2, 1, 7, 6, 7 }, // Embu/Latin/Kenya
- { 190, 12, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 538,6 , 35,18 , 18,7 , 25,12 , 27662,36 , 27698,58 , 27756,24 , 27662,36 , 27698,58 , 27756,24 , 14535,28 , 14563,49 , 14612,14 , 14535,28 , 14563,49 , 14612,14 , 496,3 , 525,6 , {85,83,68}, 6,1 , 15796,19 , 4,4 , 4,0 , 4796,3 , 4799,4 , 2, 1, 7, 6, 7 }, // Cherokee/Cherokee/UnitedStates
- { 191, 7, 137, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 27780,47 , 27827,68 , 27895,24 , 27780,47 , 27827,68 , 27895,24 , 14626,27 , 14653,48 , 14701,14 , 14626,27 , 14653,48 , 14701,14 , 0,2 , 0,2 , {77,85,82}, 184,2 , 15815,21 , 55,6 , 4,0 , 4803,14 , 4817,5 , 0, 0, 1, 6, 7 }, // Morisyen/Latin/Mauritius
- { 192, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 17841,48 , 27919,264 , 134,24 , 17841,48 , 27919,264 , 134,24 , 14715,28 , 14743,133 , 13735,14 , 14715,28 , 14743,133 , 13735,14 , 499,4 , 531,5 , {84,90,83}, 200,3 , 15745,27 , 4,4 , 4,0 , 4822,10 , 1626,8 , 0, 0, 1, 6, 7 }, // Makonde/Latin/Tanzania
- { 193, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28183,83 , 28266,111 , 28377,24 , 28183,83 , 28266,111 , 28377,24 , 14876,36 , 14912,63 , 14975,14 , 14876,36 , 14912,63 , 14975,14 , 503,3 , 536,3 , {84,90,83}, 200,3 , 15836,29 , 55,6 , 4,0 , 4832,8 , 4840,9 , 0, 0, 1, 6, 7 }, // Langi/Latin/Tanzania
- { 194, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28401,48 , 28449,97 , 134,24 , 28401,48 , 28449,97 , 134,24 , 14989,28 , 15017,66 , 15083,14 , 14989,28 , 15017,66 , 15083,14 , 0,2 , 0,2 , {85,71,88}, 205,3 , 15865,26 , 0,4 , 4,0 , 4849,7 , 4856,7 , 0, 0, 1, 6, 7 }, // Ganda/Latin/Uganda
- { 195, 7, 239, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 28546,48 , 28594,83 , 28677,24 , 28546,48 , 28594,83 , 28677,24 , 15097,80 , 15097,80 , 85,14 , 15097,80 , 15097,80 , 85,14 , 506,8 , 539,7 , {90,77,87}, 137,1 , 0,7 , 4,4 , 4,0 , 4863,9 , 1795,6 , 2, 1, 1, 6, 7 }, // Bemba/Latin/Zambia
- { 196, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 175,7 , 175,7 , 439,8 , 1469,27 , 37,5 , 8,10 , 28701,48 , 28749,85 , 134,24 , 28701,48 , 28749,85 , 134,24 , 15177,28 , 15205,73 , 15278,14 , 15177,28 , 15205,73 , 15292,14 , 89,2 , 87,2 , {67,86,69}, 285,1 , 15891,43 , 13,5 , 4,0 , 4872,12 , 4884,10 , 2, 1, 1, 6, 7 }, // Kabuverdianu/Latin/CapeVerde
- { 197, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28834,48 , 28882,86 , 28968,24 , 28834,48 , 28882,86 , 28968,24 , 15306,28 , 15334,51 , 15385,14 , 15306,28 , 15334,51 , 15385,14 , 514,2 , 546,2 , {75,69,83}, 2,3 , 15405,24 , 4,4 , 4,0 , 4894,6 , 1192,5 , 2, 1, 7, 6, 7 }, // Meru/Latin/Kenya
- { 198, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28992,49 , 29041,121 , 29162,24 , 28992,49 , 29041,121 , 29162,24 , 15399,28 , 15427,53 , 15480,14 , 15399,28 , 15427,53 , 15480,14 , 516,6 , 548,10 , {75,69,83}, 2,3 , 15934,26 , 4,4 , 4,0 , 4900,8 , 4908,12 , 2, 1, 7, 6, 7 }, // Kalenjin/Latin/Kenya
- { 199, 7, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 29186,136 , 134,24 , 0,48 , 29186,136 , 134,24 , 15494,23 , 15517,92 , 15609,14 , 15494,23 , 15517,92 , 15609,14 , 522,7 , 558,5 , {78,65,68}, 6,1 , 15960,22 , 4,4 , 4,0 , 4920,13 , 4933,8 , 2, 1, 1, 6, 7 }, // Nama/Latin/Namibia
- { 200, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 17841,48 , 27133,87 , 134,24 , 17841,48 , 27133,87 , 134,24 , 14239,28 , 14267,62 , 14329,14 , 14239,28 , 14267,62 , 14329,14 , 489,5 , 514,9 , {84,90,83}, 200,3 , 15745,27 , 4,4 , 4,0 , 4941,9 , 1626,8 , 0, 0, 1, 6, 7 }, // Machame/Latin/Tanzania
- { 201, 7, 82, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 430,8 , 430,8 , 1496,10 , 1506,23 , 37,5 , 8,10 , 29322,59 , 29381,87 , 134,24 , 29468,48 , 29381,87 , 134,24 , 15623,28 , 15651,72 , 3622,14 , 15623,28 , 15651,72 , 3622,14 , 529,16 , 563,16 , {69,85,82}, 14,1 , 15982,11 , 13,5 , 4,0 , 4950,6 , 4956,11 , 2, 1, 1, 6, 7 }, // Colognian/Latin/Germany
- { 202, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29516,51 , 29567,132 , 158,27 , 29516,51 , 29567,132 , 158,27 , 14239,28 , 15723,58 , 13735,14 , 14239,28 , 15723,58 , 13735,14 , 545,9 , 579,6 , {75,69,83}, 2,3 , 15993,25 , 4,4 , 4,0 , 4967,3 , 1192,5 , 2, 1, 7, 6, 7 }, // Masai/Latin/Kenya
- { 202, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29516,51 , 29567,132 , 158,27 , 29516,51 , 29567,132 , 158,27 , 14239,28 , 15723,58 , 13735,14 , 14239,28 , 15723,58 , 13735,14 , 545,9 , 579,6 , {84,90,83}, 200,3 , 16018,28 , 4,4 , 4,0 , 4967,3 , 4970,8 , 0, 0, 1, 6, 7 }, // Masai/Latin/Tanzania
- { 203, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28401,48 , 28449,97 , 134,24 , 28401,48 , 28449,97 , 134,24 , 15781,35 , 15816,65 , 15881,14 , 15781,35 , 15816,65 , 15881,14 , 554,6 , 585,6 , {85,71,88}, 205,3 , 15865,26 , 13,5 , 4,0 , 4978,7 , 4856,7 , 0, 0, 1, 6, 7 }, // Soga/Latin/Uganda
- { 204, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29699,48 , 17889,84 , 134,24 , 29699,48 , 17889,84 , 134,24 , 15895,21 , 15916,75 , 85,14 , 15895,21 , 15916,75 , 85,14 , 85,4 , 83,4 , {75,69,83}, 2,3 , 16046,23 , 4,4 , 72,6 , 4985,7 , 1192,5 , 2, 1, 7, 6, 7 }, // Luyia/Latin/Kenya
- { 205, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29747,48 , 17889,84 , 134,24 , 29747,48 , 17889,84 , 134,24 , 15991,28 , 9305,60 , 14329,14 , 15991,28 , 9305,60 , 14329,14 , 560,9 , 591,8 , {84,90,83}, 200,3 , 16069,28 , 13,5 , 4,0 , 4992,6 , 4998,8 , 0, 0, 1, 6, 7 }, // Asu/Latin/Tanzania
- { 206, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29795,48 , 29843,94 , 29937,24 , 29795,48 , 29843,94 , 29937,24 , 16019,28 , 16047,69 , 16116,14 , 16019,28 , 16047,69 , 16116,14 , 569,9 , 599,6 , {85,71,88}, 205,3 , 16097,28 , 4,4 , 4,0 , 5006,6 , 1691,6 , 0, 0, 1, 6, 7 }, // Teso/Latin/Uganda
- { 206, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29795,48 , 29843,94 , 29937,24 , 29795,48 , 29843,94 , 29937,24 , 16019,28 , 16047,69 , 16116,14 , 16019,28 , 16047,69 , 16116,14 , 569,9 , 599,6 , {75,69,83}, 2,3 , 16125,27 , 4,4 , 4,0 , 5006,6 , 5012,5 , 2, 1, 7, 6, 7 }, // Teso/Latin/Kenya
- { 207, 7, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,82,78}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Saho/Latin/Eritrea
- { 208, 7, 132, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 29961,46 , 30007,88 , 30095,24 , 29961,46 , 30007,88 , 30095,24 , 16130,28 , 16158,53 , 16211,14 , 16130,28 , 16158,53 , 16211,14 , 578,6 , 605,6 , {88,79,70}, 212,3 , 16152,23 , 0,4 , 4,0 , 5017,11 , 5028,5 , 0, 0, 1, 6, 7 }, // Koyra Chiini/Latin/Mali
- { 209, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 17841,48 , 27133,87 , 134,24 , 17841,48 , 27133,87 , 134,24 , 14239,28 , 14267,62 , 14329,14 , 14239,28 , 14267,62 , 14329,14 , 489,5 , 514,9 , {84,90,83}, 200,3 , 15745,27 , 0,4 , 4,0 , 5033,6 , 1626,8 , 0, 0, 1, 6, 7 }, // Rwa/Latin/Tanzania
- { 210, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 30119,48 , 30167,186 , 30353,24 , 30119,48 , 30167,186 , 30353,24 , 16225,28 , 16253,69 , 16322,14 , 16225,28 , 16253,69 , 16322,14 , 584,2 , 611,2 , {75,69,83}, 2,3 , 16175,23 , 0,4 , 4,0 , 5039,6 , 1192,5 , 2, 1, 7, 6, 7 }, // Luo/Latin/Kenya
- { 211, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26607,48 , 26655,152 , 134,24 , 26607,48 , 26655,152 , 134,24 , 13999,28 , 14027,74 , 14101,14 , 13999,28 , 14027,74 , 14101,14 , 0,2 , 0,2 , {85,71,88}, 205,3 , 15690,26 , 4,4 , 4,0 , 5045,6 , 1691,6 , 0, 0, 1, 6, 7 }, // Chiga/Latin/Uganda
- { 212, 7, 145, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 30377,48 , 30425,86 , 30511,24 , 30377,48 , 30425,86 , 30511,24 , 16336,28 , 16364,48 , 16412,14 , 16336,28 , 16364,48 , 16412,14 , 586,9 , 613,10 , {77,65,68}, 0,0 , 16198,22 , 13,5 , 4,0 , 5051,17 , 5068,6 , 2, 1, 6, 5, 6 }, // Central Morocco Tamazight/Latin/Morocco
- { 213, 7, 132, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 29961,46 , 30007,88 , 30095,24 , 29961,46 , 30007,88 , 30095,24 , 16426,28 , 16454,54 , 16211,14 , 16426,28 , 16454,54 , 16211,14 , 578,6 , 605,6 , {88,79,70}, 212,3 , 16152,23 , 0,4 , 4,0 , 5074,15 , 5028,5 , 0, 0, 1, 6, 7 }, // Koyraboro Senni/Latin/Mali
- { 214, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 17841,48 , 30535,84 , 134,24 , 17841,48 , 30535,84 , 134,24 , 16508,28 , 16536,63 , 16599,14 , 16508,28 , 16536,63 , 16599,14 , 595,5 , 623,8 , {84,90,83}, 200,3 , 16220,27 , 0,4 , 4,0 , 5089,9 , 1626,8 , 0, 0, 1, 6, 7 }, // Shambala/Latin/Tanzania
- { 215, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 538,6 , 35,18 , 18,7 , 25,12 , 30619,88 , 30619,88 , 30707,31 , 30619,88 , 30619,88 , 30707,31 , 16613,33 , 16646,54 , 16700,19 , 16613,33 , 16646,54 , 16700,19 , 600,3 , 631,6 , {73,78,82}, 127,1 , 16247,10 , 8,5 , 4,0 , 5098,4 , 2621,4 , 2, 1, 7, 7, 7 }, // Bodo/Devanagari/India
- { 218, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 30738,48 , 10650,80 , 158,27 , 30738,48 , 10650,80 , 158,27 , 16719,74 , 16719,74 , 85,14 , 16719,74 , 16719,74 , 85,14 , 0,2 , 0,2 , {82,85,66}, 129,1 , 16257,43 , 13,5 , 4,0 , 5102,7 , 5109,5 , 2, 1, 1, 6, 7 }, // Chechen/Cyrillic/Russia
- { 219, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 781,8 , 781,8 , 1529,10 , 1539,23 , 37,5 , 8,10 , 30786,65 , 30851,117 , 30968,30 , 30786,65 , 30998,117 , 30968,30 , 16793,37 , 16830,68 , 10588,14 , 16793,37 , 16830,68 , 10588,14 , 0,2 , 0,2 , {82,85,66}, 129,1 , 16300,44 , 13,5 , 4,0 , 5114,19 , 5133,7 , 2, 1, 1, 6, 7 }, // Church/Cyrillic/Russia
- { 220, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {82,85,66}, 129,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Chuvash/Cyrillic/Russia
- { 230, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 31115,49 , 31164,99 , 31263,24 , 31115,49 , 31164,99 , 31263,24 , 16898,28 , 16926,50 , 16976,14 , 16898,28 , 16926,50 , 16976,14 , 603,5 , 637,6 , {67,68,70}, 217,2 , 16344,24 , 0,4 , 4,0 , 5140,8 , 5148,16 , 2, 1, 1, 6, 7 }, // LubaKatanga/Latin/CongoKinshasa
- { 231, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 789,10 , 789,10 , 175,8 , 544,18 , 37,5 , 8,10 , 31287,48 , 31335,85 , 134,24 , 31420,59 , 31335,85 , 134,24 , 16990,28 , 17018,65 , 3622,14 , 17083,35 , 17018,65 , 3622,14 , 608,5 , 643,8 , {69,85,82}, 14,1 , 8402,19 , 13,5 , 4,0 , 5164,14 , 5178,10 , 2, 1, 1, 6, 7 }, // Luxembourgish/Latin/Luxembourg
- { 236, 7, 21, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Walloon/Latin/Belgium
- { 237, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 31479,48 , 31527,195 , 31722,24 , 31479,48 , 31527,195 , 31722,24 , 17118,28 , 17146,72 , 17218,14 , 17118,28 , 17146,72 , 17218,14 , 613,3 , 651,3 , {88,65,70}, 32,4 , 16368,21 , 0,4 , 4,0 , 5188,5 , 5193,7 , 0, 0, 1, 6, 7 }, // Aghem/Latin/Cameroon
- { 238, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 31746,48 , 31794,90 , 31884,24 , 31746,48 , 31794,90 , 31884,24 , 17232,28 , 17260,70 , 17330,14 , 17232,28 , 17260,70 , 17330,14 , 616,10 , 654,9 , {88,65,70}, 32,4 , 16389,22 , 13,5 , 4,0 , 5200,5 , 5205,8 , 0, 0, 1, 6, 7 }, // Basaa/Latin/Cameroon
- { 239, 7, 156, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 29961,46 , 30007,88 , 30095,24 , 29961,46 , 30007,88 , 30095,24 , 16426,28 , 17344,53 , 17397,14 , 16426,28 , 17344,53 , 17397,14 , 626,8 , 663,10 , {88,79,70}, 212,3 , 16152,23 , 0,4 , 4,0 , 5213,10 , 5223,5 , 0, 0, 1, 6, 7 }, // Zarma/Latin/Niger
- { 240, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 31908,49 , 31957,99 , 32056,24 , 31908,49 , 31957,99 , 32056,24 , 17411,28 , 17439,45 , 17484,14 , 17411,28 , 17439,45 , 17484,14 , 634,5 , 673,6 , {88,65,70}, 32,4 , 0,7 , 13,5 , 4,0 , 5228,5 , 1942,8 , 0, 0, 1, 6, 7 }, // Duala/Latin/Cameroon
- { 241, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 32080,36 , 32116,82 , 32198,24 , 32080,36 , 32116,82 , 32198,24 , 17498,28 , 17526,50 , 17576,14 , 17498,28 , 17526,50 , 17576,14 , 0,2 , 0,2 , {88,79,70}, 212,3 , 16411,23 , 13,5 , 4,0 , 5233,5 , 5238,7 , 0, 0, 1, 6, 7 }, // JolaFonyi/Latin/Senegal
- { 242, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 32222,50 , 32272,141 , 32413,24 , 32222,50 , 32272,141 , 32413,24 , 17590,30 , 17620,85 , 17705,14 , 17590,30 , 17620,85 , 17705,14 , 639,7 , 679,9 , {88,65,70}, 32,4 , 16434,23 , 13,5 , 4,0 , 5245,6 , 5251,7 , 0, 0, 1, 6, 7 }, // Ewondo/Latin/Cameroon
- { 243, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 32437,39 , 32476,191 , 158,27 , 32437,39 , 32476,191 , 158,27 , 17719,29 , 17748,45 , 17793,14 , 17719,29 , 17748,45 , 17793,14 , 646,6 , 688,7 , {88,65,70}, 32,4 , 16457,11 , 13,5 , 4,0 , 5258,5 , 5263,7 , 0, 0, 1, 6, 7 }, // Bafia/Latin/Cameroon
- { 244, 7, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 32667,48 , 32715,213 , 32928,24 , 32667,48 , 32715,213 , 32928,24 , 17807,28 , 17835,59 , 17894,14 , 17807,28 , 17835,59 , 17894,14 , 652,8 , 695,10 , {77,90,78}, 286,3 , 0,7 , 55,6 , 4,0 , 5270,5 , 5275,10 , 2, 1, 7, 6, 7 }, // MakhuwaMeetto/Latin/Mozambique
- { 245, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 32952,48 , 33000,139 , 33139,24 , 32952,48 , 33000,139 , 33139,24 , 17908,28 , 17936,74 , 18010,14 , 17908,28 , 17936,74 , 18010,14 , 660,5 , 705,5 , {88,65,70}, 32,4 , 16468,17 , 4,4 , 4,0 , 5285,6 , 5291,7 , 0, 0, 1, 6, 7 }, // Mundang/Latin/Cameroon
- { 246, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 33163,51 , 33214,143 , 158,27 , 33163,51 , 33214,143 , 158,27 , 18024,30 , 18054,89 , 18143,14 , 18024,30 , 18054,89 , 18143,14 , 665,4 , 710,4 , {88,65,70}, 32,4 , 16485,20 , 13,5 , 4,0 , 5298,6 , 5304,7 , 0, 0, 1, 6, 7 }, // Kwasio/Latin/Cameroon
- { 247, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1562,9 , 98,16 , 18,7 , 457,12 , 33357,54 , 33411,96 , 33507,24 , 33357,54 , 33411,96 , 33507,24 , 18157,38 , 18195,79 , 18274,14 , 18157,38 , 18195,79 , 18274,14 , 669,2 , 714,2 , {83,83,80}, 125,1 , 0,7 , 4,4 , 4,0 , 5311,9 , 0,0 , 2, 1, 1, 6, 7 }, // Nuer/Latin/SouthSudan
- { 248, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1571,6 , 1577,30 , 37,5 , 8,10 , 33531,75 , 33606,121 , 33727,24 , 33531,75 , 33606,121 , 33727,24 , 18288,21 , 18309,73 , 18382,14 , 18288,21 , 18309,73 , 18382,14 , 671,2 , 716,2 , {82,85,66}, 129,1 , 0,7 , 55,6 , 4,0 , 5320,9 , 5329,9 , 2, 1, 1, 6, 7 }, // Sakha/Cyrillic/Russia
- { 249, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 33751,48 , 33799,117 , 158,27 , 33751,48 , 33799,117 , 158,27 , 18396,28 , 18424,60 , 18484,14 , 18396,28 , 18424,60 , 18484,14 , 673,9 , 718,9 , {84,90,83}, 200,3 , 16505,25 , 0,4 , 4,0 , 5338,9 , 5347,9 , 0, 0, 1, 6, 7 }, // Sangu/Latin/Tanzania
- { 251, 7, 156, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 29961,46 , 30007,88 , 30095,24 , 29961,46 , 30007,88 , 30095,24 , 16426,28 , 16454,54 , 16211,14 , 16426,28 , 16454,54 , 16211,14 , 626,8 , 663,10 , {88,79,70}, 212,3 , 16152,23 , 0,4 , 4,0 , 5356,13 , 5223,5 , 0, 0, 1, 6, 7 }, // Tasawaq/Latin/Niger
- { 252, 35, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 33916,50 , 33916,50 , 158,27 , 33916,50 , 33916,50 , 158,27 , 18498,30 , 18498,30 , 85,14 , 18498,30 , 18498,30 , 85,14 , 0,2 , 0,2 , {76,82,68}, 6,1 , 16530,15 , 4,4 , 4,0 , 5369,2 , 5371,4 , 2, 1, 1, 6, 7 }, // Vai/Vai/Liberia
- { 252, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 33966,81 , 33966,81 , 158,27 , 33966,81 , 33966,81 , 158,27 , 18528,48 , 18528,48 , 85,14 , 18528,48 , 18528,48 , 85,14 , 0,2 , 0,2 , {76,82,68}, 6,1 , 16545,20 , 4,4 , 4,0 , 5375,3 , 5378,8 , 2, 1, 1, 6, 7 }, // Vai/Latin/Liberia
- { 253, 7, 206, 44, 8217, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 272,9 , 272,9 , 53,10 , 544,18 , 37,5 , 8,10 , 34047,48 , 34095,99 , 34194,24 , 34047,48 , 34095,99 , 34194,24 , 18576,28 , 18604,53 , 18657,14 , 18576,28 , 18604,53 , 18657,14 , 0,2 , 0,2 , {67,72,70}, 0,0 , 0,7 , 55,6 , 4,0 , 5386,6 , 5392,6 , 2, 0, 1, 6, 7 }, // Walser/Latin/Switzerland
- { 254, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 34218,51 , 34269,191 , 158,27 , 34218,51 , 34269,191 , 158,27 , 18671,21 , 18692,71 , 18763,14 , 18671,21 , 18692,71 , 18763,14 , 682,8 , 727,8 , {88,65,70}, 32,4 , 0,7 , 13,5 , 4,0 , 5398,6 , 5404,7 , 0, 0, 1, 6, 7 }, // Yangben/Latin/Cameroon
- { 256, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 591,7 , 591,7 , 300,6 , 396,22 , 37,5 , 8,10 , 34460,48 , 34508,85 , 34593,24 , 34617,48 , 34665,117 , 34593,24 , 18777,28 , 18805,54 , 3345,14 , 18777,28 , 18805,54 , 3345,14 , 690,12 , 735,11 , {69,85,82}, 14,1 , 3120,20 , 13,5 , 4,0 , 5411,9 , 2393,6 , 2, 1, 1, 6, 7 }, // Asturian/Latin/Spain
- { 257, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 799,11 , 799,11 , 810,16 , 826,9 , 53,10 , 715,18 , 37,5 , 8,10 , 34782,174 , 34782,174 , 158,27 , 34782,174 , 34782,174 , 158,27 , 18859,60 , 18859,60 , 18919,25 , 18859,60 , 18859,60 , 18919,25 , 702,8 , 746,13 , {88,65,70}, 32,4 , 16565,12 , 8,5 , 4,0 , 5420,5 , 5425,7 , 0, 0, 1, 6, 7 }, // Ngomba/Latin/Cameroon
- { 258, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 1607,10 , 599,17 , 37,5 , 8,10 , 34956,102 , 34956,102 , 158,27 , 34956,102 , 34956,102 , 158,27 , 18944,54 , 18944,54 , 18998,21 , 18944,54 , 18944,54 , 18998,21 , 0,2 , 0,2 , {88,65,70}, 32,4 , 16577,16 , 55,6 , 4,0 , 5432,4 , 5436,7 , 0, 0, 1, 6, 7 }, // Kako/Latin/Cameroon
- { 259, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 715,18 , 37,5 , 8,10 , 35058,137 , 35195,142 , 35337,36 , 35058,137 , 35195,142 , 35337,36 , 19019,49 , 19019,49 , 19068,21 , 19019,49 , 19019,49 , 19068,21 , 0,2 , 0,2 , {88,65,70}, 32,4 , 16593,12 , 8,5 , 4,0 , 5443,5 , 5448,7 , 0, 0, 1, 6, 7 }, // Meta/Latin/Cameroon
- { 260, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1617,32 , 37,5 , 8,10 , 35373,165 , 35373,165 , 158,27 , 35373,165 , 35373,165 , 158,27 , 19089,111 , 19089,111 , 85,14 , 19089,111 , 19089,111 , 85,14 , 710,9 , 759,8 , {88,65,70}, 32,4 , 16605,16 , 8,5 , 4,0 , 5455,16 , 5471,7 , 0, 0, 1, 6, 7 }, // Ngiemboon/Latin/Cameroon
- { 312, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {88,65,70}, 32,4 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Akoose/Latin/Cameroon
- { 313, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 538,6 , 35,18 , 18,7 , 25,12 , 35538,180 , 35538,180 , 158,27 , 35538,180 , 35538,180 , 158,27 , 19200,87 , 19200,87 , 85,14 , 19200,87 , 19200,87 , 19287,14 , 0,2 , 0,2 , {85,83,68}, 6,1 , 0,7 , 55,6 , 4,0 , 5478,12 , 5490,22 , 2, 1, 7, 6, 7 }, // Lakota/Latin/UnitedStates
- { 314, 9, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 439,8 , 98,16 , 37,5 , 8,10 , 26145,48 , 26193,81 , 26274,24 , 26145,48 , 26193,81 , 26274,24 , 13749,30 , 19301,48 , 85,14 , 13749,30 , 19301,48 , 85,14 , 463,6 , 482,8 , {77,65,68}, 0,0 , 15627,21 , 0,4 , 4,0 , 5512,8 , 4708,6 , 2, 1, 6, 5, 6 }, // Standard Moroccan Tamazight/Tifinagh/Morocco
- { 315, 7, 43, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {67,76,80}, 6,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Mapuche/Latin/Chile
- { 316, 1, 103, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 35718,105 , 35718,105 , 158,27 , 35718,105 , 35718,105 , 158,27 , 19349,58 , 19349,58 , 19407,14 , 19349,58 , 19349,58 , 19407,14 , 0,2 , 0,2 , {73,81,68}, 0,0 , 16621,20 , 8,5 , 4,0 , 5520,14 , 5534,5 , 0, 0, 6, 5, 6 }, // Central Kurdish/Arabic/Iraq
- { 316, 1, 102, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 35718,105 , 35718,105 , 158,27 , 35718,105 , 35718,105 , 158,27 , 19349,58 , 19349,58 , 19407,14 , 19349,58 , 19349,58 , 19407,14 , 0,2 , 0,2 , {73,82,82}, 0,0 , 16641,19 , 8,5 , 4,0 , 5520,14 , 5539,5 , 0, 0, 6, 5, 5 }, // Central Kurdish/Arabic/Iran
- { 317, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 197,7 , 197,7 , 114,6 , 544,18 , 55,4 , 59,9 , 35823,48 , 35871,85 , 15880,24 , 35956,60 , 36016,93 , 15880,24 , 19421,28 , 19449,53 , 19502,14 , 19421,28 , 19449,53 , 19502,14 , 719,9 , 767,10 , {69,85,82}, 14,1 , 16660,27 , 13,5 , 4,0 , 5544,14 , 5558,6 , 2, 1, 1, 6, 7 }, // LowerSorbian/Latin/Germany
- { 318, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 197,7 , 197,7 , 114,6 , 544,18 , 469,12 , 59,9 , 36109,48 , 36157,86 , 15880,24 , 36243,60 , 36303,93 , 15880,24 , 19516,28 , 19544,53 , 19597,14 , 19516,28 , 19544,53 , 19597,14 , 719,9 , 777,9 , {69,85,82}, 14,1 , 16687,29 , 13,5 , 4,0 , 5564,15 , 5579,6 , 2, 1, 1, 6, 7 }, // UpperSorbian/Latin/Germany
- { 319, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {88,65,70}, 32,4 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Kenyang/Latin/Cameroon
- { 320, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {67,65,68}, 247,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Mohawk/Latin/Canada
- { 321, 75, 91, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {71,78,70}, 223,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Nko/Nko/Guinea
- { 323, 7, 90, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {71,84,81}, 314,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Kiche/Latin/Guatemala
- { 324, 7, 205, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {83,69,75}, 198,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Southern Sami/Latin/Sweden
- { 325, 7, 205, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {83,69,75}, 198,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Lule Sami/Latin/Sweden
- { 326, 7, 73, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 36396,140 , 158,27 , 344,48 , 344,48 , 158,27 , 19611,21 , 19632,70 , 85,14 , 19611,21 , 19702,73 , 19775,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 16716,11 , 55,6 , 4,0 , 5585,11 , 5596,5 , 2, 1, 1, 6, 7 }, // Inari Sami/Latin/Finland
- { 327, 7, 73, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Skolt Sami/Latin/Finland
- { 328, 7, 13, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 344,48 , 344,48 , 158,27 , 344,48 , 344,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {65,85,68}, 347,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Warlpiri/Latin/Australia
- { 346, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 13772,70 , 13772,70 , 158,27 , 13772,70 , 13772,70 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {73,82,82}, 349,3 , 16727,27 , 8,5 , 4,0 , 5601,7 , 3104,5 , 0, 0, 6, 5, 5 }, // Mazanderani/Arabic/Iran
- { 349, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 36536,77 , 36536,77 , 158,27 , 36536,77 , 36536,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 5608,11 , 0,0 , 0, 0, 6, 5, 5 }, // Northern Luri/Arabic/Iran
- { 349, 1, 103, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 36536,77 , 36536,77 , 158,27 , 36536,77 , 36536,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , {73,81,68}, 0,0 , 0,7 , 8,5 , 4,0 , 5608,11 , 0,0 , 0, 0, 6, 5, 6 }, // Northern Luri/Arabic/Iraq
- { 357, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 182,5 , 182,5 , 835,5 , 835,5 , 418,8 , 447,14 , 174,6 , 191,13 , 4357,39 , 4357,39 , 158,27 , 4357,39 , 4357,39 , 158,27 , 2069,21 , 2027,28 , 2055,14 , 2069,21 , 2027,28 , 2055,14 , 79,2 , 77,2 , {72,75,68}, 142,3 , 16754,11 , 4,4 , 4,0 , 5619,2 , 568,14 , 2, 1, 7, 6, 7 }, // Cantonese/Traditional Han/HongKong
- { 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,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,0, 0,0, {0,0,0}, 0,0, 0,0, 0,0, 0,0, 0, 0, 0, 0, 0, 0,0, 0,0 } // trailing 0s
+ // lang script terr dec group list prcnt zero minus plus exp quotOpn quotEnd altQtOpn altQtEnd lpStart lpMid lpEnd lpTwo sDtFmt lDtFmt sTmFmt lTmFmt ssMonth slMonth snMonth sMonth lMonth nMonth ssDays slDays snDays sDays lDays nDays am pm byte siQuant iecQuant currISO currSym currDsply currFmt currFmtNeg endoLang endoCntry curDgt curRnd dow1st wknd+ wknd-
+ { 1, 0, 0, 46, 44, 59, 37, 48, 45, 43, 101, 34, 34, 39, 39, 0,6 , 0,6 , 0,6 , 0,6 , 0,10 , 10,17 , 0,8 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 158,27 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 99,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {0,0,0}, 0,0 , 0,7 , 0,4 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // C/AnyScript/AnyCountry
+ { 3, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 35,18 , 18,7 , 25,12 , 185,48 , 233,111 , 134,24 , 185,48 , 233,111 , 134,24 , 113,28 , 141,55 , 85,14 , 113,28 , 141,55 , 85,14 , 2,2 , 2,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,2 , 7,24 , 4,4 , 4,0 , 0,6 , 6,10 , 2, 1, 7, 6, 7 }, // Oromo/Latin/Ethiopia
+ { 3, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 35,18 , 37,5 , 8,10 , 185,48 , 233,111 , 344,24 , 185,48 , 233,111 , 134,24 , 113,28 , 141,55 , 196,14 , 113,28 , 141,55 , 196,14 , 2,2 , 2,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 0,7 , 4,4 , 4,0 , 0,6 , 16,8 , 2, 1, 7, 6, 7 }, // Oromo/Latin/Kenya
+ { 4, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Afar/Latin/Ethiopia
+ { 5, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 80,18 , 37,5 , 8,10 , 416,59 , 475,92 , 134,24 , 416,59 , 475,92 , 134,24 , 210,28 , 238,58 , 296,14 , 210,28 , 238,58 , 296,14 , 4,3 , 4,3 , 49,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 31,67 , 4,4 , 4,0 , 24,9 , 33,11 , 2, 1, 7, 6, 7 }, // Afrikaans/Latin/SouthAfrica
+ { 5, 7, 148, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 53,10 , 98,16 , 37,5 , 8,10 , 416,59 , 475,92 , 134,24 , 416,59 , 475,92 , 134,24 , 210,28 , 238,58 , 296,14 , 210,28 , 238,58 , 296,14 , 4,3 , 4,3 , 49,5 , 5,17 , 22,23 , {78,65,68}, 6,1 , 98,55 , 4,4 , 4,0 , 24,9 , 44,7 , 2, 1, 1, 6, 7 }, // Afrikaans/Latin/Namibia
+ { 6, 7, 2, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 18,7 , 42,13 , 567,48 , 615,78 , 693,24 , 717,48 , 765,78 , 843,24 , 310,28 , 338,58 , 396,14 , 310,28 , 410,58 , 396,14 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {65,76,76}, 7,4 , 153,45 , 13,5 , 4,0 , 51,5 , 56,8 , 0, 0, 1, 6, 7 }, // Albanian/Latin/Albania
+ { 6, 7, 127, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 37,5 , 8,10 , 567,48 , 615,78 , 693,24 , 717,48 , 765,78 , 843,24 , 310,28 , 338,58 , 396,14 , 310,28 , 410,58 , 396,14 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {77,75,68}, 11,3 , 198,54 , 13,5 , 4,0 , 51,5 , 64,8 , 2, 1, 1, 6, 7 }, // Albanian/Latin/Macedonia
+ { 6, 7, 257, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 14,9 , 14,9 , 114,6 , 10,17 , 37,5 , 8,10 , 567,48 , 615,78 , 693,24 , 717,48 , 765,78 , 843,24 , 310,28 , 338,58 , 396,14 , 310,28 , 410,58 , 396,14 , 7,11 , 7,10 , 54,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 252,21 , 13,5 , 4,0 , 51,5 , 72,6 , 2, 1, 1, 6, 7 }, // Albanian/Latin/Kosovo
+ { 7, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 23,6 , 23,6 , 29,9 , 38,8 , 120,10 , 130,17 , 18,7 , 25,12 , 867,46 , 913,61 , 974,24 , 867,46 , 913,61 , 974,24 , 468,27 , 495,28 , 523,14 , 468,27 , 495,28 , 523,14 , 18,3 , 17,4 , 58,3 , 61,23 , 22,23 , {69,84,66}, 15,2 , 273,34 , 4,4 , 4,0 , 78,4 , 82,5 , 2, 1, 7, 6, 7 }, // Amharic/Ethiopic/Ethiopia
+ { 8, 1, 64, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {69,71,80}, 17,5 , 307,81 , 13,5 , 4,0 , 87,7 , 94,3 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Egypt
+ { 8, 1, 3, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1097,71 , 1097,71 , 1168,24 , 1097,71 , 1097,71 , 1168,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {68,90,68}, 22,5 , 388,102 , 13,5 , 4,0 , 87,7 , 97,7 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Algeria
+ { 8, 1, 17, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {66,72,68}, 27,5 , 490,91 , 13,5 , 4,0 , 87,7 , 104,7 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Bahrain
+ { 8, 1, 42, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {88,65,70}, 32,4 , 581,112 , 13,5 , 4,0 , 87,7 , 111,4 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Chad
+ { 8, 1, 48, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 37,5 , 8,10 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {75,77,70}, 36,7 , 693,105 , 13,5 , 4,0 , 87,7 , 115,9 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Comoros
+ { 8, 1, 59, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {68,74,70}, 43,3 , 798,84 , 13,5 , 4,0 , 87,7 , 124,6 , 0, 0, 6, 6, 7 }, // Arabic/Arabic/Djibouti
+ { 8, 1, 67, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {69,82,78}, 46,3 , 882,91 , 13,5 , 4,0 , 87,7 , 130,7 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/Eritrea
+ { 8, 1, 103, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1192,92 , 1192,92 , 1284,24 , 1308,92 , 1192,92 , 1284,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {73,81,68}, 49,5 , 973,84 , 13,5 , 4,0 , 87,7 , 137,6 , 0, 0, 6, 5, 6 }, // Arabic/Arabic/Iraq
+ { 8, 1, 105, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 55,4 , 59,9 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {73,76,83}, 54,1 , 1057,133 , 13,5 , 4,0 , 87,7 , 143,7 , 2, 1, 7, 5, 6 }, // Arabic/Arabic/Israel
+ { 8, 1, 109, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1192,92 , 1192,92 , 1284,24 , 1192,92 , 1192,92 , 1284,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {74,79,68}, 55,5 , 1190,84 , 13,5 , 4,0 , 87,7 , 150,6 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Jordan
+ { 8, 1, 115, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {75,87,68}, 60,5 , 1274,84 , 13,5 , 4,0 , 87,7 , 156,6 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Kuwait
+ { 8, 1, 119, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1192,92 , 1192,92 , 1284,24 , 1192,92 , 1192,92 , 1284,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {76,66,80}, 65,5 , 1358,84 , 13,5 , 4,0 , 87,7 , 162,5 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Lebanon
+ { 8, 1, 122, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {76,89,68}, 70,5 , 1442,88 , 13,5 , 4,0 , 87,7 , 167,5 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Libya
+ { 8, 1, 136, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1400,72 , 1400,72 , 1472,24 , 1400,72 , 1400,72 , 1472,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {77,82,79}, 75,5 , 1530,112 , 13,5 , 4,0 , 87,7 , 172,9 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Mauritania
+ { 8, 1, 145, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 37,5 , 8,10 , 1496,70 , 1496,70 , 1566,24 , 1496,70 , 1496,70 , 1566,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {77,65,68}, 80,5 , 1642,87 , 13,5 , 4,0 , 87,7 , 181,6 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Morocco
+ { 8, 1, 162, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {79,77,82}, 85,5 , 1729,77 , 13,5 , 4,0 , 87,7 , 187,5 , 3, 0, 6, 5, 6 }, // Arabic/Arabic/Oman
+ { 8, 1, 165, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1192,92 , 1192,92 , 1284,24 , 1192,92 , 1192,92 , 1284,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {73,76,83}, 54,1 , 1057,133 , 13,5 , 4,0 , 87,7 , 192,18 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/PalestinianTerritories
+ { 8, 1, 175, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {81,65,82}, 90,5 , 1806,70 , 13,5 , 4,0 , 87,7 , 210,3 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Qatar
+ { 8, 1, 186, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,65,82}, 95,5 , 1876,77 , 13,5 , 4,0 , 87,7 , 213,24 , 2, 1, 7, 5, 6 }, // Arabic/Arabic/SaudiArabia
+ { 8, 1, 194, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,79,83}, 100,1 , 1953,77 , 13,5 , 4,0 , 87,7 , 237,7 , 0, 0, 1, 6, 7 }, // Arabic/Arabic/Somalia
+ { 8, 1, 201, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,68,71}, 101,4 , 2030,91 , 13,5 , 4,0 , 87,7 , 244,7 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/Sudan
+ { 8, 1, 207, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1192,92 , 1192,92 , 1284,24 , 1192,92 , 1192,92 , 1284,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,89,80}, 105,5 , 2121,77 , 13,5 , 4,0 , 87,7 , 251,5 , 0, 0, 6, 5, 6 }, // Arabic/Arabic/Syria
+ { 8, 1, 216, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 1097,71 , 1097,71 , 1168,24 , 1097,71 , 1097,71 , 1168,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {84,78,68}, 110,5 , 2198,95 , 13,5 , 4,0 , 87,7 , 256,4 , 3, 0, 7, 5, 6 }, // Arabic/Arabic/Tunisia
+ { 8, 1, 223, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {65,69,68}, 115,5 , 2293,91 , 13,5 , 4,0 , 87,7 , 260,24 , 2, 1, 6, 5, 6 }, // Arabic/Arabic/UnitedArabEmirates
+ { 8, 1, 236, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {77,65,68}, 80,5 , 1642,87 , 13,5 , 4,0 , 87,7 , 284,15 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/WesternSahara
+ { 8, 1, 237, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {89,69,82}, 120,5 , 2384,70 , 13,5 , 4,0 , 87,7 , 299,5 , 0, 0, 7, 5, 6 }, // Arabic/Arabic/Yemen
+ { 8, 1, 254, 1643, 1644, 1563, 37, 1632, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 52,7 , 59,6 , 147,10 , 157,18 , 18,7 , 25,12 , 998,75 , 998,75 , 1073,24 , 998,75 , 998,75 , 1073,24 , 537,52 , 537,52 , 589,14 , 537,52 , 537,52 , 589,14 , 21,1 , 21,1 , 84,4 , 88,41 , 22,23 , {83,83,80}, 125,1 , 2454,132 , 13,5 , 4,0 , 87,7 , 304,12 , 2, 1, 1, 6, 7 }, // Arabic/Arabic/SouthSudan
+ { 9, 10, 11, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 65,7 , 65,7 , 175,8 , 183,20 , 37,5 , 8,10 , 1590,48 , 1638,94 , 1732,24 , 1590,48 , 1756,106 , 1732,24 , 603,28 , 631,62 , 693,14 , 603,28 , 631,62 , 693,14 , 0,2 , 0,2 , 129,6 , 135,17 , 22,23 , {65,77,68}, 126,1 , 2586,46 , 8,5 , 4,0 , 316,7 , 323,8 , 0, 0, 1, 6, 7 }, // Armenian/Armenian/Armenia
+ { 10, 11, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 203,8 , 211,18 , 68,8 , 76,12 , 1862,62 , 1924,88 , 158,27 , 1862,62 , 1924,88 , 158,27 , 707,37 , 744,58 , 85,14 , 707,37 , 744,58 , 85,14 , 22,9 , 22,7 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 331,7 , 338,4 , 2, 1, 7, 7, 7 }, // Assamese/Bengali/India
+ { 12, 7, 15, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 72,8 , 72,8 , 175,8 , 229,17 , 37,5 , 8,10 , 2012,48 , 2060,77 , 158,27 , 2012,48 , 2137,77 , 158,27 , 802,27 , 829,67 , 99,14 , 802,27 , 829,67 , 99,14 , 0,2 , 0,2 , 152,4 , 5,17 , 22,23 , {65,90,78}, 128,1 , 2632,58 , 8,5 , 4,0 , 342,10 , 352,10 , 2, 1, 1, 6, 7 }, // Azerbaijani/Latin/Azerbaijan
+ { 12, 1, 102, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 6, 5, 5 }, // Azerbaijani/Arabic/Iran
+ { 12, 2, 15, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 175,8 , 229,17 , 37,5 , 8,10 , 2214,48 , 2262,77 , 158,27 , 2214,48 , 2339,77 , 158,27 , 896,27 , 923,67 , 99,14 , 896,27 , 923,67 , 99,14 , 31,2 , 29,2 , 45,4 , 5,17 , 22,23 , {65,90,78}, 128,1 , 2690,12 , 8,5 , 4,0 , 362,10 , 372,10 , 2, 1, 1, 6, 7 }, // Azerbaijani/Cyrillic/Azerbaijan
+ { 13, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Bashkir/Cyrillic/Russia
+ { 14, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8220, 8221, 0,6 , 0,6 , 80,9 , 80,9 , 246,6 , 252,26 , 37,5 , 88,12 , 2416,60 , 2476,93 , 2569,24 , 2416,60 , 2593,93 , 2569,24 , 990,28 , 1018,68 , 1086,14 , 990,28 , 1100,68 , 1086,14 , 0,2 , 0,2 , 156,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 2702,20 , 13,5 , 4,0 , 382,7 , 389,8 , 2, 1, 1, 6, 7 }, // Basque/Latin/Spain
+ { 15, 11, 18, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 89,9 , 89,9 , 278,6 , 211,18 , 18,7 , 25,12 , 2686,90 , 2686,90 , 2776,33 , 2809,77 , 2686,90 , 2776,33 , 1168,37 , 1205,58 , 1263,18 , 1168,37 , 1281,58 , 1263,18 , 0,2 , 0,2 , 163,4 , 5,17 , 22,23 , {66,68,84}, 130,1 , 2722,49 , 0,4 , 4,0 , 397,5 , 402,8 , 2, 1, 5, 6, 7 }, // Bengali/Bengali/Bangladesh
+ { 15, 11, 100, 46, 44, 59, 37, 2534, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 89,9 , 89,9 , 278,6 , 211,18 , 18,7 , 25,12 , 2686,90 , 2686,90 , 2776,33 , 2809,77 , 2686,90 , 2776,33 , 1168,37 , 1205,58 , 1263,18 , 1168,37 , 1281,58 , 1263,18 , 0,2 , 0,2 , 163,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 2771,43 , 0,4 , 4,0 , 397,5 , 410,4 , 2, 1, 7, 7, 7 }, // Bengali/Bengali/India
+ { 16, 31, 25, 46, 44, 59, 37, 3872, 45, 43, 101, 8220, 8221, 8216, 8217, 98,9 , 98,9 , 98,9 , 98,9 , 53,10 , 284,30 , 100,22 , 122,27 , 2886,63 , 2949,191 , 3140,27 , 3167,27 , 3194,132 , 3326,27 , 1339,34 , 1373,79 , 1452,27 , 1339,34 , 1373,79 , 1452,27 , 33,5 , 31,6 , 45,4 , 5,17 , 22,23 , {66,84,78}, 131,3 , 2814,15 , 4,4 , 4,0 , 414,6 , 420,5 , 2, 1, 7, 6, 7 }, // Dzongkha/Tibetan/Bhutan
+ { 19, 7, 74, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 3353,63 , 3416,78 , 3494,36 , 3530,63 , 3416,78 , 3494,36 , 1479,33 , 1512,43 , 1555,18 , 1479,33 , 1512,43 , 1555,18 , 38,4 , 37,4 , 167,7 , 174,17 , 191,23 , {69,85,82}, 14,1 , 2829,36 , 13,5 , 4,0 , 425,9 , 434,5 , 2, 1, 1, 6, 7 }, // Breton/Latin/France
+ { 20, 2, 33, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 314,12 , 326,22 , 55,4 , 59,9 , 3593,49 , 3642,82 , 3724,24 , 3593,49 , 3642,82 , 3724,24 , 1573,21 , 1594,55 , 1649,14 , 1573,21 , 1594,55 , 1649,14 , 42,6 , 41,6 , 214,7 , 5,17 , 22,23 , {66,71,78}, 134,3 , 2865,47 , 13,5 , 4,0 , 439,9 , 448,8 , 2, 1, 1, 6, 7 }, // Bulgarian/Cyrillic/Bulgaria
+ { 21, 25, 147, 46, 44, 4170, 37, 4160, 45, 43, 101, 8220, 8221, 8216, 8217, 114,5 , 114,5 , 119,10 , 119,10 , 348,8 , 98,16 , 37,5 , 149,10 , 3748,43 , 3791,88 , 3879,24 , 3748,43 , 3791,88 , 3879,24 , 1663,54 , 1663,54 , 1717,14 , 1663,54 , 1663,54 , 1717,14 , 48,5 , 47,3 , 221,5 , 5,17 , 22,23 , {77,77,75}, 137,1 , 2912,27 , 13,5 , 4,0 , 456,6 , 456,6 , 0, 0, 7, 6, 7 }, // Burmese/Myanmar/Myanmar
+ { 22, 2, 20, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 129,7 , 129,7 , 356,7 , 326,22 , 37,5 , 159,11 , 3903,48 , 3951,95 , 4046,24 , 4070,48 , 4118,98 , 4046,24 , 1731,21 , 1752,56 , 1808,14 , 1731,21 , 1752,56 , 1808,14 , 0,2 , 0,2 , 226,5 , 231,17 , 22,23 , {66,89,78}, 0,2 , 2939,89 , 13,5 , 4,0 , 462,10 , 472,8 , 2, 0, 1, 6, 7 }, // Belarusian/Cyrillic/Belarus
+ { 23, 20, 36, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 136,9 , 145,9 , 278,6 , 98,16 , 18,7 , 25,12 , 4216,71 , 4216,71 , 4287,24 , 4216,71 , 4216,71 , 4287,24 , 1822,47 , 1822,47 , 1869,14 , 1822,47 , 1822,47 , 1869,14 , 0,2 , 0,2 , 248,2 , 5,17 , 22,23 , {75,72,82}, 138,1 , 3028,29 , 0,4 , 4,0 , 480,5 , 485,7 , 2, 1, 7, 6, 7 }, // Khmer/Khmer/Cambodia
+ { 24, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 154,7 , 154,7 , 278,6 , 363,22 , 55,4 , 59,9 , 4311,60 , 4371,82 , 4453,36 , 4489,93 , 4582,115 , 4453,36 , 1883,28 , 1911,60 , 1971,21 , 1883,28 , 1911,60 , 1971,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 492,6 , 498,7 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Spain
+ { 24, 7, 5, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 154,7 , 154,7 , 278,6 , 363,22 , 55,4 , 59,9 , 4311,60 , 4371,82 , 4453,36 , 4489,93 , 4582,115 , 4453,36 , 1883,28 , 1911,60 , 1971,21 , 1883,28 , 1911,60 , 1971,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 492,6 , 505,7 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Andorra
+ { 24, 7, 74, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 154,7 , 154,7 , 278,6 , 363,22 , 55,4 , 59,9 , 4311,60 , 4371,82 , 4453,36 , 4489,93 , 4582,115 , 4453,36 , 1883,28 , 1911,60 , 1971,21 , 1883,28 , 1911,60 , 1971,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 492,6 , 512,6 , 2, 1, 1, 6, 7 }, // Catalan/Latin/France
+ { 24, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 154,7 , 154,7 , 278,6 , 363,22 , 55,4 , 59,9 , 4311,60 , 4371,82 , 4453,36 , 4489,93 , 4582,115 , 4453,36 , 1883,28 , 1911,60 , 1971,21 , 1883,28 , 1911,60 , 1971,21 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 492,6 , 518,6 , 2, 1, 1, 6, 7 }, // Catalan/Latin/Italy
+ { 25, 5, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 161,5 , 161,5 , 166,5 , 166,5 , 385,8 , 393,13 , 170,6 , 176,11 , 4697,39 , 4736,38 , 158,27 , 4697,39 , 4736,38 , 158,27 , 1992,21 , 2013,28 , 2041,14 , 1992,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 250,2 , 252,21 , 22,23 , {67,78,89}, 139,1 , 3077,13 , 4,4 , 4,0 , 524,4 , 528,2 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/China
+ { 25, 5, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 161,5 , 161,5 , 166,5 , 166,5 , 278,6 , 393,13 , 170,6 , 176,11 , 4697,39 , 4736,38 , 158,27 , 4697,39 , 4736,38 , 158,27 , 1992,21 , 2013,28 , 2041,14 , 1992,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 250,2 , 252,21 , 22,23 , {72,75,68}, 140,3 , 3090,11 , 4,4 , 4,0 , 524,4 , 530,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/HongKong
+ { 25, 5, 126, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 161,5 , 161,5 , 166,5 , 166,5 , 278,6 , 393,13 , 170,6 , 176,11 , 4697,39 , 4736,38 , 158,27 , 4697,39 , 4736,38 , 158,27 , 1992,21 , 2013,28 , 2041,14 , 1992,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 250,2 , 252,21 , 22,23 , {77,79,80}, 143,4 , 3101,13 , 4,4 , 4,0 , 524,4 , 539,9 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Macau
+ { 25, 5, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 161,5 , 161,5 , 166,5 , 166,5 , 27,8 , 393,13 , 170,6 , 176,11 , 4697,39 , 4736,38 , 158,27 , 4697,39 , 4736,38 , 158,27 , 1992,21 , 2013,28 , 2041,14 , 1992,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 250,2 , 252,21 , 22,23 , {83,71,68}, 6,1 , 3114,15 , 4,4 , 4,0 , 524,4 , 548,3 , 2, 1, 7, 6, 7 }, // Chinese/Simplified Han/Singapore
+ { 25, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 161,5 , 161,5 , 171,5 , 171,5 , 406,8 , 393,13 , 170,6 , 187,13 , 4697,39 , 4697,39 , 158,27 , 4697,39 , 4697,39 , 158,27 , 2055,21 , 2013,28 , 2041,14 , 2055,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 273,3 , 5,17 , 22,23 , {72,75,68}, 140,3 , 3090,11 , 18,5 , 4,0 , 551,4 , 555,9 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/HongKong
+ { 25, 6, 126, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 161,5 , 161,5 , 171,5 , 171,5 , 406,8 , 393,13 , 170,6 , 187,13 , 4697,39 , 4697,39 , 158,27 , 4697,39 , 4697,39 , 158,27 , 2055,21 , 2013,28 , 2041,14 , 2055,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 273,3 , 5,17 , 22,23 , {77,79,80}, 143,4 , 3129,13 , 18,5 , 4,0 , 551,4 , 564,9 , 2, 1, 7, 6, 7 }, // Chinese/Traditional Han/Macau
+ { 25, 6, 208, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 161,5 , 161,5 , 166,5 , 166,5 , 385,8 , 414,14 , 170,6 , 187,13 , 4697,39 , 4697,39 , 158,27 , 4697,39 , 4697,39 , 158,27 , 2055,21 , 2013,28 , 2041,14 , 2055,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {84,87,68}, 6,1 , 3142,13 , 4,4 , 4,0 , 551,4 , 573,2 , 2, 0, 7, 6, 7 }, // Chinese/Traditional Han/Taiwan
+ { 26, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Corsican/Latin/France
+ { 27, 7, 54, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 428,13 , 441,19 , 37,5 , 88,12 , 4774,49 , 4823,94 , 4917,39 , 4774,49 , 4956,98 , 4917,39 , 2076,28 , 2104,58 , 2162,14 , 2076,28 , 2104,58 , 2176,14 , 0,2 , 0,2 , 276,7 , 5,17 , 22,23 , {72,82,75}, 147,3 , 3155,60 , 13,5 , 4,0 , 575,8 , 583,8 , 2, 1, 1, 6, 7 }, // Croatian/Latin/Croatia
+ { 27, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 460,9 , 441,19 , 37,5 , 88,12 , 4774,49 , 4823,94 , 4917,39 , 4774,49 , 4956,98 , 4917,39 , 2076,28 , 2104,58 , 2176,14 , 2076,28 , 2104,58 , 2176,14 , 0,2 , 0,2 , 276,7 , 5,17 , 22,23 , {66,65,77}, 150,2 , 3215,85 , 13,5 , 4,0 , 575,8 , 591,19 , 2, 1, 1, 6, 7 }, // Croatian/Latin/BosniaAndHerzegowina
+ { 28, 7, 57, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 176,7 , 176,7 , 175,8 , 469,17 , 55,4 , 59,9 , 5054,48 , 5102,82 , 158,27 , 5054,48 , 5184,84 , 158,27 , 2190,21 , 2211,49 , 2260,14 , 2190,21 , 2211,49 , 2260,14 , 60,4 , 57,4 , 283,5 , 5,17 , 22,23 , {67,90,75}, 152,2 , 3300,68 , 13,5 , 4,0 , 610,7 , 617,5 , 2, 0, 1, 6, 7 }, // Czech/Latin/CzechRepublic
+ { 29, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 120,10 , 486,23 , 200,5 , 205,10 , 5268,59 , 5327,84 , 134,24 , 5268,59 , 5327,84 , 134,24 , 2274,28 , 2302,51 , 2353,14 , 2367,35 , 2302,51 , 2353,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {68,75,75}, 154,3 , 3368,42 , 13,5 , 4,0 , 622,5 , 627,7 , 2, 1, 1, 6, 7 }, // Danish/Latin/Denmark
+ { 29, 7, 86, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 120,10 , 486,23 , 215,7 , 76,12 , 5268,59 , 5327,84 , 134,24 , 5268,59 , 5327,84 , 134,24 , 2274,28 , 2302,51 , 2353,14 , 2367,35 , 2302,51 , 2353,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {68,75,75}, 154,3 , 3368,42 , 13,5 , 4,0 , 622,5 , 634,8 , 2, 1, 1, 6, 7 }, // Danish/Latin/Greenland
+ { 30, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3410,19 , 13,5 , 4,0 , 642,10 , 652,9 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Netherlands
+ { 30, 7, 12, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {65,87,71}, 157,4 , 3429,55 , 13,5 , 4,0 , 642,10 , 661,5 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Aruba
+ { 30, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 509,7 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3410,19 , 13,5 , 4,0 , 642,10 , 666,6 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Belgium
+ { 30, 7, 152, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {65,78,71}, 161,4 , 3484,97 , 13,5 , 4,0 , 642,10 , 672,7 , 2, 1, 1, 6, 7 }, // Dutch/Latin/CuraSao
+ { 30, 7, 202, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {83,82,68}, 6,1 , 3581,58 , 13,5 , 4,0 , 642,10 , 679,8 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Suriname
+ { 30, 7, 255, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3639,61 , 13,5 , 4,0 , 642,10 , 687,19 , 2, 1, 1, 6, 7 }, // Dutch/Latin/Bonaire
+ { 30, 7, 256, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 5411,59 , 5470,88 , 134,24 , 5411,59 , 5470,88 , 134,24 , 2402,21 , 2423,59 , 2482,14 , 2402,21 , 2423,59 , 2482,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {65,78,71}, 161,4 , 3484,97 , 13,5 , 4,0 , 642,10 , 706,12 , 2, 1, 1, 6, 7 }, // Dutch/Latin/SintMaarten
+ { 31, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 718,16 , 734,13 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStates
+ { 31, 3, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 165,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // English/Deseret/UnitedStates
+ { 31, 7, 4, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 754,14 , 2, 1, 7, 6, 7 }, // English/Latin/AmericanSamoa
+ { 31, 7, 7, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 768,8 , 2, 1, 1, 6, 7 }, // English/Latin/Anguilla
+ { 31, 7, 9, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 776,17 , 2, 1, 7, 6, 7 }, // English/Latin/AntiguaAndBarbuda
+ { 31, 7, 13, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 201,9 , 201,9 , 278,6 , 10,17 , 18,7 , 25,12 , 5558,59 , 48,86 , 134,24 , 5558,59 , 48,86 , 134,24 , 2496,35 , 28,57 , 2531,25 , 2496,35 , 28,57 , 2531,25 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 793,18 , 811,9 , 2, 1, 7, 6, 7 }, // English/Latin/Australia
+ { 31, 7, 14, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 8,5 , 4,0 , 747,7 , 820,7 , 2, 1, 1, 6, 7 }, // English/Latin/Austria
+ { 31, 7, 16, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,83,68}, 6,1 , 3885,53 , 4,4 , 4,0 , 747,7 , 827,7 , 2, 1, 7, 6, 7 }, // English/Latin/Bahamas
+ { 31, 7, 19, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,66,68}, 6,1 , 3938,56 , 4,4 , 4,0 , 747,7 , 834,8 , 2, 1, 1, 6, 7 }, // English/Latin/Barbados
+ { 31, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 27,8 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 13,5 , 4,0 , 747,7 , 842,7 , 2, 1, 1, 6, 7 }, // English/Latin/Belgium
+ { 31, 7, 22, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 27,8 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,90,68}, 6,1 , 3994,47 , 4,4 , 4,0 , 747,7 , 849,6 , 2, 1, 7, 6, 7 }, // English/Latin/Belize
+ { 31, 7, 24, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,77,68}, 6,1 , 4041,53 , 4,4 , 4,0 , 747,7 , 855,7 , 2, 1, 1, 6, 7 }, // English/Latin/Bermuda
+ { 31, 7, 28, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 27,8 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,87,80}, 168,1 , 4094,50 , 4,4 , 4,0 , 747,7 , 862,8 , 2, 1, 7, 6, 7 }, // English/Latin/Botswana
+ { 31, 7, 31, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 870,30 , 2, 1, 1, 6, 7 }, // English/Latin/BritishIndianOceanTerritory
+ { 31, 7, 35, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,73,70}, 169,3 , 4144,53 , 4,4 , 4,0 , 747,7 , 900,7 , 0, 0, 1, 6, 7 }, // English/Latin/Burundi
+ { 31, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 4197,83 , 4,4 , 4,0 , 747,7 , 907,8 , 0, 0, 1, 6, 7 }, // English/Latin/Cameroon
+ { 31, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 53,10 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {67,65,68}, 6,1 , 4280,53 , 4,4 , 4,0 , 915,16 , 931,6 , 2, 0, 7, 6, 7 }, // English/Latin/Canada
+ { 31, 7, 40, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {75,89,68}, 6,1 , 4333,71 , 4,4 , 4,0 , 747,7 , 937,14 , 2, 1, 1, 6, 7 }, // English/Latin/CaymanIslands
+ { 31, 7, 45, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 951,16 , 2, 1, 1, 6, 7 }, // English/Latin/ChristmasIsland
+ { 31, 7, 46, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 967,23 , 2, 1, 1, 6, 7 }, // English/Latin/CocosIslands
+ { 31, 7, 51, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4404,62 , 4,4 , 4,0 , 747,7 , 990,12 , 2, 1, 1, 6, 7 }, // English/Latin/CookIslands
+ { 31, 7, 56, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 4,4 , 4,0 , 747,7 , 1002,6 , 2, 1, 1, 6, 7 }, // English/Latin/Cyprus
+ { 31, 7, 58, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 200,5 , 205,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {68,75,75}, 154,3 , 4466,44 , 13,5 , 4,0 , 747,7 , 1008,7 , 2, 1, 1, 6, 7 }, // English/Latin/Denmark
+ { 31, 7, 60, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1015,8 , 2, 1, 7, 6, 7 }, // English/Latin/Dominica
+ { 31, 7, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,82,78}, 46,3 , 4510,50 , 4,4 , 4,0 , 747,7 , 1023,7 , 2, 1, 1, 6, 7 }, // English/Latin/Eritrea
+ { 31, 7, 70, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {70,75,80}, 125,1 , 4560,74 , 4,4 , 4,0 , 747,7 , 1030,16 , 2, 1, 1, 6, 7 }, // English/Latin/FalklandIslands
+ { 31, 7, 72, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {70,74,68}, 6,1 , 4634,47 , 4,4 , 4,0 , 747,7 , 1046,4 , 2, 1, 1, 6, 7 }, // English/Latin/Fiji
+ { 31, 7, 73, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 222,4 , 226,9 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 13,5 , 4,0 , 747,7 , 1050,7 , 2, 1, 1, 6, 7 }, // English/Latin/Finland
+ { 31, 7, 75, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 125,1 , 4681,32 , 4,4 , 4,0 , 747,7 , 1057,8 , 2, 1, 1, 6, 7 }, // English/Latin/Guernsey
+ { 31, 7, 80, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,77,68}, 172,1 , 4713,50 , 4,4 , 4,0 , 747,7 , 1065,6 , 2, 1, 1, 6, 7 }, // English/Latin/Gambia
+ { 31, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 13,5 , 4,0 , 747,7 , 1071,7 , 2, 1, 1, 6, 7 }, // English/Latin/Germany
+ { 31, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,72,83}, 173,3 , 4763,47 , 4,4 , 4,0 , 747,7 , 1078,5 , 2, 1, 1, 6, 7 }, // English/Latin/Ghana
+ { 31, 7, 84, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,73,80}, 125,1 , 4810,53 , 4,4 , 4,0 , 747,7 , 1083,9 , 2, 1, 1, 6, 7 }, // English/Latin/Gibraltar
+ { 31, 7, 87, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1092,7 , 2, 1, 1, 6, 7 }, // English/Latin/Grenada
+ { 31, 7, 89, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1099,4 , 2, 1, 7, 6, 7 }, // English/Latin/Guam
+ { 31, 7, 93, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,89,68}, 6,1 , 4863,56 , 4,4 , 4,0 , 747,7 , 1103,6 , 0, 0, 1, 6, 7 }, // English/Latin/Guyana
+ { 31, 7, 97, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 406,8 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {72,75,68}, 140,3 , 4919,56 , 4,4 , 4,0 , 747,7 , 1109,19 , 2, 1, 7, 6, 7 }, // English/Latin/HongKong
+ { 31, 7, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 27,8 , 98,16 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {73,78,82}, 127,1 , 4975,44 , 8,5 , 4,0 , 747,7 , 1128,5 , 2, 1, 7, 7, 7 }, // English/Latin/India
+ { 31, 7, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 98,16 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 4,4 , 4,0 , 747,7 , 1133,7 , 2, 1, 7, 6, 7 }, // English/Latin/Ireland
+ { 31, 7, 105, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 55,4 , 59,9 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {73,76,83}, 54,1 , 5019,62 , 4,4 , 4,0 , 747,7 , 1140,6 , 2, 1, 7, 5, 6 }, // English/Latin/Israel
+ { 31, 7, 107, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 278,6 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {74,77,68}, 6,1 , 5081,53 , 4,4 , 4,0 , 747,7 , 1146,7 , 2, 1, 7, 6, 7 }, // English/Latin/Jamaica
+ { 31, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {75,69,83}, 2,3 , 5134,53 , 4,4 , 4,0 , 747,7 , 1153,5 , 2, 1, 7, 6, 7 }, // English/Latin/Kenya
+ { 31, 7, 112, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 1158,8 , 2, 1, 1, 6, 7 }, // English/Latin/Kiribati
+ { 31, 7, 120, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 5187,61 , 4,4 , 4,0 , 747,7 , 1166,7 , 2, 1, 1, 6, 7 }, // English/Latin/Lesotho
+ { 31, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {76,82,68}, 6,1 , 5248,53 , 4,4 , 4,0 , 747,7 , 1173,7 , 2, 1, 1, 6, 7 }, // English/Latin/Liberia
+ { 31, 7, 126, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,79,80}, 143,4 , 5301,53 , 4,4 , 4,0 , 747,7 , 1180,15 , 2, 1, 7, 6, 7 }, // English/Latin/Macau
+ { 31, 7, 128, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,71,65}, 176,2 , 5354,54 , 4,4 , 4,0 , 747,7 , 1195,10 , 0, 0, 1, 6, 7 }, // English/Latin/Madagascar
+ { 31, 7, 129, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,87,75}, 178,2 , 5408,53 , 4,4 , 4,0 , 747,7 , 1205,6 , 2, 1, 1, 6, 7 }, // English/Latin/Malawi
+ { 31, 7, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,89,82}, 180,2 , 5461,59 , 4,4 , 4,0 , 747,7 , 1211,8 , 2, 1, 1, 6, 7 }, // English/Latin/Malaysia
+ { 31, 7, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 4,4 , 4,0 , 747,7 , 1219,5 , 2, 1, 7, 6, 7 }, // English/Latin/Malta
+ { 31, 7, 134, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1224,16 , 2, 1, 7, 6, 7 }, // English/Latin/MarshallIslands
+ { 31, 7, 137, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {77,85,82}, 182,2 , 5520,53 , 4,4 , 4,0 , 747,7 , 1240,9 , 0, 0, 1, 6, 7 }, // English/Latin/Mauritius
+ { 31, 7, 140, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1249,10 , 2, 1, 1, 6, 7 }, // English/Latin/Micronesia
+ { 31, 7, 144, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1259,10 , 2, 1, 1, 6, 7 }, // English/Latin/Montserrat
+ { 31, 7, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,65,68}, 6,1 , 5573,53 , 4,4 , 4,0 , 747,7 , 1269,7 , 2, 1, 1, 6, 7 }, // English/Latin/Namibia
+ { 31, 7, 149, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 1276,5 , 2, 1, 1, 6, 7 }, // English/Latin/Nauru
+ { 31, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 8,5 , 23,6 , 747,7 , 1281,11 , 2, 1, 1, 6, 7 }, // English/Latin/Netherlands
+ { 31, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 509,7 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4404,62 , 4,4 , 4,0 , 747,7 , 1292,11 , 2, 1, 7, 6, 7 }, // English/Latin/NewZealand
+ { 31, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,71,78}, 184,1 , 5626,50 , 4,4 , 4,0 , 747,7 , 1303,7 , 2, 1, 1, 6, 7 }, // English/Latin/Nigeria
+ { 31, 7, 158, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4404,62 , 4,4 , 4,0 , 747,7 , 1310,4 , 2, 1, 1, 6, 7 }, // English/Latin/Niue
+ { 31, 7, 159, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 1314,14 , 2, 1, 1, 6, 7 }, // English/Latin/NorfolkIsland
+ { 31, 7, 160, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1328,24 , 2, 1, 1, 6, 7 }, // English/Latin/NorthernMarianaIslands
+ { 31, 7, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,75,82}, 182,2 , 5676,53 , 4,4 , 4,0 , 747,7 , 1352,8 , 0, 0, 7, 6, 7 }, // English/Latin/Pakistan
+ { 31, 7, 164, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1360,5 , 2, 1, 1, 6, 7 }, // English/Latin/Palau
+ { 31, 7, 167, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,71,75}, 137,1 , 5729,73 , 4,4 , 4,0 , 747,7 , 1365,16 , 2, 1, 1, 6, 7 }, // English/Latin/PapuaNewGuinea
+ { 31, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,72,80}, 185,1 , 5802,53 , 4,4 , 4,0 , 747,7 , 1381,11 , 2, 1, 7, 6, 7 }, // English/Latin/Philippines
+ { 31, 7, 171, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4404,62 , 4,4 , 4,0 , 747,7 , 1392,16 , 2, 1, 1, 6, 7 }, // English/Latin/Pitcairn
+ { 31, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1408,11 , 2, 1, 7, 6, 7 }, // English/Latin/PuertoRico
+ { 31, 7, 179, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {82,87,70}, 186,2 , 5855,47 , 4,4 , 4,0 , 747,7 , 1419,6 , 0, 0, 1, 6, 7 }, // English/Latin/Rwanda
+ { 31, 7, 180, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1425,17 , 2, 1, 1, 6, 7 }, // English/Latin/SaintKittsAndNevis
+ { 31, 7, 181, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1442,9 , 2, 1, 1, 6, 7 }, // English/Latin/SaintLucia
+ { 31, 7, 182, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {88,67,68}, 6,1 , 3735,71 , 4,4 , 4,0 , 747,7 , 1451,24 , 2, 1, 1, 6, 7 }, // English/Latin/SaintVincentAndTheGrenadines
+ { 31, 7, 183, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {87,83,84}, 188,3 , 5902,40 , 4,4 , 4,0 , 747,7 , 1475,5 , 2, 1, 7, 6, 7 }, // English/Latin/Samoa
+ { 31, 7, 188, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,67,82}, 191,2 , 5942,59 , 4,4 , 4,0 , 747,7 , 1480,10 , 2, 1, 1, 6, 7 }, // English/Latin/Seychelles
+ { 31, 7, 189, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,76,76}, 193,2 , 6001,68 , 4,4 , 4,0 , 747,7 , 1490,12 , 0, 0, 1, 6, 7 }, // English/Latin/SierraLeone
+ { 31, 7, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 278,6 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,71,68}, 6,1 , 6069,56 , 4,4 , 4,0 , 747,7 , 1502,9 , 2, 1, 7, 6, 7 }, // English/Latin/Singapore
+ { 31, 7, 192, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 13,5 , 29,7 , 747,7 , 1511,8 , 2, 1, 1, 6, 7 }, // English/Latin/Slovenia
+ { 31, 7, 193, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,66,68}, 6,1 , 6125,74 , 4,4 , 4,0 , 747,7 , 1519,15 , 2, 1, 1, 6, 7 }, // English/Latin/SolomonIslands
+ { 31, 7, 195, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 522,10 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 5187,61 , 4,4 , 4,0 , 747,7 , 1534,12 , 2, 1, 7, 6, 7 }, // English/Latin/SouthAfrica
+ { 31, 7, 199, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,72,80}, 125,1 , 6199,56 , 4,4 , 4,0 , 747,7 , 1546,10 , 2, 1, 1, 6, 7 }, // English/Latin/SaintHelena
+ { 31, 7, 201, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,68,71}, 0,0 , 6255,50 , 4,4 , 4,0 , 747,7 , 1556,5 , 2, 1, 6, 5, 6 }, // English/Latin/Sudan
+ { 31, 7, 204, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,90,76}, 195,1 , 6305,53 , 4,4 , 4,0 , 747,7 , 1561,9 , 2, 1, 1, 6, 7 }, // English/Latin/Swaziland
+ { 31, 7, 205, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 53,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,69,75}, 196,2 , 6358,47 , 13,5 , 4,0 , 747,7 , 1570,6 , 2, 1, 1, 6, 7 }, // English/Latin/Sweden
+ { 31, 7, 206, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {67,72,70}, 0,0 , 6405,41 , 8,5 , 36,5 , 747,7 , 1576,11 , 2, 0, 1, 6, 7 }, // English/Latin/Switzerland
+ { 31, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {84,90,83}, 198,3 , 6446,62 , 4,4 , 4,0 , 747,7 , 1587,8 , 0, 0, 1, 6, 7 }, // English/Latin/Tanzania
+ { 31, 7, 213, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {78,90,68}, 6,1 , 4404,62 , 4,4 , 4,0 , 747,7 , 1595,7 , 2, 1, 1, 6, 7 }, // English/Latin/Tokelau
+ { 31, 7, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {84,79,80}, 201,2 , 6508,49 , 4,4 , 4,0 , 747,7 , 1602,5 , 2, 1, 1, 6, 7 }, // English/Latin/Tonga
+ { 31, 7, 215, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {84,84,68}, 6,1 , 6557,80 , 4,4 , 4,0 , 747,7 , 1607,17 , 2, 1, 7, 6, 7 }, // English/Latin/TrinidadAndTobago
+ { 31, 7, 219, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1624,22 , 2, 1, 1, 6, 7 }, // English/Latin/TurksAndCaicosIslands
+ { 31, 7, 220, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,85,68}, 6,1 , 3806,59 , 4,4 , 4,0 , 747,7 , 1646,6 , 2, 1, 1, 6, 7 }, // English/Latin/Tuvalu
+ { 31, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,71,88}, 203,3 , 6637,56 , 4,4 , 4,0 , 747,7 , 1652,6 , 0, 0, 1, 6, 7 }, // English/Latin/Uganda
+ { 31, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 201,9 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 68,2 , 65,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 125,1 , 6693,47 , 4,4 , 4,0 , 1658,15 , 1673,14 , 2, 1, 1, 6, 7 }, // English/Latin/UnitedKingdom
+ { 31, 7, 226, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1687,21 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStatesMinorOutlyingIslands
+ { 31, 7, 229, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {86,85,86}, 206,2 , 6740,44 , 4,4 , 4,0 , 747,7 , 1708,7 , 0, 0, 1, 6, 7 }, // English/Latin/Vanuatu
+ { 31, 7, 233, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1715,22 , 2, 1, 1, 6, 7 }, // English/Latin/BritishVirginIslands
+ { 31, 7, 234, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 516,6 , 35,18 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 3700,35 , 4,4 , 4,0 , 747,7 , 1737,19 , 2, 1, 7, 6, 7 }, // English/Latin/UnitedStatesVirginIslands
+ { 31, 7, 239, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,77,87}, 137,1 , 6784,50 , 4,4 , 4,0 , 747,7 , 1756,6 , 2, 1, 1, 6, 7 }, // English/Latin/Zambia
+ { 31, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 406,8 , 80,18 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1762,8 , 2, 1, 7, 6, 7 }, // English/Latin/Zimbabwe
+ { 31, 7, 249, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 3700,35 , 4,4 , 4,0 , 747,7 , 1770,12 , 2, 1, 1, 6, 7 }, // English/Latin/DiegoGarcia
+ { 31, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 125,1 , 4681,32 , 4,4 , 4,0 , 747,7 , 1782,11 , 2, 1, 1, 6, 7 }, // English/Latin/IsleOfMan
+ { 31, 7, 252, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {71,66,80}, 125,1 , 4681,32 , 4,4 , 4,0 , 747,7 , 1793,6 , 2, 1, 1, 6, 7 }, // English/Latin/Jersey
+ { 31, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {83,83,80}, 125,1 , 6834,68 , 4,4 , 4,0 , 747,7 , 1799,11 , 2, 1, 1, 6, 7 }, // English/Latin/SouthSudan
+ { 31, 7, 256, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 191,10 , 201,9 , 120,10 , 10,17 , 37,5 , 8,10 , 0,48 , 48,86 , 134,24 , 0,48 , 48,86 , 134,24 , 0,28 , 28,57 , 85,14 , 0,28 , 28,57 , 85,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {65,78,71}, 161,4 , 6902,95 , 4,4 , 4,0 , 747,7 , 1810,12 , 2, 1, 1, 6, 7 }, // English/Latin/SintMaarten
+ { 33, 7, 68, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 210,8 , 210,8 , 175,8 , 532,18 , 37,5 , 8,10 , 5617,59 , 5676,91 , 5767,24 , 5617,59 , 5676,91 , 5767,24 , 2556,14 , 2570,63 , 2556,14 , 2556,14 , 2570,63 , 2556,14 , 0,2 , 0,2 , 288,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 6997,20 , 13,5 , 4,0 , 1822,5 , 1827,5 , 2, 1, 1, 6, 7 }, // Estonian/Latin/Estonia
+ { 34, 7, 71, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 175,8 , 532,18 , 37,5 , 8,10 , 5791,48 , 5839,83 , 134,24 , 5922,59 , 5839,83 , 134,24 , 2633,28 , 2661,74 , 2735,14 , 2749,35 , 2661,74 , 2735,14 , 0,2 , 0,2 , 294,3 , 297,17 , 22,23 , {68,75,75}, 196,2 , 7017,43 , 13,5 , 4,0 , 1832,8 , 1840,7 , 2, 1, 1, 6, 7 }, // Faroese/Latin/FaroeIslands
+ { 34, 7, 58, 44, 46, 59, 37, 48, 8722, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 175,8 , 532,18 , 37,5 , 8,10 , 5791,48 , 5839,83 , 134,24 , 5922,59 , 5839,83 , 134,24 , 2633,28 , 2661,74 , 2735,14 , 2749,35 , 2661,74 , 2735,14 , 0,2 , 0,2 , 294,3 , 297,17 , 22,23 , {68,75,75}, 154,3 , 7017,43 , 13,5 , 4,0 , 1832,8 , 627,7 , 2, 1, 1, 6, 7 }, // Faroese/Latin/Denmark
+ { 36, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 210,8 , 210,8 , 550,8 , 469,17 , 222,4 , 226,9 , 5981,69 , 6050,105 , 6155,24 , 6179,93 , 6272,129 , 6155,24 , 2784,21 , 2805,67 , 2872,14 , 2784,21 , 2886,81 , 2872,14 , 70,3 , 67,3 , 314,5 , 319,17 , 336,23 , {69,85,82}, 14,1 , 7060,20 , 13,5 , 4,0 , 1847,5 , 1852,5 , 2, 1, 1, 6, 7 }, // Finnish/Latin/Finland
+ { 37, 7, 74, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 1865,6 , 2, 1, 1, 6, 7 }, // French/Latin/France
+ { 37, 7, 3, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {68,90,68}, 208,2 , 7080,51 , 13,5 , 4,0 , 1857,8 , 1871,7 , 2, 1, 6, 5, 6 }, // French/Latin/Algeria
+ { 37, 7, 21, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 509,7 , 98,16 , 37,5 , 235,23 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 1878,8 , 2, 1, 1, 6, 7 }, // French/Latin/Belgium
+ { 37, 7, 23, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 1886,5 , 0, 0, 1, 6, 7 }, // French/Latin/Benin
+ { 37, 7, 34, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 1891,12 , 0, 0, 1, 6, 7 }, // French/Latin/BurkinaFaso
+ { 37, 7, 35, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {66,73,70}, 169,3 , 7190,53 , 13,5 , 4,0 , 1857,8 , 900,7 , 0, 0, 1, 6, 7 }, // French/Latin/Burundi
+ { 37, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 73,5 , 70,4 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 1903,8 , 0, 0, 1, 6, 7 }, // French/Latin/Cameroon
+ { 37, 7, 38, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8221, 8220, 0,6 , 0,6 , 218,8 , 218,8 , 558,8 , 98,16 , 258,9 , 8,10 , 6549,64 , 6464,85 , 134,24 , 6549,64 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 64,4 , 61,4 , 359,6 , 174,17 , 191,23 , {67,65,68}, 6,1 , 7299,54 , 41,8 , 4,0 , 1911,17 , 931,6 , 2, 0, 7, 6, 7 }, // French/Latin/Canada
+ { 37, 7, 41, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 1928,25 , 0, 0, 1, 6, 7 }, // French/Latin/CentralAfricanRepublic
+ { 37, 7, 42, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 1953,5 , 0, 0, 1, 6, 7 }, // French/Latin/Chad
+ { 37, 7, 48, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {75,77,70}, 213,2 , 7353,51 , 13,5 , 4,0 , 1857,8 , 1958,7 , 0, 0, 1, 6, 7 }, // French/Latin/Comoros
+ { 37, 7, 49, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {67,68,70}, 215,2 , 7404,53 , 13,5 , 4,0 , 1857,8 , 1965,14 , 2, 1, 1, 6, 7 }, // French/Latin/CongoKinshasa
+ { 37, 7, 50, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 1979,17 , 0, 0, 1, 6, 7 }, // French/Latin/CongoBrazzaville
+ { 37, 7, 53, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 1996,13 , 0, 0, 1, 6, 7 }, // French/Latin/IvoryCoast
+ { 37, 7, 59, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {68,74,70}, 43,3 , 7457,57 , 13,5 , 4,0 , 1857,8 , 2009,8 , 0, 0, 6, 6, 7 }, // French/Latin/Djibouti
+ { 37, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 2017,18 , 0, 0, 1, 6, 7 }, // French/Latin/EquatorialGuinea
+ { 37, 7, 76, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2035,16 , 2, 1, 1, 6, 7 }, // French/Latin/FrenchGuiana
+ { 37, 7, 77, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,80,70}, 217,4 , 7514,35 , 13,5 , 4,0 , 1857,8 , 2051,19 , 0, 0, 1, 6, 7 }, // French/Latin/FrenchPolynesia
+ { 37, 7, 79, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,65,70}, 32,4 , 7243,56 , 13,5 , 4,0 , 1857,8 , 2070,5 , 0, 0, 1, 6, 7 }, // French/Latin/Gabon
+ { 37, 7, 88, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2075,10 , 2, 1, 1, 6, 7 }, // French/Latin/Guadeloupe
+ { 37, 7, 91, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {71,78,70}, 221,2 , 7549,48 , 13,5 , 4,0 , 1857,8 , 2085,6 , 0, 0, 1, 6, 7 }, // French/Latin/Guinea
+ { 37, 7, 94, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {72,84,71}, 223,1 , 7597,57 , 13,5 , 4,0 , 1857,8 , 2091,5 , 2, 1, 1, 6, 7 }, // French/Latin/Haiti
+ { 37, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2096,10 , 2, 1, 1, 6, 7 }, // French/Latin/Luxembourg
+ { 37, 7, 128, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {77,71,65}, 176,2 , 7654,54 , 13,5 , 4,0 , 1857,8 , 1195,10 , 0, 0, 1, 6, 7 }, // French/Latin/Madagascar
+ { 37, 7, 132, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 2106,4 , 0, 0, 1, 6, 7 }, // French/Latin/Mali
+ { 37, 7, 135, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2110,10 , 2, 1, 1, 6, 7 }, // French/Latin/Martinique
+ { 37, 7, 136, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {77,82,79}, 224,2 , 7708,66 , 13,5 , 4,0 , 1857,8 , 2120,10 , 0, 0, 1, 6, 7 }, // French/Latin/Mauritania
+ { 37, 7, 137, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {77,85,82}, 182,2 , 7774,63 , 13,5 , 4,0 , 1857,8 , 2130,7 , 0, 0, 1, 6, 7 }, // French/Latin/Mauritius
+ { 37, 7, 138, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2137,7 , 2, 1, 1, 6, 7 }, // French/Latin/Mayotte
+ { 37, 7, 142, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2144,6 , 2, 1, 1, 6, 7 }, // French/Latin/Monaco
+ { 37, 7, 145, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6613,61 , 6464,85 , 134,24 , 6613,61 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 64,4 , 61,4 , 359,6 , 174,17 , 191,23 , {77,65,68}, 226,3 , 7837,54 , 13,5 , 4,0 , 1857,8 , 2150,5 , 2, 1, 6, 5, 6 }, // French/Latin/Morocco
+ { 37, 7, 153, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,80,70}, 217,4 , 7514,35 , 13,5 , 4,0 , 1857,8 , 2155,18 , 0, 0, 1, 6, 7 }, // French/Latin/NewCaledonia
+ { 37, 7, 156, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 2173,5 , 0, 0, 1, 6, 7 }, // French/Latin/Niger
+ { 37, 7, 176, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2178,10 , 2, 1, 1, 6, 7 }, // French/Latin/Reunion
+ { 37, 7, 179, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {82,87,70}, 186,2 , 7891,50 , 13,5 , 4,0 , 1857,8 , 1419,6 , 0, 0, 1, 6, 7 }, // French/Latin/Rwanda
+ { 37, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 2188,7 , 0, 0, 1, 6, 7 }, // French/Latin/Senegal
+ { 37, 7, 188, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {83,67,82}, 191,2 , 7941,71 , 13,5 , 4,0 , 1857,8 , 1480,10 , 2, 1, 1, 6, 7 }, // French/Latin/Seychelles
+ { 37, 7, 200, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2195,24 , 2, 1, 1, 6, 7 }, // French/Latin/SaintPierreAndMiquelon
+ { 37, 7, 206, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 218,8 , 218,8 , 175,8 , 10,17 , 37,5 , 267,14 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {67,72,70}, 229,3 , 8012,45 , 13,5 , 4,0 , 2219,15 , 2234,6 , 2, 0, 1, 6, 7 }, // French/Latin/Switzerland
+ { 37, 7, 207, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {83,89,80}, 232,2 , 8057,51 , 13,5 , 4,0 , 1857,8 , 2240,5 , 0, 0, 6, 5, 6 }, // French/Latin/Syria
+ { 37, 7, 212, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,79,70}, 210,3 , 7131,59 , 13,5 , 4,0 , 1857,8 , 2245,4 , 0, 0, 1, 6, 7 }, // French/Latin/Togo
+ { 37, 7, 216, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {84,78,68}, 234,2 , 8108,51 , 13,5 , 4,0 , 1857,8 , 2249,7 , 3, 0, 7, 5, 6 }, // French/Latin/Tunisia
+ { 37, 7, 229, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 18,7 , 25,12 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {86,85,86}, 206,2 , 8159,51 , 13,5 , 4,0 , 1857,8 , 1708,7 , 0, 0, 1, 6, 7 }, // French/Latin/Vanuatu
+ { 37, 7, 235, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {88,80,70}, 217,4 , 7514,35 , 13,5 , 4,0 , 1857,8 , 2256,16 , 0, 0, 1, 6, 7 }, // French/Latin/WallisAndFutunaIslands
+ { 37, 7, 244, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2272,16 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Barthelemy
+ { 37, 7, 245, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 218,8 , 218,8 , 120,10 , 98,16 , 37,5 , 8,10 , 6401,63 , 6464,85 , 134,24 , 6401,63 , 6464,85 , 134,24 , 2967,35 , 3002,52 , 3054,14 , 2967,35 , 3002,52 , 3054,14 , 0,2 , 0,2 , 359,6 , 174,17 , 191,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 1857,8 , 2288,12 , 2, 1, 1, 6, 7 }, // French/Latin/Saint Martin
+ { 38, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 6,8 , 6,8 , 348,8 , 98,16 , 37,5 , 8,10 , 6674,48 , 6722,95 , 134,24 , 6674,48 , 6722,95 , 134,24 , 3068,21 , 3089,54 , 85,14 , 3068,21 , 3089,54 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3410,19 , 8,5 , 49,6 , 2300,10 , 2310,8 , 2, 1, 1, 6, 7 }, // Western Frisian/Latin/Netherlands
+ { 39, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 226,10 , 226,10 , 120,10 , 566,21 , 37,5 , 8,10 , 6817,61 , 6878,142 , 7020,24 , 6817,61 , 7044,167 , 7020,24 , 3143,28 , 3171,69 , 3240,14 , 3143,28 , 3171,69 , 3240,14 , 78,1 , 74,1 , 365,6 , 5,17 , 22,23 , {71,66,80}, 125,1 , 8210,86 , 4,4 , 4,0 , 2318,8 , 2326,22 , 2, 1, 1, 6, 7 }, // Gaelic/Latin/UnitedKingdom
+ { 40, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 7211,60 , 7271,87 , 7358,24 , 7382,60 , 7442,87 , 7529,36 , 3254,35 , 3289,49 , 3338,14 , 3352,35 , 3387,49 , 3436,21 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3865,20 , 13,5 , 4,0 , 2348,6 , 2354,6 , 2, 1, 1, 6, 7 }, // Galician/Latin/Spain
+ { 41, 15, 81, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 171, 187, 0,6 , 0,6 , 243,8 , 243,8 , 175,8 , 614,19 , 37,5 , 8,10 , 7565,48 , 7613,99 , 7712,24 , 7565,48 , 7613,99 , 7712,24 , 3457,28 , 3485,62 , 3547,14 , 3457,28 , 3485,62 , 3547,14 , 0,2 , 0,2 , 371,5 , 376,33 , 22,23 , {71,69,76}, 236,1 , 8296,43 , 13,5 , 4,0 , 2360,7 , 2367,10 , 2, 1, 1, 6, 7 }, // Georgian/Georgian/Georgia
+ { 42, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 7784,83 , 134,24 , 7867,59 , 7784,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 2377,7 , 2384,11 , 2, 1, 1, 6, 7 }, // German/Latin/Germany
+ { 42, 7, 14, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7926,48 , 7974,83 , 134,24 , 8057,59 , 7974,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 8,5 , 4,0 , 2395,24 , 2419,10 , 2, 1, 1, 6, 7 }, // German/Latin/Austria
+ { 42, 7, 21, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 7784,83 , 134,24 , 7867,59 , 7784,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 2377,7 , 2429,7 , 2, 1, 1, 6, 7 }, // German/Latin/Belgium
+ { 42, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7926,48 , 7974,83 , 134,24 , 8057,59 , 7974,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 2377,7 , 2436,7 , 2, 1, 1, 6, 7 }, // German/Latin/Italy
+ { 42, 7, 123, 46, 8217, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 7784,83 , 134,24 , 7867,59 , 7784,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {67,72,70}, 229,3 , 8358,58 , 8,5 , 4,0 , 2377,7 , 2443,13 , 2, 0, 1, 6, 7 }, // German/Latin/Liechtenstein
+ { 42, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 7784,83 , 134,24 , 7867,59 , 7784,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 2377,7 , 2456,9 , 2, 1, 1, 6, 7 }, // German/Latin/Luxembourg
+ { 42, 7, 206, 46, 8217, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 7784,83 , 134,24 , 7867,59 , 7784,83 , 134,24 , 3561,21 , 3582,60 , 3642,14 , 3656,28 , 3582,60 , 3642,14 , 79,5 , 75,6 , 409,5 , 5,17 , 22,23 , {67,72,70}, 229,3 , 8358,58 , 8,5 , 36,5 , 2465,21 , 2486,7 , 2, 0, 1, 6, 7 }, // German/Latin/Switzerland
+ { 43, 16, 85, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 260,9 , 260,9 , 278,6 , 10,17 , 18,7 , 25,12 , 8116,50 , 8166,115 , 8281,24 , 8305,50 , 8355,115 , 8281,24 , 3684,28 , 3712,55 , 3767,14 , 3684,28 , 3712,55 , 3767,14 , 84,4 , 81,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8416,19 , 13,5 , 4,0 , 2493,8 , 2501,6 , 2, 1, 1, 6, 7 }, // Greek/Greek/Greece
+ { 43, 16, 56, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 260,9 , 260,9 , 278,6 , 10,17 , 18,7 , 25,12 , 8116,50 , 8166,115 , 8281,24 , 8305,50 , 8355,115 , 8281,24 , 3684,28 , 3712,55 , 3767,14 , 3684,28 , 3712,55 , 3767,14 , 84,4 , 81,4 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8416,19 , 13,5 , 4,0 , 2493,8 , 2507,6 , 2, 1, 1, 6, 7 }, // Greek/Greek/Cyprus
+ { 44, 7, 86, 44, 46, 59, 37, 48, 8722, 43, 101, 187, 171, 8250, 8249, 0,6 , 0,6 , 269,11 , 269,11 , 53,10 , 633,17 , 18,7 , 25,12 , 8470,48 , 8518,96 , 134,24 , 8470,48 , 8518,96 , 134,24 , 3781,28 , 3809,98 , 3907,14 , 3781,28 , 3809,98 , 3907,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {68,75,75}, 154,3 , 8435,62 , 4,4 , 55,5 , 2513,11 , 2524,16 , 2, 1, 1, 6, 7 }, // Greenlandic/Latin/Greenland
+ { 45, 7, 168, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,89,71}, 237,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Guarani/Latin/Paraguay
+ { 46, 17, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 280,9 , 280,9 , 278,6 , 211,18 , 281,8 , 289,13 , 8614,67 , 8681,87 , 8768,31 , 8614,67 , 8681,87 , 8768,31 , 3921,32 , 3953,53 , 4006,19 , 3921,32 , 3953,53 , 4006,19 , 0,2 , 0,2 , 414,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 8497,46 , 4,4 , 4,0 , 2540,7 , 2547,4 , 2, 1, 7, 7, 7 }, // Gujarati/Gujarati/India
+ { 47, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 278,6 , 211,18 , 37,5 , 8,10 , 8799,48 , 8847,85 , 8932,24 , 8799,48 , 8847,85 , 8932,24 , 4025,28 , 4053,52 , 4105,14 , 4025,28 , 4053,52 , 4105,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 8543,12 , 8,5 , 4,0 , 2551,5 , 2556,8 , 2, 1, 1, 6, 7 }, // Hausa/Latin/Nigeria
+ { 47, 1, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Hausa/Arabic/Nigeria
+ { 47, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 278,6 , 211,18 , 37,5 , 8,10 , 8799,48 , 8847,85 , 8932,24 , 8799,48 , 8847,85 , 8932,24 , 4025,28 , 4053,52 , 4105,14 , 4025,28 , 4053,52 , 4105,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,72,83}, 173,3 , 0,7 , 8,5 , 4,0 , 2551,5 , 2564,4 , 2, 1, 1, 6, 7 }, // Hausa/Latin/Ghana
+ { 47, 7, 156, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 278,6 , 211,18 , 37,5 , 8,10 , 8799,48 , 8847,85 , 8932,24 , 8799,48 , 8847,85 , 8932,24 , 4025,28 , 4053,52 , 4105,14 , 4025,28 , 4053,52 , 4105,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 8555,36 , 8,5 , 4,0 , 2551,5 , 2568,5 , 0, 0, 1, 6, 7 }, // Hausa/Latin/Niger
+ { 48, 18, 105, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 289,6 , 289,6 , 550,8 , 650,18 , 55,4 , 59,9 , 8956,58 , 9014,72 , 158,27 , 8956,58 , 9014,72 , 158,27 , 4119,46 , 4165,65 , 4230,21 , 4119,46 , 4165,65 , 4230,21 , 88,6 , 85,5 , 418,4 , 5,17 , 22,23 , {73,76,83}, 54,1 , 8591,54 , 60,6 , 66,8 , 2573,5 , 2578,5 , 2, 1, 7, 5, 6 }, // Hebrew/Hebrew/Israel
+ { 49, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 295,9 , 304,8 , 278,6 , 10,17 , 18,7 , 25,12 , 9086,59 , 9145,73 , 9218,30 , 9086,59 , 9145,73 , 9218,30 , 4251,32 , 4283,53 , 4336,19 , 4251,32 , 4283,53 , 4336,19 , 94,9 , 90,7 , 422,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 8645,42 , 4,4 , 4,0 , 2583,6 , 2589,4 , 2, 1, 7, 7, 7 }, // Hindi/Devanagari/India
+ { 50, 7, 98, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 187, 171, 0,6 , 0,6 , 312,8 , 312,8 , 668,13 , 681,19 , 55,4 , 59,9 , 9248,64 , 9312,98 , 9410,25 , 9248,64 , 9312,98 , 9410,25 , 4355,19 , 4374,52 , 4426,17 , 4355,19 , 4374,52 , 4426,17 , 103,3 , 97,3 , 426,4 , 5,17 , 22,23 , {72,85,70}, 238,2 , 8687,46 , 13,5 , 4,0 , 2593,6 , 2599,12 , 2, 0, 1, 6, 7 }, // Hungarian/Latin/Hungary
+ { 51, 7, 99, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 183,8 , 183,8 , 550,8 , 532,18 , 37,5 , 8,10 , 9435,59 , 9494,82 , 9576,24 , 9435,59 , 9494,82 , 9576,24 , 4443,35 , 4478,81 , 4559,14 , 4443,35 , 4478,81 , 4559,14 , 106,4 , 100,4 , 430,4 , 5,17 , 22,23 , {73,83,75}, 240,3 , 8733,49 , 13,5 , 4,0 , 2611,8 , 2619,6 , 0, 0, 1, 6, 7 }, // Icelandic/Latin/Iceland
+ { 52, 7, 101, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 320,10 , 330,9 , 27,8 , 80,18 , 200,5 , 205,10 , 9600,48 , 9648,87 , 134,24 , 9600,48 , 9648,87 , 134,24 , 4573,28 , 4601,43 , 4644,14 , 4573,28 , 4601,43 , 4644,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,68,82}, 243,2 , 8782,39 , 4,4 , 4,0 , 2625,9 , 2625,9 , 0, 0, 7, 6, 7 }, // Indonesian/Latin/Indonesia
+ { 53, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Interlingua/Latin/France
+ { 55, 44, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 245,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/CanadianAboriginal/Canada
+ { 55, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 245,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Inuktitut/Latin/Canada
+ { 57, 7, 104, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 339,11 , 226,10 , 120,10 , 98,16 , 37,5 , 8,10 , 9735,62 , 9797,107 , 9904,24 , 9735,62 , 9797,107 , 9904,24 , 4658,37 , 4695,75 , 4770,14 , 4658,37 , 4695,75 , 4770,14 , 64,4 , 61,4 , 434,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8821,31 , 4,4 , 4,0 , 2634,7 , 2641,4 , 2, 1, 7, 6, 7 }, // Irish/Latin/Ireland
+ { 58, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 98,16 , 37,5 , 8,10 , 9928,48 , 9976,94 , 10070,24 , 9928,48 , 9976,94 , 10070,24 , 4784,28 , 4812,57 , 4869,14 , 4784,28 , 4812,57 , 4869,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8852,19 , 13,5 , 4,0 , 2645,8 , 2653,6 , 2, 1, 1, 6, 7 }, // Italian/Latin/Italy
+ { 58, 7, 184, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 98,16 , 37,5 , 8,10 , 9928,48 , 9976,94 , 10070,24 , 9928,48 , 9976,94 , 10070,24 , 4784,28 , 4812,57 , 4869,14 , 4784,28 , 4812,57 , 4869,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8852,19 , 13,5 , 4,0 , 2645,8 , 2659,10 , 2, 1, 1, 6, 7 }, // Italian/Latin/SanMarino
+ { 58, 7, 206, 46, 8217, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 236,7 , 236,7 , 175,8 , 10,17 , 37,5 , 8,10 , 9928,48 , 9976,94 , 10070,24 , 9928,48 , 9976,94 , 10070,24 , 4784,28 , 4812,57 , 4869,14 , 4784,28 , 4812,57 , 4869,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,72,70}, 229,3 , 8871,53 , 8,5 , 36,5 , 2645,8 , 2669,8 , 2, 0, 1, 6, 7 }, // Italian/Latin/Switzerland
+ { 58, 7, 230, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 98,16 , 37,5 , 8,10 , 9928,48 , 9976,94 , 10070,24 , 9928,48 , 9976,94 , 10070,24 , 4784,28 , 4812,57 , 4869,14 , 4784,28 , 4812,57 , 4869,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8852,19 , 13,5 , 4,0 , 2645,8 , 2677,18 , 2, 1, 1, 6, 7 }, // Italian/Latin/VaticanCityState
+ { 59, 19, 108, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 161,5 , 161,5 , 161,5 , 161,5 , 522,10 , 393,13 , 55,4 , 302,10 , 4697,39 , 4697,39 , 158,27 , 4697,39 , 4697,39 , 158,27 , 4883,14 , 4897,28 , 4883,14 , 4883,14 , 4897,28 , 4883,14 , 110,2 , 104,2 , 440,3 , 297,17 , 22,23 , {74,80,89}, 139,1 , 8924,11 , 4,4 , 4,0 , 2695,3 , 2698,2 , 0, 0, 7, 6, 7 }, // Japanese/Japanese/Japan
+ { 60, 7, 101, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,68,82}, 243,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Javanese/Latin/Indonesia
+ { 61, 21, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 350,12 , 362,11 , 278,6 , 35,18 , 281,8 , 289,13 , 10094,63 , 10157,87 , 10244,31 , 10094,63 , 10157,87 , 10244,31 , 4925,33 , 4958,54 , 5012,20 , 4925,33 , 4958,54 , 5012,20 , 112,9 , 106,7 , 443,8 , 451,33 , 22,23 , {73,78,82}, 127,1 , 8935,49 , 4,4 , 4,0 , 2700,5 , 2705,4 , 2, 1, 7, 7, 7 }, // Kannada/Kannada/India
+ { 62, 1, 100, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 516,6 , 35,18 , 18,7 , 25,12 , 10275,72 , 10275,72 , 10347,24 , 10275,72 , 10275,72 , 10347,24 , 5032,54 , 5086,56 , 5142,14 , 5032,54 , 5086,56 , 5142,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 8984,23 , 8,5 , 4,0 , 2709,5 , 2714,10 , 2, 1, 7, 7, 7 }, // Kashmiri/Arabic/India
+ { 63, 2, 110, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 373,10 , 175,8 , 700,22 , 37,5 , 8,10 , 10371,60 , 10431,83 , 10514,24 , 10538,60 , 10598,83 , 10514,24 , 5156,21 , 5177,56 , 5233,14 , 5156,21 , 5247,56 , 5233,14 , 0,2 , 0,2 , 484,4 , 488,17 , 505,23 , {75,90,84}, 248,1 , 9007,58 , 13,5 , 4,0 , 2724,10 , 2734,9 , 2, 1, 1, 6, 7 }, // Kazakh/Cyrillic/Kazakhstan
+ { 64, 7, 179, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 10681,60 , 10741,101 , 158,27 , 10681,60 , 10741,101 , 158,27 , 5303,35 , 5338,84 , 85,14 , 5303,35 , 5338,84 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,87,70}, 186,2 , 0,7 , 8,5 , 4,0 , 2743,11 , 1419,6 , 0, 0, 1, 6, 7 }, // Kinyarwanda/Latin/Rwanda
+ { 65, 2, 116, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 383,10 , 383,10 , 278,6 , 722,23 , 37,5 , 8,10 , 10842,48 , 10890,80 , 10970,24 , 10994,59 , 11053,80 , 10970,24 , 5422,38 , 5460,57 , 5517,14 , 5422,38 , 5460,57 , 5517,14 , 121,5 , 113,14 , 484,4 , 528,17 , 22,23 , {75,71,83}, 249,3 , 9065,52 , 13,5 , 4,0 , 2754,8 , 2762,10 , 2, 1, 1, 6, 7 }, // Kirghiz/Cyrillic/Kyrgyzstan
+ { 66, 22, 114, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 393,7 , 393,7 , 745,9 , 754,16 , 312,7 , 319,13 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 5531,14 , 5545,28 , 5531,14 , 5531,14 , 5545,28 , 5531,14 , 126,2 , 127,2 , 545,3 , 5,17 , 22,23 , {75,82,87}, 252,1 , 9117,19 , 4,4 , 4,0 , 2772,3 , 2775,4 , 0, 0, 7, 6, 7 }, // Korean/Korean/SouthKorea
+ { 66, 22, 113, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 393,7 , 393,7 , 745,9 , 754,16 , 312,7 , 319,13 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 11133,39 , 5531,14 , 5545,28 , 5531,14 , 5531,14 , 5545,28 , 5531,14 , 126,2 , 127,2 , 545,3 , 5,17 , 22,23 , {75,80,87}, 253,3 , 9136,39 , 4,4 , 4,0 , 2772,3 , 2779,11 , 0, 0, 1, 6, 7 }, // Korean/Korean/NorthKorea
+ { 67, 7, 217, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {84,82,89}, 256,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Kurdish/Latin/Turkey
+ { 68, 7, 35, 44, 46, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 11172,60 , 11232,106 , 158,27 , 11172,60 , 11232,106 , 158,27 , 5573,34 , 5607,89 , 85,14 , 5573,34 , 5607,89 , 85,14 , 128,5 , 129,5 , 45,4 , 5,17 , 22,23 , {66,73,70}, 169,3 , 9175,27 , 0,4 , 4,0 , 2790,8 , 2798,8 , 0, 0, 1, 6, 7 }, // Rundi/Latin/Burundi
+ { 69, 23, 117, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 400,9 , 406,8 , 770,19 , 55,4 , 332,24 , 11338,61 , 11399,75 , 158,27 , 11338,61 , 11399,75 , 158,27 , 5696,36 , 5732,57 , 5789,17 , 5696,36 , 5732,57 , 5789,17 , 133,8 , 134,8 , 45,4 , 5,17 , 22,23 , {76,65,75}, 257,1 , 9202,21 , 4,4 , 36,5 , 2806,3 , 2806,3 , 0, 0, 7, 6, 7 }, // Lao/Lao/Laos
+ { 71, 7, 118, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 409,8 , 409,8 , 175,8 , 789,26 , 37,5 , 8,10 , 11474,65 , 11539,101 , 134,24 , 11474,65 , 11539,101 , 134,24 , 5806,51 , 5857,72 , 5929,14 , 5943,51 , 5994,72 , 5929,14 , 141,14 , 142,11 , 548,5 , 297,17 , 22,23 , {69,85,82}, 14,1 , 9223,23 , 13,5 , 4,0 , 2809,8 , 2817,7 , 2, 1, 1, 6, 7 }, // Latvian/Latin/Latvia
+ { 72, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 417,9 , 417,9 , 406,8 , 98,16 , 37,5 , 8,10 , 11640,48 , 11688,203 , 11891,24 , 11640,48 , 11688,203 , 11891,24 , 6066,28 , 6094,100 , 6194,14 , 6066,28 , 6094,100 , 6194,14 , 155,8 , 153,6 , 45,4 , 5,17 , 22,23 , {67,68,70}, 215,2 , 9246,23 , 13,5 , 4,0 , 2824,7 , 2831,30 , 2, 1, 1, 6, 7 }, // Lingala/Latin/CongoKinshasa
+ { 72, 7, 6, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 417,9 , 417,9 , 406,8 , 98,16 , 37,5 , 8,10 , 11640,48 , 11688,203 , 11891,24 , 11640,48 , 11688,203 , 11891,24 , 6066,28 , 6094,100 , 6194,14 , 6066,28 , 6094,100 , 6194,14 , 155,8 , 153,6 , 45,4 , 5,17 , 22,23 , {65,79,65}, 258,2 , 9269,23 , 13,5 , 4,0 , 2824,7 , 2861,6 , 2, 1, 1, 6, 7 }, // Lingala/Latin/Angola
+ { 72, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 417,9 , 417,9 , 406,8 , 98,16 , 37,5 , 8,10 , 11640,48 , 11688,203 , 11891,24 , 11640,48 , 11688,203 , 11891,24 , 6066,28 , 6094,100 , 6194,14 , 6066,28 , 6094,100 , 6194,14 , 155,8 , 153,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 9292,23 , 13,5 , 4,0 , 2824,7 , 2867,26 , 0, 0, 1, 6, 7 }, // Lingala/Latin/CentralAfricanRepublic
+ { 72, 7, 50, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 417,9 , 417,9 , 406,8 , 98,16 , 37,5 , 8,10 , 11640,48 , 11688,203 , 11891,24 , 11640,48 , 11688,203 , 11891,24 , 6066,28 , 6094,100 , 6194,14 , 6066,28 , 6094,100 , 6194,14 , 155,8 , 153,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 9292,23 , 13,5 , 4,0 , 2824,7 , 2893,5 , 0, 0, 1, 6, 7 }, // Lingala/Latin/CongoBrazzaville
+ { 73, 7, 124, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8222, 8220, 0,6 , 0,6 , 426,8 , 426,8 , 53,10 , 815,27 , 37,5 , 8,10 , 11915,70 , 11985,96 , 12081,24 , 11915,70 , 12105,98 , 12081,24 , 6208,21 , 6229,89 , 6318,14 , 6208,21 , 6229,89 , 6318,14 , 163,9 , 159,6 , 553,6 , 5,17 , 22,23 , {69,85,82}, 14,1 , 9315,30 , 13,5 , 4,0 , 2898,8 , 2906,7 , 2, 1, 1, 6, 7 }, // Lithuanian/Latin/Lithuania
+ { 74, 2, 127, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 842,7 , 80,18 , 37,5 , 8,10 , 12203,61 , 12264,85 , 12349,24 , 12203,61 , 12264,85 , 12349,24 , 6332,35 , 6367,54 , 1649,14 , 6421,34 , 6367,54 , 1649,14 , 172,10 , 165,8 , 559,5 , 5,17 , 22,23 , {77,75,68}, 260,3 , 9345,56 , 13,5 , 4,0 , 2913,10 , 2923,10 , 2, 1, 1, 6, 7 }, // Macedonian/Cyrillic/Macedonia
+ { 75, 7, 128, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 98,16 , 37,5 , 8,10 , 12373,48 , 12421,92 , 134,24 , 12373,48 , 12421,92 , 134,24 , 6455,34 , 6489,60 , 6549,14 , 6455,34 , 6489,60 , 6549,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,71,65}, 176,2 , 9401,13 , 8,5 , 4,0 , 2933,8 , 2941,12 , 0, 0, 1, 6, 7 }, // Malagasy/Latin/Madagascar
+ { 76, 7, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 330,9 , 330,9 , 509,7 , 10,17 , 18,7 , 25,12 , 12513,48 , 12561,82 , 12643,24 , 12513,48 , 12561,82 , 12643,24 , 6563,28 , 6591,43 , 6634,14 , 6563,28 , 6591,43 , 6634,14 , 182,2 , 173,3 , 564,4 , 5,17 , 22,23 , {77,89,82}, 180,2 , 9414,39 , 4,4 , 4,0 , 2953,13 , 1211,8 , 2, 1, 1, 6, 7 }, // Malay/Latin/Malaysia
+ { 76, 1, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,89,82}, 180,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Malay/Arabic/Malaysia
+ { 76, 7, 32, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 330,9 , 330,9 , 509,7 , 849,12 , 18,7 , 25,12 , 12513,48 , 12561,82 , 12643,24 , 12513,48 , 12561,82 , 12643,24 , 6563,28 , 6591,43 , 6634,14 , 6563,28 , 6591,43 , 6634,14 , 182,2 , 173,3 , 564,4 , 5,17 , 22,23 , {66,78,68}, 6,1 , 9453,31 , 8,5 , 4,0 , 2953,13 , 2966,6 , 2, 1, 1, 6, 7 }, // Malay/Latin/Brunei
+ { 76, 7, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 330,9 , 330,9 , 509,7 , 10,17 , 18,7 , 25,12 , 12513,48 , 12561,82 , 12643,24 , 12513,48 , 12561,82 , 12643,24 , 6563,28 , 6591,43 , 6634,14 , 6563,28 , 6591,43 , 6634,14 , 182,2 , 173,3 , 564,4 , 5,17 , 22,23 , {83,71,68}, 6,1 , 9484,37 , 4,4 , 4,0 , 2953,13 , 2972,9 , 2, 1, 7, 6, 7 }, // Malay/Latin/Singapore
+ { 77, 24, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 434,13 , 447,12 , 278,6 , 861,18 , 18,7 , 25,12 , 12667,62 , 12729,88 , 12817,32 , 12667,62 , 12729,88 , 12849,31 , 6648,41 , 6689,77 , 6766,22 , 6648,41 , 6788,76 , 6864,21 , 0,2 , 0,2 , 568,6 , 574,31 , 22,23 , {73,78,82}, 127,1 , 9521,40 , 4,4 , 4,0 , 2981,6 , 2987,6 , 2, 1, 7, 7, 7 }, // Malayalam/Malayalam/India
+ { 78, 7, 133, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 459,8 , 467,7 , 120,10 , 879,23 , 37,5 , 8,10 , 12880,48 , 12928,86 , 13014,36 , 12880,48 , 12928,86 , 13050,24 , 6885,28 , 6913,63 , 6976,21 , 6885,28 , 6913,63 , 6997,20 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 9561,27 , 4,4 , 4,0 , 2993,5 , 1219,5 , 2, 1, 7, 6, 7 }, // Maltese/Latin/Malta
+ { 79, 7, 154, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,90,68}, 263,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Maori/Latin/NewZealand
+ { 80, 13, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 474,9 , 474,9 , 278,6 , 211,18 , 18,7 , 25,12 , 13074,66 , 13140,86 , 13226,32 , 13074,66 , 13140,86 , 13226,32 , 7017,32 , 7049,53 , 4336,19 , 7017,32 , 7049,53 , 4336,19 , 184,5 , 176,4 , 422,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 9588,43 , 4,4 , 4,0 , 2998,5 , 2589,4 , 2, 1, 7, 7, 7 }, // Marathi/Devanagari/India
+ { 82, 2, 143, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 902,29 , 37,5 , 8,10 , 13258,99 , 13357,189 , 158,27 , 13258,99 , 13357,189 , 158,27 , 7102,21 , 7123,43 , 7102,21 , 7102,21 , 7123,43 , 7102,21 , 189,3 , 180,3 , 484,4 , 528,17 , 22,23 , {77,78,84}, 266,1 , 9631,25 , 8,5 , 4,0 , 3003,6 , 3009,6 , 0, 0, 1, 6, 7 }, // Mongolian/Cyrillic/Mongolia
+ { 82, 8, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 267,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Mongolian/Mongolian/China
+ { 84, 13, 150, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 483,5 , 0,6 , 488,7 , 488,7 , 53,10 , 63,17 , 37,5 , 8,10 , 13546,85 , 13546,85 , 13631,27 , 13546,85 , 13658,85 , 13631,27 , 7166,33 , 7199,54 , 7253,18 , 7166,33 , 7199,54 , 7253,18 , 94,9 , 90,7 , 422,4 , 5,17 , 22,23 , {78,80,82}, 270,4 , 9656,49 , 8,5 , 4,0 , 3015,6 , 3021,5 , 2, 1, 7, 6, 7 }, // Nepali/Devanagari/Nepal
+ { 84, 13, 100, 46, 44, 59, 37, 2406, 45, 43, 101, 8220, 8221, 8216, 8217, 483,5 , 0,6 , 488,7 , 488,7 , 53,10 , 63,17 , 18,7 , 25,12 , 13546,85 , 13546,85 , 13631,27 , 13546,85 , 13658,85 , 13631,27 , 7166,33 , 7199,54 , 7253,18 , 7166,33 , 7199,54 , 7253,18 , 94,9 , 90,7 , 422,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 9705,49 , 8,5 , 4,0 , 3015,6 , 2589,4 , 2, 1, 7, 7, 7 }, // Nepali/Devanagari/India
+ { 85, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 931,10 , 469,17 , 37,5 , 8,10 , 5791,48 , 13743,83 , 134,24 , 5922,59 , 13743,83 , 134,24 , 2367,35 , 2302,51 , 2353,14 , 2367,35 , 2302,51 , 2353,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {78,79,75}, 196,2 , 9754,44 , 8,5 , 4,0 , 3026,12 , 3038,5 , 2, 1, 1, 6, 7 }, // NorwegianBokmal/Latin/Norway
+ { 85, 7, 203, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 931,10 , 469,17 , 37,5 , 8,10 , 5791,48 , 13743,83 , 134,24 , 5922,59 , 13743,83 , 134,24 , 2367,35 , 2302,51 , 2353,14 , 2367,35 , 2302,51 , 2353,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {78,79,75}, 196,2 , 9754,44 , 8,5 , 4,0 , 3026,12 , 3043,21 , 2, 1, 1, 6, 7 }, // NorwegianBokmal/Latin/SvalbardAndJanMayenIslands
+ { 86, 7, 74, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Occitan/Latin/France
+ { 87, 26, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 941,6 , 10,17 , 18,7 , 25,12 , 13826,86 , 13826,86 , 13912,32 , 13826,86 , 13826,86 , 13912,32 , 7271,33 , 7304,54 , 7358,18 , 7271,33 , 7304,54 , 7358,18 , 68,2 , 65,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 9798,11 , 8,5 , 4,0 , 3064,5 , 3069,4 , 2, 1, 7, 7, 7 }, // Oriya/Oriya/India
+ { 88, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 385,8 , 947,20 , 55,4 , 356,11 , 13944,68 , 13944,68 , 158,27 , 13944,68 , 13944,68 , 158,27 , 7376,49 , 7376,49 , 85,14 , 7376,49 , 7376,49 , 85,14 , 192,4 , 183,4 , 45,4 , 5,17 , 22,23 , {65,70,78}, 274,1 , 9809,25 , 13,5 , 4,0 , 3073,4 , 3077,9 , 0, 0, 6, 4, 5 }, // Pashto/Arabic/Afghanistan
+ { 89, 1, 102, 1643, 1644, 1563, 37, 1776, 45, 43, 101, 171, 187, 8249, 8250, 495,7 , 495,7 , 502,8 , 510,7 , 385,8 , 98,16 , 55,4 , 356,11 , 14012,70 , 14012,70 , 14082,24 , 14106,74 , 14106,74 , 14082,24 , 7376,49 , 7376,49 , 7425,14 , 7376,49 , 7376,49 , 7425,14 , 196,9 , 187,8 , 605,4 , 609,39 , 22,23 , {73,82,82}, 275,4 , 9834,37 , 74,5 , 4,0 , 3086,5 , 3091,5 , 0, 0, 6, 5, 5 }, // Persian/Arabic/Iran
+ { 89, 1, 1, 1643, 1644, 1563, 37, 1776, 45, 43, 101, 171, 187, 8249, 8250, 495,7 , 495,7 , 502,8 , 510,7 , 385,8 , 98,16 , 55,4 , 356,11 , 14180,68 , 14180,68 , 14248,24 , 14272,62 , 14180,68 , 14248,24 , 7376,49 , 7376,49 , 7425,14 , 7376,49 , 7376,49 , 7425,14 , 196,9 , 187,8 , 605,4 , 609,39 , 22,23 , {65,70,78}, 274,1 , 9871,55 , 8,5 , 4,0 , 3096,3 , 3077,9 , 0, 0, 6, 4, 5 }, // Persian/Arabic/Afghanistan
+ { 90, 7, 172, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 154,7 , 154,7 , 931,10 , 10,17 , 37,5 , 8,10 , 14334,48 , 14382,97 , 14479,24 , 14334,48 , 14503,99 , 14602,24 , 7439,34 , 7473,59 , 7532,14 , 7439,34 , 7473,59 , 7546,14 , 0,2 , 0,2 , 283,5 , 5,17 , 22,23 , {80,76,78}, 279,2 , 9926,77 , 13,5 , 4,0 , 3099,6 , 3105,6 , 2, 1, 1, 6, 7 }, // Polish/Latin/Poland
+ { 91, 7, 30, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 236,7 , 236,7 , 120,10 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7560,28 , 7588,79 , 7667,14 , 7560,28 , 7588,79 , 7667,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {66,82,76}, 281,2 , 10003,54 , 4,4 , 4,0 , 3111,9 , 3120,6 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Brazil
+ { 91, 7, 6, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {65,79,65}, 258,2 , 10057,54 , 13,5 , 4,0 , 3111,9 , 3126,6 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Angola
+ { 91, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {67,86,69}, 283,1 , 10111,69 , 13,5 , 4,0 , 3111,9 , 3132,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/CapeVerde
+ { 91, 7, 62, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {85,83,68}, 165,3 , 10180,81 , 13,5 , 4,0 , 3111,9 , 3142,11 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/EastTimor
+ { 91, 7, 66, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 10261,59 , 13,5 , 4,0 , 3111,9 , 3153,16 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/EquatorialGuinea
+ { 91, 7, 92, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {88,79,70}, 210,3 , 10320,62 , 13,5 , 4,0 , 3111,9 , 3169,12 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/GuineaBissau
+ { 91, 7, 125, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 10382,20 , 13,5 , 4,0 , 3111,9 , 3181,10 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Luxembourg
+ { 91, 7, 126, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 18,7 , 25,12 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {77,79,80}, 143,4 , 10402,53 , 13,5 , 4,0 , 3111,9 , 3191,19 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Macau
+ { 91, 7, 146, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {77,90,78}, 284,3 , 10455,72 , 13,5 , 4,0 , 3111,9 , 3210,10 , 2, 1, 7, 6, 7 }, // Portuguese/Latin/Mozambique
+ { 91, 7, 173, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 10382,20 , 13,5 , 4,0 , 3220,17 , 3237,8 , 2, 1, 1, 6, 7 }, // Portuguese/Latin/Portugal
+ { 91, 7, 185, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {83,84,68}, 287,2 , 10527,92 , 13,5 , 4,0 , 3111,9 , 3245,19 , 0, 0, 1, 6, 7 }, // Portuguese/Latin/SaoTomeAndPrincipe
+ { 91, 7, 206, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 587,27 , 37,5 , 8,10 , 14626,48 , 14674,89 , 134,24 , 14626,48 , 14674,89 , 134,24 , 7681,49 , 7588,79 , 7667,14 , 7681,49 , 7588,79 , 7667,14 , 205,8 , 195,8 , 0,5 , 5,17 , 22,23 , {67,72,70}, 229,3 , 10619,45 , 13,5 , 4,0 , 3111,9 , 3264,5 , 2, 0, 1, 6, 7 }, // Portuguese/Latin/Switzerland
+ { 92, 4, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 517,9 , 517,9 , 278,6 , 10,17 , 18,7 , 25,12 , 14763,50 , 14813,68 , 14881,28 , 14763,50 , 14813,68 , 14881,28 , 7730,36 , 7766,57 , 7823,23 , 7730,36 , 7766,57 , 7823,23 , 213,6 , 203,6 , 648,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 10664,39 , 4,4 , 4,0 , 3269,6 , 3275,4 , 2, 1, 7, 7, 7 }, // Punjabi/Gurmukhi/India
+ { 92, 1, 163, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 80,18 , 18,7 , 25,12 , 14909,67 , 14909,67 , 158,27 , 14909,67 , 14909,67 , 158,27 , 7846,37 , 7846,37 , 85,14 , 7846,37 , 7846,37 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,75,82}, 289,1 , 10703,13 , 79,6 , 4,0 , 3279,6 , 3285,7 , 0, 0, 7, 6, 7 }, // Punjabi/Arabic/Pakistan
+ { 93, 7, 169, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 211,18 , 37,5 , 8,10 , 14976,48 , 15024,128 , 158,27 , 14976,48 , 15024,128 , 158,27 , 7883,28 , 7911,53 , 7964,14 , 7883,28 , 7911,53 , 7964,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {80,69,78}, 290,2 , 0,7 , 8,5 , 4,0 , 3292,8 , 3300,4 , 2, 1, 7, 6, 7 }, // Quechua/Latin/Peru
+ { 93, 7, 26, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 211,18 , 37,5 , 8,10 , 14976,48 , 15024,128 , 158,27 , 14976,48 , 15024,128 , 158,27 , 7883,28 , 7911,53 , 7964,14 , 7883,28 , 7911,53 , 7964,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {66,79,66}, 292,2 , 0,7 , 8,5 , 4,0 , 3292,8 , 3304,7 , 2, 1, 1, 6, 7 }, // Quechua/Latin/Bolivia
+ { 93, 7, 63, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 211,18 , 37,5 , 8,10 , 14976,48 , 15024,128 , 158,27 , 14976,48 , 15024,128 , 158,27 , 7883,28 , 7911,53 , 7964,14 , 7883,28 , 7911,53 , 7964,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 8,5 , 4,0 , 3292,8 , 3311,7 , 2, 1, 1, 6, 7 }, // Quechua/Latin/Ecuador
+ { 94, 7, 206, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 348,8 , 967,28 , 37,5 , 8,10 , 15152,67 , 15219,92 , 15311,24 , 15152,67 , 15219,92 , 15311,24 , 7978,23 , 8001,56 , 8057,14 , 7978,23 , 8001,56 , 8057,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,72,70}, 229,3 , 10716,46 , 13,5 , 4,0 , 3318,9 , 3327,6 , 2, 0, 1, 6, 7 }, // Romansh/Latin/Switzerland
+ { 95, 7, 177, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 526,8 , 526,8 , 931,10 , 10,17 , 37,5 , 8,10 , 15335,60 , 15395,98 , 15493,24 , 15335,60 , 15395,98 , 15493,24 , 8071,34 , 8105,48 , 3054,14 , 8071,34 , 8105,48 , 3054,14 , 64,4 , 61,4 , 652,4 , 5,17 , 22,23 , {82,79,78}, 294,3 , 10762,57 , 13,5 , 4,0 , 3333,6 , 3339,7 , 2, 1, 1, 6, 7 }, // Romanian/Latin/Romania
+ { 95, 7, 141, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 526,8 , 526,8 , 931,10 , 10,17 , 37,5 , 8,10 , 15335,60 , 15395,98 , 15493,24 , 15335,60 , 15395,98 , 15493,24 , 8153,28 , 8105,48 , 8181,16 , 8153,28 , 8105,48 , 8181,16 , 64,4 , 61,4 , 652,4 , 5,17 , 22,23 , {77,68,76}, 297,1 , 10819,69 , 13,5 , 4,0 , 3346,13 , 3359,17 , 2, 1, 1, 6, 7 }, // Romanian/Latin/Moldova
+ { 96, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 55,4 , 59,9 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 219,2 , 209,2 , 226,5 , 528,17 , 22,23 , {82,85,66}, 129,1 , 10888,89 , 13,5 , 4,0 , 3376,7 , 3383,6 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Russia
+ { 96, 2, 20, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 55,4 , 59,9 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 219,2 , 209,2 , 226,5 , 528,17 , 22,23 , {66,89,78}, 0,2 , 10977,94 , 13,5 , 4,0 , 3376,7 , 472,8 , 2, 0, 1, 6, 7 }, // Russian/Cyrillic/Belarus
+ { 96, 2, 110, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 55,4 , 59,9 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 219,2 , 209,2 , 226,5 , 528,17 , 22,23 , {75,90,84}, 248,1 , 11071,83 , 13,5 , 4,0 , 3376,7 , 3389,9 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kazakhstan
+ { 96, 2, 116, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 55,4 , 59,9 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 219,2 , 209,2 , 226,5 , 528,17 , 22,23 , {75,71,83}, 249,3 , 11154,82 , 13,5 , 4,0 , 3376,7 , 3398,8 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Kyrgyzstan
+ { 96, 2, 141, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 55,4 , 59,9 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 219,2 , 209,2 , 226,5 , 528,17 , 22,23 , {77,68,76}, 297,1 , 11236,79 , 13,5 , 4,0 , 3376,7 , 3406,7 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Moldova
+ { 96, 2, 222, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 107,7 , 107,7 , 931,10 , 326,22 , 37,5 , 8,10 , 15517,62 , 11053,80 , 10970,24 , 15579,62 , 15641,82 , 10970,24 , 8197,21 , 8218,62 , 8280,14 , 8197,21 , 8218,62 , 8197,21 , 0,2 , 0,2 , 226,5 , 528,17 , 22,23 , {85,65,72}, 298,1 , 11315,92 , 13,5 , 4,0 , 3376,7 , 3413,7 , 2, 1, 1, 6, 7 }, // Russian/Cyrillic/Ukraine
+ { 98, 7, 41, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 15723,48 , 15771,91 , 15862,24 , 15723,48 , 15771,91 , 15862,24 , 8294,28 , 8322,66 , 8388,14 , 8294,28 , 8322,66 , 8388,14 , 221,2 , 211,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 11407,25 , 4,4 , 36,5 , 3420,5 , 3425,22 , 0, 0, 1, 6, 7 }, // Sango/Latin/CentralAfricanRepublic
+ { 99, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 7, 7 }, // Sanskrit/Devanagari/India
+ { 100, 2, 243, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 15886,48 , 15934,81 , 12349,24 , 15886,48 , 15934,81 , 12349,24 , 8402,28 , 8430,52 , 8482,14 , 8402,28 , 8430,52 , 8482,14 , 223,9 , 213,8 , 656,7 , 5,17 , 22,23 , {82,83,68}, 299,3 , 11432,58 , 13,5 , 4,0 , 3447,6 , 3453,6 , 0, 0, 1, 6, 7 }, // Serbian/Cyrillic/Serbia
+ { 100, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16015,58 , 15934,81 , 12349,24 , 16015,58 , 15934,81 , 12349,24 , 8496,33 , 8529,55 , 8482,14 , 8496,33 , 8529,55 , 8482,14 , 232,11 , 213,8 , 656,7 , 5,17 , 22,23 , {66,65,77}, 302,2 , 11490,174 , 13,5 , 4,0 , 3447,6 , 3459,19 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/BosniaAndHerzegowina
+ { 100, 2, 242, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16015,58 , 15934,81 , 12349,24 , 16015,58 , 15934,81 , 12349,24 , 8496,33 , 8529,55 , 8482,14 , 8496,33 , 8529,55 , 8482,14 , 232,11 , 213,8 , 656,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11664,23 , 13,5 , 4,0 , 3447,6 , 3478,9 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Montenegro
+ { 100, 2, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16015,58 , 15934,81 , 12349,24 , 16015,58 , 15934,81 , 12349,24 , 8496,33 , 8430,52 , 8482,14 , 8496,33 , 8430,52 , 8482,14 , 223,9 , 213,8 , 656,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11664,23 , 13,5 , 4,0 , 3447,6 , 3487,6 , 2, 1, 1, 6, 7 }, // Serbian/Cyrillic/Kosovo
+ { 100, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16073,58 , 16131,81 , 16212,24 , 16073,58 , 16131,81 , 16212,24 , 8584,33 , 8617,57 , 2162,14 , 8584,33 , 8617,57 , 2162,14 , 243,11 , 221,8 , 276,7 , 5,17 , 22,23 , {66,65,77}, 150,2 , 11687,174 , 13,5 , 4,0 , 3493,6 , 591,19 , 2, 1, 1, 6, 7 }, // Serbian/Latin/BosniaAndHerzegowina
+ { 100, 7, 242, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16073,58 , 16131,81 , 16212,24 , 16073,58 , 16131,81 , 16212,24 , 8584,33 , 8617,57 , 2162,14 , 8584,33 , 8617,57 , 2162,14 , 243,11 , 221,8 , 276,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11861,23 , 13,5 , 4,0 , 3493,6 , 3499,9 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Montenegro
+ { 100, 7, 243, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16236,48 , 16131,81 , 16212,24 , 16236,48 , 16131,81 , 16212,24 , 8674,28 , 8702,54 , 2162,14 , 8674,28 , 8702,54 , 2162,14 , 254,9 , 221,8 , 276,7 , 5,17 , 22,23 , {82,83,68}, 299,3 , 11884,58 , 13,5 , 4,0 , 3493,6 , 3508,6 , 0, 0, 1, 6, 7 }, // Serbian/Latin/Serbia
+ { 100, 7, 257, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8216, 8216, 0,6 , 0,6 , 154,7 , 154,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 16073,58 , 16131,81 , 16212,24 , 16073,58 , 16131,81 , 16212,24 , 8584,33 , 8702,54 , 2162,14 , 8584,33 , 8702,54 , 2162,14 , 254,9 , 221,8 , 276,7 , 5,17 , 22,23 , {69,85,82}, 14,1 , 11861,23 , 13,5 , 4,0 , 3493,6 , 3514,6 , 2, 1, 1, 6, 7 }, // Serbian/Latin/Kosovo
+ { 101, 2, 81, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 534,9 , 534,9 , 175,8 , 1022,23 , 37,5 , 8,10 , 16284,63 , 16347,82 , 10970,24 , 16429,60 , 16489,86 , 10970,24 , 8756,28 , 8784,61 , 8845,14 , 8859,28 , 8887,61 , 8845,14 , 263,15 , 229,15 , 45,4 , 5,17 , 22,23 , {71,69,76}, 236,1 , 11942,17 , 8,5 , 4,0 , 3520,4 , 3524,11 , 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Georgia
+ { 101, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 534,9 , 534,9 , 175,8 , 1022,23 , 37,5 , 8,10 , 16284,63 , 16347,82 , 10970,24 , 16429,60 , 16489,86 , 10970,24 , 8756,28 , 8784,61 , 8845,14 , 8859,28 , 8887,61 , 8845,14 , 263,15 , 229,15 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 11959,17 , 8,5 , 4,0 , 3520,4 , 3535,6 , 2, 1, 1, 6, 7 }, // Ossetic/Cyrillic/Russia
+ { 102, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Southern Sotho/Latin/SouthAfrica
+ { 103, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tswana/Latin/SouthAfrica
+ { 104, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 16575,48 , 16623,100 , 16723,24 , 16575,48 , 16623,100 , 16723,24 , 8948,28 , 8976,55 , 9031,14 , 8948,28 , 8976,55 , 9031,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 165,3 , 11976,22 , 4,4 , 4,0 , 3541,8 , 1762,8 , 2, 1, 7, 6, 7 }, // Shona/Latin/Zimbabwe
+ { 105, 1, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,75,82}, 182,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 7, 6, 7 }, // Sindhi/Arabic/Pakistan
+ { 106, 32, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 543,9 , 552,8 , 53,10 , 63,17 , 200,5 , 205,10 , 16747,59 , 16806,96 , 16902,32 , 16934,61 , 16806,96 , 16902,32 , 9045,39 , 9084,62 , 9146,19 , 9045,39 , 9084,62 , 9146,19 , 278,5 , 244,4 , 663,5 , 668,37 , 22,23 , {76,75,82}, 304,3 , 11998,58 , 4,4 , 4,0 , 3549,5 , 3554,11 , 2, 1, 1, 6, 7 }, // Sinhala/Sinhala/SriLanka
+ { 107, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Swati/Latin/SouthAfrica
+ { 108, 7, 191, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 176,7 , 560,7 , 1045,10 , 532,18 , 55,4 , 59,9 , 16995,48 , 17043,82 , 16212,24 , 16995,48 , 17125,89 , 16212,24 , 9165,21 , 9186,52 , 9238,14 , 9165,21 , 9186,52 , 9238,14 , 0,2 , 0,2 , 283,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 12056,26 , 13,5 , 4,0 , 3565,10 , 3575,9 , 2, 1, 1, 6, 7 }, // Slovak/Latin/Slovakia
+ { 109, 7, 192, 44, 46, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 567,8 , 567,8 , 1055,9 , 1064,19 , 37,5 , 8,10 , 17214,59 , 17273,86 , 16212,24 , 17214,59 , 17273,86 , 16212,24 , 9252,35 , 9287,52 , 9339,14 , 9252,35 , 9287,52 , 9339,14 , 60,4 , 248,4 , 54,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 12082,28 , 13,5 , 4,0 , 3584,11 , 3595,9 , 2, 1, 1, 6, 7 }, // Slovenian/Latin/Slovenia
+ { 110, 7, 194, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1083,19 , 18,7 , 25,12 , 17359,48 , 17407,189 , 17596,24 , 17359,48 , 17407,189 , 17596,24 , 9353,28 , 9381,47 , 9428,15 , 9353,28 , 9381,47 , 9428,15 , 283,3 , 252,3 , 45,4 , 5,17 , 22,23 , {83,79,83}, 100,1 , 12110,22 , 4,4 , 4,0 , 3604,8 , 3612,10 , 0, 0, 1, 6, 7 }, // Somali/Latin/Somalia
+ { 110, 7, 59, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1083,19 , 18,7 , 25,12 , 17359,48 , 17407,189 , 17596,24 , 17359,48 , 17407,189 , 17596,24 , 9353,28 , 9381,47 , 9428,15 , 9353,28 , 9381,47 , 9428,15 , 283,3 , 252,3 , 45,4 , 5,17 , 22,23 , {68,74,70}, 43,3 , 12132,21 , 4,4 , 4,0 , 3604,8 , 3622,7 , 0, 0, 6, 6, 7 }, // Somali/Latin/Djibouti
+ { 110, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1083,19 , 18,7 , 25,12 , 17359,48 , 17407,189 , 17596,24 , 17359,48 , 17407,189 , 17596,24 , 9353,28 , 9381,47 , 9428,15 , 9353,28 , 9381,47 , 9428,15 , 283,3 , 252,3 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,2 , 12153,22 , 4,4 , 4,0 , 3604,8 , 3629,8 , 2, 1, 7, 6, 7 }, // Somali/Latin/Ethiopia
+ { 110, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1083,19 , 37,5 , 8,10 , 17359,48 , 17407,189 , 17596,24 , 17359,48 , 17407,189 , 17596,24 , 9353,28 , 9381,47 , 9428,15 , 9353,28 , 9381,47 , 9428,15 , 283,3 , 252,3 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 0,7 , 4,4 , 4,0 , 3604,8 , 3637,7 , 2, 1, 7, 6, 7 }, // Somali/Latin/Kenya
+ { 111, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 55,4 , 356,11 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 7964,14 , 9443,35 , 9478,53 , 7964,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 3644,17 , 2354,6 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Spain
+ { 111, 7, 10, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 3054,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {65,82,83}, 6,1 , 12175,51 , 8,5 , 4,0 , 3661,7 , 3668,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Argentina
+ { 111, 7, 22, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {66,90,68}, 6,1 , 12226,52 , 4,4 , 4,0 , 3661,7 , 3677,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Belize
+ { 111, 7, 26, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {66,79,66}, 292,2 , 12278,35 , 4,4 , 4,0 , 3661,7 , 3304,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Bolivia
+ { 111, 7, 30, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {66,82,76}, 281,2 , 12313,52 , 4,4 , 4,0 , 3661,7 , 3120,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Brazil
+ { 111, 7, 43, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 348,8 , 587,27 , 37,5 , 8,10 , 17620,61 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {67,76,80}, 6,1 , 12365,45 , 4,4 , 36,5 , 3661,7 , 3683,5 , 0, 0, 1, 6, 7 }, // Spanish/Latin/Chile
+ { 111, 7, 47, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 509,7 , 587,27 , 18,7 , 25,12 , 17620,61 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 9531,14 , 9443,35 , 9478,53 , 3054,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {67,79,80}, 6,1 , 12410,54 , 8,5 , 4,0 , 3661,7 , 3688,8 , 0, 0, 7, 6, 7 }, // Spanish/Latin/Colombia
+ { 111, 7, 52, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {67,82,67}, 307,1 , 12464,67 , 4,4 , 4,0 , 3661,7 , 3696,10 , 2, 0, 1, 6, 7 }, // Spanish/Latin/CostaRica
+ { 111, 7, 55, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {67,85,80}, 6,1 , 12531,42 , 4,4 , 4,0 , 3661,7 , 3706,4 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Cuba
+ { 111, 7, 61, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 18,7 , 25,12 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 3054,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {68,79,80}, 308,3 , 12573,54 , 4,4 , 85,6 , 3661,7 , 3710,20 , 2, 1, 7, 6, 7 }, // Spanish/Latin/DominicanRepublic
+ { 111, 7, 63, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12627,70 , 4,4 , 36,5 , 3661,7 , 3311,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Ecuador
+ { 111, 7, 65, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12627,70 , 4,4 , 4,0 , 3661,7 , 3730,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/ElSalvador
+ { 111, 7, 66, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 55,4 , 356,11 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 7964,14 , 9443,35 , 9478,53 , 7964,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {88,65,70}, 32,4 , 12697,53 , 4,4 , 4,0 , 3661,7 , 3741,17 , 0, 0, 1, 6, 7 }, // Spanish/Latin/EquatorialGuinea
+ { 111, 7, 90, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 509,7 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {71,84,81}, 311,1 , 12750,30 , 18,5 , 4,0 , 3661,7 , 3758,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Guatemala
+ { 111, 7, 96, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 1102,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {72,78,76}, 297,1 , 12780,60 , 4,4 , 4,0 , 3661,7 , 3767,8 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Honduras
+ { 111, 7, 139, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 27,8 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17878,48 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 3054,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {77,88,78}, 6,1 , 12840,48 , 4,4 , 4,0 , 3775,17 , 3792,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Mexico
+ { 111, 7, 155, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {78,73,79}, 312,2 , 12888,69 , 4,4 , 4,0 , 3661,7 , 3798,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Nicaragua
+ { 111, 7, 166, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 1129,8 , 587,27 , 18,7 , 25,12 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,65,66}, 314,3 , 12957,54 , 4,4 , 4,0 , 3661,7 , 3807,6 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Panama
+ { 111, 7, 168, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,89,71}, 317,3 , 13011,61 , 8,5 , 23,6 , 3661,7 , 3813,8 , 0, 0, 7, 6, 7 }, // Spanish/Latin/Paraguay
+ { 111, 7, 169, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 509,7 , 587,27 , 37,5 , 8,10 , 17926,60 , 17986,88 , 17770,24 , 18074,60 , 18134,88 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,69,78}, 290,2 , 13072,43 , 4,4 , 4,0 , 3661,7 , 3300,4 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Peru
+ { 111, 7, 170, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 18,7 , 25,12 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 7964,14 , 9443,35 , 9478,53 , 7964,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {80,72,80}, 185,1 , 13115,48 , 13,5 , 4,0 , 3661,7 , 3821,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Philippines
+ { 111, 7, 174, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 1129,8 , 587,27 , 18,7 , 25,12 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12627,70 , 4,4 , 4,0 , 3661,7 , 1408,11 , 2, 1, 7, 6, 7 }, // Spanish/Latin/PuertoRico
+ { 111, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 18,7 , 25,12 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,83,68}, 6,1 , 12627,70 , 4,4 , 4,0 , 3661,7 , 3830,7 , 2, 1, 7, 6, 7 }, // Spanish/Latin/UnitedStates
+ { 111, 7, 227, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17926,60 , 17986,88 , 17770,24 , 18074,60 , 18134,88 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {85,89,85}, 6,1 , 13163,48 , 8,5 , 4,0 , 3661,7 , 3837,7 , 2, 1, 1, 6, 7 }, // Spanish/Latin/Uruguay
+ { 111, 7, 231, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 18,7 , 25,12 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {86,69,70}, 320,3 , 13211,64 , 4,4 , 36,5 , 3661,7 , 3844,9 , 2, 1, 7, 6, 7 }, // Spanish/Latin/Venezuela
+ { 111, 7, 238, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 55,4 , 356,11 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 7964,14 , 9443,35 , 9478,53 , 7964,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 3661,7 , 3853,8 , 2, 1, 1, 6, 7 }, // Spanish/Latin/CanaryIslands
+ { 111, 7, 246, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 37,5 , 8,10 , 17794,60 , 17681,89 , 17770,24 , 17794,60 , 17681,89 , 17854,24 , 9443,35 , 9478,53 , 3054,14 , 9443,35 , 9478,53 , 9531,14 , 64,4 , 61,4 , 0,5 , 5,17 , 22,23 , {0,0,0}, 0,0 , 13275,0 , 4,4 , 4,0 , 3861,23 , 3884,13 , 2, 1, 1, 6, 7 }, // Spanish/Latin/LatinAmericaAndTheCaribbean
+ { 111, 7, 250, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 587,27 , 55,4 , 356,11 , 17620,61 , 17681,89 , 17770,24 , 17620,61 , 17681,89 , 17770,24 , 9443,35 , 9478,53 , 7964,14 , 9443,35 , 9478,53 , 7964,14 , 53,5 , 50,5 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 3661,7 , 3897,15 , 2, 1, 1, 6, 7 }, // Spanish/Latin/CeutaAndMelilla
+ { 113, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 582,8 , 582,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 18270,84 , 134,24 , 18222,48 , 18270,84 , 134,24 , 9545,60 , 9545,60 , 85,14 , 9545,60 , 9545,60 , 85,14 , 286,7 , 255,6 , 548,5 , 705,47 , 22,23 , {84,90,83}, 198,3 , 13275,67 , 4,4 , 4,0 , 3912,9 , 1587,8 , 0, 0, 1, 6, 7 }, // Swahili/Latin/Tanzania
+ { 113, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 582,8 , 582,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 18270,84 , 134,24 , 18222,48 , 18270,84 , 134,24 , 9545,60 , 9545,60 , 85,14 , 9545,60 , 9545,60 , 85,14 , 286,7 , 255,6 , 548,5 , 705,47 , 22,23 , {67,68,70}, 215,2 , 13342,55 , 4,4 , 4,0 , 3921,8 , 3929,32 , 2, 1, 1, 6, 7 }, // Swahili/Latin/CongoKinshasa
+ { 113, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 582,8 , 582,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 18270,84 , 134,24 , 18222,48 , 18270,84 , 134,24 , 9545,60 , 9545,60 , 85,14 , 9545,60 , 9545,60 , 85,14 , 0,2 , 0,2 , 548,5 , 705,47 , 22,23 , {75,69,83}, 2,3 , 13397,58 , 4,4 , 4,0 , 3912,9 , 1153,5 , 2, 1, 7, 6, 7 }, // Swahili/Latin/Kenya
+ { 113, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 582,8 , 582,8 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 18270,84 , 134,24 , 18222,48 , 18270,84 , 134,24 , 9545,60 , 9545,60 , 85,14 , 9545,60 , 9545,60 , 85,14 , 286,7 , 255,6 , 548,5 , 705,47 , 22,23 , {85,71,88}, 203,3 , 13455,61 , 4,4 , 4,0 , 3912,9 , 1652,6 , 0, 0, 1, 6, 7 }, // Swahili/Latin/Uganda
+ { 114, 7, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 590,9 , 590,9 , 53,10 , 98,16 , 37,5 , 367,16 , 18354,59 , 18413,86 , 134,24 , 18354,59 , 18413,86 , 134,24 , 9605,29 , 9634,50 , 2353,14 , 9605,29 , 9634,50 , 2353,14 , 293,2 , 261,2 , 45,4 , 5,17 , 22,23 , {83,69,75}, 196,2 , 13516,45 , 13,5 , 4,0 , 3961,7 , 3968,7 , 2, 1, 1, 6, 7 }, // Swedish/Latin/Sweden
+ { 114, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 590,9 , 590,9 , 1137,10 , 98,16 , 37,5 , 367,16 , 18354,59 , 18413,86 , 134,24 , 18354,59 , 18413,86 , 134,24 , 9605,29 , 9634,50 , 2353,14 , 9605,29 , 9634,50 , 2353,14 , 293,2 , 261,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8852,19 , 13,5 , 4,0 , 3961,7 , 1050,7 , 2, 1, 1, 6, 7 }, // Swedish/Latin/Finland
+ { 114, 7, 248, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 590,9 , 590,9 , 53,10 , 98,16 , 37,5 , 367,16 , 18354,59 , 18413,86 , 134,24 , 18354,59 , 18413,86 , 134,24 , 9605,29 , 9634,50 , 2353,14 , 9605,29 , 9634,50 , 2353,14 , 293,2 , 261,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8852,19 , 13,5 , 4,0 , 3961,7 , 3975,5 , 2, 1, 1, 6, 7 }, // Swedish/Latin/AlandIslands
+ { 116, 2, 209, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {84,74,83}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tajik/Cyrillic/Tajikistan
+ { 117, 27, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 599,13 , 599,13 , 278,6 , 211,18 , 312,7 , 383,12 , 18499,58 , 18557,86 , 18643,31 , 18499,58 , 18557,86 , 18643,31 , 9684,39 , 9723,49 , 9772,20 , 9684,39 , 9723,49 , 9772,20 , 295,8 , 263,8 , 752,7 , 5,17 , 22,23 , {73,78,82}, 127,1 , 13561,49 , 8,5 , 4,0 , 3980,5 , 3985,7 , 2, 1, 7, 7, 7 }, // Tamil/Tamil/India
+ { 117, 27, 130, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 599,13 , 599,13 , 278,6 , 211,18 , 312,7 , 383,12 , 18499,58 , 18557,86 , 18643,31 , 18499,58 , 18557,86 , 18643,31 , 9684,39 , 9723,49 , 9772,20 , 9684,39 , 9723,49 , 9772,20 , 295,8 , 263,8 , 752,7 , 5,17 , 22,23 , {77,89,82}, 180,2 , 13610,61 , 8,5 , 4,0 , 3980,5 , 3992,7 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/Malaysia
+ { 117, 27, 190, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 599,13 , 599,13 , 278,6 , 211,18 , 312,7 , 383,12 , 18499,58 , 18557,86 , 18643,31 , 18499,58 , 18557,86 , 18643,31 , 9684,39 , 9723,49 , 9772,20 , 9684,39 , 9723,49 , 9772,20 , 295,8 , 263,8 , 752,7 , 5,17 , 22,23 , {83,71,68}, 6,1 , 13671,61 , 8,5 , 4,0 , 3980,5 , 3999,11 , 2, 1, 7, 6, 7 }, // Tamil/Tamil/Singapore
+ { 117, 27, 198, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 599,13 , 599,13 , 278,6 , 211,18 , 37,5 , 8,10 , 18499,58 , 18557,86 , 18643,31 , 18499,58 , 18557,86 , 18643,31 , 9684,39 , 9723,49 , 9772,20 , 9684,39 , 9723,49 , 9772,20 , 295,8 , 263,8 , 752,7 , 5,17 , 22,23 , {76,75,82}, 323,3 , 13732,49 , 8,5 , 4,0 , 3980,5 , 4010,6 , 2, 1, 1, 6, 7 }, // Tamil/Tamil/SriLanka
+ { 118, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tatar/Cyrillic/Russia
+ { 119, 28, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 612,11 , 612,11 , 348,8 , 1147,18 , 18,7 , 25,12 , 18674,66 , 18740,86 , 18826,31 , 18857,62 , 18740,86 , 18826,31 , 9792,32 , 9824,60 , 9884,18 , 9792,32 , 9824,60 , 9884,18 , 0,2 , 0,2 , 759,7 , 766,27 , 22,23 , {73,78,82}, 127,1 , 13781,26 , 4,4 , 4,0 , 4016,6 , 4022,9 , 2, 1, 7, 7, 7 }, // Telugu/Telugu/India
+ { 120, 30, 211, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 114,5 , 114,5 , 623,8 , 631,7 , 278,6 , 1165,19 , 37,5 , 395,28 , 18919,63 , 18982,98 , 18919,63 , 18919,63 , 18982,98 , 18919,63 , 9902,23 , 9925,68 , 9993,16 , 9902,23 , 9925,68 , 9993,16 , 303,10 , 271,10 , 793,4 , 5,17 , 22,23 , {84,72,66}, 326,3 , 13807,19 , 4,4 , 4,0 , 4031,3 , 4031,3 , 2, 1, 7, 6, 7 }, // Thai/Thai/Thailand
+ { 121, 31, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1184,23 , 18,7 , 25,12 , 2886,63 , 19080,159 , 158,27 , 2886,63 , 19239,147 , 158,27 , 10009,51 , 10060,79 , 10139,27 , 10009,51 , 10060,79 , 10139,27 , 313,7 , 281,8 , 45,4 , 5,17 , 22,23 , {67,78,89}, 329,1 , 13826,13 , 8,5 , 4,0 , 4034,8 , 4042,6 , 2, 1, 7, 6, 7 }, // Tibetan/Tibetan/China
+ { 121, 31, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1184,23 , 18,7 , 25,12 , 2886,63 , 19080,159 , 158,27 , 2886,63 , 19239,147 , 158,27 , 10009,51 , 10060,79 , 10139,27 , 10009,51 , 10060,79 , 10139,27 , 313,7 , 281,8 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 13839,19 , 8,5 , 4,0 , 4034,8 , 4048,7 , 2, 1, 7, 7, 7 }, // Tibetan/Tibetan/India
+ { 122, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1207,23 , 18,7 , 25,12 , 19386,36 , 19422,54 , 19476,24 , 19386,36 , 19422,54 , 19476,24 , 10166,21 , 10187,29 , 10216,14 , 10166,21 , 10230,29 , 10259,14 , 320,7 , 289,7 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,2 , 13858,16 , 4,4 , 4,0 , 4055,4 , 82,5 , 2, 1, 7, 6, 7 }, // Tigrinya/Ethiopic/Ethiopia
+ { 122, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1207,23 , 18,7 , 25,12 , 19386,36 , 19422,54 , 19476,24 , 19386,36 , 19422,54 , 19476,24 , 10166,21 , 10187,29 , 10259,14 , 10166,21 , 10230,29 , 10259,14 , 320,7 , 289,7 , 45,4 , 5,17 , 22,23 , {69,82,78}, 46,3 , 0,7 , 4,4 , 4,0 , 4055,4 , 4059,4 , 2, 1, 1, 6, 7 }, // Tigrinya/Ethiopic/Eritrea
+ { 123, 7, 214, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 638,8 , 638,8 , 638,8 , 638,8 , 278,6 , 98,16 , 18,7 , 25,12 , 19500,51 , 19551,87 , 19638,24 , 19500,51 , 19551,87 , 19638,24 , 10273,29 , 10302,60 , 10362,14 , 10273,29 , 10302,60 , 10362,14 , 327,10 , 296,6 , 797,5 , 802,59 , 861,65 , {84,79,80}, 201,2 , 13874,41 , 8,5 , 4,0 , 4063,13 , 1602,5 , 2, 1, 1, 6, 7 }, // Tongan/Latin/Tonga
+ { 124, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Tsonga/Latin/SouthAfrica
+ { 125, 7, 217, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 646,8 , 646,8 , 1230,9 , 1239,16 , 37,5 , 8,10 , 19662,48 , 19710,75 , 19785,24 , 19662,48 , 19710,75 , 19785,24 , 10376,28 , 10404,54 , 10458,14 , 10376,28 , 10404,54 , 10458,14 , 337,2 , 302,2 , 152,4 , 5,17 , 22,23 , {84,82,89}, 256,1 , 13915,40 , 4,4 , 4,0 , 4076,6 , 4082,7 , 2, 1, 1, 6, 7 }, // Turkish/Latin/Turkey
+ { 125, 7, 56, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 646,8 , 646,8 , 1230,9 , 1239,16 , 18,7 , 25,12 , 19662,48 , 19710,75 , 19785,24 , 19662,48 , 19710,75 , 19785,24 , 10376,28 , 10404,54 , 10458,14 , 10376,28 , 10404,54 , 10458,14 , 337,2 , 302,2 , 152,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 4,4 , 4,0 , 4076,6 , 4089,6 , 2, 1, 1, 6, 7 }, // Turkish/Latin/Cyprus
+ { 126, 7, 218, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8220, 8221, 0,6 , 0,6 , 654,8 , 654,8 , 931,10 , 1239,16 , 37,5 , 8,10 , 19809,51 , 19860,77 , 19937,24 , 19809,51 , 19860,77 , 19937,24 , 10472,21 , 10493,54 , 10547,14 , 10472,21 , 10493,54 , 10547,14 , 0,2 , 0,2 , 926,4 , 5,17 , 22,23 , {84,77,84}, 330,3 , 13955,49 , 13,5 , 4,0 , 4095,9 , 4104,12 , 2, 1, 1, 6, 7 }, // Turkmen/Latin/Turkmenistan
+ { 128, 1, 44, 46, 44, 59, 37, 48, 45, 43, 101, 187, 171, 8250, 8249, 0,6 , 0,6 , 191,10 , 201,9 , 53,10 , 1255,17 , 18,7 , 25,12 , 19961,84 , 19961,84 , 158,27 , 19961,84 , 19961,84 , 158,27 , 10561,21 , 10582,55 , 10637,14 , 10561,21 , 10582,55 , 10637,14 , 339,12 , 304,12 , 45,4 , 5,17 , 22,23 , {67,78,89}, 139,1 , 14004,40 , 4,4 , 4,0 , 4116,8 , 4124,5 , 2, 1, 7, 6, 7 }, // Uighur/Arabic/China
+ { 129, 2, 222, 44, 160, 59, 37, 48, 45, 43, 1077, 171, 187, 8222, 8220, 0,6 , 0,6 , 129,7 , 129,7 , 175,8 , 1272,22 , 37,5 , 8,10 , 20045,48 , 20093,95 , 20188,24 , 20212,67 , 20279,87 , 20366,24 , 1573,21 , 10651,56 , 10707,14 , 1573,21 , 10651,56 , 10707,14 , 351,2 , 316,2 , 930,5 , 528,17 , 22,23 , {85,65,72}, 298,1 , 14044,49 , 13,5 , 4,0 , 4129,10 , 4139,7 , 2, 1, 1, 6, 7 }, // Ukrainian/Cyrillic/Ukraine
+ { 130, 1, 163, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 662,10 , 672,9 , 278,6 , 157,18 , 18,7 , 25,12 , 20390,68 , 20390,68 , 134,24 , 20390,68 , 20390,68 , 134,24 , 10721,39 , 10721,39 , 85,14 , 10721,39 , 10721,39 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {80,75,82}, 182,2 , 14093,49 , 4,4 , 4,0 , 4146,4 , 3285,7 , 0, 0, 7, 6, 7 }, // Urdu/Arabic/Pakistan
+ { 130, 1, 100, 46, 44, 59, 37, 1776, 45, 43, 101, 8221, 8220, 8217, 8216, 46,6 , 46,6 , 681,6 , 681,6 , 278,6 , 157,18 , 18,7 , 25,12 , 20390,68 , 20390,68 , 134,24 , 20390,68 , 20390,68 , 134,24 , 10760,36 , 10760,36 , 85,14 , 10760,36 , 10760,36 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 14142,42 , 8,5 , 4,0 , 4146,4 , 4150,5 , 2, 1, 7, 7, 7 }, // Urdu/Arabic/India
+ { 131, 7, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8217, 8216, 0,6 , 0,6 , 687,8 , 687,8 , 27,8 , 1294,18 , 37,5 , 356,11 , 20458,48 , 20506,75 , 20581,24 , 20605,48 , 20653,75 , 20581,24 , 10796,32 , 10828,61 , 10889,14 , 10796,32 , 10828,61 , 10889,14 , 353,2 , 318,2 , 152,4 , 297,17 , 22,23 , {85,90,83}, 333,4 , 14184,58 , 13,5 , 4,0 , 4155,6 , 4161,11 , 0, 0, 1, 6, 7 }, // Uzbek/Latin/Uzbekistan
+ { 131, 1, 1, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 385,8 , 1312,33 , 55,4 , 356,11 , 20728,47 , 14180,68 , 158,27 , 20728,47 , 14180,68 , 158,27 , 10903,21 , 7376,49 , 85,14 , 10903,21 , 7376,49 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {65,70,78}, 274,1 , 14242,13 , 13,5 , 4,0 , 4172,6 , 3077,9 , 0, 0, 6, 4, 5 }, // Uzbek/Arabic/Afghanistan
+ { 131, 2, 228, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 614,19 , 37,5 , 88,12 , 10842,48 , 20775,71 , 10970,24 , 20846,48 , 20894,71 , 10970,24 , 10924,28 , 10952,53 , 11005,14 , 11019,28 , 11047,53 , 11005,14 , 355,2 , 320,2 , 45,4 , 5,17 , 22,23 , {85,90,83}, 337,3 , 14255,49 , 13,5 , 4,0 , 4178,7 , 4185,10 , 0, 0, 1, 6, 7 }, // Uzbek/Cyrillic/Uzbekistan
+ { 132, 7, 232, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 695,8 , 695,8 , 120,10 , 211,18 , 37,5 , 8,10 , 20965,75 , 21040,99 , 158,27 , 21139,75 , 21214,99 , 158,27 , 11100,33 , 11133,55 , 11188,21 , 11100,33 , 11133,55 , 11188,21 , 357,2 , 322,2 , 45,4 , 5,17 , 22,23 , {86,78,68}, 340,1 , 14304,33 , 8,5 , 4,0 , 4195,10 , 4205,8 , 0, 0, 1, 6, 7 }, // Vietnamese/Latin/Vietnam
+ { 134, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 10,17 , 37,5 , 8,10 , 21313,52 , 21365,87 , 21452,26 , 21478,59 , 21365,87 , 21452,26 , 11209,29 , 11238,77 , 11315,15 , 11330,30 , 11238,77 , 11315,15 , 359,2 , 324,2 , 935,7 , 5,17 , 22,23 , {71,66,80}, 125,1 , 14337,92 , 4,4 , 4,0 , 4213,7 , 4220,16 , 2, 1, 1, 6, 7 }, // Welsh/Latin/UnitedKingdom
+ { 135, 7, 187, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Wolof/Latin/Senegal
+ { 136, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Xhosa/Latin/SouthAfrica
+ { 138, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 21537,73 , 21610,121 , 158,27 , 21537,73 , 21610,121 , 158,27 , 11360,44 , 11404,69 , 85,14 , 11360,44 , 11404,69 , 85,14 , 361,5 , 326,5 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 14429,34 , 4,4 , 4,0 , 4236,10 , 4246,18 , 2, 1, 1, 6, 7 }, // Yoruba/Latin/Nigeria
+ { 138, 7, 23, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 21731,74 , 21805,134 , 158,27 , 21731,74 , 21805,134 , 158,27 , 11473,44 , 11517,69 , 85,14 , 11473,44 , 11517,69 , 85,14 , 366,5 , 331,5 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 14463,34 , 4,4 , 4,0 , 4236,10 , 4264,16 , 0, 0, 1, 6, 7 }, // Yoruba/Latin/Benin
+ { 140, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 703,9 , 712,8 , 516,6 , 35,18 , 37,5 , 8,10 , 21939,48 , 21987,91 , 134,24 , 21939,48 , 22078,93 , 22171,24 , 11586,28 , 11614,74 , 11688,14 , 11586,28 , 11614,74 , 11688,14 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {90,65,82}, 5,1 , 14497,67 , 4,4 , 4,0 , 4280,7 , 4287,14 , 2, 1, 7, 6, 7 }, // Zulu/Latin/SouthAfrica
+ { 141, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 183,8 , 183,8 , 931,10 , 469,17 , 37,5 , 367,16 , 5791,48 , 13743,83 , 134,24 , 22195,59 , 13743,83 , 134,24 , 11702,28 , 11730,51 , 2353,14 , 11781,28 , 11730,51 , 2353,14 , 371,9 , 336,11 , 45,4 , 5,17 , 22,23 , {78,79,75}, 196,2 , 14564,42 , 13,5 , 4,0 , 4301,7 , 4308,5 , 2, 1, 1, 6, 7 }, // NorwegianNynorsk/Latin/Norway
+ { 142, 7, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8221, 8216, 8217, 0,6 , 0,6 , 154,7 , 154,7 , 995,7 , 441,19 , 37,5 , 8,10 , 16236,48 , 22254,83 , 16212,24 , 16236,48 , 22254,83 , 16212,24 , 2076,28 , 2104,58 , 2162,14 , 2076,28 , 2104,58 , 2176,14 , 380,10 , 347,7 , 276,7 , 5,17 , 22,23 , {66,65,77}, 150,2 , 14606,170 , 13,5 , 4,0 , 4313,8 , 591,19 , 2, 1, 1, 6, 7 }, // Bosnian/Latin/BosniaAndHerzegowina
+ { 142, 2, 27, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 107,7 , 107,7 , 995,7 , 1002,20 , 37,5 , 8,10 , 15886,48 , 22337,83 , 12349,24 , 15886,48 , 22337,83 , 12349,24 , 11809,28 , 11837,54 , 8482,14 , 11809,28 , 11837,54 , 8482,14 , 223,9 , 354,7 , 45,4 , 5,17 , 22,23 , {66,65,77}, 302,2 , 14776,151 , 13,5 , 4,0 , 4321,8 , 3459,19 , 2, 1, 1, 6, 7 }, // Bosnian/Cyrillic/BosniaAndHerzegowina
+ { 143, 29, 131, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,86,82}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 5, 6, 7 }, // Divehi/Thaana/Maldives
+ { 144, 7, 251, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 633,17 , 37,5 , 8,10 , 22420,102 , 22522,140 , 158,27 , 22420,102 , 22522,140 , 158,27 , 11891,30 , 11921,57 , 85,14 , 11891,30 , 11921,57 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 125,1 , 0,7 , 4,4 , 4,0 , 4329,5 , 4334,12 , 2, 1, 1, 6, 7 }, // Manx/Latin/IsleOfMan
+ { 145, 7, 224, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 98,16 , 37,5 , 8,10 , 22662,46 , 22708,130 , 158,27 , 22662,46 , 22708,130 , 158,27 , 11978,28 , 12006,61 , 85,14 , 11978,28 , 12006,61 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {71,66,80}, 125,1 , 0,7 , 4,4 , 4,0 , 4346,8 , 4354,14 , 2, 1, 1, 6, 7 }, // Cornish/Latin/UnitedKingdom
+ { 146, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1345,8 , 1353,18 , 18,7 , 25,12 , 22838,48 , 22886,192 , 158,27 , 22838,48 , 22886,192 , 158,27 , 12067,28 , 12095,49 , 12144,14 , 12067,28 , 12095,49 , 12144,14 , 390,2 , 361,2 , 45,4 , 5,17 , 22,23 , {71,72,83}, 173,3 , 14927,17 , 4,4 , 4,0 , 4368,4 , 4372,5 , 2, 1, 1, 6, 7 }, // Akan/Latin/Ghana
+ { 147, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 941,6 , 98,16 , 18,7 , 25,12 , 23078,87 , 23078,87 , 158,27 , 23078,87 , 23078,87 , 158,27 , 7017,32 , 12158,55 , 85,14 , 7017,32 , 12158,55 , 85,14 , 184,5 , 363,5 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 4377,6 , 2589,4 , 2, 1, 7, 7, 7 }, // Konkani/Devanagari/India
+ { 148, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,72,83}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Ga/Latin/Ghana
+ { 149, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 23165,48 , 23213,86 , 158,27 , 23165,48 , 23213,86 , 158,27 , 12213,29 , 12242,57 , 85,14 , 12213,29 , 12242,57 , 85,14 , 38,4 , 368,4 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 14944,12 , 4,4 , 4,0 , 4383,4 , 1303,7 , 2, 1, 1, 6, 7 }, // Igbo/Latin/Nigeria
+ { 150, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 23299,48 , 23347,189 , 23536,24 , 23299,48 , 23347,189 , 23536,24 , 12299,28 , 12327,74 , 12401,14 , 12299,28 , 12327,74 , 12401,14 , 392,9 , 372,7 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 14956,23 , 4,4 , 4,0 , 4387,7 , 1153,5 , 2, 1, 7, 6, 7 }, // Kamba/Latin/Kenya
+ { 151, 33, 103, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,81,68}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 6, 5, 6 }, // Syriac/Syriac/Iraq
+ { 152, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,82,78}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Blin/Ethiopic/Eritrea
+ { 153, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Geez/Ethiopic/Ethiopia
+ { 155, 7, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Sidamo/Latin/Ethiopia
+ { 156, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Atsam/Latin/Nigeria
+ { 157, 14, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,82,78}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tigre/Ethiopic/Eritrea
+ { 158, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Jju/Latin/Nigeria
+ { 159, 7, 106, 44, 46, 59, 37, 48, 45, 43, 101, 8216, 8217, 8220, 8221, 0,6 , 0,6 , 236,7 , 236,7 , 27,8 , 1371,27 , 37,5 , 8,10 , 23560,48 , 23608,77 , 23685,24 , 23560,48 , 23608,77 , 23685,24 , 12415,28 , 12443,50 , 3054,14 , 12415,28 , 12443,50 , 3054,14 , 401,2 , 379,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 8,5 , 4,0 , 4394,6 , 4400,6 , 2, 1, 1, 6, 7 }, // Friulian/Latin/Italy
+ { 160, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Venda/Latin/SouthAfrica
+ { 161, 7, 83, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 720,11 , 731,10 , 516,6 , 1398,23 , 423,12 , 435,17 , 23709,48 , 23757,87 , 23844,24 , 23709,48 , 23757,87 , 23844,24 , 12493,28 , 12521,44 , 12565,14 , 12493,28 , 12521,44 , 12565,14 , 403,3 , 381,5 , 45,4 , 5,17 , 22,23 , {71,72,83}, 173,3 , 14979,37 , 4,4 , 4,0 , 4406,6 , 4412,12 , 2, 1, 1, 6, 7 }, // Ewe/Latin/Ghana
+ { 161, 7, 212, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 720,11 , 731,10 , 516,6 , 1398,23 , 37,5 , 8,10 , 23709,48 , 23757,87 , 23844,24 , 23709,48 , 23757,87 , 23844,24 , 12493,28 , 12521,44 , 12565,14 , 12493,28 , 12521,44 , 12565,14 , 403,3 , 381,5 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 15016,106 , 4,4 , 4,0 , 4406,6 , 4424,11 , 0, 0, 1, 6, 7 }, // Ewe/Latin/Togo
+ { 162, 14, 69, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,84,66}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Walamo/Ethiopic/Ethiopia
+ { 163, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 278,6 , 10,17 , 18,7 , 25,12 , 23868,59 , 23927,95 , 158,27 , 23868,59 , 23927,95 , 158,27 , 12579,21 , 12600,57 , 85,14 , 12579,21 , 12600,57 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 4,4 , 4,0 , 4435,14 , 4449,19 , 2, 1, 7, 6, 7 }, // Hawaiian/Latin/UnitedStates
+ { 164, 7, 157, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {78,71,78}, 184,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Tyap/Latin/Nigeria
+ { 165, 7, 129, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,87,75}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Nyanja/Latin/Malawi
+ { 166, 7, 170, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 741,9 , 750,8 , 516,6 , 35,18 , 18,7 , 25,12 , 24022,48 , 24070,88 , 24158,38 , 24022,48 , 24070,88 , 24022,48 , 12657,28 , 12685,55 , 12657,28 , 12657,28 , 12685,55 , 12657,28 , 0,2 , 0,2 , 0,5 , 5,17 , 22,23 , {80,72,80}, 185,1 , 15122,58 , 4,4 , 4,0 , 4468,8 , 4476,9 , 2, 1, 7, 6, 7 }, // Filipino/Latin/Philippines
+ { 167, 7, 206, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 24196,86 , 134,24 , 7736,48 , 24196,86 , 134,24 , 12740,28 , 12768,63 , 3642,14 , 12740,28 , 12768,63 , 3642,14 , 406,12 , 386,11 , 45,4 , 5,17 , 22,23 , {67,72,70}, 229,3 , 15180,55 , 13,5 , 4,0 , 4485,16 , 4501,7 , 2, 0, 1, 6, 7 }, // Swiss German/Latin/Switzerland
+ { 167, 7, 74, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 24196,86 , 134,24 , 7736,48 , 24196,86 , 134,24 , 12740,28 , 12768,63 , 3642,14 , 12740,28 , 12768,63 , 3642,14 , 406,12 , 386,11 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 4485,16 , 4508,10 , 2, 1, 1, 6, 7 }, // Swiss German/Latin/France
+ { 167, 7, 123, 46, 8217, 59, 37, 48, 8722, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 251,9 , 251,9 , 175,8 , 532,18 , 37,5 , 8,10 , 7736,48 , 24196,86 , 134,24 , 7736,48 , 24196,86 , 134,24 , 12740,28 , 12768,63 , 3642,14 , 12740,28 , 12768,63 , 3642,14 , 406,12 , 386,11 , 45,4 , 5,17 , 22,23 , {67,72,70}, 229,3 , 15180,55 , 13,5 , 4,0 , 4485,16 , 4518,13 , 2, 0, 1, 6, 7 }, // Swiss German/Latin/Liechtenstein
+ { 168, 34, 44, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 24282,38 , 24282,38 , 158,27 , 24282,38 , 24282,38 , 158,27 , 12831,21 , 12852,28 , 12880,14 , 12831,21 , 12852,28 , 12880,14 , 418,2 , 397,2 , 45,4 , 5,17 , 22,23 , {67,78,89}, 329,1 , 0,7 , 8,5 , 4,0 , 4531,3 , 4534,2 , 2, 1, 7, 6, 7 }, // Sichuan Yi/Yi/China
+ { 169, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {76,82,68}, 6,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Kpelle/Latin/Liberia
+ { 170, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 409,8 , 409,8 , 356,7 , 1421,23 , 452,10 , 462,19 , 7867,59 , 24320,85 , 134,24 , 7867,59 , 24320,85 , 134,24 , 12894,28 , 12922,65 , 3642,14 , 12894,28 , 12922,65 , 3642,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15235,15 , 13,5 , 4,0 , 4536,14 , 4550,11 , 2, 1, 1, 6, 7 }, // Low German/Latin/Germany
+ { 170, 7, 151, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 409,8 , 409,8 , 356,7 , 1421,23 , 452,10 , 462,19 , 7867,59 , 24320,85 , 134,24 , 7867,59 , 24320,85 , 134,24 , 12894,28 , 12922,65 , 3642,14 , 12894,28 , 12922,65 , 3642,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15235,15 , 13,5 , 4,0 , 4536,14 , 4561,12 , 2, 1, 1, 6, 7 }, // Low German/Latin/Netherlands
+ { 171, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // South Ndebele/Latin/SouthAfrica
+ { 172, 7, 195, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {90,65,82}, 5,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Northern Sotho/Latin/SouthAfrica
+ { 173, 7, 161, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 210,8 , 210,8 , 53,10 , 63,17 , 37,5 , 8,10 , 24405,59 , 24464,145 , 24609,24 , 24405,59 , 24464,145 , 24609,24 , 12987,33 , 13020,75 , 13095,14 , 12987,33 , 13020,75 , 13095,14 , 420,11 , 399,13 , 45,4 , 5,17 , 22,23 , {78,79,75}, 196,2 , 15250,63 , 13,5 , 4,0 , 4573,15 , 4588,5 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Norway
+ { 173, 7, 73, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 210,8 , 210,8 , 53,10 , 63,17 , 37,5 , 8,10 , 24405,59 , 24464,145 , 24609,24 , 24405,59 , 24464,145 , 24609,24 , 12987,33 , 13020,75 , 13109,14 , 12987,33 , 13123,79 , 13109,14 , 420,11 , 399,13 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15313,23 , 13,5 , 4,0 , 4573,15 , 4593,6 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Finland
+ { 173, 7, 205, 44, 160, 59, 37, 48, 8722, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 210,8 , 210,8 , 53,10 , 63,17 , 37,5 , 8,10 , 24405,59 , 24464,145 , 24609,24 , 24405,59 , 24464,145 , 24609,24 , 12987,33 , 13020,75 , 13095,14 , 12987,33 , 13020,75 , 13095,14 , 420,11 , 399,13 , 45,4 , 5,17 , 22,23 , {83,69,75}, 196,2 , 15336,63 , 13,5 , 4,0 , 4573,15 , 4599,6 , 2, 1, 1, 6, 7 }, // Northern Sami/Latin/Sweden
+ { 174, 7, 208, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {84,87,68}, 341,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Taroko/Latin/Taiwan
+ { 175, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 24633,48 , 24681,88 , 24769,24 , 24633,48 , 24681,88 , 24769,24 , 13202,28 , 13230,62 , 13292,14 , 13202,28 , 13230,62 , 13292,14 , 431,6 , 412,3 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15399,24 , 4,4 , 4,0 , 4605,8 , 1153,5 , 2, 1, 7, 6, 7 }, // Gusii/Latin/Kenya
+ { 176, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 24793,48 , 24841,221 , 25062,24 , 24793,48 , 24841,221 , 25062,24 , 13306,28 , 13334,105 , 13439,14 , 13306,28 , 13334,105 , 13439,14 , 437,10 , 415,10 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15399,24 , 4,4 , 4,0 , 4613,7 , 1153,5 , 2, 1, 7, 6, 7 }, // Taita/Latin/Kenya
+ { 177, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 25086,48 , 25134,77 , 25211,24 , 25086,48 , 25134,77 , 25211,24 , 13453,28 , 13481,59 , 13540,14 , 13453,28 , 13481,59 , 13540,14 , 447,6 , 425,7 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 15423,26 , 13,5 , 4,0 , 4620,6 , 4626,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Senegal
+ { 177, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 25086,48 , 25134,77 , 25211,24 , 25086,48 , 25134,77 , 25211,24 , 13453,28 , 13481,59 , 13540,14 , 13453,28 , 13481,59 , 13540,14 , 447,6 , 425,7 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 15449,25 , 13,5 , 4,0 , 4620,6 , 4634,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Cameroon
+ { 177, 7, 91, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 25086,48 , 25134,77 , 25211,24 , 25086,48 , 25134,77 , 25211,24 , 13453,28 , 13481,59 , 13540,14 , 13453,28 , 13481,59 , 13540,14 , 447,6 , 425,7 , 45,4 , 5,17 , 22,23 , {71,78,70}, 221,2 , 0,7 , 13,5 , 4,0 , 4620,6 , 4642,4 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Guinea
+ { 177, 7, 136, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 18,7 , 25,12 , 25086,48 , 25134,77 , 25211,24 , 25086,48 , 25134,77 , 25211,24 , 13453,28 , 13481,59 , 13540,14 , 13453,28 , 13481,59 , 13540,14 , 447,6 , 425,7 , 45,4 , 5,17 , 22,23 , {77,82,79}, 224,2 , 15474,22 , 13,5 , 4,0 , 4620,6 , 4646,8 , 0, 0, 1, 6, 7 }, // Fulah/Latin/Mauritania
+ { 178, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 25235,48 , 25283,185 , 25468,24 , 25235,48 , 25283,185 , 25468,24 , 13554,28 , 13582,63 , 13645,14 , 13554,28 , 13582,63 , 13645,14 , 453,6 , 432,8 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15496,23 , 4,4 , 4,0 , 4654,6 , 1153,5 , 2, 1, 7, 6, 7 }, // Kikuyu/Latin/Kenya
+ { 179, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 25492,48 , 25540,173 , 25713,24 , 25492,48 , 25540,173 , 25713,24 , 13659,28 , 13687,105 , 13792,14 , 13659,28 , 13687,105 , 13792,14 , 459,7 , 440,5 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15519,25 , 4,4 , 4,0 , 4660,8 , 1153,5 , 2, 1, 7, 6, 7 }, // Samburu/Latin/Kenya
+ { 180, 7, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 587,27 , 37,5 , 8,10 , 25737,48 , 25785,88 , 134,24 , 25737,48 , 25785,88 , 134,24 , 13806,28 , 13834,55 , 13889,14 , 13806,28 , 13834,55 , 13889,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,90,78}, 284,3 , 15544,28 , 0,4 , 4,0 , 4668,4 , 3210,10 , 2, 1, 7, 6, 7 }, // Sena/Latin/Mozambique
+ { 181, 7, 240, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 25873,52 , 25925,112 , 26037,24 , 25873,52 , 25925,112 , 26037,24 , 13903,28 , 13931,50 , 13981,14 , 13903,28 , 13931,50 , 13981,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 165,3 , 15572,24 , 4,4 , 4,0 , 4672,10 , 1762,8 , 2, 1, 7, 6, 7 }, // North Ndebele/Latin/Zimbabwe
+ { 182, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26061,39 , 26100,194 , 26294,24 , 26061,39 , 26100,194 , 26294,24 , 13995,29 , 14024,65 , 14089,14 , 13995,29 , 14024,65 , 14089,14 , 466,8 , 445,7 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15596,25 , 4,4 , 4,0 , 4682,9 , 1587,8 , 0, 0, 1, 6, 7 }, // Rombo/Latin/Tanzania
+ { 183, 9, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 26318,48 , 26366,81 , 26447,24 , 26318,48 , 26366,81 , 26447,24 , 14103,30 , 14133,47 , 85,14 , 14103,30 , 14133,47 , 85,14 , 474,6 , 452,8 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 15621,21 , 0,4 , 4,0 , 4691,7 , 4698,6 , 2, 1, 6, 5, 6 }, // Tachelhit/Tifinagh/Morocco
+ { 183, 7, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 26471,48 , 26519,81 , 26600,24 , 26471,48 , 26519,81 , 26600,24 , 14180,30 , 14210,48 , 85,14 , 14180,30 , 14210,48 , 85,14 , 480,6 , 460,8 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 15642,21 , 0,4 , 4,0 , 4704,10 , 4714,6 , 2, 1, 6, 5, 6 }, // Tachelhit/Latin/Morocco
+ { 184, 7, 3, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 18,7 , 25,12 , 26624,48 , 26672,84 , 26756,24 , 26624,48 , 26672,84 , 26756,24 , 14258,30 , 14288,51 , 14339,14 , 14258,30 , 14288,51 , 14339,14 , 486,7 , 468,9 , 45,4 , 5,17 , 22,23 , {68,90,68}, 208,2 , 15663,21 , 0,4 , 4,0 , 4720,9 , 4729,8 , 2, 1, 6, 5, 6 }, // Kabyle/Latin/Algeria
+ { 185, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26780,48 , 26828,152 , 134,24 , 26780,48 , 26828,152 , 134,24 , 14353,28 , 14381,74 , 14455,14 , 14353,28 , 14381,74 , 14455,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,71,88}, 203,3 , 15684,26 , 4,4 , 4,0 , 4737,10 , 1652,6 , 0, 0, 1, 6, 7 }, // Nyankole/Latin/Uganda
+ { 186, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26980,48 , 27028,254 , 27282,24 , 26980,48 , 27028,254 , 27282,24 , 14469,28 , 14497,82 , 14579,14 , 14469,28 , 14497,82 , 14579,14 , 493,7 , 477,7 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15710,29 , 0,4 , 4,0 , 4747,6 , 4753,10 , 0, 0, 1, 6, 7 }, // Bena/Latin/Tanzania
+ { 187, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 27306,87 , 134,24 , 18222,48 , 27306,87 , 134,24 , 14593,28 , 14621,62 , 14683,14 , 14593,28 , 14621,62 , 14683,14 , 500,5 , 484,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15739,27 , 4,4 , 4,0 , 4763,8 , 1587,8 , 0, 0, 1, 6, 7 }, // Vunjo/Latin/Tanzania
+ { 188, 7, 132, 46, 44, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 27393,47 , 27440,92 , 27532,24 , 27393,47 , 27440,92 , 27532,24 , 14697,28 , 14725,44 , 14769,14 , 14697,28 , 14725,44 , 14769,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 15766,24 , 4,4 , 4,0 , 4771,9 , 2106,4 , 0, 0, 1, 6, 7 }, // Bambara/Latin/Mali
+ { 188, 75, 132, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Bambara/Nko/Mali
+ { 189, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 27556,48 , 27604,207 , 27811,24 , 27556,48 , 27604,207 , 27811,24 , 14783,28 , 14811,64 , 14875,14 , 14783,28 , 14811,64 , 14875,14 , 505,2 , 493,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15399,24 , 4,4 , 4,0 , 4780,6 , 1153,5 , 2, 1, 7, 6, 7 }, // Embu/Latin/Kenya
+ { 190, 12, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 758,8 , 758,8 , 516,6 , 35,18 , 18,7 , 25,12 , 27835,36 , 27871,58 , 27929,24 , 27835,36 , 27871,58 , 27929,24 , 14889,28 , 14917,49 , 14966,14 , 14889,28 , 14917,49 , 14966,14 , 507,3 , 495,6 , 942,6 , 5,17 , 22,23 , {85,83,68}, 6,1 , 15790,25 , 4,4 , 4,0 , 4786,3 , 4789,15 , 2, 1, 7, 6, 7 }, // Cherokee/Cherokee/UnitedStates
+ { 191, 7, 137, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 27953,47 , 28000,68 , 28068,24 , 27953,47 , 28000,68 , 28068,24 , 14980,27 , 15007,48 , 15055,14 , 14980,27 , 15007,48 , 15055,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {77,85,82}, 182,2 , 15815,21 , 79,6 , 4,0 , 4804,14 , 4818,5 , 0, 0, 1, 6, 7 }, // Morisyen/Latin/Mauritius
+ { 192, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 28092,264 , 134,24 , 18222,48 , 28092,264 , 134,24 , 15069,28 , 15097,133 , 14089,14 , 15069,28 , 15097,133 , 14089,14 , 510,4 , 501,5 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15739,27 , 4,4 , 4,0 , 4823,10 , 1587,8 , 0, 0, 1, 6, 7 }, // Makonde/Latin/Tanzania
+ { 193, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8221, 8221, 8217, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28356,83 , 28439,111 , 28550,24 , 28356,83 , 28439,111 , 28550,24 , 15230,36 , 15266,63 , 15329,14 , 15230,36 , 15266,63 , 15329,14 , 514,3 , 506,3 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15836,29 , 79,6 , 4,0 , 4833,8 , 4841,9 , 0, 0, 1, 6, 7 }, // Langi/Latin/Tanzania
+ { 194, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28574,48 , 28622,97 , 134,24 , 28574,48 , 28622,97 , 134,24 , 15343,28 , 15371,66 , 15437,14 , 15343,28 , 15371,66 , 15437,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,71,88}, 203,3 , 15865,26 , 0,4 , 4,0 , 4850,7 , 4857,7 , 0, 0, 1, 6, 7 }, // Ganda/Latin/Uganda
+ { 195, 7, 239, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 28719,48 , 28767,83 , 28850,24 , 28719,48 , 28767,83 , 28850,24 , 15451,80 , 15451,80 , 85,14 , 15451,80 , 15451,80 , 85,14 , 517,8 , 509,7 , 45,4 , 5,17 , 22,23 , {90,77,87}, 137,1 , 0,7 , 4,4 , 4,0 , 4864,9 , 1756,6 , 2, 1, 1, 6, 7 }, // Bemba/Latin/Zambia
+ { 196, 7, 39, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 154,7 , 154,7 , 406,8 , 1444,27 , 37,5 , 8,10 , 28874,48 , 28922,85 , 134,24 , 28874,48 , 28922,85 , 134,24 , 15531,28 , 15559,73 , 15632,14 , 15531,28 , 15646,73 , 15632,14 , 68,2 , 65,2 , 45,4 , 297,17 , 22,23 , {67,86,69}, 283,1 , 15891,43 , 13,5 , 4,0 , 4873,12 , 4885,10 , 2, 1, 1, 6, 7 }, // Kabuverdianu/Latin/CapeVerde
+ { 197, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29007,48 , 29055,86 , 29141,24 , 29007,48 , 29055,86 , 29141,24 , 15719,28 , 15747,51 , 15798,14 , 15719,28 , 15747,51 , 15798,14 , 525,2 , 516,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15399,24 , 4,4 , 4,0 , 4895,6 , 1153,5 , 2, 1, 7, 6, 7 }, // Meru/Latin/Kenya
+ { 198, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29165,49 , 29214,121 , 29335,24 , 29165,49 , 29214,121 , 29335,24 , 15812,28 , 15840,53 , 15893,14 , 15812,28 , 15840,53 , 15893,14 , 527,6 , 518,10 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15934,26 , 4,4 , 4,0 , 4901,8 , 4909,12 , 2, 1, 7, 6, 7 }, // Kalenjin/Latin/Kenya
+ { 199, 7, 148, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 0,48 , 29359,136 , 134,24 , 0,48 , 29359,136 , 134,24 , 15907,23 , 15930,92 , 16022,14 , 15907,23 , 15930,92 , 16022,14 , 533,7 , 528,5 , 45,4 , 5,17 , 22,23 , {78,65,68}, 6,1 , 15960,22 , 4,4 , 4,0 , 4921,13 , 4934,8 , 2, 1, 1, 6, 7 }, // Nama/Latin/Namibia
+ { 200, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 27306,87 , 134,24 , 18222,48 , 27306,87 , 134,24 , 14593,28 , 14621,62 , 14683,14 , 14593,28 , 14621,62 , 14683,14 , 500,5 , 484,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15739,27 , 4,4 , 4,0 , 4942,9 , 1587,8 , 0, 0, 1, 6, 7 }, // Machame/Latin/Tanzania
+ { 201, 7, 82, 44, 160, 59, 37, 48, 8722, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 409,8 , 409,8 , 1045,10 , 1471,23 , 37,5 , 8,10 , 29495,59 , 29554,87 , 12643,24 , 29641,48 , 29554,87 , 12643,24 , 16036,28 , 16064,72 , 3642,14 , 16036,28 , 16064,72 , 3642,14 , 540,16 , 533,16 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 15982,11 , 13,5 , 4,0 , 4951,6 , 4957,11 , 2, 1, 1, 6, 7 }, // Colognian/Latin/Germany
+ { 202, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29689,51 , 29740,132 , 158,27 , 29689,51 , 29740,132 , 158,27 , 14593,28 , 16136,58 , 14089,14 , 14593,28 , 16136,58 , 14089,14 , 556,9 , 549,6 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 15993,25 , 4,4 , 4,0 , 4968,3 , 1153,5 , 2, 1, 7, 6, 7 }, // Masai/Latin/Kenya
+ { 202, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29689,51 , 29740,132 , 158,27 , 29689,51 , 29740,132 , 158,27 , 14593,28 , 16136,58 , 14089,14 , 14593,28 , 16136,58 , 14089,14 , 556,9 , 549,6 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 16018,28 , 4,4 , 4,0 , 4968,3 , 4971,8 , 0, 0, 1, 6, 7 }, // Masai/Latin/Tanzania
+ { 203, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 28574,48 , 28622,97 , 134,24 , 28574,48 , 28622,97 , 134,24 , 16194,35 , 16229,65 , 16294,14 , 16194,35 , 16229,65 , 16294,14 , 565,6 , 555,6 , 45,4 , 5,17 , 22,23 , {85,71,88}, 203,3 , 15865,26 , 13,5 , 4,0 , 4979,7 , 4857,7 , 0, 0, 1, 6, 7 }, // Soga/Latin/Uganda
+ { 204, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29872,48 , 18270,84 , 134,24 , 29872,48 , 18270,84 , 134,24 , 16308,21 , 16329,75 , 85,14 , 16308,21 , 16329,75 , 85,14 , 64,4 , 61,4 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16046,23 , 4,4 , 91,6 , 4986,7 , 1153,5 , 2, 1, 7, 6, 7 }, // Luyia/Latin/Kenya
+ { 205, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29920,48 , 18270,84 , 134,24 , 29920,48 , 18270,84 , 134,24 , 16404,28 , 9545,60 , 14683,14 , 16404,28 , 9545,60 , 14683,14 , 571,9 , 561,8 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 16069,28 , 13,5 , 4,0 , 4993,6 , 4999,8 , 0, 0, 1, 6, 7 }, // Asu/Latin/Tanzania
+ { 206, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29968,48 , 30016,94 , 30110,24 , 29968,48 , 30016,94 , 30110,24 , 16432,28 , 16460,69 , 16529,14 , 16432,28 , 16460,69 , 16529,14 , 580,9 , 569,6 , 45,4 , 5,17 , 22,23 , {85,71,88}, 203,3 , 16097,28 , 4,4 , 4,0 , 5007,6 , 1652,6 , 0, 0, 1, 6, 7 }, // Teso/Latin/Uganda
+ { 206, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 29968,48 , 30016,94 , 30110,24 , 29968,48 , 30016,94 , 30110,24 , 16432,28 , 16460,69 , 16529,14 , 16432,28 , 16460,69 , 16529,14 , 580,9 , 569,6 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16125,27 , 4,4 , 4,0 , 5007,6 , 5013,5 , 2, 1, 7, 6, 7 }, // Teso/Latin/Kenya
+ { 207, 7, 67, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,82,78}, 0,0 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Saho/Latin/Eritrea
+ { 208, 7, 132, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 30134,46 , 30180,88 , 30268,24 , 30134,46 , 30180,88 , 30268,24 , 16543,28 , 16571,53 , 16624,14 , 16543,28 , 16571,53 , 16624,14 , 589,6 , 575,6 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 16152,23 , 0,4 , 4,0 , 5018,11 , 5029,5 , 0, 0, 1, 6, 7 }, // Koyra Chiini/Latin/Mali
+ { 209, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 27306,87 , 134,24 , 18222,48 , 27306,87 , 134,24 , 14593,28 , 14621,62 , 14683,14 , 14593,28 , 14621,62 , 14683,14 , 500,5 , 484,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 15739,27 , 0,4 , 4,0 , 5034,6 , 1587,8 , 0, 0, 1, 6, 7 }, // Rwa/Latin/Tanzania
+ { 210, 7, 111, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 30292,48 , 30340,186 , 30526,24 , 30292,48 , 30340,186 , 30526,24 , 16638,28 , 16666,69 , 16735,14 , 16638,28 , 16666,69 , 16735,14 , 595,2 , 581,2 , 45,4 , 5,17 , 22,23 , {75,69,83}, 2,3 , 16175,23 , 0,4 , 4,0 , 5040,6 , 1153,5 , 2, 1, 7, 6, 7 }, // Luo/Latin/Kenya
+ { 211, 7, 221, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 26780,48 , 26828,152 , 134,24 , 26780,48 , 26828,152 , 134,24 , 14353,28 , 14381,74 , 14455,14 , 14353,28 , 14381,74 , 14455,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,71,88}, 203,3 , 15684,26 , 4,4 , 4,0 , 5046,6 , 1652,6 , 0, 0, 1, 6, 7 }, // Chiga/Latin/Uganda
+ { 212, 7, 145, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 30550,48 , 30598,86 , 30684,24 , 30550,48 , 30598,86 , 30684,24 , 16749,28 , 16777,48 , 16825,14 , 16749,28 , 16777,48 , 16825,14 , 597,9 , 583,10 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 16198,22 , 13,5 , 4,0 , 5052,17 , 5069,6 , 2, 1, 6, 5, 6 }, // Central Morocco Tamazight/Latin/Morocco
+ { 213, 7, 132, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 30134,46 , 30180,88 , 30268,24 , 30134,46 , 30180,88 , 30268,24 , 16839,28 , 16867,54 , 16624,14 , 16839,28 , 16867,54 , 16624,14 , 589,6 , 575,6 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 16152,23 , 0,4 , 4,0 , 5075,15 , 5029,5 , 0, 0, 1, 6, 7 }, // Koyraboro Senni/Latin/Mali
+ { 214, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 18222,48 , 30708,84 , 134,24 , 18222,48 , 30708,84 , 134,24 , 16921,28 , 16949,63 , 17012,14 , 16921,28 , 16949,63 , 17012,14 , 606,5 , 593,8 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 16220,27 , 0,4 , 4,0 , 5090,9 , 1587,8 , 0, 0, 1, 6, 7 }, // Shambala/Latin/Tanzania
+ { 215, 13, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 516,6 , 35,18 , 18,7 , 25,12 , 30792,88 , 30792,88 , 30880,31 , 30792,88 , 30792,88 , 30880,31 , 17026,33 , 17059,54 , 17113,19 , 17026,33 , 17059,54 , 17113,19 , 611,3 , 601,6 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 16247,10 , 8,5 , 4,0 , 5099,4 , 2589,4 , 2, 1, 7, 7, 7 }, // Bodo/Devanagari/India
+ { 218, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 20846,48 , 11053,80 , 158,27 , 20846,48 , 11053,80 , 158,27 , 17132,74 , 17132,74 , 85,14 , 17132,74 , 17132,74 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 16257,43 , 13,5 , 4,0 , 5103,7 , 5110,5 , 2, 1, 1, 6, 7 }, // Chechen/Cyrillic/Russia
+ { 219, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 766,8 , 766,8 , 1494,10 , 1504,23 , 37,5 , 8,10 , 30911,65 , 30976,117 , 31093,30 , 30911,65 , 31123,117 , 31093,30 , 17206,37 , 17243,68 , 10707,14 , 17206,37 , 17243,68 , 10707,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 16300,44 , 13,5 , 4,0 , 5115,19 , 5134,7 , 2, 1, 1, 6, 7 }, // Church/Cyrillic/Russia
+ { 220, 2, 178, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {82,85,66}, 129,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Chuvash/Cyrillic/Russia
+ { 230, 7, 49, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 31240,49 , 31289,99 , 31388,24 , 31240,49 , 31289,99 , 31388,24 , 17311,28 , 17339,50 , 17389,14 , 17311,28 , 17339,50 , 17389,14 , 614,5 , 607,6 , 45,4 , 5,17 , 22,23 , {67,68,70}, 215,2 , 16344,24 , 0,4 , 4,0 , 5141,8 , 5149,16 , 2, 1, 1, 6, 7 }, // LubaKatanga/Latin/CongoKinshasa
+ { 231, 7, 125, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 774,10 , 774,10 , 175,8 , 532,18 , 37,5 , 8,10 , 31412,48 , 31460,85 , 134,24 , 31545,59 , 31460,85 , 134,24 , 17403,28 , 17431,65 , 3642,14 , 17496,35 , 17431,65 , 3642,14 , 619,5 , 613,8 , 409,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 8339,19 , 13,5 , 4,0 , 5165,14 , 5179,10 , 2, 1, 1, 6, 7 }, // Luxembourgish/Latin/Luxembourg
+ { 236, 7, 21, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Walloon/Latin/Belgium
+ { 237, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 8218, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 31604,48 , 31652,195 , 31847,24 , 31604,48 , 31652,195 , 31847,24 , 17531,28 , 17559,72 , 17631,14 , 17531,28 , 17559,72 , 17631,14 , 624,3 , 621,3 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16368,21 , 0,4 , 4,0 , 5189,5 , 5194,7 , 0, 0, 1, 6, 7 }, // Aghem/Latin/Cameroon
+ { 238, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 31871,48 , 31919,90 , 32009,24 , 31871,48 , 31919,90 , 32009,24 , 17645,28 , 17673,70 , 17743,14 , 17645,28 , 17673,70 , 17743,14 , 627,10 , 624,9 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16389,22 , 13,5 , 4,0 , 5201,5 , 5206,8 , 0, 0, 1, 6, 7 }, // Basaa/Latin/Cameroon
+ { 239, 7, 156, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 30134,46 , 30180,88 , 30268,24 , 30134,46 , 30180,88 , 30268,24 , 16839,28 , 17757,53 , 17810,14 , 16839,28 , 17757,53 , 17810,14 , 637,8 , 633,10 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 16152,23 , 0,4 , 4,0 , 5214,10 , 5224,5 , 0, 0, 1, 6, 7 }, // Zarma/Latin/Niger
+ { 240, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 32033,49 , 32082,99 , 32181,24 , 32033,49 , 32082,99 , 32181,24 , 17824,28 , 17852,45 , 17897,14 , 17824,28 , 17852,45 , 17897,14 , 645,5 , 643,6 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 13,5 , 4,0 , 5229,5 , 1903,8 , 0, 0, 1, 6, 7 }, // Duala/Latin/Cameroon
+ { 241, 7, 187, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 32205,36 , 32241,82 , 32323,24 , 32205,36 , 32241,82 , 32323,24 , 17911,28 , 17939,50 , 17989,14 , 17911,28 , 17939,50 , 17989,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 16411,23 , 13,5 , 4,0 , 5234,5 , 5239,7 , 0, 0, 1, 6, 7 }, // JolaFonyi/Latin/Senegal
+ { 242, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 32347,50 , 32397,141 , 32538,24 , 32347,50 , 32397,141 , 32538,24 , 18003,30 , 18033,85 , 18118,14 , 18003,30 , 18033,85 , 18118,14 , 650,7 , 649,9 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16434,23 , 13,5 , 4,0 , 5246,6 , 5252,7 , 0, 0, 1, 6, 7 }, // Ewondo/Latin/Cameroon
+ { 243, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 32562,39 , 32601,191 , 158,27 , 32562,39 , 32601,191 , 158,27 , 18132,29 , 18161,45 , 18206,14 , 18132,29 , 18161,45 , 18206,14 , 657,6 , 658,7 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16457,11 , 13,5 , 4,0 , 5259,5 , 5264,7 , 0, 0, 1, 6, 7 }, // Bafia/Latin/Cameroon
+ { 244, 7, 146, 44, 46, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 32792,48 , 32840,213 , 33053,24 , 32792,48 , 32840,213 , 33053,24 , 18220,28 , 18248,59 , 18307,14 , 18220,28 , 18248,59 , 18307,14 , 663,8 , 665,10 , 45,4 , 5,17 , 22,23 , {77,90,78}, 284,3 , 0,7 , 79,6 , 4,0 , 5271,5 , 5276,10 , 2, 1, 7, 6, 7 }, // MakhuwaMeetto/Latin/Mozambique
+ { 245, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 33077,48 , 33125,139 , 33264,24 , 33077,48 , 33125,139 , 33264,24 , 18321,28 , 18349,74 , 18423,14 , 18321,28 , 18349,74 , 18423,14 , 671,5 , 675,5 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16468,17 , 4,4 , 4,0 , 5286,6 , 5292,7 , 0, 0, 1, 6, 7 }, // Mundang/Latin/Cameroon
+ { 246, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 8222, 8221, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 33288,51 , 33339,143 , 158,27 , 33288,51 , 33339,143 , 158,27 , 18437,30 , 18467,89 , 18556,14 , 18437,30 , 18467,89 , 18556,14 , 676,4 , 680,4 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16485,20 , 13,5 , 4,0 , 5299,6 , 5305,7 , 0, 0, 1, 6, 7 }, // Kwasio/Latin/Cameroon
+ { 247, 7, 254, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 1527,9 , 98,16 , 18,7 , 481,12 , 33482,54 , 33536,96 , 33632,24 , 33482,54 , 33536,96 , 33632,24 , 18570,38 , 18608,79 , 18687,14 , 18570,38 , 18608,79 , 18687,14 , 680,2 , 684,2 , 45,4 , 5,17 , 22,23 , {83,83,80}, 125,1 , 0,7 , 4,4 , 4,0 , 5312,9 , 0,0 , 2, 1, 1, 6, 7 }, // Nuer/Latin/SouthSudan
+ { 248, 2, 178, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8220, 0,6 , 0,6 , 784,11 , 784,11 , 246,6 , 1536,30 , 37,5 , 8,10 , 33656,50 , 33706,116 , 33822,24 , 33656,50 , 33846,121 , 33822,24 , 18701,21 , 18722,71 , 18793,14 , 18701,21 , 18722,71 , 18793,14 , 682,2 , 686,2 , 948,5 , 953,17 , 22,23 , {82,85,66}, 129,1 , 16505,47 , 13,5 , 4,0 , 5321,9 , 5330,9 , 2, 1, 1, 6, 7 }, // Sakha/Cyrillic/Russia
+ { 249, 7, 210, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 37,5 , 8,10 , 33967,48 , 34015,117 , 158,27 , 33967,48 , 34015,117 , 158,27 , 18807,28 , 18835,60 , 18895,14 , 18807,28 , 18835,60 , 18895,14 , 684,9 , 688,9 , 45,4 , 5,17 , 22,23 , {84,90,83}, 198,3 , 16552,25 , 0,4 , 4,0 , 5339,9 , 5348,9 , 0, 0, 1, 6, 7 }, // Sangu/Latin/Tanzania
+ { 251, 7, 156, 46, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 30134,46 , 30180,88 , 30268,24 , 30134,46 , 30180,88 , 30268,24 , 16839,28 , 16867,54 , 16624,14 , 16839,28 , 16867,54 , 16624,14 , 637,8 , 633,10 , 45,4 , 5,17 , 22,23 , {88,79,70}, 210,3 , 16152,23 , 0,4 , 4,0 , 5357,13 , 5224,5 , 0, 0, 1, 6, 7 }, // Tasawaq/Latin/Niger
+ { 252, 35, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 34132,50 , 34132,50 , 158,27 , 34132,50 , 34132,50 , 158,27 , 18909,30 , 18909,30 , 85,14 , 18909,30 , 18909,30 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {76,82,68}, 6,1 , 16577,15 , 4,4 , 4,0 , 5370,2 , 5372,4 , 2, 1, 1, 6, 7 }, // Vai/Vai/Liberia
+ { 252, 7, 121, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 120,10 , 10,17 , 18,7 , 25,12 , 34182,81 , 34182,81 , 158,27 , 34182,81 , 34182,81 , 158,27 , 18939,48 , 18939,48 , 85,14 , 18939,48 , 18939,48 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {76,82,68}, 6,1 , 16592,20 , 4,4 , 4,0 , 5376,3 , 5379,8 , 2, 1, 1, 6, 7 }, // Vai/Latin/Liberia
+ { 253, 7, 206, 44, 8217, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 251,9 , 251,9 , 53,10 , 532,18 , 37,5 , 8,10 , 34263,48 , 34311,99 , 34410,24 , 34263,48 , 34311,99 , 34410,24 , 18987,28 , 19015,53 , 19068,14 , 18987,28 , 19015,53 , 19068,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,72,70}, 0,0 , 0,7 , 79,6 , 4,0 , 5387,6 , 5393,6 , 2, 0, 1, 6, 7 }, // Walser/Latin/Switzerland
+ { 254, 7, 37, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 171, 187, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 34434,51 , 34485,191 , 158,27 , 34434,51 , 34485,191 , 158,27 , 19082,21 , 19103,71 , 19174,14 , 19082,21 , 19103,71 , 19174,14 , 693,8 , 697,8 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 13,5 , 4,0 , 5399,6 , 5405,7 , 0, 0, 1, 6, 7 }, // Yangben/Latin/Cameroon
+ { 256, 7, 197, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 575,7 , 575,7 , 278,6 , 363,22 , 37,5 , 8,10 , 34676,48 , 34724,85 , 34809,24 , 34833,48 , 34881,117 , 34809,24 , 19188,28 , 19216,54 , 3338,14 , 19188,28 , 19216,54 , 3338,14 , 701,12 , 705,11 , 0,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 3057,20 , 13,5 , 4,0 , 5412,9 , 2354,6 , 2, 1, 1, 6, 7 }, // Asturian/Latin/Spain
+ { 257, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 795,11 , 795,11 , 806,16 , 822,9 , 53,10 , 1353,18 , 37,5 , 8,10 , 34998,174 , 34998,174 , 158,27 , 34998,174 , 34998,174 , 158,27 , 19270,60 , 19270,60 , 19330,25 , 19270,60 , 19270,60 , 19330,25 , 713,8 , 716,13 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16612,12 , 8,5 , 4,0 , 5421,5 , 5426,7 , 0, 0, 1, 6, 7 }, // Ngomba/Latin/Cameroon
+ { 258, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 1566,10 , 633,17 , 37,5 , 8,10 , 35172,102 , 35172,102 , 158,27 , 35172,102 , 35172,102 , 158,27 , 19355,54 , 19355,54 , 19409,21 , 19355,54 , 19355,54 , 19409,21 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16624,16 , 79,6 , 4,0 , 5433,4 , 5437,7 , 0, 0, 1, 6, 7 }, // Kako/Latin/Cameroon
+ { 259, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 1353,18 , 37,5 , 8,10 , 35274,137 , 35411,142 , 35553,36 , 35274,137 , 35411,142 , 35553,36 , 19430,49 , 19430,49 , 19479,21 , 19430,49 , 19430,49 , 19479,21 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16640,12 , 8,5 , 4,0 , 5444,5 , 5449,7 , 0, 0, 1, 6, 7 }, // Meta/Latin/Cameroon
+ { 260, 7, 37, 44, 46, 59, 37, 48, 45, 43, 101, 171, 187, 8220, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 27,8 , 1576,32 , 37,5 , 8,10 , 35589,165 , 35589,165 , 158,27 , 35589,165 , 35589,165 , 158,27 , 19500,111 , 19500,111 , 85,14 , 19500,111 , 19500,111 , 85,14 , 721,9 , 729,8 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 16652,16 , 8,5 , 4,0 , 5456,16 , 5472,7 , 0, 0, 1, 6, 7 }, // Ngiemboon/Latin/Cameroon
+ { 272, 46, 18, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {66,68,84}, 130,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 5, 6, 7 }, // Chakma/Chakma/Bangladesh
+ { 290, 11, 100, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,78,82}, 127,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 7, 7 }, // Manipuri/Bengali/India
+ { 309, 100, 232, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {86,78,68}, 340,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // TaiDam/Tai Viet/Vietnam
+ { 312, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Akoose/Latin/Cameroon
+ { 313, 7, 225, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 516,6 , 35,18 , 18,7 , 25,12 , 35754,180 , 35754,180 , 158,27 , 35754,180 , 35754,180 , 158,27 , 19611,87 , 19611,87 , 85,14 , 19611,87 , 19611,87 , 19698,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {85,83,68}, 6,1 , 0,7 , 79,6 , 4,0 , 5479,12 , 5491,22 , 2, 1, 7, 6, 7 }, // Lakota/Latin/UnitedStates
+ { 314, 9, 145, 44, 160, 59, 37, 48, 45, 43, 101, 171, 187, 8222, 8221, 0,6 , 0,6 , 0,6 , 0,6 , 406,8 , 98,16 , 37,5 , 8,10 , 26318,48 , 26366,81 , 26447,24 , 26318,48 , 26366,81 , 26447,24 , 14103,30 , 19712,48 , 85,14 , 14103,30 , 19712,48 , 85,14 , 474,6 , 452,8 , 45,4 , 5,17 , 22,23 , {77,65,68}, 0,0 , 15621,21 , 0,4 , 4,0 , 5513,8 , 4698,6 , 2, 1, 6, 5, 6 }, // Standard Moroccan Tamazight/Tifinagh/Morocco
+ { 315, 7, 43, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,76,80}, 6,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Mapuche/Latin/Chile
+ { 316, 1, 103, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 35934,105 , 35934,105 , 36039,24 , 35934,105 , 35934,105 , 36039,24 , 19760,58 , 19760,58 , 19818,14 , 19760,58 , 19760,58 , 19818,14 , 730,3 , 737,3 , 45,4 , 5,17 , 22,23 , {73,81,68}, 0,0 , 16668,20 , 13,5 , 4,0 , 5521,14 , 5535,5 , 0, 0, 6, 5, 6 }, // Central Kurdish/Arabic/Iraq
+ { 316, 1, 102, 1643, 1644, 1563, 1642, 1632, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 35934,105 , 35934,105 , 36039,24 , 35934,105 , 35934,105 , 36039,24 , 19760,58 , 19760,58 , 19818,14 , 19760,58 , 19760,58 , 19818,14 , 730,3 , 737,3 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 16688,19 , 13,5 , 4,0 , 5521,14 , 5540,5 , 0, 0, 6, 5, 5 }, // Central Kurdish/Arabic/Iran
+ { 317, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 176,7 , 176,7 , 114,6 , 532,18 , 55,4 , 59,9 , 36063,48 , 36111,85 , 16212,24 , 36196,60 , 36256,93 , 16212,24 , 19832,28 , 19860,53 , 19913,14 , 19832,28 , 19860,53 , 19913,14 , 733,9 , 740,10 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16707,27 , 13,5 , 4,0 , 5545,14 , 5559,6 , 2, 1, 1, 6, 7 }, // LowerSorbian/Latin/Germany
+ { 318, 7, 82, 44, 46, 59, 37, 48, 45, 43, 101, 8222, 8220, 8218, 8216, 0,6 , 0,6 , 176,7 , 176,7 , 114,6 , 532,18 , 493,12 , 59,9 , 36349,48 , 36397,86 , 16212,24 , 36483,60 , 36543,93 , 16212,24 , 19927,28 , 19955,53 , 20008,14 , 19927,28 , 19955,53 , 20008,14 , 733,9 , 750,9 , 970,5 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16734,29 , 13,5 , 4,0 , 5565,15 , 5580,6 , 2, 1, 1, 6, 7 }, // UpperSorbian/Latin/Germany
+ { 319, 7, 37, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {88,65,70}, 32,4 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Kenyang/Latin/Cameroon
+ { 320, 7, 38, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {67,65,68}, 245,3 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 0, 7, 6, 7 }, // Mohawk/Latin/Canada
+ { 321, 75, 91, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,78,70}, 221,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 0, 0, 1, 6, 7 }, // Nko/Nko/Guinea
+ { 323, 7, 90, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {71,84,81}, 311,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Kiche/Latin/Guatemala
+ { 324, 7, 205, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {83,69,75}, 196,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Southern Sami/Latin/Sweden
+ { 325, 7, 205, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {83,69,75}, 196,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Lule Sami/Latin/Sweden
+ { 326, 7, 73, 44, 160, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 550,8 , 1608,18 , 222,4 , 226,9 , 36636,77 , 36713,140 , 36853,25 , 36636,77 , 36713,140 , 36853,25 , 20022,28 , 20050,70 , 85,14 , 20022,28 , 20120,73 , 20193,14 , 742,3 , 759,3 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 16763,11 , 13,5 , 4,0 , 5586,11 , 5597,5 , 2, 1, 1, 6, 7 }, // Inari Sami/Latin/Finland
+ { 327, 7, 73, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {69,85,82}, 14,1 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 1, 6, 7 }, // Skolt Sami/Latin/Finland
+ { 328, 7, 13, 46, 44, 59, 37, 48, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 368,48 , 368,48 , 158,27 , 368,48 , 368,48 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {65,85,68}, 344,2 , 0,7 , 8,5 , 4,0 , 0,0 , 0,0 , 2, 1, 7, 6, 7 }, // Warlpiri/Latin/Australia
+ { 346, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 171, 187, 8249, 8250, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 14012,70 , 14012,70 , 158,27 , 14012,70 , 14012,70 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 605,4 , 609,39 , 22,23 , {73,82,82}, 346,3 , 16774,27 , 8,5 , 4,0 , 5602,7 , 3091,5 , 0, 0, 6, 5, 5 }, // Mazanderani/Arabic/Iran
+ { 349, 1, 102, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 37,5 , 8,10 , 36878,77 , 36878,77 , 158,27 , 36878,77 , 36878,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,82,82}, 0,0 , 0,7 , 8,5 , 4,0 , 5609,11 , 0,0 , 0, 0, 6, 5, 5 }, // Northern Luri/Arabic/Iran
+ { 349, 1, 103, 1643, 1644, 1563, 1642, 1776, 45, 43, 101, 8220, 8221, 8216, 8217, 0,6 , 0,6 , 0,6 , 0,6 , 53,10 , 63,17 , 18,7 , 25,12 , 36878,77 , 36878,77 , 158,27 , 36878,77 , 36878,77 , 158,27 , 0,28 , 0,28 , 85,14 , 0,28 , 0,28 , 85,14 , 0,2 , 0,2 , 45,4 , 5,17 , 22,23 , {73,81,68}, 0,0 , 0,7 , 8,5 , 4,0 , 5609,11 , 0,0 , 0, 0, 6, 5, 6 }, // Northern Luri/Arabic/Iraq
+ { 357, 6, 97, 46, 44, 59, 37, 48, 45, 43, 101, 12300, 12301, 12302, 12303, 161,5 , 161,5 , 831,5 , 831,5 , 385,8 , 414,14 , 170,6 , 187,13 , 4697,39 , 4697,39 , 158,27 , 4697,39 , 4697,39 , 158,27 , 2055,21 , 2013,28 , 2041,14 , 2055,21 , 2013,28 , 2041,14 , 58,2 , 55,2 , 45,4 , 5,17 , 22,23 , {72,75,68}, 140,3 , 16801,11 , 4,4 , 4,0 , 5620,2 , 5622,14 , 2, 1, 7, 6, 7 }, // Cantonese/Traditional Han/HongKong
+ { 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,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,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, 0 } // trailing 0s
};
static const ushort list_pattern_part_data[] = {
@@ -1814,45 +1819,44 @@ static const ushort list_pattern_part_data[] = {
0x20, 0x25, 0x32, 0x25, 0x31, 0x1363, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x12a5, 0x1293, 0x20, 0x25, 0x32, 0x25, 0x31,
0x20, 0x12a5, 0x1293, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x648, 0x25, 0x32, 0x25,
0x31, 0x20, 0x648, 0x25, 0x32, 0x25, 0x31, 0x20, 0x587, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x259, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x20, 0x65, 0x74, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x98f, 0x9ac, 0x982, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x98f, 0x9ac, 0x982, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xf51, 0xf44, 0xf0b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
-0x438, 0x20, 0x25, 0x32, 0x25, 0x31, 0x104a, 0x20, 0x25, 0x32, 0x25, 0x31, 0x104a, 0x20, 0x1014, 0x103e, 0x1004, 0x1037, 0x103a, 0x25,
-0x32, 0x25, 0x31, 0x1014, 0x103e, 0x1004, 0x1037, 0x103a, 0x25, 0x32, 0x25, 0x31, 0x20, 0x456, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
-0x1793, 0x17b7, 0x1784, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x1793, 0x17b7, 0x1784, 0x200b, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x3001, 0x25, 0x32, 0x25, 0x31, 0x548c, 0x25, 0x32, 0x25, 0x31, 0x53ca, 0x25, 0x32, 0x25, 0x31, 0x20,
-0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x67, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6a, 0x61, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x65, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
-0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x10d3, 0x10d0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x64, 0x20, 0x25,
-0x32, 0x25, 0x31, 0x20, 0x3ba, 0x3b1, 0x3b9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x61, 0x6d, 0x6d, 0x61, 0x20, 0x25,
-0x32, 0x25, 0x31, 0x20, 0xa85, 0xaa8, 0xac7, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x5d5, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20,
-0x914, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x914, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe9, 0x73, 0x20, 0x25,
-0x32, 0x25, 0x31, 0x2c, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x2c, 0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x436, 0x4d9, 0x43d,
-0x435, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x436, 0x430, 0x43d, 0x430, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xbc0f, 0x20, 0x25,
-0x32, 0x25, 0x31, 0x20, 0xec1, 0xea5, 0xeb0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x20, 0x6d, 0x70, 0xe9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x72, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x25,
-0x32, 0x20, 0xd0e, 0xd28, 0xd4d, 0xd28, 0xd3f, 0xd35, 0x25, 0x31, 0x20, 0xd15, 0xd42, 0xd1f, 0xd3e, 0xd24, 0xd46, 0x20, 0x25, 0x32,
-0x25, 0x31, 0x2c, 0x20, 0x75, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x906, 0x923,
-0x93f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x200f, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x60c, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xa05, 0xa24, 0xa47, 0x20,
-0x25, 0x32, 0x25, 0x31, 0x20, 0x219, 0x69, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x4d5, 0x43c, 0x4d5, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x2c, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61,
-0xa0, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x79, 0x20, 0x25, 0x32, 0x25, 0x31,
-0x20, 0x6e, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x63, 0x68, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xbae, 0xbb1,
-0xbcd, 0xbb1, 0xbc1, 0xbae, 0xbcd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xc2e, 0xc30, 0xc3f, 0xc2f, 0xc41, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25,
-0x31, 0x20, 0x6d, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x77, 0x65,
-0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x627, 0x648, 0x631, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627, 0x648, 0x631, 0x20,
-0x25, 0x32, 0x25, 0x32, 0x60c, 0x20, 0x25, 0x31, 0x25, 0x31, 0x20, 0x76, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76,
-0xe0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32, 0x49, 0x2d, 0x25, 0x31, 0x20, 0x6e, 0x65,
-0x2d, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6b, 0x70, 0x6c,
-0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x74, 0x20, 0x25,
-0x32, 0x25, 0x31, 0x20, 0x438, 0x486, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x28, 0x6e, 0x29, 0x20, 0x25, 0x32, 0x25,
-0x31, 0x2c, 0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x1e3f, 0x62, 0x25b, 0x6e, 0x20, 0x14b,
-0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x70, 0x254, 0x70, 0x20, 0x25, 0x32, 0x25, 0x31, 0x540c, 0x25, 0x32,
-
+0x25, 0x31, 0x20, 0x65, 0x74, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x98f, 0x9ac, 0x982, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0xf51, 0xf44, 0xf0b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x438, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x1014, 0x103e, 0x1004, 0x1037, 0x103a, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x456, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x1793,
+0x17b7, 0x1784, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x1793, 0x17b7, 0x1784, 0x200b, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x3001, 0x25, 0x32, 0x25, 0x31, 0x548c, 0x25, 0x32, 0x25, 0x31, 0x53ca, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x67, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6a, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x65, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x65,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x10d3, 0x10d0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x64, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0x3ba, 0x3b1, 0x3b9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x61, 0x6d, 0x6d, 0x61, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0xa85, 0xaa8, 0xac7, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x5d5, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x914,
+0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x914, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe9, 0x73, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x2c, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x64, 0x61, 0x6e, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x2c, 0x20, 0x61, 0x67, 0x75, 0x73, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0xcae, 0xca4, 0xccd, 0xca4, 0xcc1, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x436, 0x4d9, 0x43d, 0x435,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x436, 0x430, 0x43d, 0x430, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xbc0f, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0xec1, 0xea5, 0xeb0, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0x6d, 0x70, 0xe9, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x72, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x25, 0x32,
+0x20, 0xd0e, 0xd28, 0xd4d, 0xd28, 0xd3f, 0xd35, 0x25, 0x31, 0x20, 0xd15, 0xd42, 0xd1f, 0xd3e, 0xd24, 0xd46, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x2c, 0x20, 0x75, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x75, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x906, 0x923, 0x93f,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x25, 0x32, 0x25, 0x31, 0x20, 0x930, 0x20, 0x25, 0x32, 0x25, 0x31, 0x60c, 0x200f, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x648, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20,
+0xa05, 0xa24, 0xa47, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x219, 0x69, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x4d5, 0x43c, 0x4d5,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xdc3, 0xdc4, 0x20, 0x25, 0x32,
+0x25, 0x31, 0x20, 0x61, 0xa0, 0x25, 0x32, 0x25, 0x31, 0x20, 0x69, 0x6e, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x79, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x6e, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6f, 0x63, 0x68, 0x20, 0x25, 0x32, 0x25,
+0x31, 0x20, 0xbae, 0xbb1, 0xbcd, 0xbb1, 0xbc1, 0xbae, 0xbcd, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xc2e, 0xc30, 0xc3f, 0xc2f, 0xc41,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31, 0xe41, 0xe25, 0xe30, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x6d, 0x6f, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x77, 0x65, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x60c, 0x20, 0x627, 0x648, 0x631, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x627, 0x648, 0x631, 0x20, 0x25,
+0x32, 0x25, 0x32, 0x60c, 0x20, 0x25, 0x31, 0x25, 0x31, 0x20, 0x76, 0x61, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x76, 0xe0,
+0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6e, 0x65, 0x2d, 0x25, 0x32,
+0x25, 0x31, 0x2c, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x6b, 0x70, 0x6c, 0x65, 0x20, 0x25,
+0x32, 0x25, 0x31, 0x2c, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x74, 0x20, 0x25, 0x32, 0x25, 0x31,
+0x20, 0x13a0, 0x13b4, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x438, 0x486, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x61, 0x28, 0x6e,
+0x29, 0x20, 0x25, 0x32, 0x25, 0x31, 0x20, 0x443, 0x43e, 0x43d, 0x43d, 0x430, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x14b,
+0x301, 0x67, 0x25b, 0x20, 0x25, 0x32, 0x25, 0x31, 0x2c, 0x20, 0x1e3f, 0x62, 0x25b, 0x6e, 0x20, 0x14b, 0x301, 0x67, 0x25b, 0x20,
+0x25, 0x32, 0x25, 0x31, 0x20, 0x70, 0x254, 0x70, 0x20, 0x25, 0x32, 0x25, 0x31, 0x540c, 0x25, 0x32
};
static const ushort date_format_data[] = {
@@ -1865,108 +1869,108 @@ static const ushort date_format_data[] = {
0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x1363, 0x64, 0x20, 0x4d, 0x4d,
0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x200f, 0x2f, 0x4d, 0x200f, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64,
0x64, 0x60c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2e, 0x4d, 0x4d,
-0x2e, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x569, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64,
-0x64, 0x64, 0x64, 0x2d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d,
-0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2c,
-0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20,
-0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x28, 0x27,
-0x65, 0x27, 0x29, 0x27, 0x6b, 0x6f, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64,
-0x64, 0x2f, 0x4d, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf63, 0xf7c, 0xf0b,
-0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0xf5a, 0xf7a, 0xf66, 0xf0b, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d,
-0x2e, 0x79, 0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
-0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x64, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x64,
-0x64, 0x64, 0x104a, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64,
-0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
-0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x64, 0x64, 0x64, 0x64, 0x64,
-0x2f, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x6708, 0x64, 0x65e5, 0x20, 0x64, 0x64, 0x64,
-0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e,
-0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x2e, 0x20, 0x4d,
-0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x6e, 0x27, 0x20, 0x64,
-0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x4d, 0x2f,
-0x64, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79,
-0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2d, 0x4d, 0x4d, 0x2d, 0x64, 0x64, 0x64, 0x64,
-0x64, 0x64, 0x2c, 0x20, 0x64, 0x27, 0x6d, 0x68, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64,
-0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64,
-0x2c, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c,
-0x20, 0x64, 0x20, 0x5d1, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d,
-0x4d, 0x2e, 0x20, 0x64, 0x64, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2e, 0x2c,
-0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x436, 0x27, 0x2e, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d,
-0x4d, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c,
-0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64,
-0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2d, 0x27, 0x436, 0x27, 0x2e, 0x79, 0x79, 0x2e, 0x20,
-0x4d, 0x2e, 0x20, 0x64, 0x2e, 0x79, 0x79, 0x79, 0x79, 0xb144, 0x20, 0x4d, 0xc6d4, 0x20, 0x64, 0xc77c, 0x20, 0x64, 0x64, 0x64,
-0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0xe97, 0xeb5, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79,
-0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x27, 0x67, 0x61, 0x64, 0x61, 0x27, 0x20, 0x64,
-0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x6d, 0x27, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
-0x20, 0x64, 0x20, 0x27, 0x64, 0x27, 0x2e, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79,
-0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x4d, 0x4d,
-0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x74,
-0x61, 0x27, 0x2019, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79,
-0x79, 0x79, 0x79, 0x20, 0x27, 0x43e, 0x43d, 0x44b, 0x27, 0x20, 0x4d, 0x4d, 0x20, 0x27, 0x441, 0x430, 0x440, 0x44b, 0x43d, 0x27,
-0x20, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x64,
-0x64, 0x64, 0x20, 0x62f, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x62f, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64,
-0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27,
-0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x69, 0x6c, 0x73, 0x27, 0x20, 0x64, 0x20, 0x27,
-0x64, 0x61, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x2e,
-0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e,
-0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27,
-0x430, 0x437, 0x27, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64,
-0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d,
-0x4d, 0x20, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x27, 0x64,
-0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x4d, 0x4d, 0x2f,
-0x64, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2c, 0x20, 0x4d, 0x4d,
-0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0xe17, 0xe35, 0xe48,
-0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d,
-0x4d, 0xf60, 0xf72, 0xf0b, 0xf5a, 0xf7a, 0xf66, 0xf0b, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x1363,
-0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x1218, 0x12d3, 0x120d, 0x1272, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64,
-0x64, 0x64, 0x1361, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x1218, 0x12d3, 0x120d, 0x1272, 0x20, 0x79, 0x79, 0x79,
-0x79, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
-0x79, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x60c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x60c, 0x20,
-0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
-0x79, 0x20, 0x27, 0x440, 0x27, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x20, 0x646, 0x686, 0x6cc, 0x20, 0x6cc, 0x6cc, 0x644, 0x20, 0x64,
-0x20, 0x646, 0x686, 0x6cc, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64, 0x20, 0x6a9, 0x648, 0x646, 0x6cc, 0x64,
-0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x6e, 0x67, 0xe0, 0x79, 0x27, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
-0x27, 0x6e, 0x103, 0x6d, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x2e, 0x64,
-0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x61, 0x6c,
-0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27,
-0x6c, 0x69, 0x61, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x69,
-0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x20, 0x4d,
-0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0xe4, 0x27, 0x20, 0x64, 0x2e, 0x20,
-0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x4d, 0x4d, 0x2e, 0x64, 0x64, 0x64,
-0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x43b, 0x27, 0x2e, 0x20, 0x79, 0x79, 0x79,
-0x79, 0x2e, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x79, 0x79, 0x79,
-0x79, 0x20, 0x27, 0x441, 0x44b, 0x43b, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x43a, 0x4af, 0x43d, 0x44d,
-0x27, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64,
-0x64, 0x20, 0x2c, 0x20, 0x27, 0x6c, 0x79, 0x25b, 0x27, 0x30c, 0x2bc, 0x20, 0x64, 0x20, 0x27, 0x6e, 0x61, 0x27, 0x20, 0x4d,
-0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79
+0x2e, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x569, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64,
+0x64, 0x64, 0x64, 0x64, 0x2d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d,
+0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x79, 0x79, 0x79, 0x79, 0x28, 0x27, 0x65, 0x27,
+0x29, 0x27, 0x6b, 0x6f, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2f,
+0x4d, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf63, 0xf7c, 0xf0b, 0x79, 0x79,
+0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0xf5a, 0xf7a, 0xf66, 0xf0b, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79,
+0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79,
+0x79, 0x79, 0x79, 0x20, 0x27, 0x433, 0x27, 0x2e, 0x64, 0x64, 0x2d, 0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x4d,
+0x2e, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27,
+0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x2f, 0x64, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d, 0x6708,
+0x64, 0x65e5, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2f, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x5e74, 0x4d,
+0x6708, 0x64, 0x65e5, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e,
+0x64, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x6e, 0x27, 0x20, 0x64, 0x2e, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x4d, 0x2f, 0x64, 0x2f,
+0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x2e,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
+0x2d, 0x4d, 0x4d, 0x2d, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x27, 0x6d, 0x68, 0x27, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
+0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x5d1, 0x4d,
+0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x4d, 0x2e, 0x20, 0x64, 0x64,
+0x2e, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2e, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64,
+0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x436, 0x27, 0x2e, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x64, 0x64,
+0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x2d, 0x27, 0x436, 0x27, 0x2e, 0x2c, 0x20, 0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c,
+0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x64, 0x2e, 0x79, 0x79, 0x79, 0x79, 0xb144, 0x20,
+0x4d, 0xc6d4, 0x20, 0x64, 0xc77c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0xe97, 0xeb5, 0x20, 0x64, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e,
+0x20, 0x27, 0x67, 0x61, 0x64, 0x61, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x79, 0x79, 0x79, 0x79, 0x20,
+0x27, 0x6d, 0x27, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x64, 0x27, 0x2e, 0x2c, 0x20, 0x64, 0x64,
+0x64, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x2e, 0x79, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x79, 0x79, 0x79, 0x79, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64,
+0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x74, 0x61, 0x27, 0x2019, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79,
+0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x43e, 0x43d, 0x44b, 0x27, 0x20, 0x4d,
+0x4d, 0x20, 0x27, 0x441, 0x430, 0x440, 0x44b, 0x43d, 0x27, 0x20, 0x64, 0x64, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79,
+0x79, 0x64, 0x2d, 0x4d, 0x2d, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x62f, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x62f,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x69, 0x6c, 0x73, 0x27, 0x20, 0x64,
+0x20, 0x27, 0x64, 0x61, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x2e, 0x79,
+0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79,
+0x20, 0x27, 0x430, 0x437, 0x27, 0x64, 0x2e, 0x20, 0x4d, 0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x20, 0x4d, 0x4d,
+0x2e, 0x20, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79,
+0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x2c, 0x20, 0x79, 0x79,
+0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x64, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
+0x27, 0x64, 0x65, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x2f, 0x79, 0x79, 0x64, 0x64, 0x2d,
+0x4d, 0x4d, 0x2d, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2c,
+0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0xe17, 0xe35, 0xe48, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
+0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0xf60, 0xf72, 0xf0b, 0xf5a, 0xf7a, 0xf66, 0xf0b,
+0x64, 0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x1363, 0x20, 0x64, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d,
+0x20, 0x1218, 0x12d3, 0x120d, 0x1272, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x2e, 0x4d, 0x4d, 0x2e, 0x79, 0x79, 0x79, 0x79, 0x64,
+0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x64, 0x64, 0x64, 0x64, 0x79, 0x79, 0x79, 0x79, 0x20,
+0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x60c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20,
+0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x20, 0x27, 0x440, 0x27, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20,
+0x64, 0x2d, 0x4d, 0x4d, 0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x20, 0x646, 0x686, 0x6cc,
+0x20, 0x6cc, 0x6cc, 0x644, 0x20, 0x64, 0x20, 0x646, 0x686, 0x6cc, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64,
+0x20, 0x6a9, 0x648, 0x646, 0x6cc, 0x79, 0x79, 0x2f, 0x4d, 0x4d, 0x2f, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x79,
+0x79, 0x79, 0x79, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x20, 0x64, 0x20, 0x27, 0x64,
+0x69, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x64, 0x61, 0x6c, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64,
+0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x6c, 0x69, 0x61, 0x27, 0x20, 0x79, 0x79, 0x79,
+0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0x65, 0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20,
+0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x4d, 0x4d, 0x4d,
+0x4d, 0x20, 0x27, 0x64, 0x69, 0x27, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x27, 0x64, 0xe4,
+0x27, 0x20, 0x64, 0x2e, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x4d,
+0x4d, 0x2e, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x64, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x27, 0x43b, 0x27,
+0x2e, 0x20, 0x79, 0x79, 0x79, 0x79, 0x2e, 0x64, 0x2f, 0x4d, 0x4d, 0x2f, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
+0x20, 0x27, 0x441, 0x44b, 0x43b, 0x27, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64, 0x20, 0x27, 0x43a, 0x4af, 0x43d, 0x44d, 0x27,
+0x2c, 0x20, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x2f, 0x4d, 0x4d, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64,
+0x20, 0x2c, 0x20, 0x27, 0x6c, 0x79, 0x25b, 0x27, 0x30c, 0x2bc, 0x20, 0x64, 0x20, 0x27, 0x6e, 0x61, 0x27, 0x20, 0x4d, 0x4d,
+0x4d, 0x4d, 0x2c, 0x20, 0x79, 0x79, 0x79, 0x79, 0x64, 0x64, 0x64, 0x64, 0x2c, 0x20, 0x4d, 0x4d, 0x4d, 0x4d, 0x20, 0x64,
+0x2e, 0x20, 0x79, 0x79, 0x79, 0x79
};
static const ushort time_format_data[] = {
0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x68, 0x3a,
0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48, 0x48, 0x3a,
0x6d, 0x6d, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x2c, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d, 0x48,
-0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x68, 0x2e,
-0x6d, 0x6d, 0x2e, 0x20, 0x41, 0x50, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48, 0x48,
-0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x29, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68, 0x20,
-0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20,
-0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48,
-0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d,
-0x74, 0x20, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73,
-0x20, 0x5b, 0x74, 0x5d, 0x68, 0x2e, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x2e, 0x6d, 0x6d, 0x2e,
-0x73, 0x73, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x48, 0x20, 0x27, 0x68, 0x27, 0x20, 0x6d,
-0x6d, 0x20, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x73, 0x20, 0x27, 0x73, 0x27, 0x20, 0x74, 0x48, 0x48, 0x2e, 0x6d,
-0x6d, 0x3a, 0x73, 0x73, 0x20, 0x27, 0x68, 0x27, 0x20, 0x74, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68, 0x68,
-0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48, 0x6642, 0x6d, 0x6d, 0x5206, 0x73, 0x73, 0x79d2, 0x20,
-0x74, 0x41, 0x50, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x41, 0x50, 0x20, 0x68, 0xc2dc, 0x20, 0x6d, 0xbd84, 0x20, 0x73, 0xcd08, 0x20,
-0x74, 0x48, 0x20, 0xec2, 0xea1, 0xe87, 0x20, 0x6d, 0x20, 0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, 0x73, 0x73, 0x20, 0xea7, 0xeb4, 0xe99,
-0xeb2, 0xe97, 0xeb5, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x29, 0x27, 0x6b, 0x6c, 0x27,
-0x2e, 0x20, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a,
-0x73, 0x73, 0x20, 0x74, 0x48, 0x20, 0xe19, 0xe32, 0xe2c, 0xe34, 0xe01, 0xe32, 0x20, 0x6d, 0x6d, 0x20, 0xe19, 0xe32, 0xe17, 0xe35,
-0x20, 0x73, 0x73, 0x20, 0xe27, 0xe34, 0xe19, 0xe32, 0xe17, 0xe35, 0x20, 0x74, 0x27, 0x6b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x48,
-0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x41, 0x50, 0x20, 0x27, 0x67, 0x61, 0x27, 0x20, 0x68, 0x3a, 0x6d, 0x6d,
-0x41, 0x50, 0x20, 0x27, 0x67, 0x61, 0x27, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x74, 0x20, 0x68,
-0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x48, 0x3a, 0x6d, 0x6d, 0x20, 0x27, 0x68, 0x6f, 0x64, 0x17a, 0x27,
-0x2e
+0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x68, 0x2e, 0x6d, 0x6d, 0x2e, 0x20, 0x41, 0x50, 0x68, 0x2e, 0x6d, 0x6d,
+0x2e, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x29,
+0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d, 0x6d, 0x20,
+0x41, 0x50, 0xf46, 0xf74, 0xf0b, 0xf5a, 0xf7c, 0xf51, 0xf0b, 0x20, 0x68, 0x20, 0xf66, 0xf90, 0xf62, 0xf0b, 0xf58, 0xf0b, 0x20, 0x6d,
+0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x20, 0x74, 0x74, 0x20, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x48,
+0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x2c, 0x20, 0x74, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x74, 0x20, 0x41, 0x50,
+0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x41, 0x50, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x5b, 0x74, 0x5d,
+0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x68, 0x2e, 0x6d, 0x6d, 0x20,
+0x41, 0x50, 0x48, 0x2e, 0x6d, 0x6d, 0x48, 0x2e, 0x6d, 0x6d, 0x2e, 0x73, 0x73, 0x20, 0x74, 0x48, 0x20, 0x27, 0x68, 0x27,
+0x20, 0x6d, 0x6d, 0x20, 0x27, 0x6d, 0x69, 0x6e, 0x27, 0x20, 0x73, 0x73, 0x20, 0x27, 0x73, 0x27, 0x20, 0x74, 0x48, 0x48,
+0x20, 0x27, 0x68, 0x27, 0x20, 0x6d, 0x6d, 0x48, 0x48, 0x2e, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x27, 0x68, 0x27, 0x20,
+0x74, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x20, 0x41, 0x50, 0x68, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50,
+0x20, 0x74, 0x48, 0x6642, 0x6d, 0x6d, 0x5206, 0x73, 0x73, 0x79d2, 0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x41,
+0x50, 0x20, 0x68, 0xc2dc, 0x20, 0x6d, 0xbd84, 0x20, 0x73, 0xcd08, 0x20, 0x74, 0x48, 0x20, 0xec2, 0xea1, 0xe87, 0x20, 0x6d, 0x20,
+0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, 0x73, 0x73, 0x20, 0xea7, 0xeb4, 0xe99, 0xeb2, 0xe97, 0xeb5, 0x20, 0x74, 0x48, 0x3a, 0x6d, 0x6d,
+0x3a, 0x73, 0x73, 0x20, 0x28, 0x74, 0x29, 0x27, 0x6b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x48, 0x3a, 0x6d, 0x6d, 0x3a, 0x73,
+0x73, 0x20, 0x74, 0x41, 0x50, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x48, 0x20, 0xe19, 0xe32, 0xe2c,
+0xe34, 0xe01, 0xe32, 0x20, 0x6d, 0x6d, 0x20, 0xe19, 0xe32, 0xe17, 0xe35, 0x20, 0x73, 0x73, 0x20, 0xe27, 0xe34, 0xe19, 0xe32, 0xe17,
+0xe35, 0x20, 0x74, 0x41, 0x50, 0x20, 0x27, 0x67, 0x61, 0x27, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x41, 0x50, 0x20, 0x27, 0x67,
+0x61, 0x27, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x74, 0x27, 0x4b, 0x6c, 0x27, 0x2e, 0x20, 0x48, 0x2e,
+0x6d, 0x6d, 0x27, 0x4b, 0x6c, 0x6f, 0x63, 0x6b, 0x27, 0x20, 0x48, 0x2e, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x28, 0x74,
+0x29, 0x74, 0x20, 0x68, 0x3a, 0x6d, 0x6d, 0x3a, 0x73, 0x73, 0x20, 0x41, 0x50, 0x48, 0x3a, 0x6d, 0x6d, 0x20, 0x27, 0x68,
+0x6f, 0x64, 0x17a, 0x27, 0x2e
};
static const ushort months_data[] = {
@@ -1987,202 +1991,219 @@ static const ushort months_data[] = {
0x61, 0x62, 0x61, 0x6a, 0x6a, 0x69, 0x69, 0x3b, 0x41, 0x64, 0x6f, 0x6f, 0x6c, 0x65, 0x65, 0x73, 0x73, 0x61, 0x3b, 0x48,
0x61, 0x67, 0x61, 0x79, 0x79, 0x61, 0x3b, 0x46, 0x75, 0x75, 0x6c, 0x62, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6e, 0x6b, 0x6f,
0x6c, 0x6f, 0x6c, 0x65, 0x65, 0x73, 0x73, 0x61, 0x3b, 0x53, 0x61, 0x64, 0x61, 0x61, 0x73, 0x61, 0x3b, 0x4d, 0x75, 0x64,
-0x64, 0x65, 0x65, 0x3b, 0x4d, 0x30, 0x31, 0x3b, 0x4d, 0x30, 0x32, 0x3b, 0x4d, 0x30, 0x33, 0x3b, 0x4d, 0x30, 0x34, 0x3b,
-0x4d, 0x30, 0x35, 0x3b, 0x4d, 0x30, 0x36, 0x3b, 0x4d, 0x30, 0x37, 0x3b, 0x4d, 0x30, 0x38, 0x3b, 0x4d, 0x30, 0x39, 0x3b,
-0x4d, 0x31, 0x30, 0x3b, 0x4d, 0x31, 0x31, 0x3b, 0x4d, 0x31, 0x32, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62,
-0x2e, 0x3b, 0x4d, 0x72, 0x74, 0x2e, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x2e,
-0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e,
-0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x73, 0x2e, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b,
-0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69,
-0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x65, 0x3b, 0x41, 0x75,
-0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74,
-0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62,
-0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x53, 0x68, 0x6b, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x50, 0x72, 0x69, 0x3b, 0x4d,
-0x61, 0x6a, 0x3b, 0x51, 0x65, 0x72, 0x3b, 0x4b, 0x6f, 0x72, 0x3b, 0x47, 0x73, 0x68, 0x3b, 0x53, 0x68, 0x74, 0x3b, 0x54,
-0x65, 0x74, 0x3b, 0x4e, 0xeb, 0x6e, 0x3b, 0x44, 0x68, 0x6a, 0x3b, 0x4a, 0x61, 0x6e, 0x61, 0x72, 0x3b, 0x53, 0x68, 0x6b,
-0x75, 0x72, 0x74, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x50, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x4d, 0x61, 0x6a, 0x3b, 0x51,
-0x65, 0x72, 0x73, 0x68, 0x6f, 0x72, 0x3b, 0x4b, 0x6f, 0x72, 0x72, 0x69, 0x6b, 0x3b, 0x47, 0x75, 0x73, 0x68, 0x74, 0x3b,
-0x53, 0x68, 0x74, 0x61, 0x74, 0x6f, 0x72, 0x3b, 0x54, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x4e, 0xeb, 0x6e, 0x74, 0x6f, 0x72,
-0x3b, 0x44, 0x68, 0x6a, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x51,
-0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x61, 0x72, 0x3b, 0x73,
-0x68, 0x6b, 0x75, 0x72, 0x74, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x70, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x6d, 0x61, 0x6a,
-0x3b, 0x71, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x72, 0x3b, 0x6b, 0x6f, 0x72, 0x72, 0x69, 0x6b, 0x3b, 0x67, 0x75, 0x73, 0x68,
-0x74, 0x3b, 0x73, 0x68, 0x74, 0x61, 0x74, 0x6f, 0x72, 0x3b, 0x74, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x6e, 0xeb, 0x6e, 0x74,
-0x6f, 0x72, 0x3b, 0x64, 0x68, 0x6a, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x1303, 0x1295, 0x12e9, 0x3b, 0x134c, 0x1265, 0x1229, 0x3b, 0x121b,
-0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x122a, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235,
-0x3b, 0x1234, 0x1355, 0x1274, 0x3b, 0x12a6, 0x12ad, 0x1276, 0x3b, 0x1296, 0x126c, 0x121d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x3b, 0x1303, 0x1295, 0x12e9,
-0x12c8, 0x122a, 0x3b, 0x134c, 0x1265, 0x1229, 0x12c8, 0x122a, 0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x122a, 0x120d, 0x3b, 0x121c, 0x12ed,
-0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x1275, 0x3b, 0x1234, 0x1355, 0x1274, 0x121d, 0x1260, 0x122d, 0x3b,
-0x12a6, 0x12ad, 0x1276, 0x1260, 0x122d, 0x3b, 0x1296, 0x126c, 0x121d, 0x1260, 0x122d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1260, 0x122d, 0x3b, 0x1303, 0x3b,
-0x134c, 0x3b, 0x121b, 0x3b, 0x12a4, 0x3b, 0x121c, 0x3b, 0x1301, 0x3b, 0x1301, 0x3b, 0x12a6, 0x3b, 0x1234, 0x3b, 0x12a6, 0x3b, 0x1296, 0x3b,
-0x12f2, 0x3b, 0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b,
-0x623, 0x628, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644,
-0x64a, 0x648, 0x3b, 0x623, 0x63a, 0x633, 0x637, 0x633, 0x3b, 0x633, 0x628, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648,
-0x628, 0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641,
-0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x648, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x633, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f,
-0x3b, 0x62c, 0x627, 0x646, 0x641, 0x64a, 0x3b, 0x641, 0x64a, 0x641, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x641,
-0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x62c, 0x648, 0x627, 0x646, 0x3b, 0x62c, 0x648, 0x64a, 0x644, 0x64a, 0x629, 0x3b,
-0x623, 0x648, 0x62a, 0x3b, 0x633, 0x628, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648,
-0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b,
-0x645, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x623, 0x3b, 0x633, 0x3b, 0x623, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x643, 0x627, 0x646, 0x648,
-0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646,
-0x64a, 0x633, 0x627, 0x646, 0x3b, 0x623, 0x64a, 0x627, 0x631, 0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648,
-0x632, 0x3b, 0x622, 0x628, 0x3b, 0x623, 0x64a, 0x644, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x623,
-0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648,
-0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x643, 0x3b, 0x634, 0x3b, 0x622, 0x3b, 0x646, 0x3b, 0x623, 0x3b, 0x62d, 0x3b,
-0x62a, 0x3b, 0x622, 0x3b, 0x623, 0x3b, 0x62a, 0x3b, 0x62a, 0x3b, 0x643, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644,
+0x64, 0x65, 0x65, 0x3b, 0x41, 0x3b, 0x47, 0x3b, 0x42, 0x3b, 0x45, 0x3b, 0x43, 0x3b, 0x57, 0x3b, 0x41, 0x3b, 0x48, 0x3b,
+0x46, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x4d, 0x30, 0x31, 0x3b, 0x4d, 0x30, 0x32, 0x3b, 0x4d, 0x30, 0x33, 0x3b,
+0x4d, 0x30, 0x34, 0x3b, 0x4d, 0x30, 0x35, 0x3b, 0x4d, 0x30, 0x36, 0x3b, 0x4d, 0x30, 0x37, 0x3b, 0x4d, 0x30, 0x38, 0x3b,
+0x4d, 0x30, 0x39, 0x3b, 0x4d, 0x31, 0x30, 0x3b, 0x4d, 0x31, 0x31, 0x3b, 0x4d, 0x31, 0x32, 0x3b, 0x4a, 0x61, 0x6e, 0x2e,
+0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x72, 0x74, 0x2e, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
+0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b,
+0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x73, 0x2e, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x69, 0x65, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x3b,
+0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x4a, 0x75, 0x6c, 0x69,
+0x65, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65,
+0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x53, 0x68, 0x6b, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x50,
+0x72, 0x69, 0x3b, 0x4d, 0x61, 0x6a, 0x3b, 0x51, 0x65, 0x72, 0x3b, 0x4b, 0x6f, 0x72, 0x3b, 0x47, 0x73, 0x68, 0x3b, 0x53,
+0x68, 0x74, 0x3b, 0x54, 0x65, 0x74, 0x3b, 0x4e, 0xeb, 0x6e, 0x3b, 0x44, 0x68, 0x6a, 0x3b, 0x4a, 0x61, 0x6e, 0x61, 0x72,
+0x3b, 0x53, 0x68, 0x6b, 0x75, 0x72, 0x74, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x50, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x4d,
+0x61, 0x6a, 0x3b, 0x51, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x72, 0x3b, 0x4b, 0x6f, 0x72, 0x72, 0x69, 0x6b, 0x3b, 0x47, 0x75,
+0x73, 0x68, 0x74, 0x3b, 0x53, 0x68, 0x74, 0x61, 0x74, 0x6f, 0x72, 0x3b, 0x54, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x4e, 0xeb,
+0x6e, 0x74, 0x6f, 0x72, 0x3b, 0x44, 0x68, 0x6a, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x50,
+0x3b, 0x4d, 0x3b, 0x51, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e,
+0x3b, 0x73, 0x68, 0x6b, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x70, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72,
+0x3b, 0x6b, 0x6f, 0x72, 0x3b, 0x67, 0x73, 0x68, 0x3b, 0x73, 0x68, 0x74, 0x3b, 0x74, 0x65, 0x74, 0x3b, 0x6e, 0xeb, 0x6e,
+0x3b, 0x64, 0x68, 0x6a, 0x3b, 0x6a, 0x61, 0x6e, 0x61, 0x72, 0x3b, 0x73, 0x68, 0x6b, 0x75, 0x72, 0x74, 0x3b, 0x6d, 0x61,
+0x72, 0x73, 0x3b, 0x70, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x71, 0x65, 0x72, 0x73, 0x68, 0x6f, 0x72,
+0x3b, 0x6b, 0x6f, 0x72, 0x72, 0x69, 0x6b, 0x3b, 0x67, 0x75, 0x73, 0x68, 0x74, 0x3b, 0x73, 0x68, 0x74, 0x61, 0x74, 0x6f,
+0x72, 0x3b, 0x74, 0x65, 0x74, 0x6f, 0x72, 0x3b, 0x6e, 0xeb, 0x6e, 0x74, 0x6f, 0x72, 0x3b, 0x64, 0x68, 0x6a, 0x65, 0x74,
+0x6f, 0x72, 0x3b, 0x6a, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x70, 0x3b, 0x6d, 0x3b, 0x71, 0x3b, 0x6b, 0x3b, 0x67, 0x3b, 0x73,
+0x3b, 0x74, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x1303, 0x1295, 0x12e9, 0x3b, 0x134c, 0x1265, 0x1229, 0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4,
+0x1355, 0x122a, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x3b, 0x1234, 0x1355, 0x1274,
+0x3b, 0x12a6, 0x12ad, 0x1276, 0x3b, 0x1296, 0x126c, 0x121d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x3b, 0x1303, 0x1295, 0x12e9, 0x12c8, 0x122a, 0x3b, 0x134c,
+0x1265, 0x1229, 0x12c8, 0x122a, 0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x122a, 0x120d, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b,
+0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x1275, 0x3b, 0x1234, 0x1355, 0x1274, 0x121d, 0x1260, 0x122d, 0x3b, 0x12a6, 0x12ad, 0x1276, 0x1260,
+0x122d, 0x3b, 0x1296, 0x126c, 0x121d, 0x1260, 0x122d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1260, 0x122d, 0x3b, 0x1303, 0x3b, 0x134c, 0x3b, 0x121b, 0x3b,
+0x12a4, 0x3b, 0x121c, 0x3b, 0x1301, 0x3b, 0x1301, 0x3b, 0x12a6, 0x3b, 0x1234, 0x3b, 0x12a6, 0x3b, 0x1296, 0x3b, 0x12f2, 0x3b, 0x64a, 0x646,
+0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x628, 0x631, 0x64a,
+0x644, 0x3b, 0x645, 0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x3b, 0x623,
+0x63a, 0x633, 0x637, 0x633, 0x3b, 0x633, 0x628, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646,
+0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623,
+0x3b, 0x648, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x633, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x62c, 0x627, 0x646,
+0x641, 0x64a, 0x3b, 0x641, 0x64a, 0x641, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x641, 0x631, 0x64a, 0x644, 0x3b,
+0x645, 0x627, 0x64a, 0x3b, 0x62c, 0x648, 0x627, 0x646, 0x3b, 0x62c, 0x648, 0x64a, 0x644, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x62a, 0x3b,
+0x633, 0x628, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631,
+0x3b, 0x62f, 0x64a, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x645, 0x3b, 0x62c, 0x3b,
+0x62c, 0x3b, 0x623, 0x3b, 0x633, 0x3b, 0x623, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644,
0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646, 0x64a, 0x633, 0x627, 0x646,
0x3b, 0x623, 0x64a, 0x627, 0x631, 0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648, 0x632, 0x3b, 0x622, 0x628,
-0x3b, 0x623, 0x64a, 0x644, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a,
+0x3b, 0x623, 0x64a, 0x644, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a,
0x634, 0x631, 0x64a, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644,
-0x623, 0x648, 0x644, 0x3b, 0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631,
-0x633, 0x3b, 0x625, 0x628, 0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a,
-0x648, 0x644, 0x64a, 0x648, 0x3b, 0x623, 0x63a, 0x634, 0x62a, 0x3b, 0x634, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648,
-0x628, 0x631, 0x3b, 0x646, 0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x62c, 0x645, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641, 0x3b,
-0x645, 0x3b, 0x625, 0x3b, 0x648, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x634, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b,
-0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x628,
-0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x632,
-0x3b, 0x63a, 0x634, 0x62a, 0x3b, 0x634, 0x62a, 0x646, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648,
-0x646, 0x628, 0x631, 0x3b, 0x62f, 0x62c, 0x646, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x645, 0x3b,
-0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x634, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x570, 0x576, 0x57e, 0x3b, 0x583, 0x57f,
-0x57e, 0x3b, 0x574, 0x580, 0x57f, 0x3b, 0x561, 0x57a, 0x580, 0x3b, 0x574, 0x575, 0x57d, 0x3b, 0x570, 0x576, 0x57d, 0x3b, 0x570, 0x56c,
-0x57d, 0x3b, 0x585, 0x563, 0x57d, 0x3b, 0x57d, 0x565, 0x57a, 0x3b, 0x570, 0x578, 0x56f, 0x3b, 0x576, 0x578, 0x575, 0x3b, 0x564, 0x565,
-0x56f, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x57e, 0x561, 0x580, 0x3b, 0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x3b, 0x574, 0x561,
-0x580, 0x57f, 0x3b, 0x561, 0x57a, 0x580, 0x56b, 0x56c, 0x3b, 0x574, 0x561, 0x575, 0x56b, 0x57d, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b,
-0x57d, 0x3b, 0x570, 0x578, 0x582, 0x56c, 0x56b, 0x57d, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x3b, 0x57d, 0x565, 0x57a,
-0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x570, 0x578, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x576, 0x578, 0x575,
-0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x564, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x540, 0x3b, 0x553, 0x3b,
-0x544, 0x3b, 0x531, 0x3b, 0x544, 0x3b, 0x540, 0x3b, 0x540, 0x3b, 0x555, 0x3b, 0x54d, 0x3b, 0x540, 0x3b, 0x546, 0x3b, 0x534, 0x3b,
-0x570, 0x578, 0x582, 0x576, 0x57e, 0x561, 0x580, 0x56b, 0x3b, 0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x56b, 0x3b, 0x574, 0x561,
-0x580, 0x57f, 0x56b, 0x3b, 0x561, 0x57a, 0x580, 0x56b, 0x56c, 0x56b, 0x3b, 0x574, 0x561, 0x575, 0x56b, 0x57d, 0x56b, 0x3b, 0x570, 0x578,
-0x582, 0x576, 0x56b, 0x57d, 0x56b, 0x3b, 0x570, 0x578, 0x582, 0x56c, 0x56b, 0x57d, 0x56b, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578,
-0x57d, 0x56b, 0x3b, 0x57d, 0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x570, 0x578, 0x56f, 0x57f, 0x565, 0x574,
-0x562, 0x565, 0x580, 0x56b, 0x3b, 0x576, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x564, 0x565, 0x56f, 0x57f, 0x565,
-0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x3b, 0x9ae, 0x9be,
-0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1,
-0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x3b, 0x9a8,
-0x9ad, 0x9c7, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9f1, 0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac,
-0x9cd, 0x9f0, 0x9c1, 0x9f1, 0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2,
-0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b7, 0x9cd, 0x99f, 0x3b,
-0x99b, 0x9c7, 0x9aa, 0x9cd, 0x9a4, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9f0, 0x3b, 0x9a8,
-0x9f1, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x9a1, 0x9bf, 0x99a, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x79, 0x61, 0x6e, 0x3b,
-0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b,
-0x69, 0x79, 0x6c, 0x3b, 0x61, 0x76, 0x71, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b,
-0x64, 0x65, 0x6b, 0x3b, 0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x4d, 0x61,
-0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x130, 0x79, 0x75, 0x6e, 0x3b, 0x130, 0x79,
-0x75, 0x6c, 0x3b, 0x41, 0x76, 0x71, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x4f,
-0x6b, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x44, 0x65, 0x6b, 0x61, 0x62, 0x72,
-0x3b, 0x79, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b,
-0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75, 0x6c, 0x3b,
-0x61, 0x76, 0x71, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x79,
-0x61, 0x62, 0x72, 0x3b, 0x6e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x458, 0x430,
-0x43d, 0x432, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440,
-0x435, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x458, 0x443, 0x43d, 0x3b, 0x438, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433,
-0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x458, 0x430, 0x431, 0x440,
-0x3b, 0x43d, 0x43e, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0x55, 0x72, 0x74, 0x2e, 0x3b,
-0x4f, 0x74, 0x73, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x70, 0x69, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x2e, 0x3b,
-0x45, 0x6b, 0x61, 0x2e, 0x3b, 0x55, 0x7a, 0x74, 0x2e, 0x3b, 0x41, 0x62, 0x75, 0x2e, 0x3b, 0x49, 0x72, 0x61, 0x2e, 0x3b,
-0x55, 0x72, 0x72, 0x2e, 0x3b, 0x41, 0x7a, 0x61, 0x2e, 0x3b, 0x41, 0x62, 0x65, 0x2e, 0x3b, 0x55, 0x72, 0x74, 0x61, 0x72,
-0x72, 0x69, 0x6c, 0x61, 0x3b, 0x4f, 0x74, 0x73, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x78, 0x6f, 0x61,
-0x3b, 0x41, 0x70, 0x69, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x4d, 0x61, 0x69, 0x61, 0x74, 0x7a, 0x61, 0x3b, 0x45, 0x6b, 0x61,
-0x69, 0x6e, 0x61, 0x3b, 0x55, 0x7a, 0x74, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x41, 0x62, 0x75, 0x7a, 0x74, 0x75, 0x61, 0x3b,
-0x49, 0x72, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x55, 0x72, 0x72, 0x69, 0x61, 0x3b, 0x41, 0x7a, 0x61, 0x72, 0x6f, 0x61, 0x3b,
-0x41, 0x62, 0x65, 0x6e, 0x64, 0x75, 0x61, 0x3b, 0x55, 0x3b, 0x4f, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x45, 0x3b,
-0x55, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x75, 0x72, 0x74, 0x2e, 0x3b, 0x6f, 0x74, 0x73,
-0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x69, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x2e, 0x3b, 0x65, 0x6b, 0x61,
-0x2e, 0x3b, 0x75, 0x7a, 0x74, 0x2e, 0x3b, 0x61, 0x62, 0x75, 0x2e, 0x3b, 0x69, 0x72, 0x61, 0x2e, 0x3b, 0x75, 0x72, 0x72,
-0x2e, 0x3b, 0x61, 0x7a, 0x61, 0x2e, 0x3b, 0x61, 0x62, 0x65, 0x2e, 0x3b, 0x75, 0x72, 0x74, 0x61, 0x72, 0x72, 0x69, 0x6c,
-0x61, 0x6b, 0x3b, 0x6f, 0x74, 0x73, 0x61, 0x69, 0x6c, 0x61, 0x6b, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x78, 0x6f, 0x61, 0x6b,
-0x3b, 0x61, 0x70, 0x69, 0x72, 0x69, 0x6c, 0x61, 0x6b, 0x3b, 0x6d, 0x61, 0x69, 0x61, 0x74, 0x7a, 0x61, 0x6b, 0x3b, 0x65,
-0x6b, 0x61, 0x69, 0x6e, 0x61, 0x6b, 0x3b, 0x75, 0x7a, 0x74, 0x61, 0x69, 0x6c, 0x61, 0x6b, 0x3b, 0x61, 0x62, 0x75, 0x7a,
-0x74, 0x75, 0x61, 0x6b, 0x3b, 0x69, 0x72, 0x61, 0x69, 0x6c, 0x61, 0x6b, 0x3b, 0x75, 0x72, 0x72, 0x69, 0x61, 0x6b, 0x3b,
-0x61, 0x7a, 0x61, 0x72, 0x6f, 0x61, 0x6b, 0x3b, 0x61, 0x62, 0x65, 0x6e, 0x64, 0x75, 0x61, 0x6b, 0x3b, 0x99c, 0x9be, 0x9a8,
-0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9b0, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ae,
-0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c,
-0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac,
-0x9b0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf,
-0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x99c, 0x9be, 0x3b, 0x9ab, 0x9c7, 0x3b, 0x9ae, 0x9be, 0x3b, 0x98f, 0x3b, 0x9ae, 0x9c7,
-0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x3b, 0x986, 0x3b, 0x9b8, 0x9c7, 0x3b, 0x985, 0x3b, 0x9a8, 0x3b, 0x9a1, 0x9bf, 0x3b,
-0xf5f, 0xfb3, 0xf0b, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf22, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf23, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf24, 0x3b,
-0xf5f, 0xfb3, 0xf0b, 0xf25, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf26, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf27, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf28, 0x3b,
-0xf5f, 0xfb3, 0xf0b, 0xf29, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf20, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b,
-0xf21, 0xf22, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72,
-0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b,
-0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b,
-0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72,
-0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56,
-0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51,
-0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66,
-0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f,
-0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f,
-0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b,
-0xf24, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b, 0xf29, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0xf21, 0xf22,
-0x3b, 0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0xf24, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b, 0xf29, 0x3b, 0xf21,
-0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0x31, 0x32, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42,
-0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3,
-0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b,
-0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3,
-0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b,
-0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72,
-0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b,
-0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0x34, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b, 0x39, 0x3b, 0xf21, 0xf20,
-0x3b, 0xf21, 0xf21, 0x3b, 0xf21, 0xf22, 0x3b, 0x47, 0x65, 0x6e, 0x2e, 0x3b, 0x43, 0x2bc, 0x68, 0x77, 0x65, 0x2e, 0x3b, 0x4d,
-0x65, 0x75, 0x72, 0x2e, 0x3b, 0x45, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a, 0x68, 0x2e, 0x3b,
-0x47, 0x6f, 0x75, 0x65, 0x2e, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x2e, 0x3b, 0x48, 0x65, 0x72,
-0x65, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x72, 0x2e, 0x3b, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x43, 0x2bc, 0x68,
-0x77, 0x65, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68, 0x3b, 0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b,
-0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x47, 0x6f, 0x75, 0x65, 0x72, 0x65, 0x3b,
-0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x67, 0x6f, 0x6c, 0x6f, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x3b, 0x44,
-0x75, 0x3b, 0x4b, 0x65, 0x72, 0x7a, 0x75, 0x3b, 0x30, 0x31, 0x3b, 0x30, 0x32, 0x3b, 0x30, 0x33, 0x3b, 0x30, 0x34, 0x3b,
-0x30, 0x35, 0x3b, 0x30, 0x36, 0x3b, 0x30, 0x37, 0x3b, 0x30, 0x38, 0x3b, 0x30, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31,
-0x3b, 0x31, 0x32, 0x3b, 0x47, 0x65, 0x6e, 0x2e, 0x3b, 0x43, 0x2bc, 0x68, 0x77, 0x65, 0x2e, 0x3b, 0x4d, 0x65, 0x75, 0x72,
-0x2e, 0x3b, 0x45, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a, 0x68, 0x2e, 0x3b, 0x47, 0x6f, 0x75,
-0x65, 0x2e, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x2e, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x3b, 0x44,
-0x75, 0x3b, 0x4b, 0x7a, 0x75, 0x2e, 0x3b, 0x44f, 0x43d, 0x443, 0x3b, 0x444, 0x435, 0x432, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b,
-0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x3b,
-0x441, 0x435, 0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x435, 0x3b, 0x434, 0x435, 0x43a, 0x3b, 0x44f, 0x43d, 0x443, 0x430,
-0x440, 0x438, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440,
-0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441,
-0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438,
-0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x44f, 0x3b,
-0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b, 0x44e, 0x3b, 0x44e, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b,
-0x434, 0x3b, 0x1007, 0x1014, 0x103a, 0x3b, 0x1016, 0x1031, 0x3b, 0x1019, 0x1010, 0x103a, 0x3b, 0x1027, 0x1015, 0x103c, 0x102e, 0x3b, 0x1019, 0x1031,
-0x3b, 0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x3b, 0x1029, 0x3b, 0x1005, 0x1000, 0x103a, 0x3b, 0x1021, 0x1031, 0x102c, 0x1000, 0x103a,
-0x3b, 0x1014, 0x102d, 0x102f, 0x3b, 0x1012, 0x102e, 0x3b, 0x1007, 0x1014, 0x103a, 0x1014, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1016, 0x1031, 0x1016,
-0x1031, 0x102c, 0x103a, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1019, 0x1010, 0x103a, 0x3b, 0x1027, 0x1015, 0x103c, 0x102e, 0x3b, 0x1019, 0x1031, 0x3b,
-0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x101c, 0x102d, 0x102f, 0x1004, 0x103a, 0x3b, 0x1029, 0x1002, 0x102f, 0x1010, 0x103a, 0x3b, 0x1005,
-0x1000, 0x103a, 0x1010, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1021, 0x1031, 0x102c, 0x1000, 0x103a, 0x1010, 0x102d, 0x102f, 0x1018, 0x102c, 0x3b, 0x1014,
-0x102d, 0x102f, 0x101d, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1012, 0x102e, 0x1007, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1007, 0x3b, 0x1016, 0x3b,
-0x1019, 0x3b, 0x1027, 0x3b, 0x1019, 0x3b, 0x1007, 0x3b, 0x1007, 0x3b, 0x1029, 0x3b, 0x1005, 0x3b, 0x1021, 0x3b, 0x1014, 0x3b, 0x1012, 0x3b,
-0x441, 0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x3b, 0x43c, 0x430, 0x439, 0x3b,
-0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d, 0x456, 0x3b, 0x432, 0x435, 0x440, 0x3b, 0x43a, 0x430, 0x441, 0x3b,
-0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x3b, 0x441, 0x442, 0x443, 0x434, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x44e, 0x442,
-0x44b, 0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x441, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43c,
-0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x436, 0x43d,
-0x456, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x430, 0x441, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x430, 0x441, 0x442, 0x440,
-0x44b, 0x447, 0x43d, 0x456, 0x43a, 0x3b, 0x43b, 0x456, 0x441, 0x442, 0x430, 0x43f, 0x430, 0x434, 0x3b, 0x441, 0x43d, 0x435, 0x436, 0x430,
-0x43d, 0x44c, 0x3b, 0x441, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x43a, 0x3b, 0x43c, 0x3b, 0x447, 0x3b, 0x43b, 0x3b, 0x436, 0x3b, 0x432,
-0x3b, 0x43a, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x441, 0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a, 0x3b, 0x43a,
-0x440, 0x430, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d, 0x456, 0x3b, 0x432,
-0x435, 0x440, 0x3b, 0x43a, 0x430, 0x441, 0x3b, 0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x3b, 0x441, 0x442, 0x443, 0x434, 0x437,
-0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x430, 0x433, 0x430, 0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456, 0x43a, 0x430, 0x3b,
-0x43a, 0x440, 0x430, 0x441, 0x430, 0x432, 0x456, 0x43a, 0x430, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x447, 0x44d, 0x440, 0x432, 0x435, 0x43d,
-0x44f, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44f, 0x3b, 0x436, 0x43d, 0x456, 0x45e, 0x43d, 0x44f, 0x3b, 0x432, 0x435, 0x440, 0x430,
-0x441, 0x43d, 0x44f, 0x3b, 0x43a, 0x430, 0x441, 0x442, 0x440, 0x44b, 0x447, 0x43d, 0x456, 0x43a, 0x430, 0x3b, 0x43b, 0x456, 0x441, 0x442,
-0x430, 0x43f, 0x430, 0x434, 0x430, 0x3b, 0x441, 0x43d, 0x435, 0x436, 0x43d, 0x44f, 0x3b, 0x1798, 0x1780, 0x179a, 0x17b6, 0x3b, 0x1780, 0x17bb,
-0x1798, 0x17d2, 0x1797, 0x17c8, 0x3b, 0x1798, 0x17b8, 0x1793, 0x17b6, 0x3b, 0x1798, 0x17c1, 0x179f, 0x17b6, 0x3b, 0x17a7, 0x179f, 0x1797, 0x17b6, 0x3b,
-0x1798, 0x17b7, 0x1790, 0x17bb, 0x1793, 0x17b6, 0x3b, 0x1780, 0x1780, 0x17d2, 0x1780, 0x178a, 0x17b6, 0x3b, 0x179f, 0x17b8, 0x17a0, 0x17b6, 0x3b, 0x1780,
-0x1789, 0x17d2, 0x1789, 0x17b6, 0x3b, 0x178f, 0x17bb, 0x179b, 0x17b6, 0x3b, 0x179c, 0x17b7, 0x1785, 0x17d2, 0x1786, 0x17b7, 0x1780, 0x17b6, 0x3b, 0x1792,
-0x17d2, 0x1793, 0x17bc, 0x3b, 0x67, 0x65, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b,
-0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b,
-0x61, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64,
-0x65, 0x73, 0x2e, 0x3b, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72,
-0xe7, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x6a, 0x75,
-0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b,
-0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x73,
-0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x47, 0x4e, 0x3b, 0x46, 0x42, 0x3b, 0x4d, 0xc7, 0x3b, 0x41, 0x42, 0x3b, 0x4d, 0x47,
-0x3b, 0x4a, 0x4e, 0x3b, 0x4a, 0x4c, 0x3b, 0x41, 0x47, 0x3b, 0x53, 0x54, 0x3b, 0x4f, 0x43, 0x3b, 0x4e, 0x56, 0x3b, 0x44,
-0x53, 0x3b, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72,
+0x623, 0x648, 0x644, 0x3b, 0x643, 0x3b, 0x634, 0x3b, 0x622, 0x3b, 0x646, 0x3b, 0x623, 0x3b, 0x62d, 0x3b, 0x62a, 0x3b, 0x622, 0x3b,
+0x623, 0x3b, 0x62a, 0x3b, 0x62a, 0x3b, 0x643, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a,
+0x3b, 0x634, 0x628, 0x627, 0x637, 0x3b, 0x622, 0x630, 0x627, 0x631, 0x3b, 0x646, 0x64a, 0x633, 0x627, 0x646, 0x3b, 0x623, 0x64a, 0x627,
+0x631, 0x3b, 0x62d, 0x632, 0x64a, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x645, 0x648, 0x632, 0x3b, 0x622, 0x628, 0x3b, 0x623, 0x64a, 0x644,
+0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x64a, 0x646,
+0x20, 0x627, 0x644, 0x62b, 0x627, 0x646, 0x64a, 0x3b, 0x643, 0x627, 0x646, 0x648, 0x646, 0x20, 0x627, 0x644, 0x623, 0x648, 0x644, 0x3b,
+0x64a, 0x646, 0x627, 0x64a, 0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x625, 0x628,
+0x631, 0x64a, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648,
+0x3b, 0x623, 0x63a, 0x634, 0x62a, 0x3b, 0x634, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646,
+0x648, 0x641, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x62c, 0x645, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x625, 0x3b,
+0x648, 0x3b, 0x646, 0x3b, 0x644, 0x3b, 0x63a, 0x3b, 0x634, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x64a, 0x646, 0x627, 0x64a,
+0x631, 0x3b, 0x641, 0x628, 0x631, 0x627, 0x64a, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x623, 0x628, 0x631, 0x64a, 0x644, 0x3b,
+0x645, 0x627, 0x64a, 0x3b, 0x64a, 0x648, 0x646, 0x64a, 0x648, 0x3b, 0x64a, 0x648, 0x644, 0x64a, 0x648, 0x632, 0x3b, 0x63a, 0x634, 0x62a,
+0x3b, 0x634, 0x62a, 0x646, 0x628, 0x631, 0x3b, 0x623, 0x643, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x646, 0x628, 0x631, 0x3b,
+0x62f, 0x62c, 0x646, 0x628, 0x631, 0x3b, 0x64a, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x623, 0x3b, 0x645, 0x3b, 0x646, 0x3b, 0x644, 0x3b,
+0x63a, 0x3b, 0x634, 0x3b, 0x643, 0x3b, 0x628, 0x3b, 0x62f, 0x3b, 0x570, 0x576, 0x57e, 0x3b, 0x583, 0x57f, 0x57e, 0x3b, 0x574, 0x580,
+0x57f, 0x3b, 0x561, 0x57a, 0x580, 0x3b, 0x574, 0x575, 0x57d, 0x3b, 0x570, 0x576, 0x57d, 0x3b, 0x570, 0x56c, 0x57d, 0x3b, 0x585, 0x563,
+0x57d, 0x3b, 0x57d, 0x565, 0x57a, 0x3b, 0x570, 0x578, 0x56f, 0x3b, 0x576, 0x578, 0x575, 0x3b, 0x564, 0x565, 0x56f, 0x3b, 0x570, 0x578,
+0x582, 0x576, 0x57e, 0x561, 0x580, 0x3b, 0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x3b, 0x574, 0x561, 0x580, 0x57f, 0x3b, 0x561,
+0x57a, 0x580, 0x56b, 0x56c, 0x3b, 0x574, 0x561, 0x575, 0x56b, 0x57d, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b, 0x57d, 0x3b, 0x570, 0x578,
+0x582, 0x56c, 0x56b, 0x57d, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x3b, 0x57d, 0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562,
+0x565, 0x580, 0x3b, 0x570, 0x578, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x576, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565,
+0x580, 0x3b, 0x564, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x3b, 0x540, 0x3b, 0x553, 0x3b, 0x544, 0x3b, 0x531, 0x3b,
+0x544, 0x3b, 0x540, 0x3b, 0x540, 0x3b, 0x555, 0x3b, 0x54d, 0x3b, 0x540, 0x3b, 0x546, 0x3b, 0x534, 0x3b, 0x570, 0x578, 0x582, 0x576,
+0x57e, 0x561, 0x580, 0x56b, 0x3b, 0x583, 0x565, 0x57f, 0x580, 0x57e, 0x561, 0x580, 0x56b, 0x3b, 0x574, 0x561, 0x580, 0x57f, 0x56b, 0x3b,
+0x561, 0x57a, 0x580, 0x56b, 0x56c, 0x56b, 0x3b, 0x574, 0x561, 0x575, 0x56b, 0x57d, 0x56b, 0x3b, 0x570, 0x578, 0x582, 0x576, 0x56b, 0x57d,
+0x56b, 0x3b, 0x570, 0x578, 0x582, 0x56c, 0x56b, 0x57d, 0x56b, 0x3b, 0x585, 0x563, 0x578, 0x57d, 0x57f, 0x578, 0x57d, 0x56b, 0x3b, 0x57d,
+0x565, 0x57a, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x570, 0x578, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b,
+0x3b, 0x576, 0x578, 0x575, 0x565, 0x574, 0x562, 0x565, 0x580, 0x56b, 0x3b, 0x564, 0x565, 0x56f, 0x57f, 0x565, 0x574, 0x562, 0x565, 0x580,
+0x56b, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b,
+0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b,
+0x986, 0x997, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x3b, 0x9a1,
+0x9bf, 0x9b8, 0x9c7, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9f1, 0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd, 0x9f0, 0x9c1, 0x9f1,
+0x9be, 0x9f0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9f0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9f0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b,
+0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b7, 0x9cd, 0x99f, 0x3b, 0x99b, 0x9c7, 0x9aa, 0x9cd,
+0x9a4, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9f0, 0x3b, 0x9a8, 0x9f1, 0x9c7, 0x9ae, 0x9cd,
+0x9ac, 0x9f0, 0x3b, 0x9a1, 0x9bf, 0x99a, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9f0, 0x3b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b,
+0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, 0x69, 0x79, 0x6c, 0x3b,
+0x61, 0x76, 0x71, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, 0x64, 0x65, 0x6b, 0x3b,
+0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41,
+0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x130, 0x79, 0x75, 0x6e, 0x3b, 0x130, 0x79, 0x75, 0x6c, 0x3b, 0x41,
+0x76, 0x71, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x79, 0x61,
+0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x44, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x79, 0x61, 0x6e,
+0x76, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65,
+0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x71, 0x75,
+0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x79, 0x61, 0x62, 0x72, 0x3b,
+0x6e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435,
+0x432, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x458, 0x43d, 0x3b, 0x438, 0x458,
+0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43d, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x458, 0x3b, 0x434, 0x435,
+0x43a, 0x3b, 0x408, 0x430, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430, 0x440, 0x442,
+0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x458, 0x443, 0x43d, 0x3b, 0x418, 0x458, 0x443, 0x43b,
+0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x41e, 0x43a, 0x442,
+0x458, 0x430, 0x431, 0x440, 0x3b, 0x41d, 0x43e, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0x458,
+0x430, 0x43d, 0x432, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f,
+0x440, 0x435, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x458, 0x443, 0x43d, 0x3b, 0x438, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432,
+0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x458, 0x430, 0x431,
+0x440, 0x3b, 0x43d, 0x43e, 0x458, 0x430, 0x431, 0x440, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0x75, 0x72, 0x74, 0x2e,
+0x3b, 0x6f, 0x74, 0x73, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x69, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x2e,
+0x3b, 0x65, 0x6b, 0x61, 0x2e, 0x3b, 0x75, 0x7a, 0x74, 0x2e, 0x3b, 0x61, 0x62, 0x75, 0x2e, 0x3b, 0x69, 0x72, 0x61, 0x2e,
+0x3b, 0x75, 0x72, 0x72, 0x2e, 0x3b, 0x61, 0x7a, 0x61, 0x2e, 0x3b, 0x61, 0x62, 0x65, 0x2e, 0x3b, 0x75, 0x72, 0x74, 0x61,
+0x72, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x4f, 0x74, 0x73, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x78, 0x6f,
+0x61, 0x3b, 0x41, 0x70, 0x69, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x4d, 0x61, 0x69, 0x61, 0x74, 0x7a, 0x61, 0x3b, 0x45, 0x6b,
+0x61, 0x69, 0x6e, 0x61, 0x3b, 0x55, 0x7a, 0x74, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x41, 0x62, 0x75, 0x7a, 0x74, 0x75, 0x61,
+0x3b, 0x49, 0x72, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x55, 0x72, 0x72, 0x69, 0x61, 0x3b, 0x41, 0x7a, 0x61, 0x72, 0x6f, 0x61,
+0x3b, 0x41, 0x62, 0x65, 0x6e, 0x64, 0x75, 0x61, 0x3b, 0x55, 0x3b, 0x4f, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x45,
+0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x55, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x75, 0x72, 0x74, 0x61, 0x72, 0x72, 0x69,
+0x6c, 0x61, 0x3b, 0x6f, 0x74, 0x73, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x78, 0x6f, 0x61, 0x3b, 0x61,
+0x70, 0x69, 0x72, 0x69, 0x6c, 0x61, 0x3b, 0x6d, 0x61, 0x69, 0x61, 0x74, 0x7a, 0x61, 0x3b, 0x65, 0x6b, 0x61, 0x69, 0x6e,
+0x61, 0x3b, 0x75, 0x7a, 0x74, 0x61, 0x69, 0x6c, 0x61, 0x3b, 0x61, 0x62, 0x75, 0x7a, 0x74, 0x75, 0x61, 0x3b, 0x69, 0x72,
+0x61, 0x69, 0x6c, 0x61, 0x3b, 0x75, 0x72, 0x72, 0x69, 0x61, 0x3b, 0x61, 0x7a, 0x61, 0x72, 0x6f, 0x61, 0x3b, 0x61, 0x62,
+0x65, 0x6e, 0x64, 0x75, 0x61, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x9cd,
+0x9b0, 0x9c1, 0x9af, 0x9bc, 0x9be, 0x9b0, 0x9c0, 0x3b, 0x9ae, 0x9be, 0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2,
+0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b,
+0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8,
+0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x99c, 0x9be, 0x3b, 0x9ab,
+0x9c7, 0x3b, 0x9ae, 0x9be, 0x3b, 0x98f, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1, 0x3b, 0x986, 0x3b, 0x9b8,
+0x9c7, 0x3b, 0x985, 0x3b, 0x9a8, 0x3b, 0x9a1, 0x9bf, 0x3b, 0x99c, 0x9be, 0x9a8, 0x9c1, 0x3b, 0x9ab, 0x9c7, 0x9ac, 0x3b, 0x9ae, 0x9be,
+0x9b0, 0x9cd, 0x99a, 0x3b, 0x98f, 0x9aa, 0x9cd, 0x9b0, 0x9bf, 0x9b2, 0x3b, 0x9ae, 0x9c7, 0x3b, 0x99c, 0x9c1, 0x9a8, 0x3b, 0x99c, 0x9c1,
+0x9b2, 0x9be, 0x987, 0x3b, 0x986, 0x997, 0x9b8, 0x9cd, 0x99f, 0x3b, 0x9b8, 0x9c7, 0x9aa, 0x9cd, 0x99f, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0,
+0x3b, 0x985, 0x995, 0x9cd, 0x99f, 0x9cb, 0x9ac, 0x9b0, 0x3b, 0x9a8, 0x9ad, 0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0x9a1, 0x9bf, 0x9b8,
+0x9c7, 0x9ae, 0x9cd, 0x9ac, 0x9b0, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf22, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf23,
+0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf24, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf25, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf26, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf27,
+0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf28, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf29, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf20, 0x3b, 0xf5f, 0xfb3, 0xf0b,
+0xf21, 0xf21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf21, 0xf22, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54,
+0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4,
+0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f,
+0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54,
+0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf66, 0xfa4, 0xfb1,
+0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3,
+0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf42,
+0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b,
+0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b,
+0xf66, 0xfa4, 0xfb1, 0xf72, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b,
+0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0xf24, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b, 0xf28, 0x3b, 0xf29, 0x3b, 0xf21, 0xf20,
+0x3b, 0xf21, 0xf21, 0x3b, 0xf21, 0xf22, 0x3b, 0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0xf24, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27,
+0x3b, 0xf28, 0x3b, 0xf29, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0x31, 0x32, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xf44, 0xf54,
+0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58,
+0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf63, 0xf94, 0xf0b,
+0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53,
+0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf51,
+0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56,
+0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49,
+0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf21, 0x3b, 0xf22, 0x3b, 0xf23, 0x3b, 0x34, 0x3b, 0xf25, 0x3b, 0xf26, 0x3b, 0xf27, 0x3b,
+0xf28, 0x3b, 0x39, 0x3b, 0xf21, 0xf20, 0x3b, 0xf21, 0xf21, 0x3b, 0xf21, 0xf22, 0x3b, 0x47, 0x65, 0x6e, 0x2e, 0x3b, 0x43, 0x2bc,
+0x68, 0x77, 0x65, 0x2e, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x2e, 0x3b, 0x45, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x65, 0x3b,
+0x4d, 0x65, 0x7a, 0x68, 0x2e, 0x3b, 0x47, 0x6f, 0x75, 0x65, 0x2e, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65,
+0x6e, 0x2e, 0x3b, 0x48, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x72, 0x2e, 0x3b, 0x47, 0x65, 0x6e, 0x76,
+0x65, 0x72, 0x3b, 0x43, 0x2bc, 0x68, 0x77, 0x65, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68, 0x3b,
+0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x47,
+0x6f, 0x75, 0x65, 0x72, 0x65, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x67, 0x6f, 0x6c, 0x6f, 0x3b,
+0x48, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x72, 0x7a, 0x75, 0x3b, 0x30, 0x31, 0x3b, 0x30, 0x32, 0x3b,
+0x30, 0x33, 0x3b, 0x30, 0x34, 0x3b, 0x30, 0x35, 0x3b, 0x30, 0x36, 0x3b, 0x30, 0x37, 0x3b, 0x30, 0x38, 0x3b, 0x30, 0x39,
+0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0x47, 0x65, 0x6e, 0x2e, 0x3b, 0x43, 0x2bc, 0x68, 0x77, 0x65,
+0x2e, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x2e, 0x3b, 0x45, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x65, 0x3b, 0x4d, 0x65, 0x7a,
+0x68, 0x2e, 0x3b, 0x47, 0x6f, 0x75, 0x65, 0x2e, 0x3b, 0x45, 0x6f, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x2e, 0x3b,
+0x48, 0x65, 0x72, 0x65, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x7a, 0x75, 0x2e, 0x3b, 0x44f, 0x43d, 0x443, 0x3b, 0x444, 0x435, 0x432,
+0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b,
+0x438, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x435, 0x3b, 0x434, 0x435,
+0x43a, 0x3b, 0x44f, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x43c, 0x430,
+0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x44e, 0x43d, 0x438, 0x3b, 0x44e, 0x43b, 0x438,
+0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43e, 0x43a,
+0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x43c,
+0x432, 0x440, 0x438, 0x3b, 0x44f, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b, 0x44e, 0x3b, 0x44e, 0x3b, 0x430, 0x3b,
+0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 0x1007, 0x1014, 0x103a, 0x3b, 0x1016, 0x1031, 0x3b, 0x1019, 0x1010, 0x103a, 0x3b, 0x1027,
+0x3b, 0x1019, 0x1031, 0x3b, 0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x3b, 0x1029, 0x3b, 0x1005, 0x1000, 0x103a, 0x3b, 0x1021, 0x1031,
+0x102c, 0x1000, 0x103a, 0x3b, 0x1014, 0x102d, 0x102f, 0x3b, 0x1012, 0x102e, 0x3b, 0x1007, 0x1014, 0x103a, 0x1014, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b,
+0x1016, 0x1031, 0x1016, 0x1031, 0x102c, 0x103a, 0x101d, 0x102b, 0x101b, 0x102e, 0x3b, 0x1019, 0x1010, 0x103a, 0x3b, 0x1027, 0x1015, 0x103c, 0x102e, 0x3b,
+0x1019, 0x1031, 0x3b, 0x1007, 0x103d, 0x1014, 0x103a, 0x3b, 0x1007, 0x1030, 0x101c, 0x102d, 0x102f, 0x1004, 0x103a, 0x3b, 0x1029, 0x1002, 0x102f, 0x1010,
+0x103a, 0x3b, 0x1005, 0x1000, 0x103a, 0x1010, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1021, 0x1031, 0x102c, 0x1000, 0x103a, 0x1010, 0x102d, 0x102f, 0x1018,
+0x102c, 0x3b, 0x1014, 0x102d, 0x102f, 0x101d, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1012, 0x102e, 0x1007, 0x1004, 0x103a, 0x1018, 0x102c, 0x3b, 0x1007,
+0x3b, 0x1016, 0x3b, 0x1019, 0x3b, 0x1027, 0x3b, 0x1019, 0x3b, 0x1007, 0x3b, 0x1007, 0x3b, 0x1029, 0x3b, 0x1005, 0x3b, 0x1021, 0x3b, 0x1014,
+0x3b, 0x1012, 0x3b, 0x441, 0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x3b, 0x43c,
+0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d, 0x456, 0x3b, 0x432, 0x435, 0x440, 0x3b, 0x43a,
+0x430, 0x441, 0x3b, 0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x3b, 0x441, 0x442, 0x443, 0x434, 0x437, 0x435, 0x43d, 0x44c, 0x3b,
+0x43b, 0x44e, 0x442, 0x44b, 0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456, 0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x441, 0x430, 0x432, 0x456,
+0x43a, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x447, 0x44d, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44c,
+0x3b, 0x436, 0x43d, 0x456, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x430, 0x441, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x430,
+0x441, 0x442, 0x440, 0x44b, 0x447, 0x43d, 0x456, 0x43a, 0x3b, 0x43b, 0x456, 0x441, 0x442, 0x430, 0x43f, 0x430, 0x434, 0x3b, 0x441, 0x43d,
+0x435, 0x436, 0x430, 0x43d, 0x44c, 0x3b, 0x441, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x43a, 0x3b, 0x43c, 0x3b, 0x447, 0x3b, 0x43b, 0x3b,
+0x436, 0x3b, 0x432, 0x3b, 0x43a, 0x3b, 0x43b, 0x3b, 0x441, 0x3b, 0x441, 0x442, 0x443, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x441, 0x430,
+0x43a, 0x3b, 0x43a, 0x440, 0x430, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x447, 0x44d, 0x440, 0x3b, 0x43b, 0x456, 0x43f, 0x3b, 0x436, 0x43d,
+0x456, 0x3b, 0x432, 0x435, 0x440, 0x3b, 0x43a, 0x430, 0x441, 0x3b, 0x43b, 0x456, 0x441, 0x3b, 0x441, 0x43d, 0x435, 0x3b, 0x441, 0x442,
+0x443, 0x434, 0x437, 0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x430, 0x433, 0x430, 0x3b, 0x441, 0x430, 0x43a, 0x430, 0x432, 0x456,
+0x43a, 0x430, 0x3b, 0x43a, 0x440, 0x430, 0x441, 0x430, 0x432, 0x456, 0x43a, 0x430, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x447, 0x44d, 0x440,
+0x432, 0x435, 0x43d, 0x44f, 0x3b, 0x43b, 0x456, 0x43f, 0x435, 0x43d, 0x44f, 0x3b, 0x436, 0x43d, 0x456, 0x45e, 0x43d, 0x44f, 0x3b, 0x432,
+0x435, 0x440, 0x430, 0x441, 0x43d, 0x44f, 0x3b, 0x43a, 0x430, 0x441, 0x442, 0x440, 0x44b, 0x447, 0x43d, 0x456, 0x43a, 0x430, 0x3b, 0x43b,
+0x456, 0x441, 0x442, 0x430, 0x43f, 0x430, 0x434, 0x430, 0x3b, 0x441, 0x43d, 0x435, 0x436, 0x43d, 0x44f, 0x3b, 0x1798, 0x1780, 0x179a, 0x17b6,
+0x3b, 0x1780, 0x17bb, 0x1798, 0x17d2, 0x1797, 0x17c8, 0x3b, 0x1798, 0x17b8, 0x1793, 0x17b6, 0x3b, 0x1798, 0x17c1, 0x179f, 0x17b6, 0x3b, 0x17a7, 0x179f,
+0x1797, 0x17b6, 0x3b, 0x1798, 0x17b7, 0x1790, 0x17bb, 0x1793, 0x17b6, 0x3b, 0x1780, 0x1780, 0x17d2, 0x1780, 0x178a, 0x17b6, 0x3b, 0x179f, 0x17b8, 0x17a0,
+0x17b6, 0x3b, 0x1780, 0x1789, 0x17d2, 0x1789, 0x17b6, 0x3b, 0x178f, 0x17bb, 0x179b, 0x17b6, 0x3b, 0x179c, 0x17b7, 0x1785, 0x17d2, 0x1786, 0x17b7, 0x1780,
+0x17b6, 0x3b, 0x1792, 0x17d2, 0x1793, 0x17bc, 0x3b, 0x1798, 0x3b, 0x1780, 0x3b, 0x1798, 0x3b, 0x1798, 0x3b, 0x17a7, 0x3b, 0x1798, 0x3b, 0x1780,
+0x3b, 0x179f, 0x3b, 0x1780, 0x3b, 0x178f, 0x3b, 0x179c, 0x3b, 0x1792, 0x3b, 0x67, 0x65, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72,
+0x2e, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x6a, 0x75, 0x6e,
+0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e,
+0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x66, 0x65, 0x62,
+0x72, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x67, 0x3b,
+0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x73, 0x65,
+0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d,
+0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x47, 0x4e, 0x3b, 0x46, 0x42, 0x3b, 0x4d,
+0xc7, 0x3b, 0x41, 0x42, 0x3b, 0x4d, 0x47, 0x3b, 0x4a, 0x4e, 0x3b, 0x4a, 0x4c, 0x3b, 0x41, 0x47, 0x3b, 0x53, 0x54, 0x3b,
+0x4f, 0x43, 0x3b, 0x4e, 0x56, 0x3b, 0x44, 0x53, 0x3b, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x2e, 0x3b, 0x64, 0x65, 0x20,
+0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x2e,
+0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x69, 0x67, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x64, 0x65, 0x20,
+0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x64,
+0x2019, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x20, 0x64, 0x65, 0x73,
+0x2e, 0x3b, 0x64, 0x65, 0x20, 0x67, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72,
0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0xe7, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x64, 0x65, 0x20,
0x6d, 0x61, 0x69, 0x67, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x64, 0x65, 0x20, 0x6a, 0x75, 0x6c, 0x69,
0x6f, 0x6c, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62,
@@ -2216,392 +2237,387 @@ static const ushort months_data[] = {
0x6e, 0x61, 0x3b, 0x64, 0x75, 0x62, 0x6e, 0x61, 0x3b, 0x6b, 0x76, 0x11b, 0x74, 0x6e, 0x61, 0x3b, 0x10d, 0x65, 0x72, 0x76,
0x6e, 0x61, 0x3b, 0x10d, 0x65, 0x72, 0x76, 0x65, 0x6e, 0x63, 0x65, 0x3b, 0x73, 0x72, 0x70, 0x6e, 0x61, 0x3b, 0x7a, 0xe1,
0x159, 0xed, 0x3b, 0x159, 0xed, 0x6a, 0x6e, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x75, 0x3b, 0x70,
-0x72, 0x6f, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
-0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b,
-0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75,
-0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72,
-0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67,
-0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65,
-0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
-0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b,
-0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73,
-0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a,
-0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x72, 0x74, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d,
-0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65,
-0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61,
-0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x72, 0x74,
-0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69,
-0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
-0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63,
-0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e,
-0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b,
-0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b,
-0x44, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x61, 0x6e, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x3b, 0x6d, 0xe4, 0x72, 0x74,
-0x73, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c,
-0x69, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64,
-0x65, 0x74, 0x73, 0x3b, 0x6a, 0x61, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72,
-0x3b, 0x6d, 0xe4, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75,
-0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70,
-0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65,
-0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x74, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x4d,
-0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a,
-0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a,
-0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e,
-0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61,
-0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e,
-0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d,
-0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72,
-0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b,
-0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a,
-0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e,
-0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69,
-0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x3b,
-0x6b, 0x65, 0x73, 0xe4, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x3b, 0x65, 0x6c, 0x6f, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x3b,
-0x6c, 0x6f, 0x6b, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x3b, 0x74, 0x61,
-0x6d, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x61, 0x6c,
-0x69, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f,
-0x6b, 0x75, 0x75, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x75, 0x75, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x75, 0x75,
-0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6c, 0x6f, 0x6b, 0x61,
-0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b,
-0x75, 0x75, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x48, 0x3b, 0x45, 0x3b, 0x53,
-0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x65,
-0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61,
-0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x75, 0x75,
-0x74, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x75,
-0x75, 0x74, 0x61, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75,
-0x74, 0x61, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61, 0x73, 0x6b,
-0x75, 0x75, 0x74, 0x61, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x76,
-0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61,
-0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65,
-0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x3b, 0x6a,
-0x61, 0x6e, 0x76, 0x69, 0x65, 0x72, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x69, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b,
-0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x6c,
-0x65, 0x74, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63,
-0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0xe9, 0x63, 0x65, 0x6d,
-0x62, 0x72, 0x65, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61,
-0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x2e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61,
-0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b,
-0x64, 0xe9, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72,
-0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70,
-0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b, 0x6a, 0x61, 0x6e, 0x6e, 0x65, 0x77, 0x61,
-0x72, 0x69, 0x73, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x77, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x61, 0x72, 0x74,
-0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x61, 0x69, 0x65, 0x3b, 0x6a, 0x75, 0x6e, 0x79, 0x3b, 0x6a, 0x75,
-0x6c, 0x79, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x69, 0x6d, 0x62, 0x65,
-0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64,
-0x65, 0x73, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x72,
-0x74, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75,
-0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f,
-0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x46, 0x61, 0x6f, 0x69, 0x3b, 0x47, 0x65, 0x61, 0x72, 0x72, 0x3b, 0x4d,
-0xe0, 0x72, 0x74, 0x3b, 0x47, 0x69, 0x62, 0x6c, 0x3b, 0x43, 0xe8, 0x69, 0x74, 0x3b, 0xd2, 0x67, 0x6d, 0x68, 0x3b, 0x49,
-0x75, 0x63, 0x68, 0x3b, 0x4c, 0xf9, 0x6e, 0x61, 0x3b, 0x53, 0x75, 0x6c, 0x74, 0x3b, 0x44, 0xe0, 0x6d, 0x68, 0x3b, 0x53,
-0x61, 0x6d, 0x68, 0x3b, 0x44, 0xf9, 0x62, 0x68, 0x3b, 0x41, 0x6d, 0x20, 0x46, 0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61,
-0x63, 0x68, 0x3b, 0x41, 0x6e, 0x20, 0x47, 0x65, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x3b, 0x41, 0x6d, 0x20, 0x4d, 0xe0, 0x72,
-0x74, 0x3b, 0x41, 0x6e, 0x20, 0x47, 0x69, 0x62, 0x6c, 0x65, 0x61, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x43, 0xe8, 0x69, 0x74,
-0x65, 0x61, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0xd2, 0x67, 0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b, 0x41, 0x6e, 0x20,
-0x74, 0x2d, 0x49, 0x75, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x41, 0x6e, 0x20, 0x4c, 0xf9, 0x6e, 0x61, 0x73, 0x74, 0x61, 0x6c,
-0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x75, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x44, 0xe0, 0x6d,
-0x68, 0x61, 0x69, 0x72, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x41, 0x6e,
-0x20, 0x44, 0xf9, 0x62, 0x68, 0x6c, 0x61, 0x63, 0x68, 0x64, 0x3b, 0x46, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x43,
-0x3b, 0xd2, 0x3b, 0x49, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x44, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20,
-0x46, 0x68, 0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x63, 0x68, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x68, 0x65,
-0x61, 0x72, 0x72, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x4d, 0x68, 0xe0, 0x72, 0x74, 0x3b, 0x64, 0x68, 0x65,
-0x6e, 0x20, 0x47, 0x68, 0x69, 0x62, 0x6c, 0x65, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x43, 0x68, 0xe8, 0x69,
-0x74, 0x65, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0xd2, 0x67, 0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b, 0x64, 0x68,
-0x65, 0x6e, 0x20, 0x49, 0x75, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x4c, 0xf9, 0x6e, 0x61, 0x73,
-0x74, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x75, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x3b, 0x64,
-0x68, 0x65, 0x6e, 0x20, 0x44, 0xe0, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x2d, 0x53,
-0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x44, 0xf9, 0x62, 0x68, 0x6c, 0x61, 0x63, 0x68,
-0x64, 0x3b, 0x58, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61,
-0x69, 0x3b, 0x58, 0x75, 0xf1, 0x3b, 0x58, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x75,
-0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x58, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x65,
-0x62, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d,
-0x61, 0x69, 0x6f, 0x3b, 0x58, 0x75, 0xf1, 0x6f, 0x3b, 0x58, 0x75, 0x6c, 0x6c, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74,
-0x6f, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x4e,
-0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x58, 0x3b, 0x46,
-0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
-0x3b, 0x78, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x69,
-0x3b, 0x78, 0x75, 0xf1, 0x3b, 0x78, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x75, 0x74,
-0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x78, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62,
-0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61,
-0x69, 0x6f, 0x3b, 0x78, 0x75, 0xf1, 0x6f, 0x3b, 0x78, 0x75, 0x6c, 0x6c, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f,
-0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f,
-0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x10d8, 0x10d0, 0x10dc, 0x3b,
-0x10d7, 0x10d4, 0x10d1, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x3b, 0x10d0, 0x10de, 0x10e0, 0x3b, 0x10db, 0x10d0, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x3b,
-0x10d8, 0x10d5, 0x10da, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x3b, 0x10e1, 0x10d4, 0x10e5, 0x3b, 0x10dd, 0x10e5, 0x10e2, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x3b,
-0x10d3, 0x10d4, 0x10d9, 0x3b, 0x10d8, 0x10d0, 0x10dc, 0x10d5, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x10d7, 0x10d4, 0x10d1, 0x10d4, 0x10e0, 0x10d5, 0x10d0, 0x10da,
-0x10d8, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x10e2, 0x10d8, 0x3b, 0x10d0, 0x10de, 0x10e0, 0x10d8, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10d8, 0x10e1, 0x10d8,
-0x3b, 0x10d8, 0x10d5, 0x10dc, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10da, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x10d8, 0x10e1,
-0x10e2, 0x10dd, 0x3b, 0x10e1, 0x10d4, 0x10e5, 0x10e2, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dd, 0x10e5, 0x10e2, 0x10dd, 0x10db, 0x10d1,
-0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x10d4, 0x10db, 0x10d1, 0x10d4,
-0x10e0, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d7, 0x3b, 0x10db, 0x3b, 0x10d0, 0x3b, 0x10db, 0x3b, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d0, 0x3b, 0x10e1,
-0x3b, 0x10dd, 0x3b, 0x10dc, 0x3b, 0x10d3, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41,
-0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53,
-0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61,
-0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c,
-0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73,
-0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b,
-0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61,
-0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61,
-0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70,
-0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x4a, 0xe4, 0x6e,
-0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e,
-0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76,
-0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a, 0xe4, 0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b,
-0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b,
-0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65,
-0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44,
-0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0xe4, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4,
-0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c,
-0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76,
-0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3ac, 0x3c1, 0x3b, 0x391,
-0x3c0, 0x3c1, 0x3b, 0x39c, 0x3ac, 0x3b9, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b, 0x391, 0x3cd, 0x3b3,
-0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf, 0x3ad, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b, 0x399, 0x3b1, 0x3bd,
-0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3c1, 0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b,
-0x39c, 0x3ac, 0x3c1, 0x3c4, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3af, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3b9,
-0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391,
-0x3cd, 0x3b3, 0x3bf, 0x3c5, 0x3c3, 0x3c4, 0x3bf, 0x3c2, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3c4, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2,
-0x3b, 0x39f, 0x3ba, 0x3c4, 0x3ce, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39d, 0x3bf, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2,
-0x3b, 0x394, 0x3b5, 0x3ba, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3b, 0x3a6, 0x3b, 0x39c, 0x3b, 0x391, 0x3b,
-0x39c, 0x3b, 0x399, 0x3b, 0x399, 0x3b, 0x391, 0x3b, 0x3a3, 0x3b, 0x39f, 0x3b, 0x39d, 0x3b, 0x394, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3b,
-0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b, 0x39c, 0x3b1, 0x390, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd,
-0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb, 0x3b, 0x391, 0x3c5, 0x3b3, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf,
-0x3b5, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x3a6, 0x3b5, 0x3b2,
-0x3c1, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3c4, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c0, 0x3c1,
-0x3b9, 0x3bb, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1, 0x390, 0x3bf, 0x3c5, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, 0x3af, 0x3bf, 0x3c5, 0x3b,
-0x399, 0x3bf, 0x3c5, 0x3bb, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c5, 0x3b3, 0x3bf, 0x3cd, 0x3c3, 0x3c4, 0x3bf, 0x3c5, 0x3b, 0x3a3, 0x3b5,
-0x3c0, 0x3c4, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3c9, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b,
-0x39d, 0x3bf, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5,
-0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61,
-0x72, 0x74, 0x73, 0x69, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x69, 0x3b, 0x6a, 0x75, 0x6e,
-0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x69, 0x3b, 0x73, 0x65, 0x70,
-0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x6e, 0x6f, 0x76,
-0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 0xa9c, 0xabe, 0xaa8,
-0xacd, 0xaaf, 0xac1, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd,
-0xab0, 0xabf, 0xab2, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8,
-0xacd, 0xa9f, 0x3b, 0xab8, 0xaaa, 0xacd, 0xa9f, 0xac7, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0x3b, 0xaa8, 0xab5, 0xac7, 0x3b, 0xaa1,
-0xabf, 0xab8, 0xac7, 0x3b, 0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf, 0xac1, 0xa86, 0xab0, 0xac0, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1,
-0xa86, 0xab0, 0xac0, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2, 0x3b, 0xaae, 0xac7, 0x3b,
-0xa9c, 0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b, 0xab8, 0xaaa, 0xacd, 0xa9f,
-0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0xaac, 0xab0, 0x3b, 0xaa8, 0xab5, 0xac7, 0xaae, 0xacd, 0xaac,
-0xab0, 0x3b, 0xaa1, 0xabf, 0xab8, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xa9c, 0xabe, 0x3b, 0xaab, 0xac7, 0x3b, 0xaae, 0xabe, 0x3b,
-0xa8f, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0x3b, 0xa9c, 0xac1, 0x3b, 0xa91, 0x3b, 0xab8, 0x3b, 0xa91, 0x3b, 0xaa8, 0x3b, 0xaa1,
-0xabf, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x61, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x66, 0x69, 0x3b, 0x4d, 0x61,
-0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4f, 0x6b,
-0x74, 0x3b, 0x4e, 0x75, 0x77, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x61, 0x69, 0x72, 0x75, 0x3b, 0x46, 0x61,
-0x62, 0x75, 0x72, 0x61, 0x69, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x41, 0x66, 0x69, 0x72, 0x69, 0x6c,
-0x75, 0x3b, 0x4d, 0x61, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x69, 0x3b, 0x59, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75,
-0x73, 0x74, 0x61, 0x3b, 0x53, 0x61, 0x74, 0x75, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e,
-0x75, 0x77, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d,
-0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x5d9,
-0x5e0, 0x5d5, 0x5f3, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5d0,
-0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5f3, 0x3b, 0x5e1, 0x5e4, 0x5d8,
-0x5f3, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5f3, 0x3b, 0x5e0, 0x5d5, 0x5d1, 0x5f3, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x5f3, 0x3b, 0x5d9, 0x5e0, 0x5d5,
-0x5d0, 0x5e8, 0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5d9, 0x5dc, 0x3b,
-0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5d5, 0x5e1, 0x5d8,
-0x3b, 0x5e1, 0x5e4, 0x5d8, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5d8, 0x5d5, 0x5d1, 0x5e8, 0x3b, 0x5e0, 0x5d5, 0x5d1, 0x5de,
-0x5d1, 0x5e8, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x91c, 0x928, 0x970, 0x3b, 0x92b, 0x93c, 0x930, 0x970, 0x3b, 0x92e, 0x93e,
+0x72, 0x6f, 0x73, 0x69, 0x6e, 0x63, 0x65, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61,
+0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c,
+0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76,
+0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61,
+0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75,
+0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e,
+0x3b, 0x6d, 0x72, 0x74, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b,
+0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b,
+0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65,
+0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d,
+0x65, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75,
+0x73, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b,
+0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61,
+0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61,
+0x79, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70,
+0x2e, 0x3b, 0x4f, 0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x61,
+0x6e, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x3b, 0x6d, 0xe4, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61,
+0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65,
+0x70, 0x74, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x74, 0x73, 0x3b, 0x6a, 0x61, 0x61, 0x6e,
+0x75, 0x61, 0x72, 0x3b, 0x76, 0x65, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0xe4, 0x72, 0x74, 0x73, 0x3b, 0x61,
+0x70, 0x72, 0x69, 0x6c, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x75, 0x6c,
+0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f,
+0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x74,
+0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a,
+0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d,
+0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61,
+0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b, 0x6a,
+0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61,
+0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61,
+0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f,
+0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72,
+0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e,
+0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e,
+0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x3b,
+0x68, 0x75, 0x68, 0x74, 0x69, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x3b, 0x68, 0x65, 0x69,
+0x6e, 0xe4, 0x3b, 0x65, 0x6c, 0x6f, 0x3b, 0x73, 0x79, 0x79, 0x73, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x3b, 0x6d, 0x61, 0x72,
+0x72, 0x61, 0x73, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x68,
+0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x68, 0x75,
+0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x75, 0x75, 0x3b, 0x6b, 0x65, 0x73, 0xe4,
+0x6b, 0x75, 0x75, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x75, 0x75, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75, 0x3b,
+0x73, 0x79, 0x79, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x75, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x72,
+0x61, 0x73, 0x6b, 0x75, 0x75, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x75, 0x75, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x4d,
+0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x48, 0x3b, 0x45, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x74,
+0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69,
+0x73, 0x6b, 0x2e, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x2e, 0x3b, 0x74, 0x6f, 0x75, 0x6b, 0x6f, 0x6b, 0x2e, 0x3b,
+0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x2e, 0x3b, 0x68, 0x65, 0x69, 0x6e, 0xe4, 0x6b, 0x2e, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x2e,
+0x3b, 0x73, 0x79, 0x79, 0x73, 0x6b, 0x2e, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x72, 0x61,
+0x73, 0x6b, 0x2e, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x2e, 0x3b, 0x74, 0x61, 0x6d, 0x6d, 0x69, 0x6b, 0x75, 0x75,
+0x74, 0x61, 0x3b, 0x68, 0x65, 0x6c, 0x6d, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x73,
+0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x75, 0x68, 0x74, 0x69, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x74, 0x6f, 0x75,
+0x6b, 0x6f, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0xe4, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x68, 0x65,
+0x69, 0x6e, 0xe4, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x65, 0x6c, 0x6f, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x73, 0x79,
+0x79, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6c, 0x6f, 0x6b, 0x61, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6d, 0x61,
+0x72, 0x72, 0x61, 0x73, 0x6b, 0x75, 0x75, 0x74, 0x61, 0x3b, 0x6a, 0x6f, 0x75, 0x6c, 0x75, 0x6b, 0x75, 0x75, 0x74, 0x61,
+0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76,
+0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61, 0x6f,
+0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64,
+0xe9, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x72, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x69, 0x65, 0x72, 0x3b,
+0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b,
+0x6a, 0x75, 0x69, 0x6c, 0x6c, 0x65, 0x74, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62,
+0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b,
+0x64, 0xe9, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x66, 0xe9, 0x76, 0x72, 0x2e,
+0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69, 0x6e, 0x3b,
+0x6a, 0x75, 0x69, 0x6c, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63,
+0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0xe9,
+0x76, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x69,
+0x2e, 0x3b, 0x6a, 0x75, 0x69, 0x6c, 0x2e, 0x3b, 0x61, 0x6f, 0xfb, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f,
+0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0xe9, 0x63, 0x2e, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65,
+0x62, 0x3b, 0x4d, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75,
+0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65,
+0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x65, 0x77, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x77, 0x61,
+0x72, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x61, 0x69,
+0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x79, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73,
+0x3b, 0x53, 0x65, 0x70, 0x74, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e,
+0x6f, 0x76, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x69, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x46, 0x61, 0x6f,
+0x69, 0x3b, 0x47, 0x65, 0x61, 0x72, 0x72, 0x3b, 0x4d, 0xe0, 0x72, 0x74, 0x3b, 0x47, 0x69, 0x62, 0x6c, 0x3b, 0x43, 0xe8,
+0x69, 0x74, 0x3b, 0xd2, 0x67, 0x6d, 0x68, 0x3b, 0x49, 0x75, 0x63, 0x68, 0x3b, 0x4c, 0xf9, 0x6e, 0x61, 0x3b, 0x53, 0x75,
+0x6c, 0x74, 0x3b, 0x44, 0xe0, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x3b, 0x44, 0xf9, 0x62, 0x68, 0x3b, 0x41, 0x6d,
+0x20, 0x46, 0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x63, 0x68, 0x3b, 0x41, 0x6e, 0x20, 0x47, 0x65, 0x61, 0x72, 0x72,
+0x61, 0x6e, 0x3b, 0x41, 0x6d, 0x20, 0x4d, 0xe0, 0x72, 0x74, 0x3b, 0x41, 0x6e, 0x20, 0x47, 0x69, 0x62, 0x6c, 0x65, 0x61,
+0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x43, 0xe8, 0x69, 0x74, 0x65, 0x61, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0xd2, 0x67,
+0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x49, 0x75, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x41, 0x6e,
+0x20, 0x4c, 0xf9, 0x6e, 0x61, 0x73, 0x74, 0x61, 0x6c, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x75, 0x6c, 0x74, 0x61,
+0x69, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x44, 0xe0, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x41, 0x6e, 0x20, 0x74, 0x2d, 0x53,
+0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x41, 0x6e, 0x20, 0x44, 0xf9, 0x62, 0x68, 0x6c, 0x61, 0x63, 0x68, 0x64, 0x3b,
+0x46, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x43, 0x3b, 0xd2, 0x3b, 0x49, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x44, 0x3b,
+0x53, 0x3b, 0x44, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x46, 0x68, 0x61, 0x6f, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x63, 0x68,
+0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x68, 0x65, 0x61, 0x72, 0x72, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20,
+0x4d, 0x68, 0xe0, 0x72, 0x74, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x47, 0x68, 0x69, 0x62, 0x6c, 0x65, 0x61, 0x6e, 0x3b,
+0x64, 0x68, 0x65, 0x6e, 0x20, 0x43, 0x68, 0xe8, 0x69, 0x74, 0x65, 0x61, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0xd2,
+0x67, 0x6d, 0x68, 0x69, 0x6f, 0x73, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x49, 0x75, 0x63, 0x68, 0x61, 0x72, 0x3b, 0x64,
+0x68, 0x65, 0x6e, 0x20, 0x4c, 0xf9, 0x6e, 0x61, 0x73, 0x74, 0x61, 0x6c, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x2d,
+0x53, 0x75, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x44, 0xe0, 0x6d, 0x68, 0x61, 0x69, 0x72,
+0x3b, 0x64, 0x68, 0x65, 0x6e, 0x20, 0x74, 0x2d, 0x53, 0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x64, 0x68, 0x65, 0x6e,
+0x20, 0x44, 0xf9, 0x62, 0x68, 0x6c, 0x61, 0x63, 0x68, 0x64, 0x3b, 0x58, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e,
+0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x58, 0x75, 0xf1, 0x6f,
+0x3b, 0x58, 0x75, 0x6c, 0x2e, 0x3b, 0x41, 0x67, 0x6f, 0x2e, 0x3b, 0x53, 0x65, 0x74, 0x2e, 0x3b, 0x4f, 0x75, 0x74, 0x2e,
+0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x63, 0x2e, 0x3b, 0x58, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46,
+0x65, 0x62, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b,
+0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x58, 0x75, 0xf1, 0x6f, 0x3b, 0x58, 0x75, 0x6c, 0x6c, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73,
+0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b,
+0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x58, 0x3b,
+0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
+0x44, 0x3b, 0x78, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72,
+0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x78, 0x75, 0xf1, 0x6f, 0x3b, 0x78, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f,
+0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x75, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63,
+0x2e, 0x3b, 0x78, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x6d,
+0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x78, 0x75, 0xf1, 0x6f,
+0x3b, 0x78, 0x75, 0x6c, 0x6c, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62,
+0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b,
+0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x78, 0x2e, 0x3b, 0x66, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x61, 0x2e,
+0x3b, 0x6d, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x61, 0x2e, 0x3b, 0x73, 0x2e, 0x3b, 0x6f, 0x2e, 0x3b, 0x6e,
+0x2e, 0x3b, 0x64, 0x2e, 0x3b, 0x10d8, 0x10d0, 0x10dc, 0x3b, 0x10d7, 0x10d4, 0x10d1, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x3b, 0x10d0, 0x10de, 0x10e0,
+0x3b, 0x10db, 0x10d0, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x3b, 0x10d8, 0x10d5, 0x10da, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x3b, 0x10e1, 0x10d4, 0x10e5,
+0x3b, 0x10dd, 0x10e5, 0x10e2, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x3b, 0x10d8, 0x10d0, 0x10dc, 0x10d5, 0x10d0, 0x10e0, 0x10d8,
+0x3b, 0x10d7, 0x10d4, 0x10d1, 0x10d4, 0x10e0, 0x10d5, 0x10d0, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10e0, 0x10e2, 0x10d8, 0x3b, 0x10d0, 0x10de, 0x10e0,
+0x10d8, 0x10da, 0x10d8, 0x3b, 0x10db, 0x10d0, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10dc, 0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d8, 0x10d5, 0x10da,
+0x10d8, 0x10e1, 0x10d8, 0x3b, 0x10d0, 0x10d2, 0x10d5, 0x10d8, 0x10e1, 0x10e2, 0x10dd, 0x3b, 0x10e1, 0x10d4, 0x10e5, 0x10e2, 0x10d4, 0x10db, 0x10d1, 0x10d4,
+0x10e0, 0x10d8, 0x3b, 0x10dd, 0x10e5, 0x10e2, 0x10dd, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10dc, 0x10dd, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0,
+0x10d8, 0x3b, 0x10d3, 0x10d4, 0x10d9, 0x10d4, 0x10db, 0x10d1, 0x10d4, 0x10e0, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d7, 0x3b, 0x10db, 0x3b, 0x10d0, 0x3b,
+0x10db, 0x3b, 0x10d8, 0x3b, 0x10d8, 0x3b, 0x10d0, 0x3b, 0x10e1, 0x3b, 0x10dd, 0x3b, 0x10dc, 0x3b, 0x10d3, 0x3b, 0x4a, 0x61, 0x6e, 0x3b,
+0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b,
+0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b,
+0x44, 0x65, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d,
+0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a,
+0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65,
+0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72,
+0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69,
+0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e,
+0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x4a, 0xe4, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x70,
+0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65,
+0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a, 0xe4, 0x6e, 0x6e, 0x65, 0x72,
+0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b,
+0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74,
+0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e,
+0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0xe4, 0x6e,
+0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69,
+0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e,
+0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3b,
+0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3ac, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b, 0x39c, 0x3ac, 0x3b9, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd,
+0x3b, 0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b, 0x391, 0x3cd, 0x3b3, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf,
+0x3ad, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x3a6, 0x3b5, 0x3b2,
+0x3c1, 0x3bf, 0x3c5, 0x3ac, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3c1, 0x3c4, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391, 0x3c0, 0x3c1,
+0x3af, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39c, 0x3ac, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x399, 0x3bf, 0x3cd, 0x3bd, 0x3b9, 0x3bf, 0x3c2, 0x3b,
+0x399, 0x3bf, 0x3cd, 0x3bb, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x391, 0x3cd, 0x3b3, 0x3bf, 0x3c5, 0x3c3, 0x3c4, 0x3bf, 0x3c2, 0x3b, 0x3a3, 0x3b5,
+0x3c0, 0x3c4, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3ce, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b,
+0x39d, 0x3bf, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3ad, 0x3bc, 0x3b2, 0x3c1, 0x3b9, 0x3bf, 0x3c2,
+0x3b, 0x399, 0x3b, 0x3a6, 0x3b, 0x39c, 0x3b, 0x391, 0x3b, 0x39c, 0x3b, 0x399, 0x3b, 0x399, 0x3b, 0x391, 0x3b, 0x3a3, 0x3b, 0x39f,
+0x3b, 0x39d, 0x3b, 0x394, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3b, 0x39c, 0x3b1, 0x3c1, 0x3b, 0x391, 0x3c0, 0x3c1,
+0x3b, 0x39c, 0x3b1, 0x390, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb, 0x3b, 0x391, 0x3c5, 0x3b3, 0x3b, 0x3a3,
+0x3b5, 0x3c0, 0x3b, 0x39f, 0x3ba, 0x3c4, 0x3b, 0x39d, 0x3bf, 0x3b5, 0x3b, 0x394, 0x3b5, 0x3ba, 0x3b, 0x399, 0x3b1, 0x3bd, 0x3bf, 0x3c5,
+0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x3a6, 0x3b5, 0x3b2, 0x3c1, 0x3bf, 0x3c5, 0x3b1, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1,
+0x3c1, 0x3c4, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c0, 0x3c1, 0x3b9, 0x3bb, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39c, 0x3b1, 0x390, 0x3bf, 0x3c5,
+0x3b, 0x399, 0x3bf, 0x3c5, 0x3bd, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x399, 0x3bf, 0x3c5, 0x3bb, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x391, 0x3c5, 0x3b3,
+0x3bf, 0x3cd, 0x3c3, 0x3c4, 0x3bf, 0x3c5, 0x3b, 0x3a3, 0x3b5, 0x3c0, 0x3c4, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39f,
+0x3ba, 0x3c4, 0x3c9, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x39d, 0x3bf, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x394,
+0x3b5, 0x3ba, 0x3b5, 0x3bc, 0x3b2, 0x3c1, 0x3af, 0x3bf, 0x3c5, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61,
+0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x75,
+0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61,
+0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73,
+0x69, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a,
+0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d,
+0x62, 0x65, 0x72, 0x69, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x69, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x69, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x69, 0x3b, 0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf, 0xac1,
+0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, 0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2,
+0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0xaa8, 0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b,
+0xab8, 0xaaa, 0xacd, 0xa9f, 0xac7, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0x3b, 0xaa8, 0xab5, 0xac7, 0x3b, 0xaa1, 0xabf, 0xab8, 0xac7,
+0x3b, 0xa9c, 0xabe, 0xaa8, 0xacd, 0xaaf, 0xac1, 0xa86, 0xab0, 0xac0, 0x3b, 0xaab, 0xac7, 0xaac, 0xacd, 0xab0, 0xac1, 0xa86, 0xab0, 0xac0,
+0x3b, 0xaae, 0xabe, 0xab0, 0xacd, 0xa9a, 0x3b, 0xa8f, 0xaaa, 0xacd, 0xab0, 0xabf, 0xab2, 0x3b, 0xaae, 0xac7, 0x3b, 0xa9c, 0xac2, 0xaa8,
+0x3b, 0xa9c, 0xac1, 0xab2, 0xabe, 0xa88, 0x3b, 0xa91, 0xa97, 0xab8, 0xacd, 0xa9f, 0x3b, 0xab8, 0xaaa, 0xacd, 0xa9f, 0xac7, 0xaae, 0xacd,
+0xaac, 0xab0, 0x3b, 0xa91, 0xa95, 0xacd, 0xa9f, 0xacb, 0xaac, 0xab0, 0x3b, 0xaa8, 0xab5, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xaa1,
+0xabf, 0xab8, 0xac7, 0xaae, 0xacd, 0xaac, 0xab0, 0x3b, 0xa9c, 0xabe, 0x3b, 0xaab, 0xac7, 0x3b, 0xaae, 0xabe, 0x3b, 0xa8f, 0x3b, 0xaae,
+0xac7, 0x3b, 0xa9c, 0xac2, 0x3b, 0xa9c, 0xac1, 0x3b, 0xa91, 0x3b, 0xab8, 0x3b, 0xa91, 0x3b, 0xaa8, 0x3b, 0xaa1, 0xabf, 0x3b, 0x4a,
+0x61, 0x6e, 0x3b, 0x46, 0x61, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x66, 0x69, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59,
+0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e,
+0x75, 0x77, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x61, 0x69, 0x72, 0x75, 0x3b, 0x46, 0x61, 0x62, 0x75, 0x72,
+0x61, 0x69, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x3b, 0x41, 0x66, 0x69, 0x72, 0x69, 0x6c, 0x75, 0x3b, 0x4d,
+0x61, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x69, 0x3b, 0x59, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x61,
+0x3b, 0x53, 0x61, 0x74, 0x75, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x75, 0x77, 0x61,
+0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
+0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x5f3,
+0x3b, 0x5e4, 0x5d1, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5f3, 0x3b, 0x5de, 0x5d0, 0x5d9, 0x3b, 0x5d9,
+0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5f3, 0x3b, 0x5e1, 0x5e4, 0x5d8, 0x5f3, 0x3b, 0x5d0,
+0x5d5, 0x5e7, 0x5f3, 0x3b, 0x5e0, 0x5d5, 0x5d1, 0x5f3, 0x3b, 0x5d3, 0x5e6, 0x5de, 0x5f3, 0x3b, 0x5d9, 0x5e0, 0x5d5, 0x5d0, 0x5e8, 0x3b,
+0x5e4, 0x5d1, 0x5e8, 0x5d5, 0x5d0, 0x5e8, 0x3b, 0x5de, 0x5e8, 0x5e5, 0x3b, 0x5d0, 0x5e4, 0x5e8, 0x5d9, 0x5dc, 0x3b, 0x5de, 0x5d0, 0x5d9,
+0x3b, 0x5d9, 0x5d5, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dc, 0x5d9, 0x3b, 0x5d0, 0x5d5, 0x5d2, 0x5d5, 0x5e1, 0x5d8, 0x3b, 0x5e1, 0x5e4,
+0x5d8, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x5d0, 0x5d5, 0x5e7, 0x5d8, 0x5d5, 0x5d1, 0x5e8, 0x3b, 0x5e0, 0x5d5, 0x5d1, 0x5de, 0x5d1, 0x5e8, 0x3b,
+0x5d3, 0x5e6, 0x5de, 0x5d1, 0x5e8, 0x3b, 0x91c, 0x928, 0x970, 0x3b, 0x92b, 0x93c, 0x930, 0x970, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a,
+0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x970, 0x3b,
+0x905, 0x917, 0x970, 0x3b, 0x938, 0x93f, 0x924, 0x970, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x970, 0x3b, 0x928, 0x935, 0x970, 0x3b,
+0x926, 0x93f, 0x938, 0x970, 0x3b, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x93c, 0x930, 0x935, 0x930, 0x940, 0x3b, 0x92e, 0x93e,
0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941,
-0x932, 0x970, 0x3b, 0x905, 0x917, 0x970, 0x3b, 0x938, 0x93f, 0x924, 0x970, 0x3b, 0x905, 0x915, 0x94d, 0x924, 0x942, 0x970, 0x3b, 0x928,
-0x935, 0x970, 0x3b, 0x926, 0x93f, 0x938, 0x970, 0x3b, 0x91c, 0x928, 0x935, 0x930, 0x940, 0x3b, 0x92b, 0x93c, 0x930, 0x935, 0x930, 0x940,
-0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x905, 0x92a, 0x94d, 0x930, 0x948, 0x932, 0x3b, 0x92e, 0x908, 0x3b, 0x91c, 0x942, 0x928,
-0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f, 0x924, 0x902, 0x92c, 0x930, 0x3b,
-0x905, 0x915, 0x94d, 0x924, 0x942, 0x92c, 0x930, 0x3b, 0x928, 0x935, 0x902, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x902, 0x92c, 0x930,
-0x3b, 0x91c, 0x3b, 0x92b, 0x93c, 0x3b, 0x92e, 0x93e, 0x3b, 0x905, 0x3b, 0x92e, 0x3b, 0x91c, 0x942, 0x3b, 0x91c, 0x941, 0x3b, 0x905,
-0x3b, 0x938, 0x93f, 0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72,
-0x2e, 0x3b, 0x6d, 0xe1, 0x72, 0x63, 0x2e, 0x3b, 0xe1, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0xe1, 0x6a, 0x2e, 0x3b, 0x6a, 0xfa,
-0x6e, 0x2e, 0x3b, 0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x7a, 0x65, 0x70, 0x74, 0x2e, 0x3b,
-0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1,
-0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0xe1, 0x72, 0x63, 0x69, 0x75, 0x73, 0x3b, 0xe1, 0x70,
-0x72, 0x69, 0x6c, 0x69, 0x73, 0x3b, 0x6d, 0xe1, 0x6a, 0x75, 0x73, 0x3b, 0x6a, 0xfa, 0x6e, 0x69, 0x75, 0x73, 0x3b, 0x6a,
-0xfa, 0x6c, 0x69, 0x75, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x7a, 0x74, 0x75, 0x73, 0x3b, 0x73, 0x7a, 0x65, 0x70,
-0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d,
-0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0xc1,
-0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x7a, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61,
-0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61,
-0xed, 0x3b, 0x6a, 0xfa, 0x6e, 0x2e, 0x3b, 0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0xe1, 0x67, 0xfa, 0x2e, 0x3b, 0x73, 0x65, 0x70,
-0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0xf3, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x6a, 0x61, 0x6e,
-0xfa, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0xfa, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72,
-0xed, 0x6c, 0x3b, 0x6d, 0x61, 0xed, 0x3b, 0x6a, 0xfa, 0x6e, 0xed, 0x3b, 0x6a, 0xfa, 0x6c, 0xed, 0x3b, 0xe1, 0x67, 0xfa,
-0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72,
-0x3b, 0x6e, 0xf3, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a,
-0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0xc1, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e,
-0x3b, 0x44, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d,
-0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f,
-0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46,
-0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x72, 0x65, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b,
-0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x75,
-0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b,
-0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x45, 0x61,
-0x6e, 0x3b, 0x46, 0x65, 0x61, 0x62, 0x68, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, 0x3b, 0x41, 0x69, 0x62, 0x3b, 0x42, 0x65,
-0x61, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x74, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, 0x3b, 0x4c, 0xfa, 0x6e, 0x3b, 0x4d, 0x46,
-0xf3, 0x6d, 0x68, 0x3b, 0x44, 0x46, 0xf3, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c, 0x3b,
-0x45, 0x61, 0x6e, 0xe1, 0x69, 0x72, 0x3b, 0x46, 0x65, 0x61, 0x62, 0x68, 0x72, 0x61, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61,
-0x3b, 0x41, 0x69, 0x62, 0x72, 0x65, 0xe1, 0x6e, 0x3b, 0x42, 0x65, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4d,
-0x65, 0x69, 0x74, 0x68, 0x65, 0x61, 0x6d, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, 0x3b, 0x4c, 0xfa, 0x6e, 0x61, 0x73, 0x61,
-0x3b, 0x4d, 0x65, 0xe1, 0x6e, 0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x44, 0x65, 0x69, 0x72, 0x65, 0x61,
-0x64, 0x68, 0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x4e,
-0x6f, 0x6c, 0x6c, 0x61, 0x69, 0x67, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x42, 0x3b, 0x4d, 0x3b, 0x49,
-0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x67, 0x65, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d,
-0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x67, 0x3b, 0x67, 0x69, 0x75, 0x3b, 0x6c, 0x75, 0x67, 0x3b, 0x61,
-0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x74, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x69, 0x63, 0x3b, 0x47,
-0x65, 0x6e, 0x6e, 0x61, 0x69, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x62, 0x72, 0x61, 0x69, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x7a,
-0x6f, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x4d, 0x61, 0x67, 0x67, 0x69, 0x6f, 0x3b, 0x47, 0x69, 0x75, 0x67,
-0x6e, 0x6f, 0x3b, 0x4c, 0x75, 0x67, 0x6c, 0x69, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74,
-0x74, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x74, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d,
-0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x47, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
-0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x67, 0x65, 0x6e,
-0x6e, 0x61, 0x69, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x62, 0x72, 0x61, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b,
-0x61, 0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x6d, 0x61, 0x67, 0x67, 0x69, 0x6f, 0x3b, 0x67, 0x69, 0x75, 0x67, 0x6e, 0x6f,
-0x3b, 0x6c, 0x75, 0x67, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65,
-0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x74, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72,
-0x65, 0x3b, 0x64, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0xc9c, 0xca8, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0x3b,
-0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd,
-0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0x3b, 0xcb8, 0xcc6, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0x3b, 0xc85, 0xc95, 0xccd,
-0xc9f, 0xccb, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0x3b, 0xc9c, 0xca8, 0xcb5, 0xcb0, 0xcbf, 0x3b,
-0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd, 0xcb0,
-0xcbf, 0xcb2, 0xccd, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0xcb8,
-0xccd, 0xc9f, 0xccd, 0x3b, 0xcb8, 0xcc6, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xc85, 0xc95, 0xccd, 0xc9f, 0xccb,
-0xcac, 0xcb0, 0xccd, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd,
-0x3b, 0xc9c, 0x3b, 0xcab, 0xcc6, 0x3b, 0xcae, 0xcbe, 0x3b, 0xc8f, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0x3b, 0xc9c, 0xcc1, 0x3b,
-0xc86, 0x3b, 0xcb8, 0xcc6, 0x3b, 0xc85, 0x3b, 0xca8, 0x3b, 0xca1, 0xcbf, 0x3b, 0x62c, 0x646, 0x624, 0x631, 0x6cc, 0x3b, 0x641, 0x631,
-0x624, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x655, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x654, 0x3b,
-0x62c, 0x648, 0x657, 0x646, 0x3b, 0x62c, 0x648, 0x657, 0x644, 0x627, 0x6cc, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a,
-0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x657, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633,
-0x645, 0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x627, 0x3b,
-0x633, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x49a, 0x430, 0x4a3, 0x2e, 0x3b, 0x410, 0x49b, 0x43f, 0x2e, 0x3b, 0x41d, 0x430,
-0x443, 0x2e, 0x3b, 0x421, 0x4d9, 0x443, 0x2e, 0x3b, 0x41c, 0x430, 0x43c, 0x2e, 0x3b, 0x41c, 0x430, 0x443, 0x2e, 0x3b, 0x428, 0x456,
-0x43b, 0x2e, 0x3b, 0x422, 0x430, 0x43c, 0x2e, 0x3b, 0x49a, 0x44b, 0x440, 0x2e, 0x3b, 0x49a, 0x430, 0x437, 0x2e, 0x3b, 0x49a, 0x430,
-0x440, 0x2e, 0x3b, 0x416, 0x435, 0x43b, 0x2e, 0x3b, 0x49a, 0x430, 0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x410, 0x49b, 0x43f, 0x430, 0x43d,
-0x3b, 0x41d, 0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x421, 0x4d9, 0x443, 0x456, 0x440, 0x3b, 0x41c, 0x430, 0x43c, 0x44b, 0x440, 0x3b,
-0x41c, 0x430, 0x443, 0x441, 0x44b, 0x43c, 0x3b, 0x428, 0x456, 0x43b, 0x434, 0x435, 0x3b, 0x422, 0x430, 0x43c, 0x44b, 0x437, 0x3b, 0x49a,
-0x44b, 0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x43d, 0x3b, 0x49a, 0x430, 0x440, 0x430, 0x448, 0x430,
-0x3b, 0x416, 0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d, 0x3b, 0x49a, 0x3b, 0x410, 0x3b, 0x41d, 0x3b, 0x421, 0x3b, 0x41c,
-0x3b, 0x41c, 0x3b, 0x428, 0x3b, 0x422, 0x3b, 0x49a, 0x3b, 0x49a, 0x3b, 0x49a, 0x3b, 0x416, 0x3b, 0x49b, 0x430, 0x4a3, 0x2e, 0x3b,
-0x430, 0x49b, 0x43f, 0x2e, 0x3b, 0x43d, 0x430, 0x443, 0x2e, 0x3b, 0x441, 0x4d9, 0x443, 0x2e, 0x3b, 0x43c, 0x430, 0x43c, 0x2e, 0x3b,
-0x43c, 0x430, 0x443, 0x2e, 0x3b, 0x448, 0x456, 0x43b, 0x2e, 0x3b, 0x442, 0x430, 0x43c, 0x2e, 0x3b, 0x49b, 0x44b, 0x440, 0x2e, 0x3b,
-0x49b, 0x430, 0x437, 0x2e, 0x3b, 0x49b, 0x430, 0x440, 0x2e, 0x3b, 0x436, 0x435, 0x43b, 0x2e, 0x3b, 0x49b, 0x430, 0x4a3, 0x442, 0x430,
-0x440, 0x3b, 0x430, 0x49b, 0x43f, 0x430, 0x43d, 0x3b, 0x43d, 0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x441, 0x4d9, 0x443, 0x456, 0x440,
-0x3b, 0x43c, 0x430, 0x43c, 0x44b, 0x440, 0x3b, 0x43c, 0x430, 0x443, 0x441, 0x44b, 0x43c, 0x3b, 0x448, 0x456, 0x43b, 0x434, 0x435, 0x3b,
-0x442, 0x430, 0x43c, 0x44b, 0x437, 0x3b, 0x49b, 0x44b, 0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49b, 0x430, 0x437, 0x430, 0x43d,
-0x3b, 0x49b, 0x430, 0x440, 0x430, 0x448, 0x430, 0x3b, 0x436, 0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d, 0x3b, 0x6d, 0x75,
-0x74, 0x2e, 0x3b, 0x67, 0x61, 0x73, 0x2e, 0x3b, 0x77, 0x65, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x2e, 0x3b, 0x67, 0x69,
-0x63, 0x2e, 0x3b, 0x6b, 0x61, 0x6d, 0x2e, 0x3b, 0x6e, 0x79, 0x61, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x6e, 0x7a,
-0x65, 0x2e, 0x3b, 0x75, 0x6b, 0x77, 0x2e, 0x3b, 0x75, 0x67, 0x75, 0x2e, 0x3b, 0x75, 0x6b, 0x75, 0x2e, 0x3b, 0x4d, 0x75,
-0x74, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x3b, 0x47, 0x61, 0x73, 0x68, 0x79, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x65, 0x3b, 0x57,
-0x65, 0x72, 0x75, 0x72, 0x77, 0x65, 0x3b, 0x4d, 0x61, 0x74, 0x61, 0x3b, 0x47, 0x69, 0x63, 0x75, 0x72, 0x61, 0x6e, 0x73,
-0x69, 0x3b, 0x4b, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x4b, 0x61,
-0x6e, 0x61, 0x6d, 0x61, 0x3b, 0x4e, 0x7a, 0x65, 0x6c, 0x69, 0x3b, 0x55, 0x6b, 0x77, 0x61, 0x6b, 0x69, 0x72, 0x61, 0x3b,
-0x55, 0x67, 0x75, 0x73, 0x68, 0x79, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x55, 0x6b, 0x75, 0x62, 0x6f, 0x7a, 0x61, 0x3b, 0x42f,
-0x43d, 0x432, 0x3b, 0x424, 0x435, 0x432, 0x3b, 0x41c, 0x430, 0x440, 0x3b, 0x410, 0x43f, 0x440, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418,
-0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x3b, 0x421, 0x435, 0x43d, 0x3b, 0x41e, 0x43a, 0x442, 0x3b, 0x41d,
-0x43e, 0x44f, 0x3b, 0x414, 0x435, 0x43a, 0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b,
-0x44c, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e,
-0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x44f,
-0x431, 0x440, 0x44c, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x414,
-0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x3b, 0x42f, 0x3b, 0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x3b, 0x41c, 0x3b, 0x418, 0x3b, 0x418,
-0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x41e, 0x3b, 0x41d, 0x3b, 0x414, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e,
-0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x2e, 0x3b,
-0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b,
-0x43d, 0x43e, 0x44f, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x444, 0x435, 0x432,
-0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x439,
-0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435,
-0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440,
-0x44c, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x3b, 0x31, 0xc6d4, 0x3b, 0x32, 0xc6d4, 0x3b, 0x33, 0xc6d4, 0x3b, 0x34,
-0xc6d4, 0x3b, 0x35, 0xc6d4, 0x3b, 0x36, 0xc6d4, 0x3b, 0x37, 0xc6d4, 0x3b, 0x38, 0xc6d4, 0x3b, 0x39, 0xc6d4, 0x3b, 0x31, 0x30, 0xc6d4,
-0x3b, 0x31, 0x31, 0xc6d4, 0x3b, 0x31, 0x32, 0xc6d4, 0x3b, 0x4d, 0x75, 0x74, 0x2e, 0x3b, 0x47, 0x61, 0x73, 0x2e, 0x3b, 0x57,
-0x65, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x74, 0x2e, 0x3b, 0x47, 0x69, 0x63, 0x2e, 0x3b, 0x4b, 0x61, 0x6d, 0x2e, 0x3b, 0x4e,
-0x79, 0x61, 0x2e, 0x3b, 0x4b, 0x61, 0x6e, 0x2e, 0x3b, 0x4e, 0x7a, 0x65, 0x2e, 0x3b, 0x55, 0x6b, 0x77, 0x2e, 0x3b, 0x55,
-0x67, 0x75, 0x2e, 0x3b, 0x55, 0x6b, 0x75, 0x2e, 0x3b, 0x4e, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x52, 0x75, 0x68, 0x75, 0x68,
-0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x74, 0x77, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x3b, 0x4e, 0x64, 0x61, 0x6d, 0x75, 0x6b,
-0x69, 0x7a, 0x61, 0x3b, 0x52, 0x75, 0x73, 0x61, 0x6d, 0x61, 0x3b, 0x52, 0x75, 0x68, 0x65, 0x73, 0x68, 0x69, 0x3b, 0x4d,
-0x75, 0x6b, 0x61, 0x6b, 0x61, 0x72, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x61, 0x72, 0x6f, 0x3b, 0x4e,
-0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x47, 0x69, 0x74, 0x75, 0x67, 0x75, 0x74, 0x75, 0x3b, 0x4d, 0x75, 0x6e,
-0x79, 0x6f, 0x6e, 0x79, 0x6f, 0x3b, 0x4b, 0x69, 0x67, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x3b, 0xea1, 0x2e, 0xe81, 0x2e, 0x3b,
-0xe81, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0x2e, 0xe99, 0x2e, 0x3b, 0xea1, 0x2e, 0xeaa, 0x2e, 0x3b, 0xe9e, 0x2e, 0xe9e, 0x2e, 0x3b,
-0xea1, 0xeb4, 0x2e, 0xe96, 0x2e, 0x3b, 0xe81, 0x2e, 0xea5, 0x2e, 0x3b, 0xeaa, 0x2e, 0xeab, 0x2e, 0x3b, 0xe81, 0x2e, 0xe8d, 0x2e,
-0x3b, 0xe95, 0x2e, 0xea5, 0x2e, 0x3b, 0xe9e, 0x2e, 0xe88, 0x2e, 0x3b, 0xe97, 0x2e, 0xea7, 0x2e, 0x3b, 0xea1, 0xeb1, 0xe87, 0xe81,
-0xead, 0xe99, 0x3b, 0xe81, 0xeb8, 0xea1, 0xe9e, 0xeb2, 0x3b, 0xea1, 0xeb5, 0xe99, 0xeb2, 0x3b, 0xec0, 0xea1, 0xeaa, 0xeb2, 0x3b, 0xe9e,
-0xeb6, 0xe94, 0xeaa, 0xeb0, 0xe9e, 0xeb2, 0x3b, 0xea1, 0xeb4, 0xe96, 0xeb8, 0xe99, 0xeb2, 0x3b, 0xe81, 0xecd, 0xea5, 0xeb0, 0xe81, 0xebb,
-0xe94, 0x3b, 0xeaa, 0xeb4, 0xe87, 0xeab, 0xeb2, 0x3b, 0xe81, 0xeb1, 0xe99, 0xe8d, 0xeb2, 0x3b, 0xe95, 0xeb8, 0xea5, 0xeb2, 0x3b, 0xe9e,
-0xeb0, 0xe88, 0xeb4, 0xe81, 0x3b, 0xe97, 0xeb1, 0xe99, 0xea7, 0xeb2, 0x3b, 0x4a, 0x61, 0x6e, 0x76, 0x2e, 0x3b, 0x46, 0x65, 0x62,
-0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x6a, 0x73, 0x3b,
-0x4a, 0x16b, 0x6e, 0x2e, 0x3b, 0x4a, 0x16b, 0x6c, 0x2e, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x2e,
-0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x63, 0x2e, 0x3b, 0x4a, 0x61, 0x6e, 0x76,
-0x101, 0x72, 0x69, 0x73, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x73,
-0x3b, 0x41, 0x70, 0x72, 0x12b, 0x6c, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x69, 0x6a, 0x73, 0x3b, 0x4a, 0x16b, 0x6e, 0x69, 0x6a,
-0x73, 0x3b, 0x4a, 0x16b, 0x6c, 0x69, 0x6a, 0x73, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x73, 0x3b, 0x53, 0x65, 0x70,
-0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x4e, 0x6f, 0x76,
-0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x6a, 0x61, 0x6e,
-0x76, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b,
-0x6d, 0x61, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6e, 0x2e, 0x3b, 0x6a, 0x16b, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e,
-0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63,
-0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x101, 0x72, 0x69, 0x73,
-0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x12b, 0x6c, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x69, 0x6a, 0x73,
-0x3b, 0x6a, 0x16b, 0x6e, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6c, 0x69, 0x6a, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73,
-0x74, 0x73, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72,
-0x69, 0x73, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72,
-0x69, 0x73, 0x3b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x62, 0x6c, 0x3b, 0x6d, 0x73, 0x69, 0x3b, 0x61, 0x70, 0x6c, 0x3b, 0x6d,
-0x61, 0x69, 0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x74, 0x3b, 0x73, 0x74, 0x62, 0x3b, 0x254,
-0x74, 0x62, 0x3b, 0x6e, 0x76, 0x62, 0x3b, 0x64, 0x73, 0x62, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20,
-0x79, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c,
-0xe9, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74, 0x6f, 0x3b, 0x73, 0xe1,
-0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0x65, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79,
-0x61, 0x20, 0x6d, 0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x6f,
-0x74, 0xf3, 0x62, 0xe1, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6e, 0x73, 0x61, 0x6d, 0x62, 0x6f,
-0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x77, 0x61, 0x6d, 0x62, 0x65, 0x3b, 0x73, 0xe1, 0x6e,
-0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6c, 0x69, 0x62, 0x77, 0x61, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61,
-0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x20,
-0x6e, 0x61, 0x20, 0x6d, 0x254, 0x30c, 0x6b, 0x254, 0x301, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a,
-0xf3, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x79, 0x3b, 0x66, 0x3b, 0x6d, 0x3b,
-0x61, 0x3b, 0x6d, 0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x254, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x73, 0x61,
-0x75, 0x73, 0x2e, 0x3b, 0x76, 0x61, 0x73, 0x2e, 0x3b, 0x6b, 0x6f, 0x76, 0x2e, 0x3b, 0x62, 0x61, 0x6c, 0x2e, 0x3b, 0x67,
-0x65, 0x67, 0x2e, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x2e, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x2e, 0x3b, 0x72, 0x75, 0x67, 0x70,
-0x2e, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x2e, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x2e, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x2e,
-0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x2e, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x69, 0x73, 0x3b, 0x76, 0x61, 0x73, 0x61, 0x72,
-0x69, 0x73, 0x3b, 0x6b, 0x6f, 0x76, 0x61, 0x73, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x69, 0x73, 0x3b, 0x67, 0x65,
-0x67, 0x75, 0x17e, 0x117, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x73, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x61, 0x3b,
-0x72, 0x75, 0x67, 0x70, 0x6a, 0x16b, 0x74, 0x69, 0x73, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x69, 0x73, 0x3b, 0x73,
-0x70, 0x61, 0x6c, 0x69, 0x73, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x74, 0x69, 0x73, 0x3b, 0x67, 0x72, 0x75, 0x6f,
-0x64, 0x69, 0x73, 0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x42, 0x3b, 0x47, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x52, 0x3b,
-0x52, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x47, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x69, 0x6f, 0x3b, 0x76, 0x61, 0x73, 0x61, 0x72,
-0x69, 0x6f, 0x3b, 0x6b, 0x6f, 0x76, 0x6f, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x17e, 0x69, 0x6f, 0x3b, 0x67, 0x65,
-0x67, 0x75, 0x17e, 0x117, 0x73, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x6f, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x6f,
-0x73, 0x3b, 0x72, 0x75, 0x67, 0x70, 0x6a, 0x16b, 0x10d, 0x69, 0x6f, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x6f, 0x3b,
-0x73, 0x70, 0x61, 0x6c, 0x69, 0x6f, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x10d, 0x69, 0x6f, 0x3b, 0x67, 0x72, 0x75,
-0x6f, 0x64, 0x17e, 0x69, 0x6f, 0x3b, 0x458, 0x430, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e,
-0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x2e, 0x3b, 0x458, 0x443, 0x43b, 0x2e, 0x3b,
-0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x435, 0x43c,
-0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x443,
-0x430, 0x440, 0x438, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458,
-0x443, 0x43d, 0x438, 0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442,
-0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x432,
-0x440, 0x438, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x458, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b,
-0x43c, 0x3b, 0x458, 0x3b, 0x458, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 0x4a, 0x61, 0x6e, 0x3b,
-0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x6f, 0x6e, 0x3b,
-0x4a, 0x6f, 0x6c, 0x3b, 0x41, 0x6f, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b,
-0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x6f, 0x61, 0x72, 0x79, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x6f, 0x61, 0x72, 0x79,
-0x3b, 0x4d, 0x61, 0x72, 0x74, 0x73, 0x61, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x79, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a,
-0x6f, 0x6e, 0x61, 0x3b, 0x4a, 0x6f, 0x6c, 0x61, 0x79, 0x3b, 0x41, 0x6f, 0x67, 0x6f, 0x73, 0x69, 0x74, 0x72, 0x61, 0x3b,
-0x53, 0x65, 0x70, 0x74, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x4e, 0x6f,
-0x76, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x4a, 0x61, 0x6e, 0x3b,
-0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b,
-0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b,
-0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69,
-0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a,
-0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x6f, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
-0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x69, 0x73,
-0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b,
-0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0xd1c, 0xd28, 0xd41, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41,
-0x3b, 0xd2e, 0xd3e, 0xd7c, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b,
-0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd13, 0xd17, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02, 0x3b, 0xd12, 0xd15, 0xd4d,
-0xd1f, 0xd4b, 0x3b, 0xd28, 0xd35, 0xd02, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0x3b, 0xd1c, 0xd28, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2b,
-0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd3e, 0xd7c, 0xd1a, 0xd4d, 0xd1a, 0xd4d, 0x3b, 0xd0f, 0xd2a, 0xd4d,
-0xd30, 0xd3f, 0xd7d, 0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd13, 0xd17,
-0xd38, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd4d, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd12, 0xd15,
-0xd4d, 0x200c, 0xd1f, 0xd4b, 0xd2c, 0xd7c, 0x3b, 0xd28, 0xd35, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0xd2c, 0xd7c, 0x3b,
-0xd1c, 0x3b, 0xd2b, 0xd46, 0x3b, 0xd2e, 0xd3e, 0x3b, 0xd0f, 0x3b, 0xd2e, 0xd46, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd13,
-0x3b, 0xd38, 0xd46, 0x3b, 0xd12, 0x3b, 0xd28, 0x3b, 0xd21, 0xd3f, 0x3b, 0xd1c, 0x3b, 0xd2b, 0x3b, 0xd2e, 0xd3e, 0x3b, 0xd0f, 0x3b,
-0xd2e, 0xd46, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd13, 0x3b, 0xd38, 0x3b, 0xd12, 0x3b, 0xd28, 0x3b, 0xd21, 0xd3f, 0x3b,
+0x932, 0x93e, 0x908, 0x3b, 0x905, 0x917, 0x938, 0x94d, 0x924, 0x3b, 0x938, 0x93f, 0x924, 0x902, 0x92c, 0x930, 0x3b, 0x905, 0x915, 0x94d,
+0x924, 0x942, 0x92c, 0x930, 0x3b, 0x928, 0x935, 0x902, 0x92c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x902, 0x92c, 0x930, 0x3b, 0x91c, 0x3b,
+0x92b, 0x93c, 0x3b, 0x92e, 0x93e, 0x3b, 0x905, 0x3b, 0x92e, 0x3b, 0x91c, 0x942, 0x3b, 0x91c, 0x941, 0x3b, 0x905, 0x3b, 0x938, 0x93f,
+0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d,
+0xe1, 0x72, 0x63, 0x2e, 0x3b, 0xe1, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0xe1, 0x6a, 0x2e, 0x3b, 0x6a, 0xfa, 0x6e, 0x2e, 0x3b,
+0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x7a, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74,
+0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66,
+0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0xe1, 0x72, 0x63, 0x69, 0x75, 0x73, 0x3b, 0xe1, 0x70, 0x72, 0x69, 0x6c,
+0x69, 0x73, 0x3b, 0x6d, 0xe1, 0x6a, 0x75, 0x73, 0x3b, 0x6a, 0xfa, 0x6e, 0x69, 0x75, 0x73, 0x3b, 0x6a, 0xfa, 0x6c, 0x69,
+0x75, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x7a, 0x74, 0x75, 0x73, 0x3b, 0x73, 0x7a, 0x65, 0x70, 0x74, 0x65, 0x6d,
+0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0xc1, 0x3b, 0x4d, 0x3b,
+0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x7a, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b,
+0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0xed, 0x3b, 0x6a,
+0xfa, 0x6e, 0x2e, 0x3b, 0x6a, 0xfa, 0x6c, 0x2e, 0x3b, 0xe1, 0x67, 0xfa, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f,
+0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0xf3, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0xfa, 0x61, 0x72,
+0x3b, 0x66, 0x65, 0x62, 0x72, 0xfa, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b,
+0x6d, 0x61, 0xed, 0x3b, 0x6a, 0xfa, 0x6e, 0xed, 0x3b, 0x6a, 0xfa, 0x6c, 0xed, 0x3b, 0xe1, 0x67, 0xfa, 0x73, 0x74, 0x3b,
+0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0xf3,
+0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0xc1, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b,
+0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
+0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
+0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72,
+0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x72, 0x65, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69,
+0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x75, 0x73, 0x3b, 0x53,
+0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76,
+0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x45, 0x61, 0x6e, 0x3b, 0x46,
+0x65, 0x61, 0x62, 0x68, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, 0x3b, 0x41, 0x69, 0x62, 0x3b, 0x42, 0x65, 0x61, 0x6c, 0x3b,
+0x4d, 0x65, 0x69, 0x74, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, 0x3b, 0x4c, 0xfa, 0x6e, 0x3b, 0x4d, 0x46, 0xf3, 0x6d, 0x68,
+0x3b, 0x44, 0x46, 0xf3, 0x6d, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c, 0x3b, 0x45, 0x61, 0x6e,
+0xe1, 0x69, 0x72, 0x3b, 0x46, 0x65, 0x61, 0x62, 0x68, 0x72, 0x61, 0x3b, 0x4d, 0xe1, 0x72, 0x74, 0x61, 0x3b, 0x41, 0x69,
+0x62, 0x72, 0x65, 0xe1, 0x6e, 0x3b, 0x42, 0x65, 0x61, 0x6c, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x74,
+0x68, 0x65, 0x61, 0x6d, 0x68, 0x3b, 0x49, 0xfa, 0x69, 0x6c, 0x3b, 0x4c, 0xfa, 0x6e, 0x61, 0x73, 0x61, 0x3b, 0x4d, 0x65,
+0xe1, 0x6e, 0x20, 0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x44, 0x65, 0x69, 0x72, 0x65, 0x61, 0x64, 0x68, 0x20,
+0x46, 0xf3, 0x6d, 0x68, 0x61, 0x69, 0x72, 0x3b, 0x53, 0x61, 0x6d, 0x68, 0x61, 0x69, 0x6e, 0x3b, 0x4e, 0x6f, 0x6c, 0x6c,
+0x61, 0x69, 0x67, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x42, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4c, 0x3b,
+0x4d, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x67, 0x65, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x67, 0x3b, 0x67, 0x69, 0x75, 0x3b, 0x6c, 0x75, 0x67, 0x3b, 0x61, 0x67, 0x6f, 0x3b,
+0x73, 0x65, 0x74, 0x3b, 0x6f, 0x74, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x69, 0x63, 0x3b, 0x67, 0x65, 0x6e, 0x6e,
+0x61, 0x69, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x62, 0x72, 0x61, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61,
+0x70, 0x72, 0x69, 0x6c, 0x65, 0x3b, 0x6d, 0x61, 0x67, 0x67, 0x69, 0x6f, 0x3b, 0x67, 0x69, 0x75, 0x67, 0x6e, 0x6f, 0x3b,
+0x6c, 0x75, 0x67, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65, 0x6d,
+0x62, 0x72, 0x65, 0x3b, 0x6f, 0x74, 0x74, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x65,
+0x3b, 0x64, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x47, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
+0x47, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0xc9c, 0xca8, 0x3b, 0xcab, 0xcc6, 0xcac,
+0xccd, 0xcb0, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f, 0xcaa, 0xccd, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c,
+0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b, 0xc86, 0xc97, 0x3b, 0xcb8, 0xcc6, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0x3b,
+0xc85, 0xc95, 0xccd, 0xc9f, 0xccb, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82, 0x3b, 0xc9c, 0xca8, 0xcb5,
+0xcb0, 0xcbf, 0x3b, 0xcab, 0xcc6, 0xcac, 0xccd, 0xcb0, 0xcb5, 0xcb0, 0xcbf, 0x3b, 0xcae, 0xcbe, 0xcb0, 0xccd, 0xc9a, 0xccd, 0x3b, 0xc8f,
+0xcaa, 0xccd, 0xcb0, 0xcbf, 0xcb2, 0xccd, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0xca8, 0xccd, 0x3b, 0xc9c, 0xcc1, 0xcb2, 0xcc8, 0x3b,
+0xc86, 0xc97, 0xcb8, 0xccd, 0xc9f, 0xccd, 0x3b, 0xcb8, 0xcc6, 0xcaa, 0xccd, 0xc9f, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xc85, 0xc95,
+0xccd, 0xc9f, 0xccb, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca8, 0xcb5, 0xcc6, 0xc82, 0xcac, 0xcb0, 0xccd, 0x3b, 0xca1, 0xcbf, 0xcb8, 0xcc6, 0xc82,
+0xcac, 0xcb0, 0xccd, 0x3b, 0xc9c, 0x3b, 0xcab, 0xcc6, 0x3b, 0xcae, 0xcbe, 0x3b, 0xc8f, 0x3b, 0xcae, 0xcc7, 0x3b, 0xc9c, 0xcc2, 0x3b,
+0xc9c, 0xcc1, 0x3b, 0xc86, 0x3b, 0xcb8, 0xcc6, 0x3b, 0xc85, 0x3b, 0xca8, 0x3b, 0xca1, 0xcbf, 0x3b, 0x62c, 0x646, 0x624, 0x631, 0x6cc,
+0x3b, 0x641, 0x631, 0x624, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x655, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645,
+0x6cc, 0x654, 0x3b, 0x62c, 0x648, 0x657, 0x646, 0x3b, 0x62c, 0x648, 0x657, 0x644, 0x627, 0x6cc, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a,
+0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x657, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631,
+0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c,
+0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x49a, 0x430, 0x4a3, 0x2e, 0x3b, 0x410, 0x49b, 0x43f, 0x2e,
+0x3b, 0x41d, 0x430, 0x443, 0x2e, 0x3b, 0x421, 0x4d9, 0x443, 0x2e, 0x3b, 0x41c, 0x430, 0x43c, 0x2e, 0x3b, 0x41c, 0x430, 0x443, 0x2e,
+0x3b, 0x428, 0x456, 0x43b, 0x2e, 0x3b, 0x422, 0x430, 0x43c, 0x2e, 0x3b, 0x49a, 0x44b, 0x440, 0x2e, 0x3b, 0x49a, 0x430, 0x437, 0x2e,
+0x3b, 0x49a, 0x430, 0x440, 0x2e, 0x3b, 0x416, 0x435, 0x43b, 0x2e, 0x3b, 0x49a, 0x430, 0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x410, 0x49b,
+0x43f, 0x430, 0x43d, 0x3b, 0x41d, 0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x421, 0x4d9, 0x443, 0x456, 0x440, 0x3b, 0x41c, 0x430, 0x43c,
+0x44b, 0x440, 0x3b, 0x41c, 0x430, 0x443, 0x441, 0x44b, 0x43c, 0x3b, 0x428, 0x456, 0x43b, 0x434, 0x435, 0x3b, 0x422, 0x430, 0x43c, 0x44b,
+0x437, 0x3b, 0x49a, 0x44b, 0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x43d, 0x3b, 0x49a, 0x430, 0x440,
+0x430, 0x448, 0x430, 0x3b, 0x416, 0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d, 0x3b, 0x49a, 0x3b, 0x410, 0x3b, 0x41d, 0x3b,
+0x421, 0x3b, 0x41c, 0x3b, 0x41c, 0x3b, 0x428, 0x3b, 0x422, 0x3b, 0x49a, 0x3b, 0x49a, 0x3b, 0x49a, 0x3b, 0x416, 0x3b, 0x49b, 0x430,
+0x4a3, 0x2e, 0x3b, 0x430, 0x49b, 0x43f, 0x2e, 0x3b, 0x43d, 0x430, 0x443, 0x2e, 0x3b, 0x441, 0x4d9, 0x443, 0x2e, 0x3b, 0x43c, 0x430,
+0x43c, 0x2e, 0x3b, 0x43c, 0x430, 0x443, 0x2e, 0x3b, 0x448, 0x456, 0x43b, 0x2e, 0x3b, 0x442, 0x430, 0x43c, 0x2e, 0x3b, 0x49b, 0x44b,
+0x440, 0x2e, 0x3b, 0x49b, 0x430, 0x437, 0x2e, 0x3b, 0x49b, 0x430, 0x440, 0x2e, 0x3b, 0x436, 0x435, 0x43b, 0x2e, 0x3b, 0x49b, 0x430,
+0x4a3, 0x442, 0x430, 0x440, 0x3b, 0x430, 0x49b, 0x43f, 0x430, 0x43d, 0x3b, 0x43d, 0x430, 0x443, 0x440, 0x44b, 0x437, 0x3b, 0x441, 0x4d9,
+0x443, 0x456, 0x440, 0x3b, 0x43c, 0x430, 0x43c, 0x44b, 0x440, 0x3b, 0x43c, 0x430, 0x443, 0x441, 0x44b, 0x43c, 0x3b, 0x448, 0x456, 0x43b,
+0x434, 0x435, 0x3b, 0x442, 0x430, 0x43c, 0x44b, 0x437, 0x3b, 0x49b, 0x44b, 0x440, 0x43a, 0x4af, 0x439, 0x435, 0x43a, 0x3b, 0x49b, 0x430,
+0x437, 0x430, 0x43d, 0x3b, 0x49b, 0x430, 0x440, 0x430, 0x448, 0x430, 0x3b, 0x436, 0x435, 0x43b, 0x442, 0x43e, 0x49b, 0x441, 0x430, 0x43d,
+0x3b, 0x6d, 0x75, 0x74, 0x2e, 0x3b, 0x67, 0x61, 0x73, 0x2e, 0x3b, 0x77, 0x65, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x2e,
+0x3b, 0x67, 0x69, 0x63, 0x2e, 0x3b, 0x6b, 0x61, 0x6d, 0x2e, 0x3b, 0x6e, 0x79, 0x61, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e,
+0x3b, 0x6e, 0x7a, 0x65, 0x2e, 0x3b, 0x75, 0x6b, 0x77, 0x2e, 0x3b, 0x75, 0x67, 0x75, 0x2e, 0x3b, 0x75, 0x6b, 0x75, 0x2e,
+0x3b, 0x4d, 0x75, 0x74, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x3b, 0x47, 0x61, 0x73, 0x68, 0x79, 0x61, 0x6e, 0x74, 0x61, 0x72,
+0x65, 0x3b, 0x57, 0x65, 0x72, 0x75, 0x72, 0x77, 0x65, 0x3b, 0x4d, 0x61, 0x74, 0x61, 0x3b, 0x47, 0x69, 0x63, 0x75, 0x72,
+0x61, 0x6e, 0x73, 0x69, 0x3b, 0x4b, 0x61, 0x6d, 0x65, 0x6e, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61,
+0x3b, 0x4b, 0x61, 0x6e, 0x61, 0x6d, 0x61, 0x3b, 0x4e, 0x7a, 0x65, 0x6c, 0x69, 0x3b, 0x55, 0x6b, 0x77, 0x61, 0x6b, 0x69,
+0x72, 0x61, 0x3b, 0x55, 0x67, 0x75, 0x73, 0x68, 0x79, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x55, 0x6b, 0x75, 0x62, 0x6f, 0x7a,
+0x61, 0x3b, 0x42f, 0x43d, 0x432, 0x3b, 0x424, 0x435, 0x432, 0x3b, 0x41c, 0x430, 0x440, 0x3b, 0x410, 0x43f, 0x440, 0x3b, 0x41c, 0x430,
+0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x3b, 0x421, 0x435, 0x43d, 0x3b, 0x41e, 0x43a,
+0x442, 0x3b, 0x41d, 0x43e, 0x44f, 0x3b, 0x414, 0x435, 0x43a, 0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432,
+0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b, 0x41c, 0x430, 0x439,
+0x3b, 0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435,
+0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440,
+0x44c, 0x3b, 0x414, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x3b, 0x42f, 0x3b, 0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x3b, 0x41c, 0x3b,
+0x418, 0x3b, 0x418, 0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x41e, 0x3b, 0x41d, 0x3b, 0x414, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444,
+0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e,
+0x43d, 0x2e, 0x3b, 0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x2e, 0x3b, 0x43e, 0x43a,
+0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b,
+0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44c, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44c, 0x3b,
+0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442,
+0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x43d, 0x43e,
+0x44f, 0x431, 0x440, 0x44c, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44c, 0x3b, 0x31, 0xc6d4, 0x3b, 0x32, 0xc6d4, 0x3b, 0x33,
+0xc6d4, 0x3b, 0x34, 0xc6d4, 0x3b, 0x35, 0xc6d4, 0x3b, 0x36, 0xc6d4, 0x3b, 0x37, 0xc6d4, 0x3b, 0x38, 0xc6d4, 0x3b, 0x39, 0xc6d4, 0x3b,
+0x31, 0x30, 0xc6d4, 0x3b, 0x31, 0x31, 0xc6d4, 0x3b, 0x31, 0x32, 0xc6d4, 0x3b, 0x4d, 0x75, 0x74, 0x2e, 0x3b, 0x47, 0x61, 0x73,
+0x2e, 0x3b, 0x57, 0x65, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x74, 0x2e, 0x3b, 0x47, 0x69, 0x63, 0x2e, 0x3b, 0x4b, 0x61, 0x6d,
+0x2e, 0x3b, 0x4e, 0x79, 0x61, 0x2e, 0x3b, 0x4b, 0x61, 0x6e, 0x2e, 0x3b, 0x4e, 0x7a, 0x65, 0x2e, 0x3b, 0x55, 0x6b, 0x77,
+0x2e, 0x3b, 0x55, 0x67, 0x75, 0x2e, 0x3b, 0x55, 0x6b, 0x75, 0x2e, 0x3b, 0x4e, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x52, 0x75,
+0x68, 0x75, 0x68, 0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x74, 0x77, 0x61, 0x72, 0x61, 0x6e, 0x74, 0x65, 0x3b, 0x4e, 0x64, 0x61,
+0x6d, 0x75, 0x6b, 0x69, 0x7a, 0x61, 0x3b, 0x52, 0x75, 0x73, 0x61, 0x6d, 0x61, 0x3b, 0x52, 0x75, 0x68, 0x65, 0x73, 0x68,
+0x69, 0x3b, 0x4d, 0x75, 0x6b, 0x61, 0x6b, 0x61, 0x72, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x61, 0x72,
+0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x6b, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x47, 0x69, 0x74, 0x75, 0x67, 0x75, 0x74, 0x75, 0x3b,
+0x4d, 0x75, 0x6e, 0x79, 0x6f, 0x6e, 0x79, 0x6f, 0x3b, 0x4b, 0x69, 0x67, 0x61, 0x72, 0x61, 0x6d, 0x61, 0x3b, 0xea1, 0x2e,
+0xe81, 0x2e, 0x3b, 0xe81, 0x2e, 0xe9e, 0x2e, 0x3b, 0xea1, 0x2e, 0xe99, 0x2e, 0x3b, 0xea1, 0x2e, 0xeaa, 0x2e, 0x3b, 0xe9e, 0x2e,
+0xe9e, 0x2e, 0x3b, 0xea1, 0xeb4, 0x2e, 0xe96, 0x2e, 0x3b, 0xe81, 0x2e, 0xea5, 0x2e, 0x3b, 0xeaa, 0x2e, 0xeab, 0x2e, 0x3b, 0xe81,
+0x2e, 0xe8d, 0x2e, 0x3b, 0xe95, 0x2e, 0xea5, 0x2e, 0x3b, 0xe9e, 0x2e, 0xe88, 0x2e, 0x3b, 0xe97, 0x2e, 0xea7, 0x2e, 0x3b, 0xea1,
+0xeb1, 0xe87, 0xe81, 0xead, 0xe99, 0x3b, 0xe81, 0xeb8, 0xea1, 0xe9e, 0xeb2, 0x3b, 0xea1, 0xeb5, 0xe99, 0xeb2, 0x3b, 0xec0, 0xea1, 0xeaa,
+0xeb2, 0x3b, 0xe9e, 0xeb6, 0xe94, 0xeaa, 0xeb0, 0xe9e, 0xeb2, 0x3b, 0xea1, 0xeb4, 0xe96, 0xeb8, 0xe99, 0xeb2, 0x3b, 0xe81, 0xecd, 0xea5,
+0xeb0, 0xe81, 0xebb, 0xe94, 0x3b, 0xeaa, 0xeb4, 0xe87, 0xeab, 0xeb2, 0x3b, 0xe81, 0xeb1, 0xe99, 0xe8d, 0xeb2, 0x3b, 0xe95, 0xeb8, 0xea5,
+0xeb2, 0x3b, 0xe9e, 0xeb0, 0xe88, 0xeb4, 0xe81, 0x3b, 0xe97, 0xeb1, 0xe99, 0xea7, 0xeb2, 0x3b, 0x6a, 0x61, 0x6e, 0x76, 0x2e, 0x3b,
+0x66, 0x65, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69,
+0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6e, 0x2e, 0x3b, 0x6a, 0x16b, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65,
+0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a,
+0x61, 0x6e, 0x76, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x101, 0x72, 0x69, 0x73, 0x3b, 0x6d, 0x61,
+0x72, 0x74, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x12b, 0x6c, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b,
+0x6e, 0x69, 0x6a, 0x73, 0x3b, 0x6a, 0x16b, 0x6c, 0x69, 0x6a, 0x73, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x73, 0x3b,
+0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x69, 0x73, 0x3b,
+0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x73, 0x3b,
+0x79, 0x61, 0x6e, 0x3b, 0x66, 0x62, 0x6c, 0x3b, 0x6d, 0x73, 0x69, 0x3b, 0x61, 0x70, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x3b,
+0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x74, 0x3b, 0x73, 0x74, 0x62, 0x3b, 0x254, 0x74, 0x62, 0x3b,
+0x6e, 0x76, 0x62, 0x3b, 0x64, 0x73, 0x62, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x79, 0x61, 0x6d,
+0x62, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x73,
+0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1,
+0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0x65, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d,
+0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x6f, 0x74, 0xf3, 0x62,
+0xe1, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6e, 0x73, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0xe1,
+0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x77, 0x61, 0x6d, 0x62, 0x65, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20,
+0x79, 0x61, 0x20, 0x6c, 0x69, 0x62, 0x77, 0x61, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3,
+0x6d, 0x69, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20,
+0x6d, 0x254, 0x30c, 0x6b, 0x254, 0x301, 0x3b, 0x73, 0xe1, 0x6e, 0x7a, 0xe1, 0x20, 0x79, 0x61, 0x20, 0x7a, 0xf3, 0x6d, 0x69,
+0x20, 0x6e, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x79, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d,
+0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x254, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x2e,
+0x3b, 0x76, 0x61, 0x73, 0x2e, 0x3b, 0x6b, 0x6f, 0x76, 0x2e, 0x3b, 0x62, 0x61, 0x6c, 0x2e, 0x3b, 0x67, 0x65, 0x67, 0x2e,
+0x3b, 0x62, 0x69, 0x72, 0x17e, 0x2e, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x2e, 0x3b, 0x72, 0x75, 0x67, 0x70, 0x2e, 0x3b, 0x72,
+0x75, 0x67, 0x73, 0x2e, 0x3b, 0x73, 0x70, 0x61, 0x6c, 0x2e, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x2e, 0x3b, 0x67, 0x72,
+0x75, 0x6f, 0x64, 0x2e, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x69, 0x73, 0x3b, 0x76, 0x61, 0x73, 0x61, 0x72, 0x69, 0x73, 0x3b,
+0x6b, 0x6f, 0x76, 0x61, 0x73, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x69, 0x73, 0x3b, 0x67, 0x65, 0x67, 0x75, 0x17e,
+0x117, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x73, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x61, 0x3b, 0x72, 0x75, 0x67,
+0x70, 0x6a, 0x16b, 0x74, 0x69, 0x73, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x69, 0x73, 0x3b, 0x73, 0x70, 0x61, 0x6c,
+0x69, 0x73, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x74, 0x69, 0x73, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x69, 0x73,
+0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x42, 0x3b, 0x47, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x52, 0x3b, 0x52, 0x3b, 0x53,
+0x3b, 0x4c, 0x3b, 0x47, 0x3b, 0x73, 0x61, 0x75, 0x73, 0x69, 0x6f, 0x3b, 0x76, 0x61, 0x73, 0x61, 0x72, 0x69, 0x6f, 0x3b,
+0x6b, 0x6f, 0x76, 0x6f, 0x3b, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x17e, 0x69, 0x6f, 0x3b, 0x67, 0x65, 0x67, 0x75, 0x17e,
+0x117, 0x73, 0x3b, 0x62, 0x69, 0x72, 0x17e, 0x65, 0x6c, 0x69, 0x6f, 0x3b, 0x6c, 0x69, 0x65, 0x70, 0x6f, 0x73, 0x3b, 0x72,
+0x75, 0x67, 0x70, 0x6a, 0x16b, 0x10d, 0x69, 0x6f, 0x3b, 0x72, 0x75, 0x67, 0x73, 0x117, 0x6a, 0x6f, 0x3b, 0x73, 0x70, 0x61,
+0x6c, 0x69, 0x6f, 0x3b, 0x6c, 0x61, 0x70, 0x6b, 0x72, 0x69, 0x10d, 0x69, 0x6f, 0x3b, 0x67, 0x72, 0x75, 0x6f, 0x64, 0x17e,
+0x69, 0x6f, 0x3b, 0x458, 0x430, 0x43d, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f,
+0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x2e, 0x3b, 0x458, 0x443, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433,
+0x2e, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x2e, 0x3b, 0x434,
+0x435, 0x43a, 0x2e, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x438, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x443, 0x430, 0x440, 0x438,
+0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x438,
+0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x432,
+0x440, 0x438, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x43d, 0x43e, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b,
+0x434, 0x435, 0x43a, 0x435, 0x43c, 0x432, 0x440, 0x438, 0x3b, 0x458, 0x3b, 0x444, 0x3b, 0x43c, 0x3b, 0x430, 0x3b, 0x43c, 0x3b, 0x458,
+0x3b, 0x458, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x43e, 0x3b, 0x43d, 0x3b, 0x434, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
+0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x6f, 0x6e, 0x3b, 0x4a, 0x6f, 0x6c,
+0x3b, 0x41, 0x6f, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73,
+0x3b, 0x4a, 0x61, 0x6e, 0x6f, 0x61, 0x72, 0x79, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x6f, 0x61, 0x72, 0x79, 0x3b, 0x4d, 0x61,
+0x72, 0x74, 0x73, 0x61, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x79, 0x3b, 0x4d, 0x65, 0x79, 0x3b, 0x4a, 0x6f, 0x6e, 0x61,
+0x3b, 0x4a, 0x6f, 0x6c, 0x61, 0x79, 0x3b, 0x41, 0x6f, 0x67, 0x6f, 0x73, 0x69, 0x74, 0x72, 0x61, 0x3b, 0x53, 0x65, 0x70,
+0x74, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x61, 0x6d,
+0x62, 0x72, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x61, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
+0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c,
+0x3b, 0x4f, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73,
+0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61,
+0x63, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61,
+0x69, 0x3b, 0x4f, 0x67, 0x6f, 0x73, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74,
+0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62,
+0x65, 0x72, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53,
+0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0xd1c, 0xd28, 0xd41, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d, 0xd30, 0xd41, 0x3b, 0xd2e, 0xd3e,
+0xd7c, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0xd32,
+0xd48, 0x3b, 0xd13, 0xd17, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02, 0x3b, 0xd12, 0xd15, 0xd4d, 0xd1f, 0xd4b, 0x3b,
+0xd28, 0xd35, 0xd02, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0x3b, 0xd1c, 0xd28, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2b, 0xd46, 0xd2c, 0xd4d,
+0xd30, 0xd41, 0xd35, 0xd30, 0xd3f, 0x3b, 0xd2e, 0xd3e, 0xd7c, 0xd1a, 0xd4d, 0xd1a, 0xd4d, 0x3b, 0xd0f, 0xd2a, 0xd4d, 0xd30, 0xd3f, 0xd7d,
+0x3b, 0xd2e, 0xd47, 0xd2f, 0xd4d, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0xd32, 0xd48, 0x3b, 0xd13, 0xd17, 0xd38, 0xd4d, 0xd31,
+0xd4d, 0xd31, 0xd4d, 0x3b, 0xd38, 0xd46, 0xd2a, 0xd4d, 0xd31, 0xd4d, 0xd31, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd12, 0xd15, 0xd4d, 0x200c, 0xd1f,
+0xd4b, 0xd2c, 0xd7c, 0x3b, 0xd28, 0xd35, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd21, 0xd3f, 0xd38, 0xd02, 0xd2c, 0xd7c, 0x3b, 0xd1c, 0x3b, 0xd2b,
+0xd46, 0x3b, 0xd2e, 0xd3e, 0x3b, 0xd0f, 0x3b, 0xd2e, 0xd46, 0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd13, 0x3b, 0xd38,
+0xd46, 0x3b, 0xd12, 0x3b, 0xd28, 0x3b, 0xd21, 0xd3f, 0x3b, 0xd1c, 0x3b, 0xd2b, 0x3b, 0xd2e, 0xd3e, 0x3b, 0xd0f, 0x3b, 0xd2e, 0xd46,
+0x3b, 0xd1c, 0xd42, 0xd7a, 0x3b, 0xd1c, 0xd42, 0x3b, 0xd13, 0x3b, 0xd38, 0xd46, 0x3b, 0xd12, 0x3b, 0xd28, 0x3b, 0xd21, 0xd3f, 0x3b,
0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x72, 0x61, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x6a, 0x3b,
0x120, 0x75, 0x6e, 0x3b, 0x4c, 0x75, 0x6c, 0x3b, 0x41, 0x77, 0x77, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x74, 0x3b,
0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x10b, 0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x61, 0x72, 0x3b, 0x46, 0x72, 0x61, 0x72, 0x3b,
@@ -2656,7 +2672,7 @@ static const ushort months_data[] = {
0xb2c, 0xb30, 0x3b, 0xb21, 0xb3f, 0xb38, 0xb47, 0xb2e, 0xb4d, 0xb2c, 0xb30, 0x3b, 0xb1c, 0xb3e, 0x3b, 0xb2b, 0xb47, 0x3b, 0xb2e, 0xb3e,
0x3b, 0xb05, 0x3b, 0xb2e, 0xb07, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb1c, 0xb41, 0x3b, 0xb05, 0x3b, 0xb38, 0xb47, 0x3b, 0xb05, 0x3b, 0xb28,
0x3b, 0xb21, 0xb3f, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x64a, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x64a, 0x3b, 0x645, 0x627, 0x631,
-0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc,
+0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cd, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc,
0x3b, 0x627, 0x6ab, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b,
0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x698, 0x627, 0x646, 0x648, 0x6cc, 0x647, 0x3b, 0x641,
0x648, 0x631, 0x6cc, 0x647, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x647, 0x3b, 0x698,
@@ -2667,105 +2683,112 @@ static const ushort months_data[] = {
0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x648, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x647, 0x654, 0x3b, 0x698, 0x648, 0x626, 0x646,
0x3b, 0x698, 0x648, 0x626, 0x6cc, 0x647, 0x654, 0x3b, 0x627, 0x648, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x627, 0x645, 0x628, 0x631, 0x3b,
0x627, 0x6a9, 0x62a, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x627, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x627, 0x645, 0x628, 0x631, 0x3b,
-0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b, 0x62c, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b,
-0x646, 0x3b, 0x62f, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b,
-0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633,
+0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e,
+0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x6cc, 0x3b, 0x627, 0x6af, 0x633,
0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628,
-0x631, 0x3b, 0x62f, 0x633, 0x645, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x628, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645,
-0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644,
-0x627, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628,
-0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x73, 0x74, 0x79, 0x3b, 0x6c, 0x75,
+0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x62c, 0x3b, 0x641, 0x3b, 0x645, 0x3b, 0x627, 0x3b, 0x645, 0x3b, 0x62c, 0x3b,
+0x62c, 0x3b, 0x627, 0x3b, 0x633, 0x3b, 0x627, 0x3b, 0x646, 0x3b, 0x62f, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631, 0x648,
+0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646,
+0x3b, 0x62c, 0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x67e, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a,
+0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x3b, 0x73, 0x74, 0x79, 0x3b, 0x6c, 0x75,
0x74, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6b, 0x77, 0x69, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x3b, 0x6c, 0x69,
0x70, 0x3b, 0x73, 0x69, 0x65, 0x3b, 0x77, 0x72, 0x7a, 0x3b, 0x70, 0x61, 0x17a, 0x3b, 0x6c, 0x69, 0x73, 0x3b, 0x67, 0x72,
0x75, 0x3b, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x65, 0x144, 0x3b, 0x6c, 0x75, 0x74, 0x79, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x65,
0x63, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x63, 0x69, 0x65, 0x144, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x63, 0x7a, 0x65, 0x72, 0x77,
0x69, 0x65, 0x63, 0x3b, 0x6c, 0x69, 0x70, 0x69, 0x65, 0x63, 0x3b, 0x73, 0x69, 0x65, 0x72, 0x70, 0x69, 0x65, 0x144, 0x3b,
0x77, 0x72, 0x7a, 0x65, 0x73, 0x69, 0x65, 0x144, 0x3b, 0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e, 0x69, 0x6b,
-0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x67, 0x72, 0x75, 0x64, 0x7a, 0x69, 0x65, 0x144, 0x3b, 0x73,
-0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x63, 0x3b, 0x6c, 0x3b, 0x73, 0x3b, 0x77, 0x3b, 0x70, 0x3b, 0x6c,
-0x3b, 0x67, 0x3b, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x6e, 0x69, 0x61, 0x3b, 0x6c, 0x75, 0x74, 0x65, 0x67, 0x6f, 0x3b, 0x6d,
+0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x3b, 0x67, 0x72, 0x75, 0x64, 0x7a, 0x69, 0x65, 0x144, 0x3b, 0x53,
+0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x57, 0x3b, 0x50, 0x3b, 0x4c,
+0x3b, 0x47, 0x3b, 0x73, 0x74, 0x79, 0x63, 0x7a, 0x6e, 0x69, 0x61, 0x3b, 0x6c, 0x75, 0x74, 0x65, 0x67, 0x6f, 0x3b, 0x6d,
0x61, 0x72, 0x63, 0x61, 0x3b, 0x6b, 0x77, 0x69, 0x65, 0x74, 0x6e, 0x69, 0x61, 0x3b, 0x6d, 0x61, 0x6a, 0x61, 0x3b, 0x63,
0x7a, 0x65, 0x72, 0x77, 0x63, 0x61, 0x3b, 0x6c, 0x69, 0x70, 0x63, 0x61, 0x3b, 0x73, 0x69, 0x65, 0x72, 0x70, 0x6e, 0x69,
0x61, 0x3b, 0x77, 0x72, 0x7a, 0x65, 0x15b, 0x6e, 0x69, 0x61, 0x3b, 0x70, 0x61, 0x17a, 0x64, 0x7a, 0x69, 0x65, 0x72, 0x6e,
0x69, 0x6b, 0x61, 0x3b, 0x6c, 0x69, 0x73, 0x74, 0x6f, 0x70, 0x61, 0x64, 0x61, 0x3b, 0x67, 0x72, 0x75, 0x64, 0x6e, 0x69,
-0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61,
-0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x75,
-0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x7a, 0x3b, 0x6a, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x66, 0x65,
-0x76, 0x65, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b,
-0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x61, 0x67, 0x6f,
-0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74, 0x75, 0x62, 0x72, 0x6f,
-0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0xa1c,
-0xa28, 0x3b, 0xa2b, 0xa3c, 0xa30, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48, 0x3b, 0xa2e, 0xa08, 0x3b,
-0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32, 0xa3e, 0x3b, 0xa05, 0xa17, 0x3b, 0xa38, 0xa24, 0xa70, 0x3b, 0xa05, 0xa15, 0xa24, 0xa42,
-0x3b, 0xa28, 0xa35, 0xa70, 0x3b, 0xa26, 0xa38, 0xa70, 0x3b, 0xa1c, 0xa28, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2b, 0xa3c, 0xa30, 0xa35, 0xa30,
-0xa40, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48, 0xa32, 0x3b, 0xa2e, 0xa08, 0x3b, 0xa1c, 0xa42, 0xa28,
-0x3b, 0xa1c, 0xa41, 0xa32, 0xa3e, 0xa08, 0x3b, 0xa05, 0xa17, 0xa38, 0xa24, 0x3b, 0xa38, 0xa24, 0xa70, 0xa2c, 0xa30, 0x3b, 0xa05, 0xa15,
-0xa24, 0xa42, 0xa2c, 0xa30, 0x3b, 0xa28, 0xa35, 0xa70, 0xa2c, 0xa30, 0x3b, 0xa26, 0xa38, 0xa70, 0xa2c, 0xa30, 0x3b, 0xa1c, 0x3b, 0xa2b,
-0xa3c, 0x3b, 0xa2e, 0xa3e, 0x3b, 0xa05, 0x3b, 0xa2e, 0x3b, 0xa1c, 0xa42, 0x3b, 0xa1c, 0xa41, 0x3b, 0xa05, 0x3b, 0xa38, 0x3b, 0xa05,
-0x3b, 0xa28, 0x3b, 0xa26, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631,
-0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627, 0x626,
-0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b,
-0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x51, 0x75, 0x6c, 0x3b, 0x48, 0x61, 0x74, 0x3b,
-0x50, 0x61, 0x75, 0x3b, 0x41, 0x79, 0x72, 0x3b, 0x41, 0x79, 0x6d, 0x3b, 0x49, 0x6e, 0x74, 0x3b, 0x41, 0x6e, 0x74, 0x3b,
-0x51, 0x68, 0x61, 0x3b, 0x55, 0x6d, 0x61, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x41, 0x79, 0x61, 0x3b, 0x4b, 0x61, 0x70, 0x3b,
-0x51, 0x75, 0x6c, 0x6c, 0x61, 0x20, 0x70, 0x75, 0x71, 0x75, 0x79, 0x3b, 0x48, 0x61, 0x74, 0x75, 0x6e, 0x20, 0x70, 0x75,
-0x71, 0x75, 0x79, 0x3b, 0x50, 0x61, 0x75, 0x71, 0x61, 0x72, 0x20, 0x77, 0x61, 0x72, 0x61, 0x79, 0x3b, 0x41, 0x79, 0x72,
-0x69, 0x77, 0x61, 0x3b, 0x41, 0x79, 0x6d, 0x75, 0x72, 0x61, 0x79, 0x3b, 0x49, 0x6e, 0x74, 0x69, 0x20, 0x72, 0x61, 0x79,
-0x6d, 0x69, 0x3b, 0x41, 0x6e, 0x74, 0x61, 0x20, 0x53, 0x69, 0x74, 0x77, 0x61, 0x3b, 0x51, 0x68, 0x61, 0x70, 0x61, 0x71,
-0x20, 0x53, 0x69, 0x74, 0x77, 0x61, 0x3b, 0x55, 0x6d, 0x61, 0x20, 0x72, 0x61, 0x79, 0x6d, 0x69, 0x3b, 0x4b, 0x61, 0x6e,
-0x74, 0x61, 0x72, 0x61, 0x79, 0x3b, 0x41, 0x79, 0x61, 0x6d, 0x61, 0x72, 0x71, 0x2bc, 0x61, 0x3b, 0x4b, 0x61, 0x70, 0x61,
-0x71, 0x20, 0x52, 0x61, 0x79, 0x6d, 0x69, 0x3b, 0x73, 0x63, 0x68, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x61, 0x76, 0x72, 0x2e,
-0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b, 0x7a, 0x65, 0x72, 0x63,
-0x6c, 0x2e, 0x3b, 0x66, 0x61, 0x6e, 0x2e, 0x3b, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x2e, 0x3b,
-0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x73, 0x63, 0x68, 0x61, 0x6e,
-0x65, 0x72, 0x3b, 0x66, 0x61, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x67,
-0x6c, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b, 0x7a, 0x65, 0x72, 0x63, 0x6c, 0x61, 0x64, 0x75, 0x72, 0x3b, 0x66, 0x61, 0x6e,
-0x61, 0x64, 0x75, 0x72, 0x3b, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72,
-0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65,
-0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x46,
-0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x69, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e,
-0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, 0x6e, 0x2e, 0x3b,
-0x69, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e,
-0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x69, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b,
-0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x65, 0x3b, 0x61, 0x70, 0x72,
-0x69, 0x6c, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x69, 0x75, 0x6c, 0x69, 0x65,
-0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x6f,
-0x63, 0x74, 0x6f, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x6e, 0x6f, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x64,
-0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49,
-0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435,
-0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e,
-0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x43e,
-0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x44f, 0x43d, 0x432, 0x2e, 0x3b,
-0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x44f, 0x3b,
-0x438, 0x44e, 0x43d, 0x2e, 0x3b, 0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x2e,
-0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x44f, 0x43d, 0x432,
-0x430, 0x440, 0x44f, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x430, 0x3b, 0x430, 0x43f,
-0x440, 0x435, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x44f, 0x3b, 0x438, 0x44e, 0x43b, 0x44f, 0x3b, 0x430,
-0x432, 0x433, 0x443, 0x441, 0x442, 0x430, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x43e, 0x43a, 0x442, 0x44f,
-0x431, 0x440, 0x44f, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44f, 0x3b, 0x4e,
-0x79, 0x65, 0x3b, 0x46, 0x75, 0x6c, 0x3b, 0x4d, 0x62, 0xe4, 0x3b, 0x4e, 0x67, 0x75, 0x3b, 0x42, 0xea, 0x6c, 0x3b, 0x46,
-0xf6, 0x6e, 0x3b, 0x4c, 0x65, 0x6e, 0x3b, 0x4b, 0xfc, 0x6b, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x4e, 0x67, 0x62, 0x3b, 0x4e,
-0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6b, 0x3b, 0x4e, 0x79, 0x65, 0x6e, 0x79, 0x65, 0x3b, 0x46, 0x75, 0x6c, 0x75, 0x6e, 0x64,
-0xef, 0x67, 0x69, 0x3b, 0x4d, 0x62, 0xe4, 0x6e, 0x67, 0xfc, 0x3b, 0x4e, 0x67, 0x75, 0x62, 0xf9, 0x65, 0x3b, 0x42, 0xea,
-0x6c, 0xe4, 0x77, 0xfc, 0x3b, 0x46, 0xf6, 0x6e, 0x64, 0x6f, 0x3b, 0x4c, 0x65, 0x6e, 0x67, 0x75, 0x61, 0x3b, 0x4b, 0xfc,
-0x6b, 0xfc, 0x72, 0xfc, 0x3b, 0x4d, 0x76, 0x75, 0x6b, 0x61, 0x3b, 0x4e, 0x67, 0x62, 0x65, 0x72, 0x65, 0x72, 0x65, 0x3b,
-0x4e, 0x61, 0x62, 0xe4, 0x6e, 0x64, 0xfc, 0x72, 0x75, 0x3b, 0x4b, 0x61, 0x6b, 0x61, 0x75, 0x6b, 0x61, 0x3b, 0x4e, 0x3b,
-0x46, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b,
-0x4b, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430,
-0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43f, 0x3b, 0x43e, 0x43a,
-0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x431,
-0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b,
-0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435,
-0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432, 0x435, 0x43c, 0x431, 0x430,
-0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d,
-0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61,
-0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a,
-0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61,
-0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67,
-0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61,
-0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b,
-0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x6f, 0x3b,
-0x6e, 0x3b, 0x64, 0x3b, 0x42f, 0x43d, 0x432, 0x2e, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x2e,
+0x61, 0x3b, 0x73, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x63, 0x3b, 0x6c, 0x3b, 0x73, 0x3b, 0x77, 0x3b,
+0x70, 0x3b, 0x6c, 0x3b, 0x67, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62,
+0x72, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65,
+0x74, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x7a, 0x3b, 0x6a, 0x61, 0x6e, 0x65, 0x69, 0x72,
+0x6f, 0x3b, 0x66, 0x65, 0x76, 0x65, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0xe7, 0x6f, 0x3b, 0x61, 0x62,
+0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x68, 0x6f,
+0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x6f, 0x75, 0x74,
+0x75, 0x62, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x64, 0x65, 0x7a, 0x65, 0x6d, 0x62,
+0x72, 0x6f, 0x3b, 0xa1c, 0xa28, 0x3b, 0xa2b, 0xa3c, 0xa30, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48,
+0x3b, 0xa2e, 0xa08, 0x3b, 0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32, 0xa3e, 0x3b, 0xa05, 0xa17, 0x3b, 0xa38, 0xa24, 0xa70, 0x3b,
+0xa05, 0xa15, 0xa24, 0xa42, 0x3b, 0xa28, 0xa35, 0xa70, 0x3b, 0xa26, 0xa38, 0xa70, 0x3b, 0xa1c, 0xa28, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2b,
+0xa3c, 0xa30, 0xa35, 0xa30, 0xa40, 0x3b, 0xa2e, 0xa3e, 0xa30, 0xa1a, 0x3b, 0xa05, 0xa2a, 0xa4d, 0xa30, 0xa48, 0xa32, 0x3b, 0xa2e, 0xa08,
+0x3b, 0xa1c, 0xa42, 0xa28, 0x3b, 0xa1c, 0xa41, 0xa32, 0xa3e, 0xa08, 0x3b, 0xa05, 0xa17, 0xa38, 0xa24, 0x3b, 0xa38, 0xa24, 0xa70, 0xa2c,
+0xa30, 0x3b, 0xa05, 0xa15, 0xa24, 0xa42, 0xa2c, 0xa30, 0x3b, 0xa28, 0xa35, 0xa70, 0xa2c, 0xa30, 0x3b, 0xa26, 0xa38, 0xa70, 0xa2c, 0xa30,
+0x3b, 0xa1c, 0x3b, 0xa2b, 0xa3c, 0x3b, 0xa2e, 0xa3e, 0x3b, 0xa05, 0x3b, 0xa2e, 0x3b, 0xa1c, 0xa42, 0x3b, 0xa1c, 0xa41, 0x3b, 0xa05,
+0x3b, 0xa38, 0x3b, 0xa05, 0x3b, 0xa28, 0x3b, 0xa26, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc,
+0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c,
+0x648, 0x644, 0x627, 0x626, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a,
+0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x51, 0x75, 0x6c, 0x3b,
+0x48, 0x61, 0x74, 0x3b, 0x50, 0x61, 0x75, 0x3b, 0x41, 0x79, 0x72, 0x3b, 0x41, 0x79, 0x6d, 0x3b, 0x49, 0x6e, 0x74, 0x3b,
+0x41, 0x6e, 0x74, 0x3b, 0x51, 0x68, 0x61, 0x3b, 0x55, 0x6d, 0x61, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x41, 0x79, 0x61, 0x3b,
+0x4b, 0x61, 0x70, 0x3b, 0x51, 0x75, 0x6c, 0x6c, 0x61, 0x20, 0x70, 0x75, 0x71, 0x75, 0x79, 0x3b, 0x48, 0x61, 0x74, 0x75,
+0x6e, 0x20, 0x70, 0x75, 0x71, 0x75, 0x79, 0x3b, 0x50, 0x61, 0x75, 0x71, 0x61, 0x72, 0x20, 0x77, 0x61, 0x72, 0x61, 0x79,
+0x3b, 0x41, 0x79, 0x72, 0x69, 0x77, 0x61, 0x3b, 0x41, 0x79, 0x6d, 0x75, 0x72, 0x61, 0x79, 0x3b, 0x49, 0x6e, 0x74, 0x69,
+0x20, 0x72, 0x61, 0x79, 0x6d, 0x69, 0x3b, 0x41, 0x6e, 0x74, 0x61, 0x20, 0x53, 0x69, 0x74, 0x77, 0x61, 0x3b, 0x51, 0x68,
+0x61, 0x70, 0x61, 0x71, 0x20, 0x53, 0x69, 0x74, 0x77, 0x61, 0x3b, 0x55, 0x6d, 0x61, 0x20, 0x72, 0x61, 0x79, 0x6d, 0x69,
+0x3b, 0x4b, 0x61, 0x6e, 0x74, 0x61, 0x72, 0x61, 0x79, 0x3b, 0x41, 0x79, 0x61, 0x6d, 0x61, 0x72, 0x71, 0x2bc, 0x61, 0x3b,
+0x4b, 0x61, 0x70, 0x61, 0x71, 0x20, 0x52, 0x61, 0x79, 0x6d, 0x69, 0x3b, 0x73, 0x63, 0x68, 0x61, 0x6e, 0x2e, 0x3b, 0x66,
+0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b,
+0x7a, 0x65, 0x72, 0x63, 0x6c, 0x2e, 0x3b, 0x66, 0x61, 0x6e, 0x2e, 0x3b, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65,
+0x74, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x73,
+0x63, 0x68, 0x61, 0x6e, 0x65, 0x72, 0x3b, 0x66, 0x61, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61,
+0x76, 0x72, 0x69, 0x67, 0x6c, 0x3b, 0x6d, 0x61, 0x74, 0x67, 0x3b, 0x7a, 0x65, 0x72, 0x63, 0x6c, 0x61, 0x64, 0x75, 0x72,
+0x3b, 0x66, 0x61, 0x6e, 0x61, 0x64, 0x75, 0x72, 0x3b, 0x61, 0x76, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x74, 0x74, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d,
+0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x69, 0x61, 0x6e, 0x2e, 0x3b,
+0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69,
+0x75, 0x6e, 0x2e, 0x3b, 0x69, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b,
+0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x69, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x69, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x69, 0x65,
+0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x65, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x69, 0x75, 0x6e, 0x69, 0x65, 0x3b, 0x69,
+0x75, 0x6c, 0x69, 0x65, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72,
+0x69, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x6f, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x6e, 0x6f, 0x69, 0x65, 0x6d, 0x62, 0x72,
+0x69, 0x65, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x69, 0x65, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
+0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x44f, 0x43d, 0x432,
+0x2e, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430,
+0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x44c, 0x3b, 0x438, 0x44e, 0x43b, 0x44c, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43d,
+0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e, 0x3b, 0x44f,
+0x43d, 0x432, 0x2e, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x2e, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b,
+0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x2e, 0x3b, 0x438, 0x44e, 0x43b, 0x2e, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441,
+0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x43e, 0x43a, 0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x2e, 0x3b, 0x434, 0x435, 0x43a, 0x2e,
+0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x44f, 0x3b, 0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x440, 0x442,
+0x430, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x44f, 0x3b, 0x43c, 0x430, 0x44f, 0x3b, 0x438, 0x44e, 0x43d, 0x44f, 0x3b, 0x438, 0x44e,
+0x43b, 0x44f, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x430, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b,
+0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44f, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431,
+0x440, 0x44f, 0x3b, 0x4e, 0x79, 0x65, 0x3b, 0x46, 0x75, 0x6c, 0x3b, 0x4d, 0x62, 0xe4, 0x3b, 0x4e, 0x67, 0x75, 0x3b, 0x42,
+0xea, 0x6c, 0x3b, 0x46, 0xf6, 0x6e, 0x3b, 0x4c, 0x65, 0x6e, 0x3b, 0x4b, 0xfc, 0x6b, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x4e,
+0x67, 0x62, 0x3b, 0x4e, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6b, 0x3b, 0x4e, 0x79, 0x65, 0x6e, 0x79, 0x65, 0x3b, 0x46, 0x75,
+0x6c, 0x75, 0x6e, 0x64, 0xef, 0x67, 0x69, 0x3b, 0x4d, 0x62, 0xe4, 0x6e, 0x67, 0xfc, 0x3b, 0x4e, 0x67, 0x75, 0x62, 0xf9,
+0x65, 0x3b, 0x42, 0xea, 0x6c, 0xe4, 0x77, 0xfc, 0x3b, 0x46, 0xf6, 0x6e, 0x64, 0x6f, 0x3b, 0x4c, 0x65, 0x6e, 0x67, 0x75,
+0x61, 0x3b, 0x4b, 0xfc, 0x6b, 0xfc, 0x72, 0xfc, 0x3b, 0x4d, 0x76, 0x75, 0x6b, 0x61, 0x3b, 0x4e, 0x67, 0x62, 0x65, 0x72,
+0x65, 0x72, 0x65, 0x3b, 0x4e, 0x61, 0x62, 0xe4, 0x6e, 0x64, 0xfc, 0x72, 0x75, 0x3b, 0x4b, 0x61, 0x6b, 0x61, 0x75, 0x6b,
+0x61, 0x3b, 0x4e, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b,
+0x4e, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x458, 0x430, 0x43d, 0x3b, 0x444, 0x435, 0x431, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f,
+0x440, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435,
+0x43f, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x432, 0x3b, 0x434, 0x435, 0x446, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440,
+0x3b, 0x444, 0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b,
+0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441,
+0x435, 0x43f, 0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432,
+0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x458, 0x430, 0x43d, 0x2e, 0x3b,
+0x444, 0x435, 0x431, 0x2e, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x2e, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458,
+0x443, 0x43d, 0x3b, 0x458, 0x443, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x2e, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x2e, 0x3b, 0x43e, 0x43a,
+0x442, 0x2e, 0x3b, 0x43d, 0x43e, 0x432, 0x2e, 0x3b, 0x434, 0x435, 0x446, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65,
+0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e,
+0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e,
+0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65,
+0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a,
+0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74,
+0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b,
+0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x6a, 0x61, 0x6e, 0x3b,
+0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b,
+0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b,
+0x64, 0x65, 0x63, 0x3b, 0x42f, 0x43d, 0x432, 0x2e, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x2e, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x2e,
0x3b, 0x410, 0x43f, 0x440, 0x2e, 0x3b, 0x41c, 0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x44c, 0x3b, 0x418, 0x44e, 0x43b, 0x44c, 0x3b,
0x410, 0x432, 0x433, 0x2e, 0x3b, 0x421, 0x435, 0x43d, 0x442, 0x2e, 0x3b, 0x41e, 0x43a, 0x442, 0x2e, 0x3b, 0x41d, 0x43e, 0x44f, 0x431,
0x2e, 0x3b, 0x414, 0x435, 0x43a, 0x2e, 0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x44c, 0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b,
@@ -2781,239 +2804,224 @@ static const ushort months_data[] = {
0x442, 0x44b, 0x3b, 0x441, 0x435, 0x43d, 0x442, 0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x44b, 0x3b,
0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x44b, 0x3b, 0x434, 0x435, 0x43a, 0x430, 0x431, 0x440, 0x44b, 0x3b, 0x4e, 0x64, 0x69, 0x3b, 0x4b,
0x75, 0x6b, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x4b, 0x75, 0x62, 0x3b, 0x43, 0x68, 0x76, 0x3b, 0x43, 0x68, 0x6b, 0x3b, 0x43,
-0x68, 0x67, 0x3b, 0x4e, 0x79, 0x61, 0x3b, 0x47, 0x75, 0x6e, 0x3b, 0x47, 0x75, 0x6d, 0x3b, 0x4d, 0x62, 0x3b, 0x5a, 0x76,
-0x69, 0x3b, 0x4e, 0x64, 0x69, 0x72, 0x61, 0x3b, 0x4b, 0x75, 0x6b, 0x61, 0x64, 0x7a, 0x69, 0x3b, 0x4b, 0x75, 0x72, 0x75,
-0x6d, 0x65, 0x3b, 0x4b, 0x75, 0x62, 0x76, 0x75, 0x6d, 0x62, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x76, 0x61, 0x62, 0x76, 0x75,
-0x3b, 0x43, 0x68, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x6b, 0x75, 0x6e, 0x67, 0x75, 0x72, 0x75, 0x3b,
-0x4e, 0x79, 0x61, 0x6d, 0x61, 0x76, 0x68, 0x75, 0x76, 0x68, 0x75, 0x3b, 0x47, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x61, 0x3b,
-0x47, 0x75, 0x6d, 0x69, 0x67, 0x75, 0x72, 0x75, 0x3b, 0x4d, 0x62, 0x75, 0x64, 0x7a, 0x69, 0x3b, 0x5a, 0x76, 0x69, 0x74,
-0x61, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4e, 0x3b, 0x47, 0x3b,
-0x47, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0x3b, 0xd85, 0xdb4,
-0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd,
-0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0x3b, 0xd94, 0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0x3b,
-0xdaf, 0xdd9, 0xdc3, 0xdd0, 0x3b, 0xda2, 0xdb1, 0xdc0, 0xdcf, 0xdbb, 0xdd2, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0xdbb, 0xdc0, 0xdcf, 0xdbb, 0xdd2,
+0x68, 0x67, 0x3b, 0x4e, 0x79, 0x61, 0x3b, 0x47, 0x75, 0x6e, 0x3b, 0x47, 0x75, 0x6d, 0x3b, 0x4d, 0x62, 0x75, 0x3b, 0x5a,
+0x76, 0x69, 0x3b, 0x4e, 0x64, 0x69, 0x72, 0x61, 0x3b, 0x4b, 0x75, 0x6b, 0x61, 0x64, 0x7a, 0x69, 0x3b, 0x4b, 0x75, 0x72,
+0x75, 0x6d, 0x65, 0x3b, 0x4b, 0x75, 0x62, 0x76, 0x75, 0x6d, 0x62, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x76, 0x61, 0x62, 0x76,
+0x75, 0x3b, 0x43, 0x68, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x6b, 0x75, 0x6e, 0x67, 0x75, 0x72, 0x75,
+0x3b, 0x4e, 0x79, 0x61, 0x6d, 0x61, 0x76, 0x68, 0x75, 0x76, 0x68, 0x75, 0x3b, 0x47, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x61,
+0x3b, 0x47, 0x75, 0x6d, 0x69, 0x67, 0x75, 0x72, 0x75, 0x3b, 0x4d, 0x62, 0x75, 0x64, 0x7a, 0x69, 0x3b, 0x5a, 0x76, 0x69,
+0x74, 0x61, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4e, 0x3b, 0x47,
+0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0x3b, 0xd85,
+0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6,
+0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0x3b, 0xd94, 0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0,
+0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0x3b, 0xda2, 0xdb1, 0xdc0, 0xdcf, 0xdbb, 0xdd2, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0xdbb, 0xdc0, 0xdcf, 0xdbb,
+0xdd2, 0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0xdd4, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0,
+0xdba, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0xdc3, 0xdca, 0xdad, 0xdd4,
+0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0xdad, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xd94, 0xd9a, 0xdca, 0xdad, 0xddd, 0xdb6, 0xdbb,
+0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb,
+0xdca, 0x3b, 0xda2, 0x3b, 0xdb4, 0xdd9, 0x3b, 0xdb8, 0xdcf, 0x3b, 0xd85, 0x3b, 0xdb8, 0xdd0, 0x3b, 0xda2, 0xdd6, 0x3b, 0xda2, 0xdd6,
+0x3b, 0xd85, 0x3b, 0xdc3, 0xdd0, 0x3b, 0xd94, 0x3b, 0xdb1, 0xdd9, 0x3b, 0xdaf, 0xdd9, 0x3b, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6,
0x3b, 0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0xdd4, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba,
-0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0xdc3, 0xdca, 0xdad, 0xdd4, 0x3b,
-0xdc3, 0xdd0, 0xdb4, 0xdca, 0xdad, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xd94, 0xd9a, 0xdca, 0xdad, 0xddd, 0xdb6, 0xdbb, 0xdca,
-0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0xdb8, 0xdca, 0xdb6, 0xdbb, 0xdca,
-0x3b, 0xda2, 0x3b, 0xdb4, 0xdd9, 0x3b, 0xdb8, 0xdcf, 0x3b, 0xd85, 0x3b, 0xdb8, 0xdd0, 0x3b, 0xda2, 0xdd6, 0x3b, 0xda2, 0xdd6, 0x3b,
-0xd85, 0x3b, 0xdc3, 0xdd0, 0x3b, 0xd94, 0x3b, 0xdb1, 0xdd9, 0x3b, 0xdaf, 0xdd9, 0x3b, 0xda2, 0xdb1, 0x3b, 0xdb4, 0xdd9, 0xdb6, 0x3b,
-0xdb8, 0xdcf, 0xdbb, 0xdca, 0xdad, 0xdd4, 0x3b, 0xd85, 0xdb4, 0xdca, 0x200d, 0xdbb, 0xdda, 0xdbd, 0xdca, 0x3b, 0xdb8, 0xdd0, 0xdba, 0xdd2,
-0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca, 0x3b,
-0xd94, 0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65,
-0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa,
-0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65,
-0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0x61, 0x72,
-0x65, 0x63, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa, 0x6c,
-0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b,
-0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d,
-0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x61, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x61,
-0x3b, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x61, 0x3b, 0x6d, 0xe1, 0x6a, 0x61, 0x3b, 0x6a,
-0xfa, 0x6e, 0x61, 0x3b, 0x6a, 0xfa, 0x6c, 0x61, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x70,
-0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x72, 0x61, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d,
-0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b,
+0xdd2, 0x3b, 0xda2, 0xdd6, 0xdb1, 0xdd2, 0x3b, 0xda2, 0xdd6, 0xdbd, 0xdd2, 0x3b, 0xd85, 0xd9c, 0xddd, 0x3b, 0xdc3, 0xdd0, 0xdb4, 0xdca,
+0x3b, 0xd94, 0xd9a, 0xdca, 0x3b, 0xdb1, 0xddc, 0xdc0, 0xdd0, 0x3b, 0xdaf, 0xdd9, 0xdc3, 0xdd0, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66,
+0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a,
+0xfa, 0x6c, 0x3b, 0x61, 0x75, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64,
+0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72, 0x3b, 0x6d, 0x61,
+0x72, 0x65, 0x63, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x3b, 0x6d, 0xe1, 0x6a, 0x3b, 0x6a, 0xfa, 0x6e, 0x3b, 0x6a, 0xfa,
+0x6c, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f,
+0x6b, 0x74, 0xf3, 0x62, 0x65, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0xe1, 0x72, 0x61, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0xe1, 0x72,
+0x61, 0x3b, 0x6d, 0x61, 0x72, 0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0xed, 0x6c, 0x61, 0x3b, 0x6d, 0xe1, 0x6a, 0x61, 0x3b,
+0x6a, 0xfa, 0x6e, 0x61, 0x3b, 0x6a, 0xfa, 0x6c, 0x61, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b, 0x73, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0xf3, 0x62, 0x72, 0x61, 0x3b, 0x6e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66,
+0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75,
+0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b,
+0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b,
0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x65, 0x63, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b,
0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6a, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x3b, 0x61, 0x76, 0x67, 0x75,
0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72,
-0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6a,
-0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d,
-0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x76, 0x67, 0x2e, 0x3b, 0x73, 0x65,
-0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x4b, 0x6f,
-0x62, 0x3b, 0x4c, 0x61, 0x62, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x41, 0x66, 0x72, 0x3b, 0x53, 0x68, 0x61, 0x3b, 0x4c, 0x69,
-0x78, 0x3b, 0x54, 0x6f, 0x64, 0x3b, 0x53, 0x69, 0x64, 0x3b, 0x53, 0x61, 0x67, 0x3b, 0x54, 0x6f, 0x62, 0x3b, 0x4b, 0x49,
-0x54, 0x3b, 0x4c, 0x49, 0x54, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x6f, 0x62, 0x61, 0x61, 0x64, 0x3b,
-0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53,
-0x61, 0x64, 0x64, 0x65, 0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x41, 0x66, 0x72, 0x61, 0x61,
-0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x68, 0x61, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68,
-0x61, 0x20, 0x4c, 0x69, 0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x54, 0x6f, 0x64, 0x6f, 0x62,
-0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x69, 0x64, 0x65, 0x65, 0x64, 0x61, 0x61, 0x64, 0x3b,
-0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x61, 0x67, 0x61, 0x61, 0x6c, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68,
-0x61, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x77, 0x20,
-0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x61,
-0x62, 0x61, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x53,
-0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x65,
-0x6e, 0x65, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d,
-0x61, 0x79, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73,
-0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x3b,
-0x65, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b,
-0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c,
-0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65,
-0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64,
-0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a,
-0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66, 0x65,
-0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a, 0x75,
-0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x63,
-0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x3b, 0x65, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61,
-0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x65, 0x6e, 0x65,
-0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6a, 0x75, 0x6e,
-0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x63, 0x74, 0x3b, 0x6e, 0x6f, 0x76,
-0x3b, 0x64, 0x69, 0x63, 0x3b, 0x45, 0x6e, 0x65, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b,
-0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x79, 0x2e, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b,
-0x41, 0x67, 0x6f, 0x2e, 0x3b, 0x53, 0x65, 0x74, 0x2e, 0x3b, 0x4f, 0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b,
-0x44, 0x69, 0x63, 0x2e, 0x3b, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x4d,
-0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x6f, 0x3b, 0x4a, 0x75, 0x6e, 0x69,
-0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x69, 0x65,
-0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62,
-0x72, 0x65, 0x3b, 0x44, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66, 0x65,
-0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a, 0x75,
-0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f, 0x63,
-0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x3b, 0x65, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x66,
-0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d,
-0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73,
-0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65,
-0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65,
-0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69,
-0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74,
-0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62,
-0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x4d,
-0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69,
-0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76,
-0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x6b, 0x3b, 0x70, 0x3b, 0x74, 0x3b, 0x69,
-0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x74, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x6b, 0x77,
-0x3b, 0x6d, 0x70, 0x69, 0x3b, 0x6d, 0x74, 0x75, 0x3b, 0x6d, 0x69, 0x6e, 0x3b, 0x6d, 0x74, 0x6e, 0x3b, 0x6d, 0x73, 0x74,
-0x3b, 0x6d, 0x73, 0x62, 0x3b, 0x6d, 0x75, 0x6e, 0x3b, 0x6d, 0x74, 0x73, 0x3b, 0x6d, 0x6b, 0x75, 0x3b, 0x6d, 0x6b, 0x6d,
-0x3b, 0x6d, 0x6b, 0x62, 0x3b, 0x6d, 0x77, 0x65, 0x7a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x6b, 0x77, 0x61, 0x6e, 0x6a, 0x61,
-0x3b, 0x6d, 0x77, 0x65, 0x7a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x77, 0x65, 0x7a, 0x69,
-0x20, 0x79, 0x61, 0x20, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x6d, 0x77, 0x65, 0x7a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x69, 0x6e,
-0x65, 0x3b, 0x6d, 0x77, 0x65, 0x7a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x6d, 0x77, 0x65, 0x7a,
-0x69, 0x20, 0x79, 0x61, 0x20, 0x73, 0x69, 0x74, 0x61, 0x3b, 0x6d, 0x77, 0x65, 0x7a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x73,
-0x61, 0x62, 0x61, 0x3b, 0x6d, 0x77, 0x65, 0x7a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x75, 0x6e, 0x61, 0x6e, 0x65, 0x3b,
-0x6d, 0x77, 0x65, 0x7a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x6d, 0x77, 0x65, 0x7a, 0x69, 0x20,
-0x79, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x6d, 0x77, 0x65, 0x7a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x6b, 0x75, 0x6d,
-0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x79, 0x61, 0x3b, 0x6d, 0x77, 0x65, 0x7a, 0x69, 0x20, 0x79, 0x61, 0x20, 0x6b,
-0x75, 0x6d, 0x69, 0x20, 0x79, 0x61, 0x20, 0x6d, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65,
-0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e,
-0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74,
-0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b,
-0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b,
-0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74,
-0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b,
-0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0xb9c, 0xba9,
-0x2e, 0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xb8f, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae,
-0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd,
-0x2e, 0x3b, 0xb85, 0xb95, 0xbcd, 0x2e, 0x3b, 0xba8, 0xbb5, 0x2e, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0x2e, 0x3b, 0xb9c, 0xba9, 0xbb5, 0xbb0,
-0xbbf, 0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd, 0xbb0, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0xb9a, 0xbcd, 0x3b, 0xb8f, 0xbaa,
-0xbcd, 0xbb0, 0xbb2, 0xbcd, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95,
-0xbb8, 0xbcd, 0xb9f, 0xbc1, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd, 0xb9f, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb85, 0xb95, 0xbcd, 0xb9f,
-0xbcb, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xba8, 0xbb5, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0xbae, 0xbcd, 0xbaa, 0xbb0,
-0xbcd, 0x3b, 0xb9c, 0x3b, 0xbaa, 0xbbf, 0x3b, 0xbae, 0xbbe, 0x3b, 0xb8f, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0x3b, 0xb9c, 0xbc2,
-0x3b, 0xb86, 0x3b, 0xb9a, 0xbc6, 0x3b, 0xb85, 0x3b, 0xba8, 0x3b, 0xb9f, 0xbbf, 0x3b, 0xb9c, 0xba9, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbaa,
-0xbbf, 0xbaa, 0xbcd, 0xbb0, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0xb9a, 0xbcd, 0x3b, 0xb8f, 0xbaa, 0xbcd, 0xbb0, 0xbb2,
-0xbcd, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95, 0xbb8, 0xbcd, 0xb9f,
-0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd, 0xb9f, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb85, 0xb95, 0xbcd, 0xb9f, 0xbcb, 0xbaa, 0xbb0,
-0xbcd, 0x3b, 0xba8, 0xbb5, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xc1c,
-0xc28, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f,
-0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0xc38, 0xc4d, 0xc1f, 0xc41,
-0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0x3b, 0xc28, 0xc35, 0xc02, 0x3b, 0xc21,
-0xc3f, 0xc38, 0xc46, 0xc02, 0x3b, 0xc1c, 0xc28, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0xc35, 0xc30, 0xc3f, 0x3b,
-0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0xc32, 0xc4d, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42,
-0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0xc38, 0xc4d, 0xc1f, 0xc41, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f,
-0xc46, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc28, 0xc35, 0xc02, 0xc2c, 0xc30,
-0xc4d, 0x3b, 0xc21, 0xc3f, 0xc38, 0xc46, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc1c, 0x3b, 0xc2b, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0x3b, 0xc0f,
-0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0x3b, 0xc1c, 0xc41, 0x3b, 0xc06, 0x3b, 0xc38, 0xc46, 0x3b, 0xc05, 0x3b, 0xc28, 0x3b, 0xc21,
-0xc3f, 0x3b, 0xc1c, 0xc28, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a,
-0xc4d, 0xc30, 0xc3f, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0x3b,
-0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0x3b, 0xc28, 0xc35, 0xc02, 0x3b, 0xc21, 0xc3f,
-0xc38, 0xc46, 0xc02, 0x3b, 0xe21, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe1e, 0x2e, 0x3b, 0xe21, 0xe35, 0x2e, 0xe04, 0x2e, 0x3b,
-0xe40, 0xe21, 0x2e, 0xe22, 0x2e, 0x3b, 0xe1e, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe34, 0x2e, 0xe22, 0x2e, 0x3b, 0xe01, 0x2e, 0xe04,
-0x2e, 0x3b, 0xe2a, 0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe22, 0x2e, 0x3b, 0xe15, 0x2e, 0xe04, 0x2e, 0x3b, 0xe1e, 0x2e, 0xe22,
-0x2e, 0x3b, 0xe18, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe01, 0xe23, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe38, 0xe21, 0xe20, 0xe32, 0xe1e,
-0xe31, 0xe19, 0xe18, 0xe4c, 0x3b, 0xe21, 0xe35, 0xe19, 0xe32, 0xe04, 0xe21, 0x3b, 0xe40, 0xe21, 0xe29, 0xe32, 0xe22, 0xe19, 0x3b, 0xe1e,
-0xe24, 0xe29, 0xe20, 0xe32, 0xe04, 0xe21, 0x3b, 0xe21, 0xe34, 0xe16, 0xe38, 0xe19, 0xe32, 0xe22, 0xe19, 0x3b, 0xe01, 0xe23, 0xe01, 0xe0e,
-0xe32, 0xe04, 0xe21, 0x3b, 0xe2a, 0xe34, 0xe07, 0xe2b, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe31, 0xe19, 0xe22, 0xe32, 0xe22, 0xe19, 0x3b,
-0xe15, 0xe38, 0xe25, 0xe32, 0xe04, 0xe21, 0x3b, 0xe1e, 0xe24, 0xe28, 0xe08, 0xe34, 0xe01, 0xe32, 0xe22, 0xe19, 0x3b, 0xe18, 0xe31, 0xe19,
-0xe27, 0xe32, 0xe04, 0xe21, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b,
-0xf56, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b,
-0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
-0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f,
-0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf62, 0xf92,
-0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3,
-0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42,
-0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66,
-0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
-0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0x3b, 0xf5f,
-0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0x3b,
-0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf51, 0xf74,
-0xf53, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b,
-0xf56, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0x3b, 0xf5f,
-0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
-0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0x3b, 0x1303, 0x1295, 0x12e9, 0x3b, 0x134c, 0x1265, 0x1229, 0x3b, 0x121b,
-0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x1228, 0x3b, 0x121c, 0x12ed, 0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235,
-0x3b, 0x1234, 0x1355, 0x1274, 0x3b, 0x12a6, 0x12ad, 0x1270, 0x3b, 0x1296, 0x126c, 0x121d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x3b, 0x1303, 0x1295, 0x12e9,
-0x12c8, 0x122a, 0x3b, 0x134c, 0x1265, 0x1229, 0x12c8, 0x122a, 0x3b, 0x121b, 0x122d, 0x127d, 0x3b, 0x12a4, 0x1355, 0x1228, 0x120d, 0x3b, 0x121c, 0x12ed,
-0x3b, 0x1301, 0x1295, 0x3b, 0x1301, 0x120b, 0x12ed, 0x3b, 0x12a6, 0x1308, 0x1235, 0x1275, 0x3b, 0x1234, 0x1355, 0x1274, 0x121d, 0x1260, 0x122d, 0x3b,
-0x12a6, 0x12ad, 0x1270, 0x12cd, 0x1260, 0x122d, 0x3b, 0x1296, 0x126c, 0x121d, 0x1260, 0x122d, 0x3b, 0x12f2, 0x1234, 0x121d, 0x1260, 0x122d, 0x3b, 0x1325,
-0x122a, 0x3b, 0x1208, 0x12ab, 0x1272, 0x3b, 0x1218, 0x130b, 0x1262, 0x3b, 0x121a, 0x12eb, 0x12dd, 0x3b, 0x130d, 0x1295, 0x1266, 0x3b, 0x1230, 0x1290,
-0x3b, 0x1213, 0x121d, 0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218, 0x1235, 0x12a8, 0x3b, 0x1325, 0x1245, 0x121d, 0x3b, 0x1215, 0x12f3, 0x122d,
-0x3b, 0x1273, 0x1215, 0x1233, 0x3b, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x1272, 0x1275, 0x3b, 0x1218, 0x130b, 0x1262, 0x1275, 0x3b, 0x121a, 0x12eb,
-0x12dd, 0x12eb, 0x3b, 0x130d, 0x1295, 0x1266, 0x1275, 0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d, 0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218,
-0x1235, 0x12a8, 0x1228, 0x121d, 0x3b, 0x1325, 0x1245, 0x121d, 0x1272, 0x3b, 0x1215, 0x12f3, 0x122d, 0x3b, 0x1273, 0x1215, 0x1233, 0x1235, 0x3b, 0x53,
-0x101, 0x6e, 0x3b, 0x46, 0x113, 0x70, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x3b, 0x4d, 0x113, 0x3b,
-0x53, 0x75, 0x6e, 0x3b, 0x53, 0x69, 0x75, 0x3b, 0x2bb, 0x41, 0x6f, 0x6b, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x2bb, 0x4f, 0x6b,
-0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x3b, 0x54, 0x12b, 0x73, 0x3b, 0x53, 0x101, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46, 0x113,
-0x70, 0x75, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, 0x73, 0x69, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x6c, 0x65, 0x6c,
-0x69, 0x3b, 0x4d, 0x113, 0x3b, 0x53, 0x75, 0x6e, 0x65, 0x3b, 0x53, 0x69, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x6f,
-0x6b, 0x6f, 0x73, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x69, 0x74, 0x65, 0x6d, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x74, 0x6f,
-0x70, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x65, 0x6d, 0x61, 0x3b, 0x54, 0x12b, 0x73, 0x65, 0x6d, 0x61, 0x3b, 0x53, 0x3b, 0x46,
-0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x54,
-0x3b, 0x4f, 0x63, 0x61, 0x3b, 0x15e, 0x75, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4e, 0x69, 0x73, 0x3b, 0x4d, 0x61, 0x79,
-0x3b, 0x48, 0x61, 0x7a, 0x3b, 0x54, 0x65, 0x6d, 0x3b, 0x41, 0x11f, 0x75, 0x3b, 0x45, 0x79, 0x6c, 0x3b, 0x45, 0x6b, 0x69,
-0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x4f, 0x63, 0x61, 0x6b, 0x3b, 0x15e, 0x75, 0x62, 0x61, 0x74, 0x3b,
-0x4d, 0x61, 0x72, 0x74, 0x3b, 0x4e, 0x69, 0x73, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x79, 0x131, 0x73, 0x3b, 0x48, 0x61, 0x7a,
-0x69, 0x72, 0x61, 0x6e, 0x3b, 0x54, 0x65, 0x6d, 0x6d, 0x75, 0x7a, 0x3b, 0x41, 0x11f, 0x75, 0x73, 0x74, 0x6f, 0x73, 0x3b,
-0x45, 0x79, 0x6c, 0xfc, 0x6c, 0x3b, 0x45, 0x6b, 0x69, 0x6d, 0x3b, 0x4b, 0x61, 0x73, 0x131, 0x6d, 0x3b, 0x41, 0x72, 0x61,
-0x6c, 0x131, 0x6b, 0x3b, 0x4f, 0x3b, 0x15e, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x41, 0x3b,
-0x45, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x41, 0x3b, 0xfd, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x77, 0x3b, 0x6d, 0x61, 0x72, 0x74,
-0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c, 0x3b, 0x61,
-0x77, 0x67, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0xfd, 0x3b, 0x64, 0x65, 0x6b, 0x3b, 0xfd,
-0x61, 0x6e, 0x77, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x77, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70,
-0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c, 0x3b, 0x61, 0x77,
-0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xfd, 0x61, 0x62,
-0x72, 0x3b, 0x6e, 0x6f, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0xdd, 0x3b, 0x46, 0x3b,
-0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b,
-0x64a, 0x627, 0x646, 0x6cb, 0x627, 0x631, 0x3b, 0x641, 0x6d0, 0x6cb, 0x631, 0x627, 0x644, 0x3b, 0x645, 0x627, 0x631, 0x62a, 0x3b, 0x626,
-0x627, 0x67e, 0x631, 0x6d0, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x626, 0x649, 0x64a, 0x6c7, 0x646, 0x3b, 0x626, 0x649, 0x64a, 0x6c7,
-0x644, 0x3b, 0x626, 0x627, 0x6cb, 0x63a, 0x6c7, 0x633, 0x62a, 0x3b, 0x633, 0x6d0, 0x646, 0x62a, 0x6d5, 0x628, 0x649, 0x631, 0x3b, 0x626,
-0x6c6, 0x643, 0x62a, 0x6d5, 0x628, 0x649, 0x631, 0x3b, 0x646, 0x648, 0x64a, 0x627, 0x628, 0x649, 0x631, 0x3b, 0x62f, 0x6d0, 0x643, 0x627,
-0x628, 0x649, 0x631, 0x3b, 0x421, 0x456, 0x447, 0x3b, 0x41b, 0x44e, 0x442, 0x3b, 0x411, 0x435, 0x440, 0x3b, 0x41a, 0x432, 0x456, 0x3b,
-0x422, 0x440, 0x430, 0x3b, 0x427, 0x435, 0x440, 0x3b, 0x41b, 0x438, 0x43f, 0x3b, 0x421, 0x435, 0x440, 0x3b, 0x412, 0x435, 0x440, 0x3b,
-0x416, 0x43e, 0x432, 0x3b, 0x41b, 0x438, 0x441, 0x3b, 0x413, 0x440, 0x443, 0x3b, 0x441, 0x456, 0x447, 0x435, 0x43d, 0x44c, 0x3b, 0x43b,
-0x44e, 0x442, 0x438, 0x439, 0x3b, 0x431, 0x435, 0x440, 0x435, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x435, 0x43d,
-0x44c, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x438,
-0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x435, 0x43d,
-0x44c, 0x3b, 0x436, 0x43e, 0x432, 0x442, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x3b, 0x433,
-0x440, 0x443, 0x434, 0x435, 0x43d, 0x44c, 0x3b, 0x421, 0x3b, 0x41b, 0x3b, 0x411, 0x3b, 0x41a, 0x3b, 0x422, 0x3b, 0x427, 0x3b, 0x41b,
-0x3b, 0x421, 0x3b, 0x412, 0x3b, 0x416, 0x3b, 0x41b, 0x3b, 0x413, 0x3b, 0x441, 0x456, 0x447, 0x2e, 0x3b, 0x43b, 0x44e, 0x442, 0x2e,
-0x3b, 0x431, 0x435, 0x440, 0x2e, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x2e, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x2e, 0x3b, 0x447, 0x435,
-0x440, 0x432, 0x2e, 0x3b, 0x43b, 0x438, 0x43f, 0x2e, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x2e, 0x3b, 0x432, 0x435, 0x440, 0x2e, 0x3b,
-0x436, 0x43e, 0x432, 0x442, 0x2e, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x2e, 0x3b, 0x433, 0x440, 0x443, 0x434, 0x2e, 0x3b, 0x441, 0x456,
-0x447, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x43e, 0x433, 0x43e, 0x3b, 0x431, 0x435, 0x440, 0x435, 0x437, 0x43d, 0x44f, 0x3b, 0x43a,
-0x432, 0x456, 0x442, 0x43d, 0x44f, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x43d, 0x44f, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x43d, 0x44f, 0x3b,
-0x43b, 0x438, 0x43f, 0x43d, 0x44f, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x43d, 0x44f, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x43d, 0x44f,
-0x3b, 0x436, 0x43e, 0x432, 0x442, 0x43d, 0x44f, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x430, 0x3b, 0x433, 0x440,
-0x443, 0x434, 0x43d, 0x44f, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631, 0x6cc, 0x3b, 0x645, 0x627, 0x631,
-0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x627,
-0x626, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627, 0x6a9, 0x62a, 0x648, 0x628, 0x631,
-0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x59, 0x61, 0x6e, 0x76, 0x3b, 0x46, 0x65,
-0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79, 0x75, 0x6e, 0x3b, 0x49,
-0x79, 0x75, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x79, 0x61,
-0x3b, 0x44, 0x65, 0x6b, 0x3b, 0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x4d,
-0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79, 0x75, 0x6e, 0x3b, 0x49,
-0x79, 0x75, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x4f,
-0x6b, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x44, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b,
-0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b,
-0x4e, 0x3b, 0x44, 0x3b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b,
-0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, 0x69, 0x79, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x6e, 0x3b,
-0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, 0x64, 0x65, 0x6b, 0x3b, 0x79, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x66,
-0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0x79,
-0x3b, 0x69, 0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65,
-0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x6e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b,
-0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x3b, 0x627,
-0x67e, 0x631, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x3b, 0x633, 0x67e,
-0x62a, 0x3b, 0x627, 0x6a9, 0x62a, 0x3b, 0x646, 0x648, 0x645, 0x3b, 0x62f, 0x633, 0x645, 0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440, 0x3b,
-0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x41c, 0x430,
-0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435, 0x43d,
-0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x3b, 0x414, 0x435,
+0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4b,
+0x6f, 0x62, 0x3b, 0x4c, 0x61, 0x62, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x41, 0x66, 0x72, 0x3b, 0x53, 0x68, 0x61, 0x3b, 0x4c,
+0x69, 0x78, 0x3b, 0x54, 0x6f, 0x64, 0x3b, 0x53, 0x69, 0x64, 0x3b, 0x53, 0x61, 0x67, 0x3b, 0x54, 0x6f, 0x62, 0x3b, 0x4b,
+0x49, 0x54, 0x3b, 0x4c, 0x49, 0x54, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x6f, 0x62, 0x61, 0x61, 0x64,
+0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c, 0x61, 0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20,
+0x53, 0x61, 0x64, 0x64, 0x65, 0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x41, 0x66, 0x72, 0x61,
+0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x68, 0x61, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73,
+0x68, 0x61, 0x20, 0x4c, 0x69, 0x78, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x54, 0x6f, 0x64, 0x6f,
+0x62, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x69, 0x64, 0x65, 0x65, 0x64, 0x61, 0x61, 0x64,
+0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x53, 0x61, 0x67, 0x61, 0x61, 0x6c, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73,
+0x68, 0x61, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4b, 0x6f, 0x77,
+0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x42, 0x69, 0x73, 0x68, 0x61, 0x20, 0x4c,
+0x61, 0x62, 0x61, 0x20, 0x69, 0x79, 0x6f, 0x20, 0x54, 0x6f, 0x62, 0x6e, 0x61, 0x61, 0x64, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b,
+0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4c, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b,
+0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b,
+0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a, 0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b,
+0x73, 0x65, 0x70, 0x74, 0x2e, 0x3b, 0x6f, 0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e,
+0x3b, 0x65, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f,
+0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75,
+0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72,
+0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b,
+0x64, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x45, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
+0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66,
+0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a,
+0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f,
+0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x3b, 0x65, 0x3b, 0x66, 0x3b, 0x6d, 0x3b,
+0x61, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x61, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x65, 0x6e,
+0x65, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6a, 0x75,
+0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x63, 0x74, 0x3b, 0x6e, 0x6f,
+0x76, 0x3b, 0x64, 0x69, 0x63, 0x3b, 0x45, 0x6e, 0x65, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0x61, 0x72, 0x2e,
+0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x79, 0x2e, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e,
+0x3b, 0x41, 0x67, 0x6f, 0x2e, 0x3b, 0x53, 0x65, 0x74, 0x2e, 0x3b, 0x4f, 0x63, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e,
+0x3b, 0x44, 0x69, 0x63, 0x2e, 0x3b, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b,
+0x4d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x6f, 0x3b, 0x4a, 0x75, 0x6e,
+0x69, 0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x69,
+0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x63, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x76, 0x69, 0x65, 0x6d,
+0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x65, 0x6e, 0x65, 0x2e, 0x3b, 0x66,
+0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x62, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x79, 0x2e, 0x3b, 0x6a,
+0x75, 0x6e, 0x2e, 0x3b, 0x6a, 0x75, 0x6c, 0x2e, 0x3b, 0x61, 0x67, 0x6f, 0x2e, 0x3b, 0x73, 0x65, 0x74, 0x2e, 0x3b, 0x6f,
+0x63, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x69, 0x63, 0x2e, 0x3b, 0x65, 0x6e, 0x65, 0x72, 0x6f, 0x3b,
+0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x6f, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b,
+0x6d, 0x61, 0x79, 0x6f, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x6f, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6f, 0x3b, 0x61, 0x67, 0x6f,
+0x73, 0x74, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x74, 0x75, 0x62, 0x72,
+0x65, 0x3b, 0x6e, 0x6f, 0x76, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x69, 0x63, 0x69, 0x65, 0x6d, 0x62, 0x72,
+0x65, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65,
+0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b,
+0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65,
+0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x69, 0x3b,
+0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74,
+0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f,
+0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66,
+0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75,
+0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b,
+0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x63, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69,
+0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c,
+0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x75, 0x73,
+0x74, 0x69, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72,
+0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0xb9c,
+0xba9, 0x2e, 0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd, 0x2e, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0x2e, 0x3b, 0xb8f, 0xbaa, 0xbcd, 0x2e, 0x3b,
+0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86, 0xb95, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbaa,
+0xbcd, 0x2e, 0x3b, 0xb85, 0xb95, 0xbcd, 0x2e, 0x3b, 0xba8, 0xbb5, 0x2e, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0x2e, 0x3b, 0xb9c, 0xba9, 0xbb5,
+0xbb0, 0xbbf, 0x3b, 0xbaa, 0xbbf, 0xbaa, 0xbcd, 0xbb0, 0xbb5, 0xbb0, 0xbbf, 0x3b, 0xbae, 0xbbe, 0xbb0, 0xbcd, 0xb9a, 0xbcd, 0x3b, 0xb8f,
+0xbaa, 0xbcd, 0xbb0, 0xbb2, 0xbcd, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0xba9, 0xbcd, 0x3b, 0xb9c, 0xbc2, 0xbb2, 0xbc8, 0x3b, 0xb86,
+0xb95, 0xbb8, 0xbcd, 0xb9f, 0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbaa, 0xbcd, 0xb9f, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb85, 0xb95, 0xbcd,
+0xb9f, 0xbcb, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xba8, 0xbb5, 0xbae, 0xbcd, 0xbaa, 0xbb0, 0xbcd, 0x3b, 0xb9f, 0xbbf, 0xb9a, 0xbae, 0xbcd, 0xbaa,
+0xbb0, 0xbcd, 0x3b, 0xb9c, 0x3b, 0xbaa, 0xbbf, 0x3b, 0xbae, 0xbbe, 0x3b, 0xb8f, 0x3b, 0xbae, 0xbc7, 0x3b, 0xb9c, 0xbc2, 0x3b, 0xb9c,
+0xbc2, 0x3b, 0xb86, 0x3b, 0xb9a, 0xbc6, 0x3b, 0xb85, 0x3b, 0xba8, 0x3b, 0xb9f, 0xbbf, 0x3b, 0xc1c, 0xc28, 0x3b, 0xc2b, 0xc3f, 0xc2c,
+0xc4d, 0xc30, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c,
+0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0xc38, 0xc4d, 0xc1f, 0xc41, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d,
+0xc1f, 0xc46, 0xc02, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0x3b, 0xc28, 0xc35, 0xc02, 0x3b, 0xc21, 0xc3f, 0xc38, 0xc46, 0xc02, 0x3b,
+0xc1c, 0xc28, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0xc35, 0xc30, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a,
+0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0xc32, 0xc4d, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41,
+0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0xc38, 0xc4d, 0xc1f, 0xc41, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f, 0xc46, 0xc02, 0xc2c, 0xc30, 0xc4d,
+0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc28, 0xc35, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc21, 0xc3f, 0xc38,
+0xc46, 0xc02, 0xc2c, 0xc30, 0xc4d, 0x3b, 0xc1c, 0x3b, 0xc2b, 0xc3f, 0x3b, 0xc2e, 0xc3e, 0x3b, 0xc0f, 0x3b, 0xc2e, 0xc47, 0x3b, 0xc1c,
+0xc42, 0x3b, 0xc1c, 0xc41, 0x3b, 0xc06, 0x3b, 0xc38, 0xc46, 0x3b, 0xc05, 0x3b, 0xc28, 0x3b, 0xc21, 0xc3f, 0x3b, 0xc1c, 0xc28, 0x3b,
+0xc2b, 0xc3f, 0xc2c, 0xc4d, 0xc30, 0x3b, 0xc2e, 0xc3e, 0xc30, 0xc4d, 0xc1a, 0xc3f, 0x3b, 0xc0f, 0xc2a, 0xc4d, 0xc30, 0xc3f, 0x3b, 0xc2e,
+0xc47, 0x3b, 0xc1c, 0xc42, 0xc28, 0xc4d, 0x3b, 0xc1c, 0xc41, 0xc32, 0xc48, 0x3b, 0xc06, 0xc17, 0x3b, 0xc38, 0xc46, 0xc2a, 0xc4d, 0xc1f,
+0xc46, 0xc02, 0x3b, 0xc05, 0xc15, 0xc4d, 0xc1f, 0xc4b, 0x3b, 0xc28, 0xc35, 0xc02, 0x3b, 0xc21, 0xc3f, 0xc38, 0xc46, 0xc02, 0x3b, 0xe21,
+0x2e, 0xe04, 0x2e, 0x3b, 0xe01, 0x2e, 0xe1e, 0x2e, 0x3b, 0xe21, 0xe35, 0x2e, 0xe04, 0x2e, 0x3b, 0xe40, 0xe21, 0x2e, 0xe22, 0x2e,
+0x3b, 0xe1e, 0x2e, 0xe04, 0x2e, 0x3b, 0xe21, 0xe34, 0x2e, 0xe22, 0x2e, 0x3b, 0xe01, 0x2e, 0xe04, 0x2e, 0x3b, 0xe2a, 0x2e, 0xe04,
+0x2e, 0x3b, 0xe01, 0x2e, 0xe22, 0x2e, 0x3b, 0xe15, 0x2e, 0xe04, 0x2e, 0x3b, 0xe1e, 0x2e, 0xe22, 0x2e, 0x3b, 0xe18, 0x2e, 0xe04,
+0x2e, 0x3b, 0xe21, 0xe01, 0xe23, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe38, 0xe21, 0xe20, 0xe32, 0xe1e, 0xe31, 0xe19, 0xe18, 0xe4c, 0x3b,
+0xe21, 0xe35, 0xe19, 0xe32, 0xe04, 0xe21, 0x3b, 0xe40, 0xe21, 0xe29, 0xe32, 0xe22, 0xe19, 0x3b, 0xe1e, 0xe24, 0xe29, 0xe20, 0xe32, 0xe04,
+0xe21, 0x3b, 0xe21, 0xe34, 0xe16, 0xe38, 0xe19, 0xe32, 0xe22, 0xe19, 0x3b, 0xe01, 0xe23, 0xe01, 0xe0e, 0xe32, 0xe04, 0xe21, 0x3b, 0xe2a,
+0xe34, 0xe07, 0xe2b, 0xe32, 0xe04, 0xe21, 0x3b, 0xe01, 0xe31, 0xe19, 0xe22, 0xe32, 0xe22, 0xe19, 0x3b, 0xe15, 0xe38, 0xe25, 0xe32, 0xe04,
+0xe21, 0x3b, 0xe1e, 0xe24, 0xe28, 0xe08, 0xe34, 0xe01, 0xe32, 0xe22, 0xe19, 0x3b, 0xe18, 0xe31, 0xe19, 0xe27, 0xe32, 0xe04, 0xe21, 0x3b,
+0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf49, 0xf72,
+0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3,
+0xf0b, 0xf56, 0xf0b, 0xf56, 0xf5e, 0xf72, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56,
+0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0xf0b,
+0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf42, 0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45,
+0xf74, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54,
+0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf5f,
+0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf44, 0xf0b, 0xf54, 0xf7c, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf49, 0xf72, 0xf66, 0xf0b,
+0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf42, 0xf66, 0xf74, 0xf58, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56,
+0xf5e, 0xf72, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf63, 0xf94, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
+0xf51, 0xfb2, 0xf74, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf51, 0xf74, 0xf53, 0xf0b, 0xf54, 0x3b, 0xf5f,
+0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf62, 0xf92, 0xfb1, 0xf51, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf51, 0xf42, 0xf74,
+0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56,
+0xf45, 0xf74, 0xf0b, 0xf42, 0xf45, 0xf72, 0xf42, 0xf0b, 0xf54, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0xf56, 0xf45, 0xf74, 0xf0b, 0xf42,
+0xf49, 0xf72, 0xf66, 0xf0b, 0xf54, 0x3b, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x3b, 0x1218, 0x130b, 0x3b, 0x121a, 0x12eb, 0x3b, 0x130d, 0x1295,
+0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d, 0x3b, 0x1290, 0x1213, 0x3b, 0x1218, 0x1235, 0x3b, 0x1325, 0x1245, 0x3b, 0x1215, 0x12f3, 0x3b, 0x1273,
+0x1215, 0x3b, 0x1325, 0x122a, 0x3b, 0x1208, 0x12ab, 0x1272, 0x1275, 0x3b, 0x1218, 0x130b, 0x1262, 0x1275, 0x3b, 0x121a, 0x12eb, 0x12dd, 0x12eb, 0x3b,
+0x130d, 0x1295, 0x1266, 0x1275, 0x3b, 0x1230, 0x1290, 0x3b, 0x1213, 0x121d, 0x1208, 0x3b, 0x1290, 0x1213, 0x1230, 0x3b, 0x1218, 0x1235, 0x12a8, 0x1228,
+0x121d, 0x3b, 0x1325, 0x1245, 0x121d, 0x1272, 0x3b, 0x1215, 0x12f3, 0x122d, 0x3b, 0x1273, 0x1215, 0x1233, 0x1235, 0x3b, 0x1325, 0x3b, 0x1208, 0x3b,
+0x1218, 0x3b, 0x121a, 0x3b, 0x130d, 0x3b, 0x1230, 0x3b, 0x1213, 0x3b, 0x1290, 0x3b, 0x1218, 0x3b, 0x1325, 0x3b, 0x1215, 0x3b, 0x1273, 0x3b,
+0x53, 0x101, 0x6e, 0x3b, 0x46, 0x113, 0x70, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x3b, 0x4d, 0x113,
+0x3b, 0x53, 0x75, 0x6e, 0x3b, 0x53, 0x69, 0x75, 0x3b, 0x2bb, 0x41, 0x6f, 0x6b, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x2bb, 0x4f,
+0x6b, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x3b, 0x54, 0x12b, 0x73, 0x3b, 0x53, 0x101, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46,
+0x113, 0x70, 0x75, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x2bb, 0x61, 0x73, 0x69, 0x3b, 0x2bb, 0x45, 0x70, 0x65, 0x6c, 0x65,
+0x6c, 0x69, 0x3b, 0x4d, 0x113, 0x3b, 0x53, 0x75, 0x6e, 0x65, 0x3b, 0x53, 0x69, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41,
+0x6f, 0x6b, 0x6f, 0x73, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x69, 0x74, 0x65, 0x6d, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x74,
+0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x14d, 0x76, 0x65, 0x6d, 0x61, 0x3b, 0x54, 0x12b, 0x73, 0x65, 0x6d, 0x61, 0x3b, 0x53, 0x3b,
+0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
+0x54, 0x3b, 0x4f, 0x63, 0x61, 0x3b, 0x15e, 0x75, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4e, 0x69, 0x73, 0x3b, 0x4d, 0x61,
+0x79, 0x3b, 0x48, 0x61, 0x7a, 0x3b, 0x54, 0x65, 0x6d, 0x3b, 0x41, 0x11f, 0x75, 0x3b, 0x45, 0x79, 0x6c, 0x3b, 0x45, 0x6b,
+0x69, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x4f, 0x63, 0x61, 0x6b, 0x3b, 0x15e, 0x75, 0x62, 0x61, 0x74,
+0x3b, 0x4d, 0x61, 0x72, 0x74, 0x3b, 0x4e, 0x69, 0x73, 0x61, 0x6e, 0x3b, 0x4d, 0x61, 0x79, 0x131, 0x73, 0x3b, 0x48, 0x61,
+0x7a, 0x69, 0x72, 0x61, 0x6e, 0x3b, 0x54, 0x65, 0x6d, 0x6d, 0x75, 0x7a, 0x3b, 0x41, 0x11f, 0x75, 0x73, 0x74, 0x6f, 0x73,
+0x3b, 0x45, 0x79, 0x6c, 0xfc, 0x6c, 0x3b, 0x45, 0x6b, 0x69, 0x6d, 0x3b, 0x4b, 0x61, 0x73, 0x131, 0x6d, 0x3b, 0x41, 0x72,
+0x61, 0x6c, 0x131, 0x6b, 0x3b, 0x4f, 0x3b, 0x15e, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x41,
+0x3b, 0x45, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x41, 0x3b, 0xfd, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x77, 0x3b, 0x6d, 0x61, 0x72,
+0x74, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d, 0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c, 0x3b,
+0x61, 0x77, 0x67, 0x3b, 0x73, 0x65, 0x6e, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0xfd, 0x3b, 0x64, 0x65, 0x6b, 0x3b,
+0xfd, 0x61, 0x6e, 0x77, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x77, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61,
+0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61, 0xfd, 0x3b, 0x69, 0xfd, 0x75, 0x6e, 0x3b, 0x69, 0xfd, 0x75, 0x6c, 0x3b, 0x61,
+0x77, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x6e, 0x74, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0xfd, 0x61,
+0x62, 0x72, 0x3b, 0x6e, 0x6f, 0xfd, 0x61, 0x62, 0x72, 0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0xdd, 0x3b, 0x46,
+0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
+0x3b, 0x64a, 0x627, 0x646, 0x6cb, 0x627, 0x631, 0x3b, 0x641, 0x6d0, 0x6cb, 0x631, 0x627, 0x644, 0x3b, 0x645, 0x627, 0x631, 0x62a, 0x3b,
+0x626, 0x627, 0x67e, 0x631, 0x6d0, 0x644, 0x3b, 0x645, 0x627, 0x64a, 0x3b, 0x626, 0x649, 0x64a, 0x6c7, 0x646, 0x3b, 0x626, 0x649, 0x64a,
+0x6c7, 0x644, 0x3b, 0x626, 0x627, 0x6cb, 0x63a, 0x6c7, 0x633, 0x62a, 0x3b, 0x633, 0x6d0, 0x646, 0x62a, 0x6d5, 0x628, 0x649, 0x631, 0x3b,
+0x626, 0x6c6, 0x643, 0x62a, 0x6d5, 0x628, 0x649, 0x631, 0x3b, 0x646, 0x648, 0x64a, 0x627, 0x628, 0x649, 0x631, 0x3b, 0x62f, 0x6d0, 0x643,
+0x627, 0x628, 0x649, 0x631, 0x3b, 0x441, 0x456, 0x447, 0x3b, 0x43b, 0x44e, 0x442, 0x3b, 0x431, 0x435, 0x440, 0x3b, 0x43a, 0x432, 0x456,
+0x3b, 0x442, 0x440, 0x430, 0x3b, 0x447, 0x435, 0x440, 0x3b, 0x43b, 0x438, 0x43f, 0x3b, 0x441, 0x435, 0x440, 0x3b, 0x432, 0x435, 0x440,
+0x3b, 0x436, 0x43e, 0x432, 0x3b, 0x43b, 0x438, 0x441, 0x3b, 0x433, 0x440, 0x443, 0x3b, 0x441, 0x456, 0x447, 0x435, 0x43d, 0x44c, 0x3b,
+0x43b, 0x44e, 0x442, 0x438, 0x439, 0x3b, 0x431, 0x435, 0x440, 0x435, 0x437, 0x435, 0x43d, 0x44c, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x435,
+0x43d, 0x44c, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x43b,
+0x438, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x435, 0x43d, 0x44c, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x435,
+0x43d, 0x44c, 0x3b, 0x436, 0x43e, 0x432, 0x442, 0x435, 0x43d, 0x44c, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x3b,
+0x433, 0x440, 0x443, 0x434, 0x435, 0x43d, 0x44c, 0x3b, 0x421, 0x3b, 0x41b, 0x3b, 0x411, 0x3b, 0x41a, 0x3b, 0x422, 0x3b, 0x427, 0x3b,
+0x41b, 0x3b, 0x421, 0x3b, 0x412, 0x3b, 0x416, 0x3b, 0x41b, 0x3b, 0x413, 0x3b, 0x441, 0x456, 0x447, 0x2e, 0x3b, 0x43b, 0x44e, 0x442,
+0x2e, 0x3b, 0x431, 0x435, 0x440, 0x2e, 0x3b, 0x43a, 0x432, 0x456, 0x442, 0x2e, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x2e, 0x3b, 0x447,
+0x435, 0x440, 0x432, 0x2e, 0x3b, 0x43b, 0x438, 0x43f, 0x2e, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x2e, 0x3b, 0x432, 0x435, 0x440, 0x2e,
+0x3b, 0x436, 0x43e, 0x432, 0x442, 0x2e, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x2e, 0x3b, 0x433, 0x440, 0x443, 0x434, 0x2e, 0x3b, 0x441,
+0x456, 0x447, 0x43d, 0x44f, 0x3b, 0x43b, 0x44e, 0x442, 0x43e, 0x433, 0x43e, 0x3b, 0x431, 0x435, 0x440, 0x435, 0x437, 0x43d, 0x44f, 0x3b,
+0x43a, 0x432, 0x456, 0x442, 0x43d, 0x44f, 0x3b, 0x442, 0x440, 0x430, 0x432, 0x43d, 0x44f, 0x3b, 0x447, 0x435, 0x440, 0x432, 0x43d, 0x44f,
+0x3b, 0x43b, 0x438, 0x43f, 0x43d, 0x44f, 0x3b, 0x441, 0x435, 0x440, 0x43f, 0x43d, 0x44f, 0x3b, 0x432, 0x435, 0x440, 0x435, 0x441, 0x43d,
+0x44f, 0x3b, 0x436, 0x43e, 0x432, 0x442, 0x43d, 0x44f, 0x3b, 0x43b, 0x438, 0x441, 0x442, 0x43e, 0x43f, 0x430, 0x434, 0x430, 0x3b, 0x433,
+0x440, 0x443, 0x434, 0x43d, 0x44f, 0x3b, 0x441, 0x3b, 0x43b, 0x3b, 0x431, 0x3b, 0x43a, 0x3b, 0x442, 0x3b, 0x447, 0x3b, 0x43b, 0x3b,
+0x441, 0x3b, 0x432, 0x3b, 0x436, 0x3b, 0x43b, 0x3b, 0x433, 0x3b, 0x62c, 0x646, 0x648, 0x631, 0x6cc, 0x3b, 0x641, 0x631, 0x648, 0x631,
+0x6cc, 0x3b, 0x645, 0x627, 0x631, 0x686, 0x3b, 0x627, 0x67e, 0x631, 0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x646,
+0x3b, 0x62c, 0x648, 0x644, 0x627, 0x626, 0x6cc, 0x3b, 0x627, 0x6af, 0x633, 0x62a, 0x3b, 0x633, 0x62a, 0x645, 0x628, 0x631, 0x3b, 0x627,
+0x6a9, 0x62a, 0x648, 0x628, 0x631, 0x3b, 0x646, 0x648, 0x645, 0x628, 0x631, 0x3b, 0x62f, 0x633, 0x645, 0x628, 0x631, 0x3b, 0x59, 0x61,
+0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79,
+0x6e, 0x3b, 0x49, 0x79, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f,
+0x79, 0x3b, 0x44, 0x65, 0x6b, 0x3b, 0x59, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b,
+0x4d, 0x61, 0x72, 0x74, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x49, 0x79, 0x75, 0x6e, 0x3b,
+0x49, 0x79, 0x75, 0x6c, 0x3b, 0x41, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b,
+0x4f, 0x6b, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x4e, 0x6f, 0x79, 0x61, 0x62, 0x72, 0x3b, 0x44, 0x65, 0x6b, 0x61, 0x62, 0x72,
+0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
+0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x79, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x70, 0x72,
+0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x69, 0x79, 0x6e, 0x3b, 0x69, 0x79, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x3b, 0x73, 0x65, 0x6e,
+0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x79, 0x3b, 0x64, 0x65, 0x6b, 0x3b, 0x79, 0x61, 0x6e, 0x76, 0x61, 0x72, 0x3b,
+0x66, 0x65, 0x76, 0x72, 0x61, 0x6c, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x61,
+0x79, 0x3b, 0x69, 0x79, 0x75, 0x6e, 0x3b, 0x69, 0x79, 0x75, 0x6c, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73,
+0x65, 0x6e, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x61, 0x62, 0x72, 0x3b, 0x6e, 0x6f, 0x79, 0x61, 0x62, 0x72,
+0x3b, 0x64, 0x65, 0x6b, 0x61, 0x62, 0x72, 0x3b, 0x62c, 0x646, 0x648, 0x3b, 0x641, 0x628, 0x631, 0x3b, 0x645, 0x627, 0x631, 0x3b,
+0x627, 0x67e, 0x631, 0x3b, 0x645, 0x6cc, 0x3b, 0x62c, 0x648, 0x646, 0x3b, 0x62c, 0x648, 0x644, 0x3b, 0x627, 0x6af, 0x633, 0x3b, 0x633,
+0x67e, 0x62a, 0x3b, 0x627, 0x6a9, 0x62a, 0x3b, 0x646, 0x648, 0x645, 0x3b, 0x62f, 0x633, 0x645, 0x3b, 0x42f, 0x43d, 0x432, 0x430, 0x440,
+0x3b, 0x424, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x41c, 0x430, 0x440, 0x442, 0x3b, 0x410, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x41c,
+0x430, 0x439, 0x3b, 0x418, 0x44e, 0x43d, 0x3b, 0x418, 0x44e, 0x43b, 0x3b, 0x410, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x421, 0x435,
+0x43d, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x41d, 0x43e, 0x44f, 0x431, 0x440, 0x3b, 0x414,
+0x435, 0x43a, 0x430, 0x431, 0x440, 0x3b, 0x44f, 0x43d, 0x432, 0x3b, 0x444, 0x435, 0x432, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f,
+0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x3b, 0x438, 0x44e, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435,
+0x43d, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e, 0x44f, 0x3b, 0x434, 0x435, 0x43a, 0x3b, 0x44f, 0x43d, 0x432, 0x430, 0x440, 0x3b,
+0x444, 0x435, 0x432, 0x440, 0x430, 0x43b, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x435, 0x43b, 0x3b, 0x43c, 0x430,
+0x439, 0x3b, 0x438, 0x44e, 0x43d, 0x3b, 0x438, 0x44e, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43d,
+0x442, 0x44f, 0x431, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x44f, 0x431, 0x440, 0x3b, 0x43d, 0x43e, 0x44f, 0x431, 0x440, 0x3b, 0x434, 0x435,
0x43a, 0x430, 0x431, 0x440, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x31, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x32, 0x3b, 0x54, 0x68, 0x67,
0x20, 0x33, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x34, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x35, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x36,
0x3b, 0x54, 0x68, 0x67, 0x20, 0x37, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x38, 0x3b, 0x54, 0x68, 0x67, 0x20, 0x39, 0x3b, 0x54,
@@ -3069,699 +3077,707 @@ static const ushort months_data[] = {
0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x73, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x68, 0x72, 0x65, 0x6c, 0x69, 0x3b,
0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x61,
0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62,
-0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b,
-0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
-0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b, 0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72,
-0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e,
-0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f, 0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e,
-0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74,
-0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69,
-0x3b, 0x61, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b,
-0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d,
-0x62, 0x61, 0x72, 0x3b, 0x458, 0x430, 0x43d, 0x443, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c,
-0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440, 0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x438, 0x3b, 0x458,
-0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433, 0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x431, 0x430, 0x440,
-0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430, 0x440, 0x3b, 0x43d, 0x43e, 0x432, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x434, 0x435,
-0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x4a, 0x2d, 0x67, 0x75, 0x65, 0x72, 0x3b, 0x54, 0x2d, 0x61, 0x72, 0x72, 0x65,
-0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41, 0x76, 0x72, 0x72, 0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c,
-0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4a, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65,
-0x65, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72,
-0x3b, 0x4a, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4d, 0x2d, 0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d,
-0x2d, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63, 0x6b, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x67, 0x65, 0x75, 0x72,
-0x65, 0x65, 0x3b, 0x54, 0x6f, 0x73, 0x68, 0x69, 0x61, 0x67, 0x68, 0x74, 0x2d, 0x61, 0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d,
-0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41, 0x76, 0x65, 0x72, 0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e,
-0x3b, 0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d,
-0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61,
-0x6e, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x66, 0x6f, 0x75, 0x79,
-0x69, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x20, 0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x65, 0x65, 0x20, 0x6e, 0x79,
-0x20, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63, 0x6b, 0x3b, 0x47, 0x65, 0x6e, 0x3b, 0x48, 0x77, 0x65, 0x3b, 0x4d, 0x65, 0x75,
-0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x3b, 0x4d, 0x65, 0x74, 0x3b, 0x47, 0x6f, 0x72, 0x3b, 0x45, 0x73, 0x74, 0x3b,
-0x47, 0x77, 0x6e, 0x3b, 0x48, 0x65, 0x64, 0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x76, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47,
-0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x48, 0x77, 0x65, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x69,
-0x73, 0x20, 0x4d, 0x65, 0x75, 0x72, 0x74, 0x68, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b, 0x6d,
-0x69, 0x73, 0x20, 0x4d, 0x65, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x6d,
-0x69, 0x73, 0x20, 0x47, 0x6f, 0x72, 0x74, 0x68, 0x65, 0x72, 0x65, 0x6e, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x45, 0x73, 0x74,
-0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x77, 0x79, 0x6e, 0x6e, 0x67, 0x61, 0x6c, 0x61, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x48,
-0x65, 0x64, 0x72, 0x61, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x44, 0x75, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4b, 0x65, 0x76, 0x61,
-0x72, 0x64, 0x68, 0x75, 0x3b, 0x53, 0x2d, 0x186, 0x3b, 0x4b, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x4f,
-0x3b, 0x45, 0x2d, 0x4b, 0x3b, 0x4f, 0x2d, 0x41, 0x3b, 0x41, 0x2d, 0x4b, 0x3b, 0x44, 0x2d, 0x186, 0x3b, 0x46, 0x2d, 0x190,
-0x3b, 0x186, 0x2d, 0x41, 0x3b, 0x186, 0x2d, 0x4f, 0x3b, 0x4d, 0x2d, 0x186, 0x3b, 0x53, 0x61, 0x6e, 0x64, 0x61, 0x2d, 0x186,
-0x70, 0x25b, 0x70, 0x254, 0x6e, 0x3b, 0x4b, 0x77, 0x61, 0x6b, 0x77, 0x61, 0x72, 0x2d, 0x186, 0x67, 0x79, 0x65, 0x66, 0x75,
-0x6f, 0x3b, 0x45, 0x62, 0x254, 0x77, 0x2d, 0x186, 0x62, 0x65, 0x6e, 0x65, 0x6d, 0x3b, 0x45, 0x62, 0x254, 0x62, 0x69, 0x72,
-0x61, 0x2d, 0x4f, 0x66, 0x6f, 0x72, 0x69, 0x73, 0x75, 0x6f, 0x3b, 0x45, 0x73, 0x75, 0x73, 0x6f, 0x77, 0x20, 0x41, 0x6b,
-0x65, 0x74, 0x73, 0x65, 0x61, 0x62, 0x61, 0x2d, 0x4b, 0x254, 0x74, 0x254, 0x6e, 0x69, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x62,
-0x69, 0x72, 0x61, 0x64, 0x65, 0x2d, 0x41, 0x79, 0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x6d, 0x75, 0x6d, 0x75, 0x3b, 0x41, 0x79,
-0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x2d, 0x4b, 0x69, 0x74, 0x61, 0x77, 0x6f, 0x6e, 0x73, 0x61, 0x3b, 0x44, 0x69, 0x66, 0x75,
-0x75, 0x2d, 0x186, 0x73, 0x61, 0x6e, 0x64, 0x61, 0x61, 0x3b, 0x46, 0x61, 0x6e, 0x6b, 0x77, 0x61, 0x2d, 0x190, 0x62, 0x254,
-0x3b, 0x186, 0x62, 0x25b, 0x73, 0x25b, 0x2d, 0x41, 0x68, 0x69, 0x6e, 0x69, 0x6d, 0x65, 0x3b, 0x186, 0x62, 0x65, 0x72, 0x25b,
-0x66, 0x25b, 0x77, 0x2d, 0x4f, 0x62, 0x75, 0x62, 0x75, 0x6f, 0x3b, 0x4d, 0x75, 0x6d, 0x75, 0x2d, 0x186, 0x70, 0x25b, 0x6e,
-0x69, 0x6d, 0x62, 0x61, 0x3b, 0x91c, 0x93e, 0x928, 0x947, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941,
-0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947,
-0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x948, 0x3b, 0x913, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d,
-0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x913, 0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947,
-0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x4a, 0x65, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
-0x4d, 0x61, 0x61, 0x3b, 0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
-0x1ecc, 0x67, 0x1ecd, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x1ecc, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b,
-0x4a, 0x65, 0x6e, 0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x4d,
-0x61, 0x61, 0x63, 0x68, 0x1ecb, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x6e,
-0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x1ecb, 0x3b, 0x1ecc, 0x67, 0x1ecd, 0x1ecd, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d,
-0x62, 0x61, 0x3b, 0x1ecc, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69,
-0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4d, 0x62, 0x65, 0x3b, 0x4b, 0x65, 0x6c, 0x3b, 0x4b, 0x74, 0x169, 0x3b, 0x4b, 0x61,
-0x6e, 0x3b, 0x4b, 0x74, 0x6e, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x4d, 0x6f, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x3b, 0x4b, 0x6e,
-0x64, 0x3b, 0x128, 0x6b, 0x75, 0x3b, 0x128, 0x6b, 0x6d, 0x3b, 0x128, 0x6b, 0x6c, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77,
-0x61, 0x20, 0x6d, 0x62, 0x65, 0x65, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129, 0x3b,
-0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20,
-0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61,
-0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x169,
-0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x75, 0x6f, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69,
-0x20, 0x77, 0x61, 0x20, 0x6e, 0x79, 0x61, 0x61, 0x6e, 0x79, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20,
-0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x3b,
-0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x129, 0x6d, 0x77,
-0x65, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69,
-0x6c, 0x129, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4b,
-0x3b, 0x128, 0x3b, 0x128, 0x3b, 0x128, 0x3b, 0x5a, 0x65, 0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41,
-0x76, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x67, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x3b, 0x53,
-0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x63, 0x3b, 0x5a, 0x65, 0x6e, 0xe2, 0x72,
-0x3b, 0x46, 0x65, 0x76, 0x72, 0xe2, 0x72, 0x3b, 0x4d, 0x61, 0x72, 0xe7, 0x3b, 0x41, 0x76, 0x72, 0xee, 0x6c, 0x3b, 0x4d,
-0x61, 0x69, 0x3b, 0x4a, 0x75, 0x67, 0x6e, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x73, 0x74, 0x3b, 0x53, 0x65,
-0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
-0x61, 0x72, 0x3b, 0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
-0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x64, 0x7a, 0x76, 0x3b,
-0x64, 0x7a, 0x64, 0x3b, 0x74, 0x65, 0x64, 0x3b, 0x61, 0x66, 0x254, 0x3b, 0x64, 0x61, 0x6d, 0x3b, 0x6d, 0x61, 0x73, 0x3b,
-0x73, 0x69, 0x61, 0x3b, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x6e, 0x79, 0x3b, 0x6b, 0x65, 0x6c, 0x3b, 0x61, 0x64, 0x65, 0x3b,
-0x64, 0x7a, 0x6d, 0x3b, 0x64, 0x7a, 0x6f, 0x76, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x74, 0x65, 0x64,
-0x6f, 0x78, 0x65, 0x3b, 0x61, 0x66, 0x254, 0x66, 0x129, 0x65, 0x3b, 0x64, 0x61, 0x6d, 0x61, 0x3b, 0x6d, 0x61, 0x73, 0x61,
-0x3b, 0x73, 0x69, 0x61, 0x6d, 0x6c, 0x254, 0x6d, 0x3b, 0x64, 0x65, 0x61, 0x73, 0x69, 0x61, 0x6d, 0x69, 0x6d, 0x65, 0x3b,
-0x61, 0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254, 0x3b, 0x6b, 0x65, 0x6c, 0x65, 0x3b, 0x61, 0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b,
-0x70, 0x254, 0x78, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x6d, 0x65, 0x3b, 0x64, 0x3b, 0x64, 0x3b, 0x74, 0x3b, 0x61, 0x3b, 0x64,
-0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x61, 0x3b, 0x6b, 0x3b, 0x61, 0x3b, 0x64, 0x3b, 0x49, 0x61, 0x6e, 0x2e, 0x3b,
-0x50, 0x65, 0x70, 0x2e, 0x3b, 0x4d, 0x61, 0x6c, 0x2e, 0x3b, 0x2bb, 0x41, 0x70, 0x2e, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49,
-0x75, 0x6e, 0x2e, 0x3b, 0x49, 0x75, 0x6c, 0x2e, 0x3b, 0x2bb, 0x41, 0x75, 0x2e, 0x3b, 0x4b, 0x65, 0x70, 0x2e, 0x3b, 0x2bb,
-0x4f, 0x6b, 0x2e, 0x3b, 0x4e, 0x6f, 0x77, 0x2e, 0x3b, 0x4b, 0x65, 0x6b, 0x2e, 0x3b, 0x49, 0x61, 0x6e, 0x75, 0x61, 0x6c,
-0x69, 0x3b, 0x50, 0x65, 0x70, 0x65, 0x6c, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x6b, 0x69, 0x3b, 0x2bb,
-0x41, 0x70, 0x65, 0x6c, 0x69, 0x6c, 0x61, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x65, 0x3b, 0x49, 0x75, 0x6c,
-0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x75, 0x6b, 0x61, 0x6b, 0x65, 0x3b, 0x4b, 0x65, 0x70, 0x61, 0x6b, 0x65, 0x6d, 0x61, 0x70,
-0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x6b, 0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x6f, 0x77, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b,
-0x4b, 0x65, 0x6b, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b, 0x45, 0x6e, 0x65, 0x3b, 0x50, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72,
-0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f,
-0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x45, 0x6e, 0x65,
-0x72, 0x6f, 0x3b, 0x50, 0x65, 0x62, 0x72, 0x65, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x41, 0x62, 0x72,
-0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6e, 0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6c, 0x79, 0x6f, 0x3b,
-0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x6b, 0x74,
-0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f, 0x62, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x73, 0x79, 0x65,
-0x6d, 0x62, 0x72, 0x65, 0x3b, 0x45, 0x3b, 0x50, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x75, 0x6e, 0x3b, 0x48,
-0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44,
-0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4,
-0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75,
-0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x63, 0x68, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0xe4, 0x6d, 0x62, 0x65,
-0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b,
-0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0xa2cd, 0xa1aa, 0x3b, 0xa44d, 0xa1aa, 0x3b, 0xa315, 0xa1aa, 0x3b, 0xa1d6, 0xa1aa,
-0x3b, 0xa26c, 0xa1aa, 0x3b, 0xa0d8, 0xa1aa, 0x3b, 0xa3c3, 0xa1aa, 0x3b, 0xa246, 0xa1aa, 0x3b, 0xa22c, 0xa1aa, 0x3b, 0xa2b0, 0xa1aa, 0x3b, 0xa2b0,
-0xa2aa, 0xa1aa, 0x3b, 0xa2b0, 0xa44b, 0xa1aa, 0x3b, 0x6f, 0x111, 0x111, 0x6a, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x3b, 0x6e, 0x6a, 0x75,
-0x6b, 0x3b, 0x63, 0x75, 0x6f, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x3b, 0x73, 0x75, 0x6f, 0x69,
-0x3b, 0x62, 0x6f, 0x72, 0x67, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x3b, 0x73, 0x6b, 0xe1, 0x62,
-0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x3b, 0x6f, 0x111, 0x111, 0x61, 0x6a, 0x61, 0x67, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b,
-0x67, 0x75, 0x6f, 0x76, 0x76, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x10d, 0x61, 0x6d, 0xe1,
-0x6e, 0x6e, 0x75, 0x3b, 0x63, 0x75, 0x6f, 0x14b, 0x6f, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x73,
-0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x73,
-0x75, 0x6f, 0x69, 0x64, 0x6e, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x65, 0x6d, 0xe1, 0x6e,
-0x6e, 0x75, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x67, 0x6f,
-0x74, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x6d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6a,
-0x75, 0x6f, 0x76, 0x6c, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x4f, 0x3b, 0x47, 0x3b, 0x4e, 0x3b, 0x43, 0x3b, 0x4d,
-0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x10c, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 0x6f, 0x111, 0x111, 0x61, 0x6a,
-0x61, 0x67, 0x65, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x76, 0x61, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x10d, 0x61, 0x3b, 0x63, 0x75,
-0x6f, 0x14b, 0x6f, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x73, 0x65, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x73, 0x65, 0x3b, 0x73, 0x75,
-0x6f, 0x69, 0x64, 0x6e, 0x65, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x65, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x61, 0x3b, 0x67, 0x6f,
-0x6c, 0x67, 0x67, 0x6f, 0x74, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x6d, 0x61, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0x61, 0x3b,
-0x43, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
-0x4a, 0x75, 0x6e, 0x3b, 0x43, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
-0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x43, 0x68, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62,
-0x75, 0x72, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x69, 0x72, 0x69, 0x72, 0x69, 0x3b,
-0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x43, 0x68, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73,
-0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62, 0x61, 0x3b,
-0x4e, 0x6f, 0x62, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x43, 0x3b, 0x46, 0x3b,
-0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b,
-0x49, 0x6d, 0x62, 0x3b, 0x4b, 0x61, 0x77, 0x3b, 0x4b, 0x61, 0x64, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b,
-0x4b, 0x61, 0x72, 0x3b, 0x4d, 0x66, 0x75, 0x3b, 0x57, 0x75, 0x6e, 0x3b, 0x49, 0x6b, 0x65, 0x3b, 0x49, 0x6b, 0x75, 0x3b,
-0x49, 0x6d, 0x77, 0x3b, 0x49, 0x77, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6d,
-0x62, 0x69, 0x72, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x77, 0x69, 0x3b,
-0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x4d, 0x6f, 0x72,
-0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77,
-0x61, 0x20, 0x6b, 0x61, 0x73, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b,
-0x61, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6d,
-0x66, 0x75, 0x6e, 0x67, 0x61, 0x64, 0x65, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x77, 0x75,
-0x6e, 0x79, 0x61, 0x6e, 0x79, 0x61, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x65,
-0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b,
-0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69,
-0x6d, 0x77, 0x65, 0x72, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d,
-0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x77, 0x69, 0x3b, 0x49, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b,
-0x3b, 0x4d, 0x3b, 0x57, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x73, 0x69, 0x69, 0x3b, 0x63, 0x6f, 0x6c,
-0x3b, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0x65, 0x65, 0x3b, 0x64, 0x75, 0x75, 0x3b, 0x6b, 0x6f, 0x72, 0x3b, 0x6d, 0x6f, 0x72,
-0x3b, 0x6a, 0x75, 0x6b, 0x3b, 0x73, 0x6c, 0x74, 0x3b, 0x79, 0x61, 0x72, 0x3b, 0x6a, 0x6f, 0x6c, 0x3b, 0x62, 0x6f, 0x77,
-0x3b, 0x73, 0x69, 0x69, 0x6c, 0x6f, 0x3b, 0x63, 0x6f, 0x6c, 0x74, 0x65, 0x3b, 0x6d, 0x62, 0x6f, 0x6f, 0x79, 0x3b, 0x73,
-0x65, 0x65, 0x257, 0x74, 0x6f, 0x3b, 0x64, 0x75, 0x75, 0x6a, 0x61, 0x6c, 0x3b, 0x6b, 0x6f, 0x72, 0x73, 0x65, 0x3b, 0x6d,
-0x6f, 0x72, 0x73, 0x6f, 0x3b, 0x6a, 0x75, 0x6b, 0x6f, 0x3b, 0x73, 0x69, 0x69, 0x6c, 0x74, 0x6f, 0x3b, 0x79, 0x61, 0x72,
-0x6b, 0x6f, 0x6d, 0x61, 0x61, 0x3b, 0x6a, 0x6f, 0x6c, 0x61, 0x6c, 0x3b, 0x62, 0x6f, 0x77, 0x74, 0x65, 0x3b, 0x73, 0x3b,
-0x63, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x73, 0x3b, 0x79, 0x3b, 0x6a, 0x3b,
-0x62, 0x3b, 0x4a, 0x45, 0x4e, 0x3b, 0x57, 0x4b, 0x52, 0x3b, 0x57, 0x47, 0x54, 0x3b, 0x57, 0x4b, 0x4e, 0x3b, 0x57, 0x54,
-0x4e, 0x3b, 0x57, 0x54, 0x44, 0x3b, 0x57, 0x4d, 0x4a, 0x3b, 0x57, 0x4e, 0x4e, 0x3b, 0x57, 0x4b, 0x44, 0x3b, 0x57, 0x49,
-0x4b, 0x3b, 0x57, 0x4d, 0x57, 0x3b, 0x44, 0x49, 0x54, 0x3b, 0x4e, 0x6a, 0x65, 0x6e, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x4d,
-0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x72, 0x129, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77,
-0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61,
-0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d,
-0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77,
-0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x169, 0x67, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72,
-0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61,
-0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d,
-0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20,
-0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4e, 0x64, 0x69, 0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x4b, 0x3b, 0x47,
-0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x44, 0x3b, 0x4f,
-0x62, 0x6f, 0x3b, 0x57, 0x61, 0x61, 0x3b, 0x4f, 0x6b, 0x75, 0x3b, 0x4f, 0x6e, 0x67, 0x3b, 0x49, 0x6d, 0x65, 0x3b, 0x49,
-0x6c, 0x65, 0x3b, 0x53, 0x61, 0x70, 0x3b, 0x49, 0x73, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x3b, 0x54, 0x6f, 0x6d, 0x3b, 0x54,
-0x6f, 0x62, 0x3b, 0x54, 0x6f, 0x77, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f, 0x62, 0x6f, 0x3b, 0x4c,
-0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x77, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65,
-0x20, 0x6f, 0x6b, 0x75, 0x6e, 0x69, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x67, 0x2019, 0x77,
-0x61, 0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x6d, 0x65, 0x74, 0x3b, 0x4c, 0x61, 0x70, 0x61,
-0x20, 0x6c, 0x65, 0x20, 0x69, 0x6c, 0x65, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x73, 0x61, 0x70, 0x61,
-0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x73, 0x69, 0x65, 0x74, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20,
-0x6c, 0x65, 0x20, 0x73, 0x61, 0x61, 0x6c, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f,
-0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x6f, 0x62, 0x6f, 0x3b,
-0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x77, 0x61, 0x61, 0x72, 0x65, 0x3b,
-0x4f, 0x3b, 0x57, 0x3b, 0x4f, 0x3b, 0x4f, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x54, 0x3b,
-0x54, 0x3b, 0x54, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b,
-0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x74, 0x3b,
-0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x4a, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b,
-0x46, 0x65, 0x76, 0x72, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x63, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c,
-0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x4a, 0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x41, 0x75,
-0x67, 0x75, 0x73, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x72,
-0x6f, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b,
-0x5a, 0x69, 0x62, 0x3b, 0x4e, 0x68, 0x6c, 0x6f, 0x3b, 0x4d, 0x62, 0x69, 0x3b, 0x4d, 0x61, 0x62, 0x3b, 0x4e, 0x6b, 0x77,
-0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x3b, 0x4e, 0x74, 0x75, 0x3b, 0x4e, 0x63, 0x77, 0x3b, 0x4d, 0x70, 0x61, 0x6e, 0x3b, 0x4d,
-0x66, 0x75, 0x3b, 0x4c, 0x77, 0x65, 0x3b, 0x4d, 0x70, 0x61, 0x6c, 0x3b, 0x5a, 0x69, 0x62, 0x61, 0x6e, 0x64, 0x6c, 0x65,
-0x6c, 0x61, 0x3b, 0x4e, 0x68, 0x6c, 0x6f, 0x6c, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x62, 0x69, 0x6d, 0x62, 0x69, 0x74,
-0x68, 0x6f, 0x3b, 0x4d, 0x61, 0x62, 0x61, 0x73, 0x61, 0x3b, 0x4e, 0x6b, 0x77, 0x65, 0x6e, 0x6b, 0x77, 0x65, 0x7a, 0x69,
-0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x61, 0x3b, 0x4e, 0x74, 0x75, 0x6c, 0x69, 0x6b, 0x61, 0x7a, 0x69,
-0x3b, 0x4e, 0x63, 0x77, 0x61, 0x62, 0x61, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x4d, 0x70, 0x61, 0x6e, 0x64, 0x75, 0x6c, 0x61,
-0x3b, 0x4d, 0x66, 0x75, 0x6d, 0x66, 0x75, 0x3b, 0x4c, 0x77, 0x65, 0x7a, 0x69, 0x3b, 0x4d, 0x70, 0x61, 0x6c, 0x61, 0x6b,
-0x61, 0x7a, 0x69, 0x3b, 0x5a, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b,
-0x4d, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x31, 0x3b, 0x4d, 0x32, 0x3b, 0x4d, 0x33, 0x3b, 0x4d, 0x34, 0x3b,
-0x4d, 0x35, 0x3b, 0x4d, 0x36, 0x3b, 0x4d, 0x37, 0x3b, 0x4d, 0x38, 0x3b, 0x4d, 0x39, 0x3b, 0x4d, 0x31, 0x30, 0x3b, 0x4d,
-0x31, 0x31, 0x3b, 0x4d, 0x31, 0x32, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x77, 0x61, 0x6e,
-0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77,
-0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
-0x77, 0x61, 0x20, 0x6b, 0x61, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x61,
-0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x73, 0x69, 0x74, 0x61, 0x3b, 0x4d, 0x77, 0x65,
-0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
-0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d,
-0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
-0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65,
-0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x62, 0x69, 0x6c, 0x69,
-0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49,
-0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x2d49, 0x2d4f, 0x2d4f, 0x3b, 0x2d31, 0x2d55, 0x2d30, 0x3b, 0x2d4e, 0x2d30, 0x2d55, 0x3b, 0x2d49, 0x2d31, 0x2d54,
-0x3b, 0x2d4e, 0x2d30, 0x2d62, 0x3b, 0x2d62, 0x2d53, 0x2d4f, 0x3b, 0x2d62, 0x2d53, 0x2d4d, 0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x3b, 0x2d5b, 0x2d53, 0x2d5c,
-0x3b, 0x2d3d, 0x2d5c, 0x2d53, 0x3b, 0x2d4f, 0x2d53, 0x2d61, 0x3b, 0x2d37, 0x2d53, 0x2d4a, 0x3b, 0x2d49, 0x2d4f, 0x2d4f, 0x2d30, 0x2d62, 0x2d54, 0x3b,
-0x2d31, 0x2d55, 0x2d30, 0x2d62, 0x2d55, 0x3b, 0x2d4e, 0x2d30, 0x2d55, 0x2d5a, 0x3b, 0x2d49, 0x2d31, 0x2d54, 0x2d49, 0x2d54, 0x3b, 0x2d4e, 0x2d30, 0x2d62,
-0x2d62, 0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4f, 0x2d62, 0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4d, 0x2d62, 0x2d53, 0x2d63, 0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x2d5c,
-0x3b, 0x2d5b, 0x2d53, 0x2d5c, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d3d, 0x2d5c, 0x2d53, 0x2d31, 0x2d54, 0x3b, 0x2d4f, 0x2d53, 0x2d61, 0x2d30,
-0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d37, 0x2d53, 0x2d4a, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d49, 0x3b, 0x2d31, 0x3b, 0x2d4e, 0x3b,
-0x2d49, 0x3b, 0x2d4e, 0x3b, 0x2d62, 0x3b, 0x2d62, 0x3b, 0x2d56, 0x3b, 0x2d5b, 0x3b, 0x2d3d, 0x3b, 0x2d4f, 0x3b, 0x2d37, 0x3b, 0x69, 0x6e,
-0x6e, 0x3b, 0x62, 0x1e5b, 0x61, 0x3b, 0x6d, 0x61, 0x1e5b, 0x3b, 0x69, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75,
-0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x263, 0x75, 0x63, 0x3b, 0x63, 0x75, 0x74, 0x3b, 0x6b, 0x74, 0x75, 0x3b, 0x6e, 0x75,
-0x77, 0x3b, 0x64, 0x75, 0x6a, 0x3b, 0x69, 0x6e, 0x6e, 0x61, 0x79, 0x72, 0x3b, 0x62, 0x1e5b, 0x61, 0x79, 0x1e5b, 0x3b, 0x6d,
-0x61, 0x1e5b, 0x1e63, 0x3b, 0x69, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x79, 0x75, 0x6e, 0x79,
-0x75, 0x3b, 0x79, 0x75, 0x6c, 0x79, 0x75, 0x7a, 0x3b, 0x263, 0x75, 0x63, 0x74, 0x3b, 0x63, 0x75, 0x74, 0x61, 0x6e, 0x62,
-0x69, 0x72, 0x3b, 0x6b, 0x74, 0x75, 0x62, 0x72, 0x3b, 0x6e, 0x75, 0x77, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x64, 0x75,
-0x6a, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x69, 0x3b, 0x62, 0x3b, 0x6d, 0x3b, 0x69, 0x3b, 0x6d, 0x3b, 0x79, 0x3b, 0x79,
-0x3b, 0x263, 0x3b, 0x63, 0x3b, 0x6b, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x59, 0x65, 0x6e, 0x3b, 0x46, 0x75, 0x72, 0x3b, 0x4d,
-0x65, 0x263, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194,
-0x75, 0x63, 0x3b, 0x43, 0x74, 0x65, 0x3b, 0x54, 0x75, 0x62, 0x3b, 0x4e, 0x75, 0x6e, 0x3b, 0x44, 0x75, 0x1e7, 0x3b, 0x59,
-0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x46, 0x75, 0x1e5b, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x263, 0x72, 0x65, 0x73,
-0x3b, 0x59, 0x65, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b,
-0x59, 0x75, 0x6c, 0x79, 0x75, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b, 0x43, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x54,
-0x75, 0x62, 0x65, 0x1e5b, 0x3b, 0x4e, 0x75, 0x6e, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x44, 0x75, 0x1e7, 0x65, 0x6d, 0x62,
-0x65, 0x1e5b, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43,
-0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4b, 0x42, 0x5a, 0x3b, 0x4b, 0x42, 0x52, 0x3b, 0x4b, 0x53, 0x54, 0x3b, 0x4b,
-0x4b, 0x4e, 0x3b, 0x4b, 0x54, 0x4e, 0x3b, 0x4b, 0x4d, 0x4b, 0x3b, 0x4b, 0x4d, 0x53, 0x3b, 0x4b, 0x4d, 0x4e, 0x3b, 0x4b,
-0x4d, 0x57, 0x3b, 0x4b, 0x4b, 0x4d, 0x3b, 0x4b, 0x4e, 0x4b, 0x3b, 0x4b, 0x4e, 0x42, 0x3b, 0x4f, 0x6b, 0x77, 0x6f, 0x6b,
-0x75, 0x62, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4f, 0x6b,
-0x77, 0x61, 0x6b, 0x61, 0x73, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4f,
-0x6b, 0x77, 0x61, 0x6b, 0x61, 0x74, 0x61, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61,
-0x67, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x6a, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61,
-0x6d, 0x75, 0x6e, 0x61, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x77, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4f,
-0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e,
-0x61, 0x20, 0x6b, 0x75, 0x6d, 0x77, 0x65, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61,
-0x20, 0x69, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x48, 0x75, 0x74, 0x3b, 0x56, 0x69, 0x6c, 0x3b, 0x44, 0x61, 0x74, 0x3b, 0x54,
-0x61, 0x69, 0x3b, 0x48, 0x61, 0x6e, 0x3b, 0x53, 0x69, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61, 0x6e, 0x3b, 0x54,
-0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d, 0x3b, 0x4b, 0x6d, 0x6a, 0x3b, 0x4b, 0x6d, 0x62, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77,
-0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x68, 0x75, 0x74, 0x61, 0x6c, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d,
-0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70, 0x61, 0x20,
-0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x64, 0x61, 0x74, 0x75, 0x3b, 0x70, 0x61,
-0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x74, 0x61, 0x69, 0x3b, 0x70, 0x61,
-0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x70,
-0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x69, 0x74, 0x61, 0x3b, 0x70, 0x61,
-0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x70, 0x61, 0x20,
-0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x70, 0x61, 0x20, 0x6d,
-0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77,
-0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65,
-0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61,
-0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20,
-0x6e, 0x61, 0x20, 0x6d, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x48, 0x3b, 0x56, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x53,
-0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69,
-0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69,
-0x6c, 0x79, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x61, 0x69,
-0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74,
-0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b,
-0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x77, 0x69, 0x3b, 0x6d, 0x25b, 0x3b, 0x7a,
-0x75, 0x77, 0x3b, 0x7a, 0x75, 0x6c, 0x3b, 0x75, 0x74, 0x69, 0x3b, 0x73, 0x25b, 0x74, 0x3b, 0x254, 0x6b, 0x75, 0x3b, 0x6e,
-0x6f, 0x77, 0x3b, 0x64, 0x65, 0x73, 0x3b, 0x7a, 0x61, 0x6e, 0x77, 0x75, 0x79, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x75, 0x72,
-0x75, 0x79, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x69, 0x73, 0x69, 0x3b, 0x61, 0x77, 0x69, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d,
-0x25b, 0x3b, 0x7a, 0x75, 0x77, 0x25b, 0x6e, 0x3b, 0x7a, 0x75, 0x6c, 0x75, 0x79, 0x65, 0x3b, 0x75, 0x74, 0x69, 0x3b, 0x73,
-0x25b, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x254, 0x6b, 0x75, 0x74, 0x254, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x6e,
-0x6f, 0x77, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x5a,
-0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x5a, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x186, 0x3b, 0x4e,
-0x3b, 0x44, 0x3b, 0x4d, 0x62, 0x65, 0x3b, 0x4b, 0x61, 0x69, 0x3b, 0x4b, 0x61, 0x74, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x47,
-0x61, 0x74, 0x3b, 0x47, 0x61, 0x6e, 0x3b, 0x4d, 0x75, 0x67, 0x3b, 0x4b, 0x6e, 0x6e, 0x3b, 0x4b, 0x65, 0x6e, 0x3b, 0x49,
-0x6b, 0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b, 0x49, 0x67, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
-0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x129, 0x72, 0x69,
-0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x68, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77,
-0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61,
-0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74,
-0x61, 0x6e, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x169, 0x67, 0x77,
-0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x6e, 0x61,
-0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72,
-0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
-0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
-0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x4b, 0x61, 0x129, 0x72, 0x129, 0x3b, 0x4d, 0x3b,
-0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b,
-0x49, 0x3b, 0x13a4, 0x13c3, 0x3b, 0x13a7, 0x13a6, 0x3b, 0x13a0, 0x13c5, 0x3b, 0x13a7, 0x13ec, 0x3b, 0x13a0, 0x13c2, 0x3b, 0x13d5, 0x13ad, 0x3b,
-0x13ab, 0x13f0, 0x3b, 0x13a6, 0x13b6, 0x3b, 0x13da, 0x13b5, 0x3b, 0x13da, 0x13c2, 0x3b, 0x13c5, 0x13d3, 0x3b, 0x13a5, 0x13cd, 0x3b, 0x13a4, 0x13c3,
-0x13b8, 0x13d4, 0x13c5, 0x3b, 0x13a7, 0x13a6, 0x13b5, 0x3b, 0x13a0, 0x13c5, 0x13f1, 0x3b, 0x13a7, 0x13ec, 0x13c2, 0x3b, 0x13a0, 0x13c2, 0x13cd, 0x13ac,
-0x13d8, 0x3b, 0x13d5, 0x13ad, 0x13b7, 0x13f1, 0x3b, 0x13ab, 0x13f0, 0x13c9, 0x13c2, 0x3b, 0x13a6, 0x13b6, 0x13c2, 0x3b, 0x13da, 0x13b5, 0x13cd, 0x13d7,
-0x3b, 0x13da, 0x13c2, 0x13c5, 0x13d7, 0x3b, 0x13c5, 0x13d3, 0x13d5, 0x13c6, 0x3b, 0x13a5, 0x13cd, 0x13a9, 0x13f1, 0x3b, 0x13a4, 0x3b, 0x13a7, 0x3b,
-0x13a0, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13d5, 0x3b, 0x13ab, 0x3b, 0x13a6, 0x3b, 0x13da, 0x3b, 0x13da, 0x3b, 0x13c5, 0x3b, 0x13a5, 0x3b,
-0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x76, 0x72, 0x3b, 0x6d, 0x65, 0x3b, 0x7a,
-0x69, 0x6e, 0x3b, 0x7a, 0x69, 0x6c, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e,
-0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b, 0x7a, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b, 0x66, 0x65, 0x76, 0x72, 0x69, 0x79,
-0x65, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x65, 0x3b, 0x7a, 0x69, 0x6e, 0x3b,
-0x7a, 0x69, 0x6c, 0x79, 0x65, 0x3b, 0x6f, 0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x61, 0x6d, 0x3b, 0x6f, 0x6b, 0x74,
-0x6f, 0x62, 0x3b, 0x6e, 0x6f, 0x76, 0x61, 0x6d, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6d, 0x3b, 0x7a, 0x3b, 0x66, 0x3b, 0x6d,
-0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x7a, 0x3b, 0x7a, 0x3b, 0x6f, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x4d,
-0x77, 0x65, 0x64, 0x69, 0x20, 0x4e, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61,
-0x20, 0x50, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x54, 0x61, 0x74, 0x75, 0x3b,
-0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4d, 0x77, 0x65,
-0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77,
-0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x55, 0x6d, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64,
-0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x69, 0x76, 0x69, 0x6c,
-0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61,
-0x20, 0x4d, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79,
-0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69,
-0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f,
+0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x55, 0x4d,
+0x61, 0x73, 0x69, 0x6e, 0x67, 0x61, 0x6e, 0x61, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x77, 0x61, 0x72, 0x69, 0x3b, 0x4d,
+0x61, 0x73, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x68, 0x72, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x79, 0x69, 0x3b, 0x4a, 0x75,
+0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70,
+0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x68, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d,
+0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d,
+0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6a, 0x61, 0x6e, 0x2e, 0x3b,
+0x66, 0x65, 0x62, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b, 0x61, 0x70, 0x72, 0x2e, 0x3b, 0x6d, 0x61, 0x69, 0x3b, 0x6a,
+0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x75, 0x67, 0x2e, 0x3b, 0x73, 0x65, 0x70, 0x2e, 0x3b, 0x6f,
+0x6b, 0x74, 0x2e, 0x3b, 0x6e, 0x6f, 0x76, 0x2e, 0x3b, 0x64, 0x65, 0x73, 0x2e, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72,
+0x3b, 0x66, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x3b, 0x61, 0x70, 0x72, 0x69, 0x6c, 0x3b,
+0x6d, 0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x3b, 0x61, 0x76, 0x67, 0x75, 0x73, 0x74,
+0x3b, 0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b, 0x6e,
+0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x458, 0x430, 0x43d,
+0x443, 0x430, 0x440, 0x3b, 0x444, 0x435, 0x431, 0x440, 0x443, 0x430, 0x440, 0x3b, 0x43c, 0x430, 0x440, 0x442, 0x3b, 0x430, 0x43f, 0x440,
+0x438, 0x43b, 0x3b, 0x43c, 0x430, 0x458, 0x3b, 0x458, 0x443, 0x43d, 0x438, 0x3b, 0x458, 0x443, 0x43b, 0x438, 0x3b, 0x430, 0x432, 0x433,
+0x443, 0x441, 0x442, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x43e, 0x43a, 0x442, 0x43e, 0x431, 0x430,
+0x440, 0x3b, 0x43d, 0x43e, 0x432, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b, 0x434, 0x435, 0x446, 0x435, 0x43c, 0x431, 0x430, 0x440, 0x3b,
+0x4a, 0x2d, 0x67, 0x75, 0x65, 0x72, 0x3b, 0x54, 0x2d, 0x61, 0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e,
+0x74, 0x3b, 0x41, 0x76, 0x72, 0x72, 0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x73,
+0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4a, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x69,
+0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4a, 0x2d, 0x66, 0x6f, 0x75, 0x79,
+0x69, 0x72, 0x3b, 0x4d, 0x2d, 0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x2d, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63,
+0x6b, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x67, 0x65, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x54, 0x6f, 0x73, 0x68,
+0x69, 0x61, 0x67, 0x68, 0x74, 0x2d, 0x61, 0x72, 0x72, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x79, 0x72, 0x6e, 0x74, 0x3b, 0x41,
+0x76, 0x65, 0x72, 0x69, 0x6c, 0x3b, 0x42, 0x6f, 0x61, 0x6c, 0x64, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x73,
+0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x73, 0x6f, 0x75, 0x72, 0x65, 0x65, 0x3b,
+0x4c, 0x75, 0x61, 0x6e, 0x69, 0x73, 0x74, 0x79, 0x6e, 0x3b, 0x4d, 0x65, 0x61, 0x6e, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69,
+0x72, 0x3b, 0x4a, 0x65, 0x72, 0x72, 0x65, 0x79, 0x2d, 0x66, 0x6f, 0x75, 0x79, 0x69, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x20,
+0x48, 0x6f, 0x75, 0x6e, 0x65, 0x79, 0x3b, 0x4d, 0x65, 0x65, 0x20, 0x6e, 0x79, 0x20, 0x4e, 0x6f, 0x6c, 0x6c, 0x69, 0x63,
+0x6b, 0x3b, 0x47, 0x65, 0x6e, 0x3b, 0x48, 0x77, 0x65, 0x3b, 0x4d, 0x65, 0x75, 0x3b, 0x45, 0x62, 0x72, 0x3b, 0x4d, 0x65,
+0x3b, 0x4d, 0x65, 0x74, 0x3b, 0x47, 0x6f, 0x72, 0x3b, 0x45, 0x73, 0x74, 0x3b, 0x47, 0x77, 0x6e, 0x3b, 0x48, 0x65, 0x64,
+0x3b, 0x44, 0x75, 0x3b, 0x4b, 0x65, 0x76, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x65, 0x6e, 0x76, 0x65, 0x72, 0x3b, 0x6d,
+0x69, 0x73, 0x20, 0x48, 0x77, 0x65, 0x76, 0x72, 0x65, 0x72, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x75, 0x72, 0x74,
+0x68, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x45, 0x62, 0x72, 0x65, 0x6c, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4d, 0x65, 0x3b, 0x6d,
+0x69, 0x73, 0x20, 0x4d, 0x65, 0x74, 0x68, 0x65, 0x76, 0x65, 0x6e, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x6f, 0x72, 0x74,
+0x68, 0x65, 0x72, 0x65, 0x6e, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x45, 0x73, 0x74, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x47, 0x77,
+0x79, 0x6e, 0x6e, 0x67, 0x61, 0x6c, 0x61, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x48, 0x65, 0x64, 0x72, 0x61, 0x3b, 0x6d, 0x69,
+0x73, 0x20, 0x44, 0x75, 0x3b, 0x6d, 0x69, 0x73, 0x20, 0x4b, 0x65, 0x76, 0x61, 0x72, 0x64, 0x68, 0x75, 0x3b, 0x53, 0x2d,
+0x186, 0x3b, 0x4b, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x186, 0x3b, 0x45, 0x2d, 0x4f, 0x3b, 0x45, 0x2d, 0x4b, 0x3b, 0x4f, 0x2d,
+0x41, 0x3b, 0x41, 0x2d, 0x4b, 0x3b, 0x44, 0x2d, 0x186, 0x3b, 0x46, 0x2d, 0x190, 0x3b, 0x186, 0x2d, 0x41, 0x3b, 0x186, 0x2d,
+0x4f, 0x3b, 0x4d, 0x2d, 0x186, 0x3b, 0x53, 0x61, 0x6e, 0x64, 0x61, 0x2d, 0x186, 0x70, 0x25b, 0x70, 0x254, 0x6e, 0x3b, 0x4b,
+0x77, 0x61, 0x6b, 0x77, 0x61, 0x72, 0x2d, 0x186, 0x67, 0x79, 0x65, 0x66, 0x75, 0x6f, 0x3b, 0x45, 0x62, 0x254, 0x77, 0x2d,
+0x186, 0x62, 0x65, 0x6e, 0x65, 0x6d, 0x3b, 0x45, 0x62, 0x254, 0x62, 0x69, 0x72, 0x61, 0x2d, 0x4f, 0x66, 0x6f, 0x72, 0x69,
+0x73, 0x75, 0x6f, 0x3b, 0x45, 0x73, 0x75, 0x73, 0x6f, 0x77, 0x20, 0x41, 0x6b, 0x65, 0x74, 0x73, 0x65, 0x61, 0x62, 0x61,
+0x2d, 0x4b, 0x254, 0x74, 0x254, 0x6e, 0x69, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x62, 0x69, 0x72, 0x61, 0x64, 0x65, 0x2d, 0x41,
+0x79, 0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x6d, 0x75, 0x6d, 0x75, 0x3b, 0x41, 0x79, 0x25b, 0x77, 0x6f, 0x68, 0x6f, 0x2d, 0x4b,
+0x69, 0x74, 0x61, 0x77, 0x6f, 0x6e, 0x73, 0x61, 0x3b, 0x44, 0x69, 0x66, 0x75, 0x75, 0x2d, 0x186, 0x73, 0x61, 0x6e, 0x64,
+0x61, 0x61, 0x3b, 0x46, 0x61, 0x6e, 0x6b, 0x77, 0x61, 0x2d, 0x190, 0x62, 0x254, 0x3b, 0x186, 0x62, 0x25b, 0x73, 0x25b, 0x2d,
+0x41, 0x68, 0x69, 0x6e, 0x69, 0x6d, 0x65, 0x3b, 0x186, 0x62, 0x65, 0x72, 0x25b, 0x66, 0x25b, 0x77, 0x2d, 0x4f, 0x62, 0x75,
+0x62, 0x75, 0x6f, 0x3b, 0x4d, 0x75, 0x6d, 0x75, 0x2d, 0x186, 0x70, 0x25b, 0x6e, 0x69, 0x6d, 0x62, 0x61, 0x3b, 0x91c, 0x93e,
+0x928, 0x947, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e,
+0x930, 0x94d, 0x91a, 0x3b, 0x90f, 0x92a, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x942, 0x928, 0x3b, 0x91c, 0x941,
+0x932, 0x948, 0x3b, 0x913, 0x917, 0x938, 0x94d, 0x91f, 0x3b, 0x938, 0x947, 0x92a, 0x94d, 0x91f, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x913,
+0x915, 0x94d, 0x91f, 0x94b, 0x92c, 0x930, 0x3b, 0x928, 0x94b, 0x935, 0x94d, 0x939, 0x947, 0x902, 0x92c, 0x930, 0x3b, 0x921, 0x93f, 0x938,
+0x947, 0x902, 0x92c, 0x930, 0x3b, 0x4a, 0x65, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x45, 0x70, 0x72,
+0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x1ecc, 0x67, 0x1ecd, 0x3b, 0x53, 0x65, 0x70,
+0x3b, 0x1ecc, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x65, 0x6e, 0x1ee5, 0x77, 0x61, 0x72,
+0x1ecb, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x1ee5, 0x77, 0x61, 0x72, 0x1ecb, 0x3b, 0x4d, 0x61, 0x61, 0x63, 0x68, 0x1ecb, 0x3b, 0x45,
+0x70, 0x72, 0x65, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x1ecb, 0x3b,
+0x1ecc, 0x67, 0x1ecd, 0x1ecd, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x1ecc, 0x6b, 0x74, 0x6f,
+0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4d,
+0x62, 0x65, 0x3b, 0x4b, 0x65, 0x6c, 0x3b, 0x4b, 0x74, 0x169, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x74, 0x6e, 0x3b, 0x54,
+0x68, 0x61, 0x3b, 0x4d, 0x6f, 0x6f, 0x3b, 0x4e, 0x79, 0x61, 0x3b, 0x4b, 0x6e, 0x64, 0x3b, 0x128, 0x6b, 0x75, 0x3b, 0x128,
+0x6b, 0x6d, 0x3b, 0x128, 0x6b, 0x6c, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x65, 0x3b,
+0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61,
+0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61,
+0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x61, 0x69,
+0x20, 0x77, 0x61, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77,
+0x61, 0x20, 0x6d, 0x75, 0x6f, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6e, 0x79, 0x61,
+0x61, 0x6e, 0x79, 0x61, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d,
+0x77, 0x61, 0x69, 0x20, 0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20, 0x77, 0x61,
+0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x129, 0x6d, 0x77, 0x65, 0x3b, 0x4d, 0x77, 0x61, 0x69, 0x20,
+0x77, 0x61, 0x20, 0x129, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x6c, 0x129, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x128, 0x3b, 0x128, 0x3b, 0x128, 0x3b,
+0x5a, 0x65, 0x6e, 0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x76, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b,
+0x4a, 0x75, 0x67, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b,
+0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x63, 0x3b, 0x5a, 0x65, 0x6e, 0xe2, 0x72, 0x3b, 0x46, 0x65, 0x76, 0x72, 0xe2, 0x72,
+0x3b, 0x4d, 0x61, 0x72, 0xe7, 0x3b, 0x41, 0x76, 0x72, 0xee, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x67, 0x6e,
+0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x41, 0x76, 0x6f, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b,
+0x4f, 0x74, 0x75, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x69, 0x63, 0x65,
+0x6d, 0x62, 0x61, 0x72, 0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4c, 0x3b, 0x41,
+0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x64, 0x7a, 0x76, 0x3b, 0x64, 0x7a, 0x64, 0x3b, 0x74, 0x65, 0x64,
+0x3b, 0x61, 0x66, 0x254, 0x3b, 0x64, 0x61, 0x6d, 0x3b, 0x6d, 0x61, 0x73, 0x3b, 0x73, 0x69, 0x61, 0x3b, 0x64, 0x65, 0x61,
+0x3b, 0x61, 0x6e, 0x79, 0x3b, 0x6b, 0x65, 0x6c, 0x3b, 0x61, 0x64, 0x65, 0x3b, 0x64, 0x7a, 0x6d, 0x3b, 0x64, 0x7a, 0x6f,
+0x76, 0x65, 0x3b, 0x64, 0x7a, 0x6f, 0x64, 0x7a, 0x65, 0x3b, 0x74, 0x65, 0x64, 0x6f, 0x78, 0x65, 0x3b, 0x61, 0x66, 0x254,
+0x66, 0x129, 0x65, 0x3b, 0x64, 0x61, 0x6d, 0x61, 0x3b, 0x6d, 0x61, 0x73, 0x61, 0x3b, 0x73, 0x69, 0x61, 0x6d, 0x6c, 0x254,
+0x6d, 0x3b, 0x64, 0x65, 0x61, 0x73, 0x69, 0x61, 0x6d, 0x69, 0x6d, 0x65, 0x3b, 0x61, 0x6e, 0x79, 0x254, 0x6e, 0x79, 0x254,
+0x3b, 0x6b, 0x65, 0x6c, 0x65, 0x3b, 0x61, 0x64, 0x65, 0x25b, 0x6d, 0x65, 0x6b, 0x70, 0x254, 0x78, 0x65, 0x3b, 0x64, 0x7a,
+0x6f, 0x6d, 0x65, 0x3b, 0x64, 0x3b, 0x64, 0x3b, 0x74, 0x3b, 0x61, 0x3b, 0x64, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64, 0x3b,
+0x61, 0x3b, 0x6b, 0x3b, 0x61, 0x3b, 0x64, 0x3b, 0x49, 0x61, 0x6e, 0x2e, 0x3b, 0x50, 0x65, 0x70, 0x2e, 0x3b, 0x4d, 0x61,
+0x6c, 0x2e, 0x3b, 0x2bb, 0x41, 0x70, 0x2e, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x2e, 0x3b, 0x49, 0x75, 0x6c,
+0x2e, 0x3b, 0x2bb, 0x41, 0x75, 0x2e, 0x3b, 0x4b, 0x65, 0x70, 0x2e, 0x3b, 0x2bb, 0x4f, 0x6b, 0x2e, 0x3b, 0x4e, 0x6f, 0x77,
+0x2e, 0x3b, 0x4b, 0x65, 0x6b, 0x2e, 0x3b, 0x49, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x50, 0x65, 0x70, 0x65, 0x6c,
+0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x6b, 0x69, 0x3b, 0x2bb, 0x41, 0x70, 0x65, 0x6c, 0x69, 0x6c, 0x61,
+0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x49, 0x75, 0x6e, 0x65, 0x3b, 0x49, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x2bb, 0x41, 0x75, 0x6b,
+0x61, 0x6b, 0x65, 0x3b, 0x4b, 0x65, 0x70, 0x61, 0x6b, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b, 0x2bb, 0x4f, 0x6b, 0x61, 0x6b,
+0x6f, 0x70, 0x61, 0x3b, 0x4e, 0x6f, 0x77, 0x65, 0x6d, 0x61, 0x70, 0x61, 0x3b, 0x4b, 0x65, 0x6b, 0x65, 0x6d, 0x61, 0x70,
+0x61, 0x3b, 0x45, 0x6e, 0x65, 0x3b, 0x50, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61,
+0x79, 0x3b, 0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b,
+0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x45, 0x6e, 0x65, 0x72, 0x6f, 0x3b, 0x50, 0x65, 0x62, 0x72,
+0x65, 0x72, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x79, 0x6f,
+0x3b, 0x48, 0x75, 0x6e, 0x79, 0x6f, 0x3b, 0x48, 0x75, 0x6c, 0x79, 0x6f, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x6f, 0x3b,
+0x53, 0x65, 0x74, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x4f, 0x6b, 0x74, 0x75, 0x62, 0x72, 0x65, 0x3b, 0x4e, 0x6f,
+0x62, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x44, 0x69, 0x73, 0x79, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x45, 0x3b,
+0x50, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x48, 0x75, 0x6e, 0x3b, 0x48, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b,
+0x53, 0x65, 0x74, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75,
+0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69,
+0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x75,
+0x73, 0x63, 0x68, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f,
+0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65,
+0x72, 0x3b, 0xa2cd, 0xa1aa, 0x3b, 0xa44d, 0xa1aa, 0x3b, 0xa315, 0xa1aa, 0x3b, 0xa1d6, 0xa1aa, 0x3b, 0xa26c, 0xa1aa, 0x3b, 0xa0d8, 0xa1aa, 0x3b,
+0xa3c3, 0xa1aa, 0x3b, 0xa246, 0xa1aa, 0x3b, 0xa22c, 0xa1aa, 0x3b, 0xa2b0, 0xa1aa, 0x3b, 0xa2b0, 0xa2aa, 0xa1aa, 0x3b, 0xa2b0, 0xa44b, 0xa1aa, 0x3b,
+0x4a, 0x61, 0x6e, 0x75, 0x61, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x72,
+0x7a, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c,
+0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f,
+0x6b, 0x74, 0x6f, 0x76, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x6f, 0x111, 0x111, 0x6a, 0x3b, 0x67, 0x75, 0x6f, 0x76, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x3b,
+0x63, 0x75, 0x6f, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x3b, 0x73, 0x75, 0x6f, 0x69, 0x3b, 0x62,
+0x6f, 0x72, 0x67, 0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x3b, 0x6a,
+0x75, 0x6f, 0x76, 0x3b, 0x6f, 0x111, 0x111, 0x61, 0x6a, 0x61, 0x67, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x75,
+0x6f, 0x76, 0x76, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6e, 0x6a, 0x75, 0x6b, 0x10d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e,
+0x75, 0x3b, 0x63, 0x75, 0x6f, 0x14b, 0x6f, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6d, 0x69, 0x65, 0x73, 0x73, 0x65, 0x6d,
+0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x65, 0x61, 0x73, 0x73, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x73, 0x75, 0x6f,
+0x69, 0x64, 0x6e, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x62, 0x6f, 0x72, 0x67, 0x65, 0x6d, 0xe1, 0x6e, 0x6e, 0x75,
+0x3b, 0x10d, 0x61, 0x6b, 0x10d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x67, 0x6f, 0x6c, 0x67, 0x67, 0x6f, 0x74, 0x6d,
+0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x73, 0x6b, 0xe1, 0x62, 0x6d, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x6a, 0x75, 0x6f,
+0x76, 0x6c, 0x61, 0x6d, 0xe1, 0x6e, 0x6e, 0x75, 0x3b, 0x4f, 0x3b, 0x47, 0x3b, 0x4e, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0x47,
+0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x10c, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 0x43, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62,
+0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x43, 0x75, 0x6c,
+0x3b, 0x41, 0x67, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x62, 0x3b, 0x44, 0x69, 0x73,
+0x3b, 0x43, 0x68, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x72, 0x61, 0x72, 0x69, 0x3b, 0x4d,
+0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x69, 0x72, 0x69, 0x72, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e,
+0x69, 0x3b, 0x43, 0x68, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74,
+0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x62, 0x65, 0x6d, 0x62, 0x61,
+0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x43, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4a,
+0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x49, 0x6d, 0x62, 0x3b, 0x4b, 0x61, 0x77,
+0x3b, 0x4b, 0x61, 0x64, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x4b, 0x61, 0x72, 0x3b, 0x4d, 0x66, 0x75,
+0x3b, 0x57, 0x75, 0x6e, 0x3b, 0x49, 0x6b, 0x65, 0x3b, 0x49, 0x6b, 0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b, 0x49, 0x77, 0x69,
+0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6d, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4d, 0x6f,
+0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x77, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68,
+0x77, 0x61, 0x20, 0x6b, 0x61, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20,
+0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x73, 0x61, 0x6e,
+0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x72, 0x61, 0x6e, 0x64, 0x61, 0x64,
+0x75, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x6d, 0x66, 0x75, 0x6e, 0x67, 0x61, 0x64, 0x65,
+0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x77, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x79, 0x61, 0x3b,
+0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x6f, 0x72,
+0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x6f, 0x72, 0x69, 0x20, 0x67, 0x68,
+0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x6d, 0x77, 0x65, 0x72, 0x69, 0x3b, 0x4d,
+0x6f, 0x72, 0x69, 0x20, 0x67, 0x68, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x77,
+0x69, 0x3b, 0x49, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x57, 0x3b, 0x49, 0x3b,
+0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x73, 0x69, 0x69, 0x3b, 0x63, 0x6f, 0x6c, 0x3b, 0x6d, 0x62, 0x6f, 0x3b, 0x73, 0x65,
+0x65, 0x3b, 0x64, 0x75, 0x75, 0x3b, 0x6b, 0x6f, 0x72, 0x3b, 0x6d, 0x6f, 0x72, 0x3b, 0x6a, 0x75, 0x6b, 0x3b, 0x73, 0x6c,
+0x74, 0x3b, 0x79, 0x61, 0x72, 0x3b, 0x6a, 0x6f, 0x6c, 0x3b, 0x62, 0x6f, 0x77, 0x3b, 0x73, 0x69, 0x69, 0x6c, 0x6f, 0x3b,
+0x63, 0x6f, 0x6c, 0x74, 0x65, 0x3b, 0x6d, 0x62, 0x6f, 0x6f, 0x79, 0x3b, 0x73, 0x65, 0x65, 0x257, 0x74, 0x6f, 0x3b, 0x64,
+0x75, 0x75, 0x6a, 0x61, 0x6c, 0x3b, 0x6b, 0x6f, 0x72, 0x73, 0x65, 0x3b, 0x6d, 0x6f, 0x72, 0x73, 0x6f, 0x3b, 0x6a, 0x75,
+0x6b, 0x6f, 0x3b, 0x73, 0x69, 0x69, 0x6c, 0x74, 0x6f, 0x3b, 0x79, 0x61, 0x72, 0x6b, 0x6f, 0x6d, 0x61, 0x61, 0x3b, 0x6a,
+0x6f, 0x6c, 0x61, 0x6c, 0x3b, 0x62, 0x6f, 0x77, 0x74, 0x65, 0x3b, 0x73, 0x3b, 0x63, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x64,
+0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x73, 0x3b, 0x79, 0x3b, 0x6a, 0x3b, 0x62, 0x3b, 0x4a, 0x45, 0x4e, 0x3b, 0x57,
+0x4b, 0x52, 0x3b, 0x57, 0x47, 0x54, 0x3b, 0x57, 0x4b, 0x4e, 0x3b, 0x57, 0x54, 0x4e, 0x3b, 0x57, 0x54, 0x44, 0x3b, 0x57,
+0x4d, 0x4a, 0x3b, 0x57, 0x4e, 0x4e, 0x3b, 0x57, 0x4b, 0x44, 0x3b, 0x57, 0x49, 0x4b, 0x3b, 0x57, 0x4d, 0x57, 0x3b, 0x44,
+0x49, 0x54, 0x3b, 0x4e, 0x6a, 0x65, 0x6e, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61,
+0x20, 0x6b, 0x65, 0x72, 0x129, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74,
+0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72,
+0x65, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61,
+0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20,
+0x6d, 0x169, 0x67, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61,
+0x6e, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b,
+0x4d, 0x77, 0x65, 0x72, 0x65, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x65,
+0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4e, 0x64,
+0x69, 0x74, 0x68, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x4b, 0x3b, 0x47, 0x3b, 0x47, 0x3b,
+0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x44, 0x3b, 0x4f, 0x62, 0x6f, 0x3b, 0x57, 0x61, 0x61, 0x3b,
+0x4f, 0x6b, 0x75, 0x3b, 0x4f, 0x6e, 0x67, 0x3b, 0x49, 0x6d, 0x65, 0x3b, 0x49, 0x6c, 0x65, 0x3b, 0x53, 0x61, 0x70, 0x3b,
+0x49, 0x73, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x3b, 0x54, 0x6f, 0x6d, 0x3b, 0x54, 0x6f, 0x62, 0x3b, 0x54, 0x6f, 0x77, 0x3b,
+0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f, 0x62, 0x6f, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20,
+0x77, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f, 0x6b, 0x75, 0x6e, 0x69, 0x3b,
+0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x6f, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61,
+0x20, 0x6c, 0x65, 0x20, 0x69, 0x6d, 0x65, 0x74, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x69, 0x6c, 0x65,
+0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x73, 0x61, 0x70, 0x61, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c,
+0x65, 0x20, 0x69, 0x73, 0x69, 0x65, 0x74, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x73, 0x61, 0x61, 0x6c,
+0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20,
+0x6c, 0x65, 0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x6f, 0x62, 0x6f, 0x3b, 0x4c, 0x61, 0x70, 0x61, 0x20, 0x6c, 0x65,
+0x20, 0x74, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x77, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4f, 0x3b, 0x57, 0x3b, 0x4f, 0x3b, 0x4f,
+0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4a, 0x61, 0x6e,
+0x3b, 0x46, 0x65, 0x76, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e,
+0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x6f, 0x76,
+0x3b, 0x44, 0x65, 0x63, 0x3b, 0x4a, 0x61, 0x6e, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x65, 0x76, 0x72, 0x65, 0x69, 0x72,
+0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x63, 0x6f, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x6f, 0x3b, 0x4a,
+0x75, 0x6e, 0x68, 0x6f, 0x3b, 0x4a, 0x75, 0x6c, 0x68, 0x6f, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x6f, 0x3b, 0x53,
+0x65, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x72, 0x6f, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d,
+0x62, 0x72, 0x6f, 0x3b, 0x44, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x6f, 0x3b, 0x5a, 0x69, 0x62, 0x3b, 0x4e, 0x68, 0x6c,
+0x6f, 0x3b, 0x4d, 0x62, 0x69, 0x3b, 0x4d, 0x61, 0x62, 0x3b, 0x4e, 0x6b, 0x77, 0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x3b, 0x4e,
+0x74, 0x75, 0x3b, 0x4e, 0x63, 0x77, 0x3b, 0x4d, 0x70, 0x61, 0x6e, 0x3b, 0x4d, 0x66, 0x75, 0x3b, 0x4c, 0x77, 0x65, 0x3b,
+0x4d, 0x70, 0x61, 0x6c, 0x3b, 0x5a, 0x69, 0x62, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x6c, 0x61, 0x3b, 0x4e, 0x68, 0x6c, 0x6f,
+0x6c, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x62, 0x69, 0x6d, 0x62, 0x69, 0x74, 0x68, 0x6f, 0x3b, 0x4d, 0x61, 0x62, 0x61,
+0x73, 0x61, 0x3b, 0x4e, 0x6b, 0x77, 0x65, 0x6e, 0x6b, 0x77, 0x65, 0x7a, 0x69, 0x3b, 0x4e, 0x68, 0x6c, 0x61, 0x6e, 0x67,
+0x75, 0x6c, 0x61, 0x3b, 0x4e, 0x74, 0x75, 0x6c, 0x69, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x4e, 0x63, 0x77, 0x61, 0x62, 0x61,
+0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x4d, 0x70, 0x61, 0x6e, 0x64, 0x75, 0x6c, 0x61, 0x3b, 0x4d, 0x66, 0x75, 0x6d, 0x66, 0x75,
+0x3b, 0x4c, 0x77, 0x65, 0x7a, 0x69, 0x3b, 0x4d, 0x70, 0x61, 0x6c, 0x61, 0x6b, 0x61, 0x7a, 0x69, 0x3b, 0x5a, 0x3b, 0x4e,
+0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4d,
+0x3b, 0x4d, 0x31, 0x3b, 0x4d, 0x32, 0x3b, 0x4d, 0x33, 0x3b, 0x4d, 0x34, 0x3b, 0x4d, 0x35, 0x3b, 0x4d, 0x36, 0x3b, 0x4d,
+0x37, 0x3b, 0x4d, 0x38, 0x3b, 0x4d, 0x39, 0x3b, 0x4d, 0x31, 0x30, 0x3b, 0x4d, 0x31, 0x31, 0x3b, 0x4d, 0x31, 0x32, 0x3b,
+0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72,
+0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x6b, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x61, 0x6e,
+0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72,
+0x69, 0x20, 0x77, 0x61, 0x20, 0x73, 0x69, 0x74, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x73,
+0x61, 0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61,
+0x20, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x75, 0x6d,
+0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69,
+0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x2d49, 0x2d4f,
+0x2d4f, 0x3b, 0x2d31, 0x2d55, 0x2d30, 0x3b, 0x2d4e, 0x2d30, 0x2d55, 0x3b, 0x2d49, 0x2d31, 0x2d54, 0x3b, 0x2d4e, 0x2d30, 0x2d62, 0x3b, 0x2d62, 0x2d53,
+0x2d4f, 0x3b, 0x2d62, 0x2d53, 0x2d4d, 0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x3b, 0x2d5b, 0x2d53, 0x2d5c, 0x3b, 0x2d3d, 0x2d5c, 0x2d53, 0x3b, 0x2d4f, 0x2d53,
+0x2d61, 0x3b, 0x2d37, 0x2d53, 0x2d4a, 0x3b, 0x2d49, 0x2d4f, 0x2d4f, 0x2d30, 0x2d62, 0x2d54, 0x3b, 0x2d31, 0x2d55, 0x2d30, 0x2d62, 0x2d55, 0x3b, 0x2d4e,
+0x2d30, 0x2d55, 0x2d5a, 0x3b, 0x2d49, 0x2d31, 0x2d54, 0x2d49, 0x2d54, 0x3b, 0x2d4e, 0x2d30, 0x2d62, 0x2d62, 0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4f, 0x2d62,
+0x2d53, 0x3b, 0x2d62, 0x2d53, 0x2d4d, 0x2d62, 0x2d53, 0x2d63, 0x3b, 0x2d56, 0x2d53, 0x2d5b, 0x2d5c, 0x3b, 0x2d5b, 0x2d53, 0x2d5c, 0x2d30, 0x2d4f, 0x2d31,
+0x2d49, 0x2d54, 0x3b, 0x2d3d, 0x2d5c, 0x2d53, 0x2d31, 0x2d54, 0x3b, 0x2d4f, 0x2d53, 0x2d61, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d37, 0x2d53,
+0x2d4a, 0x2d30, 0x2d4f, 0x2d31, 0x2d49, 0x2d54, 0x3b, 0x2d49, 0x3b, 0x2d31, 0x3b, 0x2d4e, 0x3b, 0x2d49, 0x3b, 0x2d4e, 0x3b, 0x2d62, 0x3b, 0x2d62,
+0x3b, 0x2d56, 0x3b, 0x2d5b, 0x3b, 0x2d3d, 0x3b, 0x2d4f, 0x3b, 0x2d37, 0x3b, 0x69, 0x6e, 0x6e, 0x3b, 0x62, 0x1e5b, 0x61, 0x3b, 0x6d,
+0x61, 0x1e5b, 0x3b, 0x69, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x79, 0x75, 0x6e, 0x3b, 0x79, 0x75, 0x6c, 0x3b, 0x263,
+0x75, 0x63, 0x3b, 0x63, 0x75, 0x74, 0x3b, 0x6b, 0x74, 0x75, 0x3b, 0x6e, 0x75, 0x77, 0x3b, 0x64, 0x75, 0x6a, 0x3b, 0x69,
+0x6e, 0x6e, 0x61, 0x79, 0x72, 0x3b, 0x62, 0x1e5b, 0x61, 0x79, 0x1e5b, 0x3b, 0x6d, 0x61, 0x1e5b, 0x1e63, 0x3b, 0x69, 0x62, 0x72,
+0x69, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x79, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x79, 0x75, 0x6c, 0x79, 0x75,
+0x7a, 0x3b, 0x263, 0x75, 0x63, 0x74, 0x3b, 0x63, 0x75, 0x74, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x6b, 0x74, 0x75, 0x62,
+0x72, 0x3b, 0x6e, 0x75, 0x77, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x64, 0x75, 0x6a, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b,
+0x69, 0x3b, 0x62, 0x3b, 0x6d, 0x3b, 0x69, 0x3b, 0x6d, 0x3b, 0x79, 0x3b, 0x79, 0x3b, 0x263, 0x3b, 0x63, 0x3b, 0x6b, 0x3b,
+0x6e, 0x3b, 0x64, 0x3b, 0x59, 0x65, 0x6e, 0x3b, 0x46, 0x75, 0x72, 0x3b, 0x4d, 0x65, 0x263, 0x3b, 0x59, 0x65, 0x62, 0x3b,
+0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75, 0x63, 0x3b, 0x43, 0x74, 0x65, 0x3b,
+0x54, 0x75, 0x62, 0x3b, 0x4e, 0x75, 0x6e, 0x3b, 0x44, 0x75, 0x1e7, 0x3b, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72,
+0x3b, 0x46, 0x75, 0x1e5b, 0x61, 0x72, 0x3b, 0x4d, 0x65, 0x263, 0x72, 0x65, 0x73, 0x3b, 0x59, 0x65, 0x62, 0x72, 0x69, 0x72,
+0x3b, 0x4d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6c, 0x79, 0x75, 0x3b, 0x194,
+0x75, 0x63, 0x74, 0x3b, 0x43, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x54, 0x75, 0x62, 0x65, 0x1e5b, 0x3b, 0x4e, 0x75,
+0x6e, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x44, 0x75, 0x1e7, 0x65, 0x6d, 0x62, 0x65, 0x1e5b, 0x3b, 0x59, 0x3b, 0x46, 0x3b,
+0x4d, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x44, 0x3b,
+0x4b, 0x42, 0x5a, 0x3b, 0x4b, 0x42, 0x52, 0x3b, 0x4b, 0x53, 0x54, 0x3b, 0x4b, 0x4b, 0x4e, 0x3b, 0x4b, 0x54, 0x4e, 0x3b,
+0x4b, 0x4d, 0x4b, 0x3b, 0x4b, 0x4d, 0x53, 0x3b, 0x4b, 0x4d, 0x4e, 0x3b, 0x4b, 0x4d, 0x57, 0x3b, 0x4b, 0x4b, 0x4d, 0x3b,
+0x4b, 0x4e, 0x4b, 0x3b, 0x4b, 0x4e, 0x42, 0x3b, 0x4f, 0x6b, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x61, 0x6e, 0x7a, 0x61, 0x3b,
+0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x73, 0x68, 0x61,
+0x74, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6b, 0x61, 0x74, 0x61,
+0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61,
+0x6d, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x6a, 0x75, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x75, 0x6e, 0x61, 0x61, 0x6e, 0x61,
+0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x77, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d,
+0x69, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x77, 0x65,
+0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x69, 0x62, 0x69, 0x72, 0x69, 0x3b,
+0x48, 0x75, 0x74, 0x3b, 0x56, 0x69, 0x6c, 0x3b, 0x44, 0x61, 0x74, 0x3b, 0x54, 0x61, 0x69, 0x3b, 0x48, 0x61, 0x6e, 0x3b,
+0x53, 0x69, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61, 0x6e, 0x3b, 0x54, 0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d, 0x3b,
+0x4b, 0x6d, 0x6a, 0x3b, 0x4b, 0x6d, 0x62, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77,
+0x61, 0x20, 0x68, 0x75, 0x74, 0x61, 0x6c, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67,
+0x77, 0x61, 0x20, 0x77, 0x75, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20,
+0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x64, 0x61, 0x74, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69,
+0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x74, 0x61, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69,
+0x20, 0x67, 0x77, 0x61, 0x20, 0x77, 0x75, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a,
+0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x69, 0x74, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69,
+0x20, 0x67, 0x77, 0x61, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20,
+0x67, 0x77, 0x61, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67,
+0x77, 0x61, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77,
+0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65, 0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61,
+0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x77, 0x65,
+0x64, 0x7a, 0x69, 0x20, 0x67, 0x77, 0x61, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x62, 0x69, 0x6c,
+0x69, 0x3b, 0x48, 0x3b, 0x56, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x48, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b,
+0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61,
+0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x72, 0x69, 0x6c, 0x79, 0x69, 0x3b, 0x4d, 0x65, 0x69,
+0x3b, 0x4a, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x79, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x74, 0x69,
+0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76,
+0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62,
+0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x77, 0x69, 0x3b, 0x6d, 0x25b, 0x3b, 0x7a, 0x75, 0x77, 0x3b, 0x7a, 0x75, 0x6c, 0x3b,
+0x75, 0x74, 0x69, 0x3b, 0x73, 0x25b, 0x74, 0x3b, 0x254, 0x6b, 0x75, 0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x73, 0x3b,
+0x7a, 0x61, 0x6e, 0x77, 0x75, 0x79, 0x65, 0x3b, 0x66, 0x65, 0x62, 0x75, 0x72, 0x75, 0x79, 0x65, 0x3b, 0x6d, 0x61, 0x72,
+0x69, 0x73, 0x69, 0x3b, 0x61, 0x77, 0x69, 0x72, 0x69, 0x6c, 0x69, 0x3b, 0x6d, 0x25b, 0x3b, 0x7a, 0x75, 0x77, 0x25b, 0x6e,
+0x3b, 0x7a, 0x75, 0x6c, 0x75, 0x79, 0x65, 0x3b, 0x75, 0x74, 0x69, 0x3b, 0x73, 0x25b, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x72,
+0x75, 0x3b, 0x254, 0x6b, 0x75, 0x74, 0x254, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x6e, 0x6f, 0x77, 0x61, 0x6e, 0x62, 0x75, 0x72,
+0x75, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x75, 0x3b, 0x5a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b,
+0x4d, 0x3b, 0x5a, 0x3b, 0x5a, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x186, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4d, 0x62, 0x65, 0x3b,
+0x4b, 0x61, 0x69, 0x3b, 0x4b, 0x61, 0x74, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x47, 0x61, 0x74, 0x3b, 0x47, 0x61, 0x6e, 0x3b,
+0x4d, 0x75, 0x67, 0x3b, 0x4b, 0x6e, 0x6e, 0x3b, 0x4b, 0x65, 0x6e, 0x3b, 0x49, 0x6b, 0x75, 0x3b, 0x49, 0x6d, 0x77, 0x3b,
+0x49, 0x67, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4d,
+0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x129, 0x72, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
+0x77, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x68, 0x61, 0x74, 0x169, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20,
+0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x6f,
+0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x74, 0x61, 0x74, 0x169, 0x3b,
+0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x169, 0x67, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4d, 0x77,
+0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x6e, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
+0x77, 0x61, 0x20, 0x6b, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b,
+0x169, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d, 0x69, 0x20, 0x6e,
+0x61, 0x20, 0x169, 0x6d, 0x77, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x61, 0x20, 0x69, 0x6b, 0x169, 0x6d,
+0x69, 0x20, 0x6e, 0x61, 0x20, 0x4b, 0x61, 0x129, 0x72, 0x129, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x47,
+0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x13a4, 0x13c3, 0x3b, 0x13a7, 0x13a6,
+0x3b, 0x13a0, 0x13c5, 0x3b, 0x13a7, 0x13ec, 0x3b, 0x13a0, 0x13c2, 0x3b, 0x13d5, 0x13ad, 0x3b, 0x13ab, 0x13f0, 0x3b, 0x13a6, 0x13b6, 0x3b, 0x13da,
+0x13b5, 0x3b, 0x13da, 0x13c2, 0x3b, 0x13c5, 0x13d3, 0x3b, 0x13a5, 0x13cd, 0x3b, 0x13a4, 0x13c3, 0x13b8, 0x13d4, 0x13c5, 0x3b, 0x13a7, 0x13a6, 0x13b5,
+0x3b, 0x13a0, 0x13c5, 0x13f1, 0x3b, 0x13a7, 0x13ec, 0x13c2, 0x3b, 0x13a0, 0x13c2, 0x13cd, 0x13ac, 0x13d8, 0x3b, 0x13d5, 0x13ad, 0x13b7, 0x13f1, 0x3b,
+0x13ab, 0x13f0, 0x13c9, 0x13c2, 0x3b, 0x13a6, 0x13b6, 0x13c2, 0x3b, 0x13da, 0x13b5, 0x13cd, 0x13d7, 0x3b, 0x13da, 0x13c2, 0x13c5, 0x13d7, 0x3b, 0x13c5,
+0x13d3, 0x13d5, 0x13c6, 0x3b, 0x13a5, 0x13cd, 0x13a9, 0x13f1, 0x3b, 0x13a4, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13a7, 0x3b, 0x13a0, 0x3b, 0x13d5,
+0x3b, 0x13ab, 0x3b, 0x13a6, 0x3b, 0x13da, 0x3b, 0x13da, 0x3b, 0x13c5, 0x3b, 0x13a5, 0x3b, 0x7a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x76,
+0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x76, 0x72, 0x3b, 0x6d, 0x65, 0x3b, 0x7a, 0x69, 0x6e, 0x3b, 0x7a, 0x69, 0x6c, 0x3b,
+0x6f, 0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f, 0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x76, 0x3b, 0x64, 0x65, 0x73, 0x3b,
+0x7a, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b, 0x66, 0x65, 0x76, 0x72, 0x69, 0x79, 0x65, 0x3b, 0x6d, 0x61, 0x72, 0x73, 0x3b,
+0x61, 0x76, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x65, 0x3b, 0x7a, 0x69, 0x6e, 0x3b, 0x7a, 0x69, 0x6c, 0x79, 0x65, 0x3b, 0x6f,
+0x75, 0x74, 0x3b, 0x73, 0x65, 0x70, 0x74, 0x61, 0x6d, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x3b, 0x6e, 0x6f, 0x76, 0x61,
+0x6d, 0x3b, 0x64, 0x65, 0x73, 0x61, 0x6d, 0x3b, 0x7a, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x7a, 0x3b,
+0x7a, 0x3b, 0x6f, 0x3b, 0x73, 0x3b, 0x6f, 0x3b, 0x6e, 0x3b, 0x64, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x4e, 0x74,
+0x61, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x3b, 0x4d,
+0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x54, 0x61, 0x74, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77,
+0x61, 0x20, 0x4e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e,
+0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e,
+0x6f, 0x20, 0x6e, 0x61, 0x20, 0x55, 0x6d, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e,
+0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x69, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69,
+0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x69, 0x74, 0x61, 0x74, 0x75,
0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20,
-0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x55, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61,
-0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61,
-0x20, 0x4d, 0x3b, 0x46, 0xfa, 0x6e, 0x67, 0x61, 0x74, 0x268, 0x3b, 0x4e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x65, 0x65,
-0x6e, 0x64, 0x61, 0x3b, 0x49, 0x6b, 0xfa, 0x6d, 0x69, 0x3b, 0x49, 0x6e, 0x79, 0x61, 0x6d, 0x62, 0x61, 0x6c, 0x61, 0x3b,
-0x49, 0x64, 0x77, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x4d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x56, 0x268, 0x268, 0x72,
-0x268, 0x3b, 0x53, 0x61, 0x61, 0x74, 0x289, 0x3b, 0x49, 0x6e, 0x79, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x53,
-0x61, 0x73, 0x61, 0x74, 0x289, 0x3b, 0x4b, 0x289, 0x66, 0xfa, 0x6e, 0x67, 0x61, 0x74, 0x268, 0x3b, 0x4b, 0x289, 0x6e, 0x61,
-0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x289, 0x6b, 0x65, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6b, 0x75, 0x6d,
-0x69, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e, 0x79, 0x61, 0x6d, 0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x64,
-0x77, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x4b, 0x289, 0x6d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x4b, 0x289, 0x76, 0x268,
-0x268, 0x72, 0x268, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x61, 0x74, 0x289, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e, 0x79, 0x69, 0x3b,
-0x4b, 0x289, 0x73, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x73, 0x61, 0x74, 0x289, 0x3b, 0x46, 0x3b, 0x4e,
-0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x53,
-0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x75, 0x3b, 0x4d, 0x61, 0x61,
-0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x62, 0x3b, 0x4f, 0x6b, 0x69,
-0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x77, 0x61, 0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x46,
-0x65, 0x62, 0x77, 0x61, 0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x70, 0x75, 0x6c,
-0x69, 0x3b, 0x4d, 0x61, 0x61, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x61, 0x79,
-0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x69, 0x74, 0x6f, 0x3b, 0x53, 0x65, 0x62, 0x75, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x61,
-0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65,
-0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x45, 0x70,
-0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x61, 0x3b, 0x53, 0x65,
-0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72,
-0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x72,
-0x65, 0x6f, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67,
-0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61,
-0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x46,
-0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44,
-0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69,
-0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75,
-0x3b, 0x4e, 0x75, 0x76, 0x3b, 0x44, 0x69, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x46, 0x65, 0x62, 0x72,
-0x65, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x75, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x75,
-0x3b, 0x4a, 0x75, 0x6e, 0x68, 0x75, 0x3b, 0x4a, 0x75, 0x6c, 0x68, 0x75, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b,
-0x53, 0x65, 0x74, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x72, 0x75, 0x3b, 0x4e, 0x75, 0x76, 0x65,
-0x6e, 0x62, 0x72, 0x75, 0x3b, 0x44, 0x69, 0x7a, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x4a, 0x41, 0x4e, 0x3b, 0x46, 0x45,
-0x42, 0x3b, 0x4d, 0x41, 0x43, 0x3b, 0x128, 0x50, 0x55, 0x3b, 0x4d, 0x128, 0x128, 0x3b, 0x4e, 0x4a, 0x55, 0x3b, 0x4e, 0x4a,
-0x52, 0x3b, 0x41, 0x47, 0x41, 0x3b, 0x53, 0x50, 0x54, 0x3b, 0x4f, 0x4b, 0x54, 0x3b, 0x4e, 0x4f, 0x56, 0x3b, 0x44, 0x45,
-0x43, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x72, 0x75, 0x61, 0x72, 0x129, 0x3b,
-0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x128, 0x70, 0x75, 0x72, 0x169, 0x3b, 0x4d, 0x129, 0x129, 0x3b, 0x4e, 0x6a, 0x75, 0x6e,
-0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x72, 0x61, 0x129, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74,
-0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x169, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b,
-0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x128, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b,
-0x4e, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x61, 0x74,
-0x3b, 0x54, 0x61, 0x61, 0x3b, 0x49, 0x77, 0x6f, 0x3b, 0x4d, 0x61, 0x6d, 0x3b, 0x50, 0x61, 0x61, 0x3b, 0x4e, 0x67, 0x65,
-0x3b, 0x52, 0x6f, 0x6f, 0x3b, 0x42, 0x75, 0x72, 0x3b, 0x45, 0x70, 0x65, 0x3b, 0x4b, 0x70, 0x74, 0x3b, 0x4b, 0x70, 0x61,
-0x3b, 0x4d, 0x75, 0x6c, 0x67, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x2019, 0x61, 0x74, 0x79, 0x61, 0x61, 0x74, 0x6f, 0x3b, 0x4b,
-0x69, 0x70, 0x74, 0x61, 0x61, 0x6d, 0x6f, 0x3b, 0x49, 0x77, 0x6f, 0x6f, 0x74, 0x6b, 0x75, 0x75, 0x74, 0x3b, 0x4d, 0x61,
-0x6d, 0x75, 0x75, 0x74, 0x3b, 0x50, 0x61, 0x61, 0x67, 0x69, 0x3b, 0x4e, 0x67, 0x2019, 0x65, 0x69, 0x79, 0x65, 0x65, 0x74,
-0x3b, 0x52, 0x6f, 0x6f, 0x70, 0x74, 0x75, 0x69, 0x3b, 0x42, 0x75, 0x72, 0x65, 0x65, 0x74, 0x3b, 0x45, 0x70, 0x65, 0x65,
-0x73, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x20, 0x74, 0x61, 0x61, 0x69,
-0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x62, 0x6f, 0x20, 0x61, 0x65, 0x6e, 0x67,
-0x2019, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x42, 0x3b,
-0x45, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x1c3, 0x4b, 0x68, 0x61, 0x6e, 0x6e, 0x69, 0x3b, 0x1c3, 0x4b, 0x68, 0x61, 0x6e, 0x1c0,
-0x67, 0xf4, 0x61, 0x62, 0x3b, 0x1c0, 0x4b, 0x68, 0x75, 0x75, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x1c3, 0x48, 0xf4, 0x61,
-0x1c2, 0x6b, 0x68, 0x61, 0x69, 0x62, 0x3b, 0x1c3, 0x4b, 0x68, 0x61, 0x69, 0x74, 0x73, 0xe2, 0x62, 0x3b, 0x47, 0x61, 0x6d,
-0x61, 0x1c0, 0x61, 0x65, 0x62, 0x3b, 0x1c2, 0x4b, 0x68, 0x6f, 0x65, 0x73, 0x61, 0x6f, 0x62, 0x3b, 0x41, 0x6f, 0x1c1, 0x6b,
-0x68, 0x75, 0x75, 0x6d, 0xfb, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x54, 0x61, 0x72, 0x61, 0x1c0, 0x6b, 0x68, 0x75, 0x75,
-0x6d, 0xfb, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x1c2, 0x4e, 0xfb, 0x1c1, 0x6e, 0xe2, 0x69, 0x73, 0x65, 0x62, 0x3b, 0x1c0,
-0x48, 0x6f, 0x6f, 0x1c2, 0x67, 0x61, 0x65, 0x62, 0x3b, 0x48, 0xf4, 0x61, 0x73, 0x6f, 0x72, 0x65, 0x1c1, 0x6b, 0x68, 0xe2,
-0x62, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0xe4, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x7a, 0x2e, 0x3b, 0x41, 0x70, 0x72,
-0x2e, 0x3b, 0x4d, 0xe4, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x4f, 0x75, 0x6a, 0x2e,
-0x3b, 0x53, 0xe4, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e,
-0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x65, 0x77, 0x61, 0x3b, 0x46, 0xe4, 0x62, 0x72, 0x6f, 0x77, 0x61, 0x3b, 0x4d, 0xe4, 0xe4,
-0x7a, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c, 0x6c, 0x3b, 0x4d, 0xe4, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x4a,
-0x75, 0x75, 0x6c, 0x69, 0x3b, 0x4f, 0x75, 0x6a, 0x6f, 0xdf, 0x3b, 0x53, 0x65, 0x70, 0x74, 0xe4, 0x6d, 0x62, 0x65, 0x72,
-0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44,
-0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0xe4, 0x62, 0x3b, 0x4d, 0xe4, 0x7a, 0x3b,
-0x41, 0x70, 0x72, 0x3b, 0x4d, 0xe4, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x75, 0x6a, 0x3b,
-0x53, 0xe4, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x44, 0x61, 0x6c, 0x3b,
-0x41, 0x72, 0xe1, 0x3b, 0x186, 0x25b, 0x6e, 0x3b, 0x44, 0x6f, 0x79, 0x3b, 0x4c, 0xe9, 0x70, 0x3b, 0x52, 0x6f, 0x6b, 0x3b,
-0x53, 0xe1, 0x73, 0x3b, 0x42, 0x254, 0x301, 0x72, 0x3b, 0x4b, 0xfa, 0x73, 0x3b, 0x47, 0xed, 0x73, 0x3b, 0x53, 0x68, 0x289,
-0x301, 0x3b, 0x4e, 0x74, 0x289, 0x301, 0x3b, 0x4f, 0x6c, 0x61, 0x64, 0x61, 0x6c, 0x289, 0x301, 0x3b, 0x41, 0x72, 0xe1, 0x74,
-0x3b, 0x186, 0x25b, 0x6e, 0x268, 0x301, 0x254, 0x268, 0x14b, 0x254, 0x6b, 0x3b, 0x4f, 0x6c, 0x6f, 0x64, 0x6f, 0x79, 0xed, 0xf3,
-0x72, 0xed, 0xea, 0x20, 0x69, 0x6e, 0x6b, 0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4f, 0x6c, 0x6f, 0x69, 0x6c, 0xe9, 0x70, 0x16b,
-0x6e, 0x79, 0x12b, 0x113, 0x20, 0x69, 0x6e, 0x6b, 0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4b, 0xfa, 0x6a, 0xfa, 0x254, 0x72, 0x254,
-0x6b, 0x3b, 0x4d, 0xf3, 0x72, 0x75, 0x73, 0xe1, 0x73, 0x69, 0x6e, 0x3b, 0x186, 0x6c, 0x254, 0x301, 0x268, 0x301, 0x62, 0x254,
-0x301, 0x72, 0xe1, 0x72, 0x25b, 0x3b, 0x4b, 0xfa, 0x73, 0x68, 0xee, 0x6e, 0x3b, 0x4f, 0x6c, 0x67, 0xed, 0x73, 0x61, 0x6e,
-0x3b, 0x50, 0x289, 0x73, 0x68, 0x289, 0x301, 0x6b, 0x61, 0x3b, 0x4e, 0x74, 0x289, 0x301, 0x14b, 0x289, 0x301, 0x73, 0x3b, 0x4a,
-0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a,
-0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e,
-0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41,
-0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53,
-0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x4d,
-0x75, 0x6b, 0x3b, 0x4b, 0x77, 0x61, 0x3b, 0x44, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x6f, 0x64, 0x3b, 0x4a,
-0x6f, 0x6c, 0x3b, 0x50, 0x65, 0x64, 0x3b, 0x53, 0x6f, 0x6b, 0x3b, 0x54, 0x69, 0x62, 0x3b, 0x4c, 0x61, 0x62, 0x3b, 0x50,
-0x6f, 0x6f, 0x3b, 0x4f, 0x72, 0x61, 0x72, 0x61, 0x3b, 0x4f, 0x6d, 0x75, 0x6b, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x67,
-0x2019, 0x3b, 0x4f, 0x64, 0x75, 0x6e, 0x67, 0x2019, 0x65, 0x6c, 0x3b, 0x4f, 0x6d, 0x61, 0x72, 0x75, 0x6b, 0x3b, 0x4f, 0x6d,
-0x6f, 0x64, 0x6f, 0x6b, 0x2019, 0x6b, 0x69, 0x6e, 0x67, 0x2019, 0x6f, 0x6c, 0x3b, 0x4f, 0x6a, 0x6f, 0x6c, 0x61, 0x3b, 0x4f,
-0x70, 0x65, 0x64, 0x65, 0x6c, 0x3b, 0x4f, 0x73, 0x6f, 0x6b, 0x6f, 0x73, 0x6f, 0x6b, 0x6f, 0x6d, 0x61, 0x3b, 0x4f, 0x74,
-0x69, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6c, 0x61, 0x62, 0x6f, 0x72, 0x3b, 0x4f, 0x70, 0x6f, 0x6f, 0x3b, 0x52, 0x3b, 0x4d,
-0x3b, 0x4b, 0x3b, 0x44, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x50,
-0x3b, 0x17d, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x77, 0x69, 0x3b, 0x4d, 0x65, 0x3b,
-0x17d, 0x75, 0x77, 0x3b, 0x17d, 0x75, 0x79, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e,
-0x6f, 0x6f, 0x3b, 0x44, 0x65, 0x65, 0x3b, 0x17d, 0x61, 0x6e, 0x77, 0x69, 0x79, 0x65, 0x3b, 0x46, 0x65, 0x65, 0x77, 0x69,
-0x72, 0x69, 0x79, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x69, 0x3b, 0x41, 0x77, 0x69, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65,
-0x3b, 0x17d, 0x75, 0x77, 0x65, 0x14b, 0x3b, 0x17d, 0x75, 0x79, 0x79, 0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x74,
-0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x75, 0x72, 0x3b, 0x4e, 0x6f, 0x6f, 0x77, 0x61,
-0x6e, 0x62, 0x75, 0x72, 0x3b, 0x44, 0x65, 0x65, 0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x17d, 0x3b, 0x46, 0x3b, 0x4d,
-0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x17d, 0x3b, 0x17d, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x44,
-0x41, 0x43, 0x3b, 0x44, 0x41, 0x52, 0x3b, 0x44, 0x41, 0x44, 0x3b, 0x44, 0x41, 0x4e, 0x3b, 0x44, 0x41, 0x48, 0x3b, 0x44,
-0x41, 0x55, 0x3b, 0x44, 0x41, 0x4f, 0x3b, 0x44, 0x41, 0x42, 0x3b, 0x44, 0x4f, 0x43, 0x3b, 0x44, 0x41, 0x50, 0x3b, 0x44,
-0x47, 0x49, 0x3b, 0x44, 0x41, 0x47, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x63, 0x68, 0x69, 0x65,
-0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20,
-0x6d, 0x61, 0x72, 0x20, 0x41, 0x64, 0x65, 0x6b, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x6e, 0x67,
-0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x69, 0x63, 0x68, 0x3b, 0x44,
-0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x75, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d,
-0x61, 0x72, 0x20, 0x41, 0x62, 0x69, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41,
-0x62, 0x6f, 0x72, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x4f, 0x63, 0x68, 0x69, 0x6b, 0x6f, 0x3b,
-0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x70, 0x61, 0x72, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72,
-0x20, 0x67, 0x69, 0x20, 0x61, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41,
-0x70, 0x61, 0x72, 0x20, 0x67, 0x69, 0x20, 0x61, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x43, 0x3b, 0x52, 0x3b, 0x44, 0x3b, 0x4e,
-0x3b, 0x42, 0x3b, 0x55, 0x3b, 0x42, 0x3b, 0x42, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x59, 0x65, 0x6e,
-0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x49, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e,
-0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75, 0x63, 0x3b, 0x43, 0x75, 0x74, 0x3b, 0x4b, 0x1e6d, 0x75, 0x3b, 0x4e, 0x77, 0x61,
-0x3b, 0x44, 0x75, 0x6a, 0x3b, 0x59, 0x65, 0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x59, 0x65, 0x62, 0x72, 0x61, 0x79,
-0x65, 0x72, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x49, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x79, 0x75, 0x3b,
-0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6c, 0x79, 0x75, 0x7a, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b, 0x43, 0x75,
-0x74, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x4b, 0x1e6d, 0x75, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x77, 0x61, 0x6e, 0x62, 0x69,
-0x72, 0x3b, 0x44, 0x75, 0x6a, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4d,
-0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b, 0x43, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61,
-0x6c, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x6c, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70,
-0x6c, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b,
-0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f,
-0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x91c,
-0x93e, 0x928, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e,
-0x93e, 0x930, 0x94d, 0x938, 0x3b, 0x90f, 0x92b, 0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c,
-0x941, 0x932, 0x93e, 0x907, 0x3b, 0x906, 0x917, 0x938, 0x94d, 0x925, 0x3b, 0x938, 0x947, 0x92c, 0x925, 0x947, 0x91c, 0x94d, 0x92c, 0x93c,
-0x930, 0x3b, 0x905, 0x916, 0x925, 0x92c, 0x930, 0x3b, 0x928, 0x92c, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b, 0x926, 0x93f, 0x938,
-0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b, 0x91c, 0x3b, 0x92b, 0x947, 0x3b, 0x92e, 0x93e, 0x3b, 0x90f, 0x3b, 0x92e, 0x947, 0x3b,
-0x91c, 0x941, 0x3b, 0x91c, 0x941, 0x3b, 0x906, 0x3b, 0x938, 0x947, 0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x3b, 0x44f, 0x43d,
-0x432, 0x3b, 0x444, 0x435, 0x432, 0x3b, 0x43c, 0x430, 0x440, 0x3b, 0x430, 0x43f, 0x440, 0x3b, 0x43c, 0x430, 0x439, 0x3b, 0x438, 0x44e,
-0x43d, 0x3b, 0x438, 0x44e, 0x43b, 0x3b, 0x430, 0x432, 0x433, 0x3b, 0x441, 0x435, 0x43d, 0x3b, 0x43e, 0x43a, 0x442, 0x3b, 0x43d, 0x43e,
-0x44f, 0x3b, 0x434, 0x435, 0x43a, 0x3b, 0x456, 0x486, 0x430, 0x2de9, 0x487, 0x3b, 0x444, 0x435, 0x2de1, 0x487, 0x3b, 0x43c, 0x430, 0x2dec,
-0x487, 0x3b, 0x430, 0x486, 0x43f, 0x2dec, 0x487, 0x3b, 0x43c, 0x430, 0xa675, 0x3b, 0x456, 0x486, 0xa64b, 0x2de9, 0x487, 0x3b, 0x456, 0x486,
-0xa64b, 0x2de7, 0x487, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x2de2, 0x487, 0x3b, 0x441, 0x435, 0x2deb, 0x487, 0x3b, 0x47b, 0x486, 0x43a, 0x2dee,
-0x3b, 0x43d, 0x43e, 0x435, 0x2de8, 0x3b, 0x434, 0x435, 0x2de6, 0x487, 0x3b, 0x456, 0x486, 0x430, 0x43d, 0x43d, 0xa64b, 0x430, 0x301, 0x440,
-0x457, 0x439, 0x3b, 0x444, 0x435, 0x432, 0x440, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x439, 0x3b, 0x43c, 0x430, 0x301, 0x440, 0x442, 0x44a,
-0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456, 0x301, 0x43b, 0x43b, 0x457, 0x439, 0x3b, 0x43c, 0x430, 0x301, 0x457, 0x439, 0x3b, 0x456, 0x486,
-0xa64b, 0x301, 0x43d, 0x457, 0x439, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43b, 0x457, 0x439, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x433, 0xa64b,
-0x441, 0x442, 0x44a, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x47b, 0x486, 0x43a, 0x442,
-0x461, 0x301, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x43d, 0x43e, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x434, 0x435, 0x43a,
-0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x406, 0x486, 0x3b, 0x424, 0x3b, 0x41c, 0x3b, 0x410, 0x486, 0x3b, 0x41c, 0x3b,
-0x406, 0x486, 0x3b, 0x406, 0x486, 0x3b, 0x410, 0x486, 0x3b, 0x421, 0x3b, 0x47a, 0x486, 0x3b, 0x41d, 0x3b, 0x414, 0x3b, 0x456, 0x486,
-0x430, 0x43d, 0x43d, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x430, 0x3b, 0x444, 0x435, 0x432, 0x440, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x430,
-0x3b, 0x43c, 0x430, 0x301, 0x440, 0x442, 0x430, 0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456, 0x301, 0x43b, 0x43b, 0x457, 0x430, 0x3b, 0x43c,
-0x430, 0x301, 0x457, 0x430, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43d, 0x457, 0x430, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43b, 0x457, 0x430,
-0x3b, 0x430, 0x486, 0x301, 0x475, 0x433, 0xa64b, 0x441, 0x442, 0x430, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x301, 0x43c, 0x432, 0x440,
-0x457, 0x430, 0x3b, 0x47b, 0x486, 0x43a, 0x442, 0x461, 0x301, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x43d, 0x43e, 0x435, 0x301, 0x43c, 0x432,
-0x440, 0x457, 0x430, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x43, 0x69, 0x6f, 0x3b, 0x4c,
-0x75, 0x69, 0x3b, 0x4c, 0x75, 0x73, 0x3b, 0x4d, 0x75, 0x75, 0x3b, 0x4c, 0x75, 0x6d, 0x3b, 0x4c, 0x75, 0x66, 0x3b, 0x4b,
-0x61, 0x62, 0x3b, 0x4c, 0x75, 0x73, 0x68, 0x3b, 0x4c, 0x75, 0x74, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b,
-0x43, 0x69, 0x73, 0x3b, 0x43, 0x69, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0xf9, 0x69, 0x73, 0x68, 0x69, 0x3b, 0x4c, 0x75,
-0x73, 0xf2, 0x6c, 0x6f, 0x3b, 0x4d, 0xf9, 0x75, 0x79, 0xe0, 0x3b, 0x4c, 0x75, 0x6d, 0xf9, 0x6e, 0x67, 0xf9, 0x6c, 0xf9,
-0x3b, 0x4c, 0x75, 0x66, 0x75, 0x69, 0x6d, 0x69, 0x3b, 0x4b, 0x61, 0x62, 0xe0, 0x6c, 0xe0, 0x73, 0x68, 0xec, 0x70, 0xf9,
-0x3b, 0x4c, 0xf9, 0x73, 0x68, 0xec, 0x6b, 0xe0, 0x3b, 0x4c, 0x75, 0x74, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x6f, 0x3b, 0x4c,
-0x75, 0x6e, 0x67, 0xf9, 0x64, 0x69, 0x3b, 0x4b, 0x61, 0x73, 0x77, 0xe8, 0x6b, 0xe8, 0x73, 0xe8, 0x3b, 0x43, 0x69, 0x73,
-0x77, 0xe0, 0x3b, 0x43, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x4c, 0x3b, 0x4c,
-0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x43, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0xe4, 0x65, 0x3b, 0x41,
-0x62, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x75, 0x67, 0x3b, 0x53,
-0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61,
-0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x65, 0x72, 0x7a, 0x3b, 0x41, 0x62, 0x72, 0xeb,
-0x6c, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67,
-0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x65,
-0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b,
-0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x65, 0x2e, 0x3b, 0x41, 0x62, 0x72, 0x2e, 0x3b,
-0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41, 0x75, 0x67, 0x2e, 0x3b, 0x53,
-0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x6e,
-0xf9, 0x6d, 0x3b, 0x6b, 0x268, 0x7a, 0x3b, 0x74, 0x268, 0x64, 0x3b, 0x74, 0x61, 0x61, 0x3b, 0x73, 0x65, 0x65, 0x3b, 0x6e,
-0x7a, 0x75, 0x3b, 0x64, 0x75, 0x6d, 0x3b, 0x66, 0x254, 0x65, 0x3b, 0x64, 0x7a, 0x75, 0x3b, 0x6c, 0x254, 0x6d, 0x3b, 0x6b,
-0x61, 0x61, 0x3b, 0x66, 0x77, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6e, 0xf9, 0x6d, 0x3b, 0x6e,
-0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6b, 0x197, 0x300, 0x7a, 0xf9, 0x294, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b,
-0x254, 0x300, 0x74, 0x197, 0x300, 0x64, 0x289, 0x300, 0x67, 0x68, 0xe0, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300,
-0x74, 0x1ce, 0x61, 0x66, 0x289, 0x304, 0x67, 0x68, 0x101, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0xe8, 0x73, 0xe8, 0x65,
-0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6e, 0x7a, 0xf9, 0x67, 0x68, 0xf2, 0x3b, 0x6e, 0x64, 0x7a, 0x254,
-0x300, 0x14b, 0x254, 0x300, 0x64, 0xf9, 0x6d, 0x6c, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6b, 0x77,
-0xee, 0x66, 0x254, 0x300, 0x65, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x74, 0x197, 0x300, 0x66, 0x289, 0x300,
-0x67, 0x68, 0xe0, 0x64, 0x7a, 0x75, 0x67, 0x68, 0xf9, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x67, 0x68,
-0x1d4, 0x75, 0x77, 0x65, 0x6c, 0x254, 0x300, 0x6d, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x63, 0x68, 0x77,
-0x61, 0x294, 0xe0, 0x6b, 0x61, 0x61, 0x20, 0x77, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0xe8, 0x66, 0x77, 0xf2,
-0x6f, 0x3b, 0x6e, 0x3b, 0x6b, 0x3b, 0x74, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x6b, 0x3b, 0x66, 0x3b, 0x64, 0x3b,
-0x6c, 0x3b, 0x63, 0x3b, 0x66, 0x3b, 0x6b, 0x254, 0x6e, 0x3b, 0x6d, 0x61, 0x63, 0x3b, 0x6d, 0x61, 0x74, 0x3b, 0x6d, 0x74,
-0x6f, 0x3b, 0x6d, 0x70, 0x75, 0x3b, 0x68, 0x69, 0x6c, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x68, 0x69, 0x6b, 0x3b, 0x64, 0x69,
-0x70, 0x3b, 0x62, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6c, 0x69, 0x253, 0x3b, 0x4b, 0x254, 0x6e, 0x64, 0x254, 0x14b,
-0x3b, 0x4d, 0xe0, 0x63, 0x25b, 0x302, 0x6c, 0x3b, 0x4d, 0xe0, 0x74, 0xf9, 0x6d, 0x62, 0x3b, 0x4d, 0xe0, 0x74, 0x6f, 0x70,
-0x3b, 0x4d, 0x300, 0x70, 0x75, 0x79, 0x25b, 0x3b, 0x48, 0xec, 0x6c, 0xf2, 0x6e, 0x64, 0x25b, 0x300, 0x3b, 0x4e, 0x6a, 0xe8,
-0x62, 0xe0, 0x3b, 0x48, 0xec, 0x6b, 0x61, 0x14b, 0x3b, 0x44, 0xec, 0x70, 0x254, 0x300, 0x73, 0x3b, 0x42, 0xec, 0xf2, 0xf4,
-0x6d, 0x3b, 0x4d, 0xe0, 0x79, 0x25b, 0x73, 0xe8, 0x70, 0x3b, 0x4c, 0xec, 0x62, 0x75, 0x79, 0x20, 0x6c, 0x69, 0x20, 0x144,
-0x79, 0xe8, 0x65, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x68, 0x3b, 0x6e, 0x3b, 0x68, 0x3b,
-0x64, 0x3b, 0x62, 0x3b, 0x6d, 0x3b, 0x6c, 0x3b, 0x64, 0x69, 0x3b, 0x14b, 0x67, 0x254, 0x6e, 0x3b, 0x73, 0x254, 0x14b, 0x3b,
-0x64, 0x69, 0x253, 0x3b, 0x65, 0x6d, 0x69, 0x3b, 0x65, 0x73, 0x254, 0x3b, 0x6d, 0x61, 0x64, 0x3b, 0x64, 0x69, 0x14b, 0x3b,
-0x6e, 0x79, 0x25b, 0x74, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x74, 0x69, 0x6e, 0x3b, 0x65, 0x6c, 0xe1, 0x3b, 0x64, 0x69, 0x6d,
-0x254, 0x301, 0x64, 0x69, 0x3b, 0x14b, 0x67, 0x254, 0x6e, 0x64, 0x25b, 0x3b, 0x73, 0x254, 0x14b, 0x25b, 0x3b, 0x64, 0x69, 0x253,
-0xe1, 0x253, 0xe1, 0x3b, 0x65, 0x6d, 0x69, 0x61, 0x73, 0x65, 0x6c, 0x65, 0x3b, 0x65, 0x73, 0x254, 0x70, 0x25b, 0x73, 0x254,
-0x70, 0x25b, 0x3b, 0x6d, 0x61, 0x64, 0x69, 0x253, 0x25b, 0x301, 0x64, 0xed, 0x253, 0x25b, 0x301, 0x3b, 0x64, 0x69, 0x14b, 0x67,
-0x69, 0x6e, 0x64, 0x69, 0x3b, 0x6e, 0x79, 0x25b, 0x74, 0x25b, 0x6b, 0x69, 0x3b, 0x6d, 0x61, 0x79, 0xe9, 0x73, 0x25b, 0x301,
-0x3b, 0x74, 0x69, 0x6e, 0xed, 0x6e, 0xed, 0x3b, 0x65, 0x6c, 0xe1, 0x14b, 0x67, 0x25b, 0x301, 0x3b, 0x64, 0x3b, 0x14b, 0x3b,
-0x73, 0x3b, 0x64, 0x3b, 0x65, 0x3b, 0x65, 0x3b, 0x6d, 0x3b, 0x64, 0x3b, 0x6e, 0x3b, 0x6d, 0x3b, 0x74, 0x3b, 0x65, 0x3b,
-0x53, 0x61, 0x3b, 0x46, 0x65, 0x3b, 0x4d, 0x61, 0x3b, 0x41, 0x62, 0x3b, 0x4d, 0x65, 0x3b, 0x53, 0x75, 0x3b, 0x53, 0xfa,
-0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x3b, 0x4f, 0x6b, 0x3b, 0x4e, 0x6f, 0x3b, 0x44, 0x65, 0x3b, 0x53, 0x61, 0x6e, 0x76,
-0x69, 0x65, 0x3b, 0x46, 0xe9, 0x62, 0x69, 0x72, 0x69, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x73, 0x3b, 0x41, 0x62, 0x75, 0x72,
-0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x53, 0x75, 0x65, 0x14b, 0x3b, 0x53, 0xfa, 0x75, 0x79, 0x65, 0x65, 0x3b, 0x55,
-0x74, 0x3b, 0x53, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x72, 0x3b,
-0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x53, 0x3b,
-0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b,
-0x44, 0x3b, 0x6e, 0x67, 0x6f, 0x3b, 0x6e, 0x67, 0x62, 0x3b, 0x6e, 0x67, 0x6c, 0x3b, 0x6e, 0x67, 0x6e, 0x3b, 0x6e, 0x67,
-0x74, 0x3b, 0x6e, 0x67, 0x73, 0x3b, 0x6e, 0x67, 0x7a, 0x3b, 0x6e, 0x67, 0x6d, 0x3b, 0x6e, 0x67, 0x65, 0x3b, 0x6e, 0x67,
-0x61, 0x3b, 0x6e, 0x67, 0x61, 0x64, 0x3b, 0x6e, 0x67, 0x61, 0x62, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6f, 0x73, 0xfa,
-0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x62, 0x25b, 0x30c, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6c, 0xe1, 0x6c, 0x61, 0x3b,
-0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6e, 0x79, 0x69, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x74, 0xe1, 0x6e, 0x61,
-0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x73, 0x61, 0x6d, 0x259, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x7a, 0x61,
-0x6d, 0x67, 0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6d, 0x77, 0x6f, 0x6d, 0x3b, 0x6e, 0x67, 0x254,
-0x6e, 0x20, 0x65, 0x62, 0x75, 0x6c, 0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x3b, 0x6e, 0x67,
-0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x20, 0x61, 0x69, 0x20, 0x64, 0x7a, 0x69, 0xe1, 0x3b, 0x6e, 0x67, 0x254, 0x6e,
-0x20, 0x61, 0x77, 0xf3, 0x6d, 0x20, 0x61, 0x69, 0x20, 0x62, 0x25b, 0x30c, 0x3b, 0x6f, 0x3b, 0x62, 0x3b, 0x6c, 0x3b, 0x6e,
-0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x61, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x14b, 0x31, 0x3b,
-0x14b, 0x32, 0x3b, 0x14b, 0x33, 0x3b, 0x14b, 0x34, 0x3b, 0x14b, 0x35, 0x3b, 0x14b, 0x36, 0x3b, 0x14b, 0x37, 0x3b, 0x14b, 0x38,
-0x3b, 0x14b, 0x39, 0x3b, 0x14b, 0x31, 0x30, 0x3b, 0x14b, 0x31, 0x31, 0x3b, 0x14b, 0x31, 0x32, 0x3b, 0x14b, 0x77, 0xed, 0xed,
-0x20, 0x61, 0x20, 0x6e, 0x74, 0x254, 0x301, 0x6e, 0x74, 0x254, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20,
-0x62, 0x25b, 0x301, 0x25b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x72, 0xe1, 0xe1, 0x3b, 0x14b, 0x77,
-0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20,
-0x74, 0xe1, 0x61, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x66, 0x254, 0x6b,
-0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x62, 0x25b, 0x25b, 0x3b, 0x14b, 0x77, 0xed,
-0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x72, 0x61, 0x61, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b,
-0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x6e, 0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74,
-0x25b, 0x6b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x20, 0x64, 0x69, 0x20,
-0x62, 0x254, 0x301, 0x6b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x20, 0x64,
-0x69, 0x20, 0x62, 0x25b, 0x301, 0x25b, 0x3b, 0x4b, 0x77, 0x61, 0x3b, 0x55, 0x6e, 0x61, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x43,
-0x68, 0x65, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x4d, 0x6f, 0x63, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61, 0x6e, 0x3b, 0x54,
-0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d, 0x3b, 0x4d, 0x6f, 0x6a, 0x3b, 0x59, 0x65, 0x6c, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69,
-0x20, 0x77, 0x6f, 0x20, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20,
-0x75, 0x6e, 0x61, 0x79, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x65,
-0x72, 0x61, 0x72, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x65, 0x63, 0x68, 0x65,
-0x73, 0x68, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x65, 0x74, 0x68, 0x61, 0x6e,
-0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x75, 0x20, 0x6e, 0x61, 0x20,
-0x6d, 0x6f, 0x63, 0x68, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x73, 0x61, 0x62, 0x61, 0x3b,
-0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20,
-0x77, 0x6f, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d,
-0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x6d,
-0x6f, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x20, 0x6e, 0x61,
-0x20, 0x79, 0x65, 0x6c, 0x2019, 0x6c, 0x69, 0x3b, 0x4b, 0x3b, 0x55, 0x3b, 0x52, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4d, 0x3b,
-0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x46, 0x4c, 0x4f, 0x3b, 0x43, 0x4c, 0x41, 0x3b,
-0x43, 0x4b, 0x49, 0x3b, 0x46, 0x4d, 0x46, 0x3b, 0x4d, 0x41, 0x44, 0x3b, 0x4d, 0x42, 0x49, 0x3b, 0x4d, 0x4c, 0x49, 0x3b,
-0x4d, 0x41, 0x4d, 0x3b, 0x46, 0x44, 0x45, 0x3b, 0x46, 0x4d, 0x55, 0x3b, 0x46, 0x47, 0x57, 0x3b, 0x46, 0x59, 0x55, 0x3b,
-0x46, 0x129, 0x69, 0x20, 0x4c, 0x6f, 0x6f, 0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61, 0x6b, 0x6c, 0x61, 0x14b, 0x6e, 0x65,
-0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61, 0x6b, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4d, 0x61, 0x72, 0x66,
-0x6f, 0x6f, 0x3b, 0x4d, 0x61, 0x64, 0x1dd, 0x1dd, 0x75, 0x75, 0x74, 0x1dd, 0x62, 0x69, 0x6a, 0x61, 0x14b, 0x3b, 0x4d, 0x61,
-0x6d, 0x1dd, 0x14b, 0x67, 0x77, 0xe3, 0x61, 0x66, 0x61, 0x68, 0x62, 0x69, 0x69, 0x3b, 0x4d, 0x61, 0x6d, 0x1dd, 0x14b, 0x67,
-0x77, 0xe3, 0x61, 0x6c, 0x69, 0x69, 0x3b, 0x4d, 0x61, 0x64, 0x1dd, 0x6d, 0x62, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20,
-0x44, 0x1dd, 0x253, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4d, 0x75, 0x6e, 0x64, 0x61, 0x14b, 0x3b, 0x46, 0x129,
-0x69, 0x20, 0x47, 0x77, 0x61, 0x68, 0x6c, 0x6c, 0x65, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x59, 0x75, 0x72, 0x75, 0x3b, 0x4f,
-0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x55, 0x3b, 0x57,
-0x3b, 0x59, 0x3b, 0x6e, 0x67, 0x31, 0x3b, 0x6e, 0x67, 0x32, 0x3b, 0x6e, 0x67, 0x33, 0x3b, 0x6e, 0x67, 0x34, 0x3b, 0x6e,
-0x67, 0x35, 0x3b, 0x6e, 0x67, 0x36, 0x3b, 0x6e, 0x67, 0x37, 0x3b, 0x6e, 0x67, 0x38, 0x3b, 0x6e, 0x67, 0x39, 0x3b, 0x6e,
-0x67, 0x31, 0x30, 0x3b, 0x6e, 0x67, 0x31, 0x31, 0x3b, 0x6b, 0x72, 0x69, 0x73, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20,
-0x6d, 0x61, 0x74, 0xe1, 0x68, 0x72, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6d, 0x62, 0x61, 0x3b, 0x6e,
-0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6c, 0x61, 0x6c, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6e, 0x61, 0x3b,
-0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x74, 0x61, 0x6e, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x74, 0x75,
-0xf3, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x68, 0x25b, 0x6d, 0x62, 0x75, 0x25b, 0x72, 0xed, 0x3b, 0x6e, 0x67, 0x77,
-0x25b, 0x6e, 0x20, 0x6c, 0x254, 0x6d, 0x62, 0x69, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x72, 0x25b, 0x62, 0x76, 0x75,
-0xe2, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x77, 0x75, 0x6d, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x77, 0x75,
-0x6d, 0x20, 0x6e, 0x61, 0x76, 0x1d4, 0x72, 0x3b, 0x6b, 0x72, 0xed, 0x73, 0x69, 0x6d, 0x69, 0x6e, 0x3b, 0x54, 0x69, 0x6f,
-0x70, 0x3b, 0x50, 0x25b, 0x74, 0x3b, 0x44, 0x75, 0x254, 0x331, 0x254, 0x331, 0x3b, 0x47, 0x75, 0x61, 0x6b, 0x3b, 0x44, 0x75,
-0xe4, 0x3b, 0x4b, 0x6f, 0x72, 0x3b, 0x50, 0x61, 0x79, 0x3b, 0x54, 0x68, 0x6f, 0x6f, 0x3b, 0x54, 0x25b, 0x25b, 0x3b, 0x4c,
-0x61, 0x61, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x54, 0x69, 0x64, 0x3b, 0x54, 0x69, 0x6f, 0x70, 0x20, 0x74, 0x68, 0x61, 0x72,
-0x20, 0x70, 0x25b, 0x74, 0x3b, 0x50, 0x25b, 0x74, 0x3b, 0x44, 0x75, 0x254, 0x331, 0x254, 0x331, 0x14b, 0x3b, 0x47, 0x75, 0x61,
-0x6b, 0x3b, 0x44, 0x75, 0xe4, 0x74, 0x3b, 0x4b, 0x6f, 0x72, 0x6e, 0x79, 0x6f, 0x6f, 0x74, 0x3b, 0x50, 0x61, 0x79, 0x20,
-0x79, 0x69, 0x65, 0x331, 0x74, 0x6e, 0x69, 0x3b, 0x54, 0x68, 0x6f, 0x331, 0x6f, 0x331, 0x72, 0x3b, 0x54, 0x25b, 0x25b, 0x72,
-0x3b, 0x4c, 0x61, 0x61, 0x74, 0x68, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x54, 0x69, 0x6f, 0x331, 0x70, 0x20, 0x69, 0x6e, 0x20,
-0x64, 0x69, 0x331, 0x69, 0x331, 0x74, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x4b, 0x3b, 0x50,
-0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x422, 0x43e, 0x445, 0x441, 0x3b, 0x41e, 0x43b, 0x443, 0x43d,
-0x3b, 0x41a, 0x43b, 0x43d, 0x5f, 0x442, 0x442, 0x440, 0x3b, 0x41c, 0x443, 0x441, 0x5f, 0x443, 0x441, 0x442, 0x3b, 0x42b, 0x430, 0x43c,
-0x5f, 0x439, 0x43d, 0x3b, 0x411, 0x44d, 0x441, 0x5f, 0x439, 0x43d, 0x3b, 0x41e, 0x442, 0x5f, 0x439, 0x43d, 0x3b, 0x410, 0x442, 0x440,
-0x434, 0x44c, 0x5f, 0x439, 0x43d, 0x3b, 0x411, 0x43b, 0x495, 0x43d, 0x5f, 0x439, 0x43d, 0x3b, 0x410, 0x43b, 0x442, 0x3b, 0x421, 0x44d,
-0x442, 0x3b, 0x410, 0x445, 0x441, 0x3b, 0x422, 0x43e, 0x445, 0x441, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x41e, 0x43b, 0x443, 0x43d,
+0x4e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79,
+0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20,
+0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20,
+0x6e, 0x61, 0x20, 0x55, 0x3b, 0x4d, 0x77, 0x65, 0x64, 0x69, 0x20, 0x77, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f,
+0x20, 0x6e, 0x61, 0x20, 0x4e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x4d, 0x3b, 0x46, 0xfa, 0x6e, 0x67,
+0x61, 0x74, 0x268, 0x3b, 0x4e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x65, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x49, 0x6b, 0xfa,
+0x6d, 0x69, 0x3b, 0x49, 0x6e, 0x79, 0x61, 0x6d, 0x62, 0x61, 0x6c, 0x61, 0x3b, 0x49, 0x64, 0x77, 0x61, 0x61, 0x74, 0x61,
+0x3b, 0x4d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x56, 0x268, 0x268, 0x72, 0x268, 0x3b, 0x53, 0x61, 0x61, 0x74, 0x289,
+0x3b, 0x49, 0x6e, 0x79, 0x69, 0x3b, 0x53, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x53, 0x61, 0x73, 0x61, 0x74, 0x289, 0x3b, 0x4b,
+0x289, 0x66, 0xfa, 0x6e, 0x67, 0x61, 0x74, 0x268, 0x3b, 0x4b, 0x289, 0x6e, 0x61, 0x61, 0x6e, 0x268, 0x3b, 0x4b, 0x289, 0x6b,
+0x65, 0x65, 0x6e, 0x64, 0x61, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e,
+0x79, 0x61, 0x6d, 0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x64, 0x77, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x4b,
+0x289, 0x6d, 0x289, 0x289, 0x6e, 0x63, 0x68, 0x268, 0x3b, 0x4b, 0x289, 0x76, 0x268, 0x268, 0x72, 0x268, 0x3b, 0x4b, 0x289, 0x73,
+0x61, 0x61, 0x74, 0x289, 0x3b, 0x4b, 0x77, 0x69, 0x69, 0x6e, 0x79, 0x69, 0x3b, 0x4b, 0x289, 0x73, 0x61, 0x61, 0x6e, 0x6f,
+0x3b, 0x4b, 0x289, 0x73, 0x61, 0x73, 0x61, 0x74, 0x289, 0x3b, 0x46, 0x3b, 0x4e, 0x3b, 0x4b, 0x3b, 0x49, 0x3b, 0x49, 0x3b,
+0x49, 0x3b, 0x4d, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65,
+0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x75, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x75, 0x3b, 0x4a, 0x75,
+0x6c, 0x3b, 0x41, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x62, 0x3b, 0x4f, 0x6b, 0x69, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65,
+0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x77, 0x61, 0x6c, 0x69, 0x79, 0x6f, 0x3b, 0x46, 0x65, 0x62, 0x77, 0x61, 0x6c, 0x69, 0x79,
+0x6f, 0x3b, 0x4d, 0x61, 0x72, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x70, 0x75, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x61, 0x79, 0x69,
+0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x61, 0x79, 0x69, 0x3b, 0x41, 0x67, 0x75, 0x73, 0x69,
+0x74, 0x6f, 0x3b, 0x53, 0x65, 0x62, 0x75, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x69, 0x74, 0x6f, 0x62,
+0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a,
+0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x45, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a,
+0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x67, 0x61, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e,
+0x6f, 0x76, 0x3b, 0x44, 0x69, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75,
+0x61, 0x72, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x45, 0x70, 0x72, 0x65, 0x6f, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
+0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x4f, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65,
+0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62,
+0x61, 0x3b, 0x44, 0x69, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x4d, 0x3b,
+0x4a, 0x3b, 0x4a, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65,
+0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75,
+0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x74, 0x75, 0x3b, 0x4e, 0x75, 0x76, 0x3b, 0x44, 0x69,
+0x7a, 0x3b, 0x4a, 0x61, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x4d, 0x61, 0x72,
+0x73, 0x75, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x75, 0x3b, 0x4a, 0x75, 0x6e, 0x68, 0x75, 0x3b,
+0x4a, 0x75, 0x6c, 0x68, 0x75, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x53, 0x65, 0x74, 0x65, 0x6e, 0x62, 0x72,
+0x75, 0x3b, 0x4f, 0x74, 0x75, 0x62, 0x72, 0x75, 0x3b, 0x4e, 0x75, 0x76, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x44, 0x69,
+0x7a, 0x65, 0x6e, 0x62, 0x72, 0x75, 0x3b, 0x4a, 0x41, 0x4e, 0x3b, 0x46, 0x45, 0x42, 0x3b, 0x4d, 0x41, 0x43, 0x3b, 0x128,
+0x50, 0x55, 0x3b, 0x4d, 0x128, 0x128, 0x3b, 0x4e, 0x4a, 0x55, 0x3b, 0x4e, 0x4a, 0x52, 0x3b, 0x41, 0x47, 0x41, 0x3b, 0x53,
+0x50, 0x54, 0x3b, 0x4f, 0x4b, 0x54, 0x3b, 0x4e, 0x4f, 0x56, 0x3b, 0x44, 0x45, 0x43, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61,
+0x72, 0x129, 0x3b, 0x46, 0x65, 0x62, 0x75, 0x72, 0x75, 0x61, 0x72, 0x129, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x128,
+0x70, 0x75, 0x72, 0x169, 0x3b, 0x4d, 0x129, 0x129, 0x3b, 0x4e, 0x6a, 0x75, 0x6e, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x72, 0x61,
+0x129, 0x3b, 0x41, 0x67, 0x61, 0x73, 0x74, 0x69, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b,
+0x74, 0x169, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x44, 0x69, 0x63, 0x65, 0x6d, 0x62, 0x61,
+0x3b, 0x4a, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x128, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f,
+0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x4e, 0x67, 0x61, 0x74, 0x3b, 0x54, 0x61, 0x61, 0x3b, 0x49, 0x77,
+0x6f, 0x3b, 0x4d, 0x61, 0x6d, 0x3b, 0x50, 0x61, 0x61, 0x3b, 0x4e, 0x67, 0x65, 0x3b, 0x52, 0x6f, 0x6f, 0x3b, 0x42, 0x75,
+0x72, 0x3b, 0x45, 0x70, 0x65, 0x3b, 0x4b, 0x70, 0x74, 0x3b, 0x4b, 0x70, 0x61, 0x3b, 0x4d, 0x75, 0x6c, 0x67, 0x75, 0x6c,
+0x3b, 0x4e, 0x67, 0x2019, 0x61, 0x74, 0x79, 0x61, 0x61, 0x74, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x74, 0x61, 0x61, 0x6d, 0x6f,
+0x3b, 0x49, 0x77, 0x6f, 0x6f, 0x74, 0x6b, 0x75, 0x75, 0x74, 0x3b, 0x4d, 0x61, 0x6d, 0x75, 0x75, 0x74, 0x3b, 0x50, 0x61,
+0x61, 0x67, 0x69, 0x3b, 0x4e, 0x67, 0x2019, 0x65, 0x69, 0x79, 0x65, 0x65, 0x74, 0x3b, 0x52, 0x6f, 0x6f, 0x70, 0x74, 0x75,
+0x69, 0x3b, 0x42, 0x75, 0x72, 0x65, 0x65, 0x74, 0x3b, 0x45, 0x70, 0x65, 0x65, 0x73, 0x6f, 0x3b, 0x4b, 0x69, 0x70, 0x73,
+0x75, 0x75, 0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x20, 0x74, 0x61, 0x61, 0x69, 0x3b, 0x4b, 0x69, 0x70, 0x73, 0x75, 0x75,
+0x6e, 0x64, 0x65, 0x20, 0x6e, 0x65, 0x62, 0x6f, 0x20, 0x61, 0x65, 0x6e, 0x67, 0x2019, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x54,
+0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x50, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x42, 0x3b, 0x45, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x1c3,
+0x4b, 0x68, 0x61, 0x6e, 0x6e, 0x69, 0x3b, 0x1c3, 0x4b, 0x68, 0x61, 0x6e, 0x1c0, 0x67, 0xf4, 0x61, 0x62, 0x3b, 0x1c0, 0x4b,
+0x68, 0x75, 0x75, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x1c3, 0x48, 0xf4, 0x61, 0x1c2, 0x6b, 0x68, 0x61, 0x69, 0x62, 0x3b,
+0x1c3, 0x4b, 0x68, 0x61, 0x69, 0x74, 0x73, 0xe2, 0x62, 0x3b, 0x47, 0x61, 0x6d, 0x61, 0x1c0, 0x61, 0x65, 0x62, 0x3b, 0x1c2,
+0x4b, 0x68, 0x6f, 0x65, 0x73, 0x61, 0x6f, 0x62, 0x3b, 0x41, 0x6f, 0x1c1, 0x6b, 0x68, 0x75, 0x75, 0x6d, 0xfb, 0x1c1, 0x6b,
+0x68, 0xe2, 0x62, 0x3b, 0x54, 0x61, 0x72, 0x61, 0x1c0, 0x6b, 0x68, 0x75, 0x75, 0x6d, 0xfb, 0x1c1, 0x6b, 0x68, 0xe2, 0x62,
+0x3b, 0x1c2, 0x4e, 0xfb, 0x1c1, 0x6e, 0xe2, 0x69, 0x73, 0x65, 0x62, 0x3b, 0x1c0, 0x48, 0x6f, 0x6f, 0x1c2, 0x67, 0x61, 0x65,
+0x62, 0x3b, 0x48, 0xf4, 0x61, 0x73, 0x6f, 0x72, 0x65, 0x1c1, 0x6b, 0x68, 0xe2, 0x62, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b,
+0x46, 0xe4, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x7a, 0x2e, 0x3b, 0x41, 0x70, 0x72, 0x2e, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a,
+0x75, 0x6e, 0x2e, 0x3b, 0x4a, 0x75, 0x6c, 0x2e, 0x3b, 0x4f, 0x75, 0x6a, 0x2e, 0x3b, 0x53, 0xe4, 0x70, 0x2e, 0x3b, 0x4f,
+0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44, 0x65, 0x7a, 0x2e, 0x3b, 0x4a, 0x61, 0x6e, 0x6e, 0x65, 0x77,
+0x61, 0x3b, 0x46, 0xe4, 0x62, 0x72, 0x6f, 0x77, 0x61, 0x3b, 0x4d, 0xe4, 0xe4, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x65, 0x6c,
+0x6c, 0x3b, 0x4d, 0x61, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x75, 0x6c, 0x69, 0x3b, 0x4f, 0x75,
+0x6a, 0x6f, 0xdf, 0x3b, 0x53, 0x65, 0x70, 0x74, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x68, 0x62,
+0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0xe4, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0xe4, 0x6d, 0x62, 0x65, 0x72,
+0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0xe4, 0x62, 0x3b, 0x4d, 0xe4, 0x7a, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x61, 0x69,
+0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x4f, 0x75, 0x6a, 0x3b, 0x53, 0xe4, 0x70, 0x3b, 0x4f, 0x6b, 0x74,
+0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b, 0x44, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0xe1, 0x3b, 0x186, 0x25b, 0x6e,
+0x3b, 0x44, 0x6f, 0x79, 0x3b, 0x4c, 0xe9, 0x70, 0x3b, 0x52, 0x6f, 0x6b, 0x3b, 0x53, 0xe1, 0x73, 0x3b, 0x42, 0x254, 0x301,
+0x72, 0x3b, 0x4b, 0xfa, 0x73, 0x3b, 0x47, 0xed, 0x73, 0x3b, 0x53, 0x68, 0x289, 0x301, 0x3b, 0x4e, 0x74, 0x289, 0x301, 0x3b,
+0x4f, 0x6c, 0x61, 0x64, 0x61, 0x6c, 0x289, 0x301, 0x3b, 0x41, 0x72, 0xe1, 0x74, 0x3b, 0x186, 0x25b, 0x6e, 0x268, 0x301, 0x254,
+0x268, 0x14b, 0x254, 0x6b, 0x3b, 0x4f, 0x6c, 0x6f, 0x64, 0x6f, 0x79, 0xed, 0xf3, 0x72, 0xed, 0xea, 0x20, 0x69, 0x6e, 0x6b,
+0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4f, 0x6c, 0x6f, 0x69, 0x6c, 0xe9, 0x70, 0x16b, 0x6e, 0x79, 0x12b, 0x113, 0x20, 0x69, 0x6e,
+0x6b, 0xf3, 0x6b, 0xfa, 0xe2, 0x3b, 0x4b, 0xfa, 0x6a, 0xfa, 0x254, 0x72, 0x254, 0x6b, 0x3b, 0x4d, 0xf3, 0x72, 0x75, 0x73,
+0xe1, 0x73, 0x69, 0x6e, 0x3b, 0x186, 0x6c, 0x254, 0x301, 0x268, 0x301, 0x62, 0x254, 0x301, 0x72, 0xe1, 0x72, 0x25b, 0x3b, 0x4b,
+0xfa, 0x73, 0x68, 0xee, 0x6e, 0x3b, 0x4f, 0x6c, 0x67, 0xed, 0x73, 0x61, 0x6e, 0x3b, 0x50, 0x289, 0x73, 0x68, 0x289, 0x301,
+0x6b, 0x61, 0x3b, 0x4e, 0x74, 0x289, 0x301, 0x14b, 0x289, 0x301, 0x73, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
+0x4d, 0x61, 0x72, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
+0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x73, 0x3b,
+0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x63, 0x3b, 0x41, 0x70, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b,
+0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b,
+0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x63, 0x3b, 0x52, 0x61, 0x72, 0x3b, 0x4d, 0x75, 0x6b, 0x3b, 0x4b, 0x77, 0x61, 0x3b,
+0x44, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x6f, 0x64, 0x3b, 0x4a, 0x6f, 0x6c, 0x3b, 0x50, 0x65, 0x64, 0x3b,
+0x53, 0x6f, 0x6b, 0x3b, 0x54, 0x69, 0x62, 0x3b, 0x4c, 0x61, 0x62, 0x3b, 0x50, 0x6f, 0x6f, 0x3b, 0x4f, 0x72, 0x61, 0x72,
+0x61, 0x3b, 0x4f, 0x6d, 0x75, 0x6b, 0x3b, 0x4f, 0x6b, 0x77, 0x61, 0x6d, 0x67, 0x2019, 0x3b, 0x4f, 0x64, 0x75, 0x6e, 0x67,
+0x2019, 0x65, 0x6c, 0x3b, 0x4f, 0x6d, 0x61, 0x72, 0x75, 0x6b, 0x3b, 0x4f, 0x6d, 0x6f, 0x64, 0x6f, 0x6b, 0x2019, 0x6b, 0x69,
+0x6e, 0x67, 0x2019, 0x6f, 0x6c, 0x3b, 0x4f, 0x6a, 0x6f, 0x6c, 0x61, 0x3b, 0x4f, 0x70, 0x65, 0x64, 0x65, 0x6c, 0x3b, 0x4f,
+0x73, 0x6f, 0x6b, 0x6f, 0x73, 0x6f, 0x6b, 0x6f, 0x6d, 0x61, 0x3b, 0x4f, 0x74, 0x69, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6c,
+0x61, 0x62, 0x6f, 0x72, 0x3b, 0x4f, 0x70, 0x6f, 0x6f, 0x3b, 0x52, 0x3b, 0x4d, 0x3b, 0x4b, 0x3b, 0x44, 0x3b, 0x4d, 0x3b,
+0x4d, 0x3b, 0x4a, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x50, 0x3b, 0x17d, 0x61, 0x6e, 0x3b, 0x46, 0x65,
+0x65, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x77, 0x69, 0x3b, 0x4d, 0x65, 0x3b, 0x17d, 0x75, 0x77, 0x3b, 0x17d, 0x75, 0x79,
+0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x6f, 0x3b, 0x44, 0x65, 0x65, 0x3b,
+0x17d, 0x61, 0x6e, 0x77, 0x69, 0x79, 0x65, 0x3b, 0x46, 0x65, 0x65, 0x77, 0x69, 0x72, 0x69, 0x79, 0x65, 0x3b, 0x4d, 0x61,
+0x72, 0x73, 0x69, 0x3b, 0x41, 0x77, 0x69, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x3b, 0x17d, 0x75, 0x77, 0x65, 0x14b, 0x3b,
+0x17d, 0x75, 0x79, 0x79, 0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x6b, 0x74, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x4f,
+0x6b, 0x74, 0x6f, 0x6f, 0x62, 0x75, 0x72, 0x3b, 0x4e, 0x6f, 0x6f, 0x77, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x44, 0x65,
+0x65, 0x73, 0x61, 0x6e, 0x62, 0x75, 0x72, 0x3b, 0x17d, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x17d, 0x3b,
+0x17d, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x44, 0x41, 0x43, 0x3b, 0x44, 0x41, 0x52, 0x3b,
+0x44, 0x41, 0x44, 0x3b, 0x44, 0x41, 0x4e, 0x3b, 0x44, 0x41, 0x48, 0x3b, 0x44, 0x41, 0x55, 0x3b, 0x44, 0x41, 0x4f, 0x3b,
+0x44, 0x41, 0x42, 0x3b, 0x44, 0x4f, 0x43, 0x3b, 0x44, 0x41, 0x50, 0x3b, 0x44, 0x47, 0x49, 0x3b, 0x44, 0x41, 0x47, 0x3b,
+0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d,
+0x61, 0x72, 0x20, 0x41, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x64, 0x65,
+0x6b, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x6e, 0x67, 0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x44, 0x77,
+0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x69, 0x63, 0x68, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20,
+0x41, 0x75, 0x63, 0x68, 0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x69, 0x72,
+0x69, 0x79, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x62, 0x6f, 0x72, 0x6f, 0x3b, 0x44, 0x77,
+0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x4f, 0x63, 0x68, 0x69, 0x6b, 0x6f, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72,
+0x20, 0x41, 0x70, 0x61, 0x72, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x67, 0x69, 0x20, 0x61, 0x63, 0x68,
+0x69, 0x65, 0x6c, 0x3b, 0x44, 0x77, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x20, 0x41, 0x70, 0x61, 0x72, 0x20, 0x67, 0x69, 0x20,
+0x61, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x43, 0x3b, 0x52, 0x3b, 0x44, 0x3b, 0x4e, 0x3b, 0x42, 0x3b, 0x55, 0x3b, 0x42, 0x3b,
+0x42, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x59, 0x65, 0x6e, 0x3b, 0x59, 0x65, 0x62, 0x3b, 0x4d, 0x61,
+0x72, 0x3b, 0x49, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x59, 0x75, 0x6e, 0x3b, 0x59, 0x75, 0x6c, 0x3b, 0x194, 0x75,
+0x63, 0x3b, 0x43, 0x75, 0x74, 0x3b, 0x4b, 0x1e6d, 0x75, 0x3b, 0x4e, 0x77, 0x61, 0x3b, 0x44, 0x75, 0x6a, 0x3b, 0x59, 0x65,
+0x6e, 0x6e, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x59, 0x65, 0x62, 0x72, 0x61, 0x79, 0x65, 0x72, 0x3b, 0x4d, 0x61, 0x72, 0x73,
+0x3b, 0x49, 0x62, 0x72, 0x69, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x79, 0x75, 0x3b, 0x59, 0x75, 0x6e, 0x79, 0x75, 0x3b, 0x59,
+0x75, 0x6c, 0x79, 0x75, 0x7a, 0x3b, 0x194, 0x75, 0x63, 0x74, 0x3b, 0x43, 0x75, 0x74, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b,
+0x4b, 0x1e6d, 0x75, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x77, 0x61, 0x6e, 0x62, 0x69, 0x72, 0x3b, 0x44, 0x75, 0x6a, 0x61, 0x6e,
+0x62, 0x69, 0x72, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x59, 0x3b, 0x194, 0x3b,
+0x43, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x4a, 0x61, 0x6e, 0x75, 0x61, 0x6c, 0x69, 0x3b, 0x46, 0x65, 0x62, 0x6c,
+0x75, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x61, 0x63, 0x68, 0x69, 0x3b, 0x41, 0x70, 0x6c, 0x69, 0x6c, 0x69, 0x3b, 0x4d, 0x65,
+0x69, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x61, 0x69, 0x3b, 0x41, 0x67, 0x6f, 0x73, 0x74, 0x69, 0x3b,
+0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x4f, 0x6b, 0x74, 0x6f, 0x62, 0x61, 0x3b, 0x4e, 0x6f, 0x76, 0x65,
+0x6d, 0x62, 0x61, 0x3b, 0x44, 0x65, 0x73, 0x65, 0x6d, 0x62, 0x61, 0x3b, 0x91c, 0x93e, 0x928, 0x941, 0x935, 0x93e, 0x930, 0x940,
+0x3b, 0x92b, 0x947, 0x92c, 0x94d, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x940, 0x3b, 0x92e, 0x93e, 0x930, 0x94d, 0x938, 0x3b, 0x90f, 0x92b,
+0x94d, 0x930, 0x93f, 0x932, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x928, 0x3b, 0x91c, 0x941, 0x932, 0x93e, 0x907, 0x3b, 0x906, 0x917,
+0x938, 0x94d, 0x925, 0x3b, 0x938, 0x947, 0x92c, 0x925, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b, 0x905, 0x916, 0x925, 0x92c, 0x930,
+0x3b, 0x928, 0x92c, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b, 0x926, 0x93f, 0x938, 0x947, 0x91c, 0x94d, 0x92c, 0x93c, 0x930, 0x3b,
+0x91c, 0x3b, 0x92b, 0x947, 0x3b, 0x92e, 0x93e, 0x3b, 0x90f, 0x3b, 0x92e, 0x947, 0x3b, 0x91c, 0x941, 0x3b, 0x91c, 0x941, 0x3b, 0x906,
+0x3b, 0x938, 0x947, 0x3b, 0x905, 0x3b, 0x928, 0x3b, 0x926, 0x93f, 0x3b, 0x456, 0x486, 0x430, 0x2de9, 0x487, 0x3b, 0x444, 0x435, 0x2de1,
+0x487, 0x3b, 0x43c, 0x430, 0x2dec, 0x487, 0x3b, 0x430, 0x486, 0x43f, 0x2dec, 0x487, 0x3b, 0x43c, 0x430, 0xa675, 0x3b, 0x456, 0x486, 0xa64b,
+0x2de9, 0x487, 0x3b, 0x456, 0x486, 0xa64b, 0x2de7, 0x487, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x2de2, 0x487, 0x3b, 0x441, 0x435, 0x2deb, 0x487,
+0x3b, 0x47b, 0x486, 0x43a, 0x2dee, 0x3b, 0x43d, 0x43e, 0x435, 0x2de8, 0x3b, 0x434, 0x435, 0x2de6, 0x487, 0x3b, 0x456, 0x486, 0x430, 0x43d,
+0x43d, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x439, 0x3b, 0x444, 0x435, 0x432, 0x440, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x439, 0x3b, 0x43c,
+0x430, 0x301, 0x440, 0x442, 0x44a, 0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456, 0x301, 0x43b, 0x43b, 0x457, 0x439, 0x3b, 0x43c, 0x430, 0x301,
+0x457, 0x439, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43d, 0x457, 0x439, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43b, 0x457, 0x439, 0x3b, 0x430,
+0x486, 0x301, 0x475, 0x433, 0xa64b, 0x441, 0x442, 0x44a, 0x3b, 0x441, 0x435, 0x43f, 0x442, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439,
+0x3b, 0x47b, 0x486, 0x43a, 0x442, 0x461, 0x301, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x43d, 0x43e, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457,
+0x439, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x439, 0x3b, 0x406, 0x486, 0x3b, 0x424, 0x3b, 0x41c, 0x3b,
+0x410, 0x486, 0x3b, 0x41c, 0x3b, 0x406, 0x486, 0x3b, 0x406, 0x486, 0x3b, 0x410, 0x486, 0x3b, 0x421, 0x3b, 0x47a, 0x486, 0x3b, 0x41d,
+0x3b, 0x414, 0x3b, 0x456, 0x486, 0x430, 0x43d, 0x43d, 0xa64b, 0x430, 0x301, 0x440, 0x457, 0x430, 0x3b, 0x444, 0x435, 0x432, 0x440, 0xa64b,
+0x430, 0x301, 0x440, 0x457, 0x430, 0x3b, 0x43c, 0x430, 0x301, 0x440, 0x442, 0x430, 0x3b, 0x430, 0x486, 0x43f, 0x440, 0x456, 0x301, 0x43b,
+0x43b, 0x457, 0x430, 0x3b, 0x43c, 0x430, 0x301, 0x457, 0x430, 0x3b, 0x456, 0x486, 0xa64b, 0x301, 0x43d, 0x457, 0x430, 0x3b, 0x456, 0x486,
+0xa64b, 0x301, 0x43b, 0x457, 0x430, 0x3b, 0x430, 0x486, 0x301, 0x475, 0x433, 0xa64b, 0x441, 0x442, 0x430, 0x3b, 0x441, 0x435, 0x43f, 0x442,
+0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x47b, 0x486, 0x43a, 0x442, 0x461, 0x301, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x43d,
+0x43e, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b, 0x434, 0x435, 0x43a, 0x435, 0x301, 0x43c, 0x432, 0x440, 0x457, 0x430, 0x3b,
+0x43, 0x69, 0x6f, 0x3b, 0x4c, 0x75, 0x69, 0x3b, 0x4c, 0x75, 0x73, 0x3b, 0x4d, 0x75, 0x75, 0x3b, 0x4c, 0x75, 0x6d, 0x3b,
+0x4c, 0x75, 0x66, 0x3b, 0x4b, 0x61, 0x62, 0x3b, 0x4c, 0x75, 0x73, 0x68, 0x3b, 0x4c, 0x75, 0x74, 0x3b, 0x4c, 0x75, 0x6e,
+0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x43, 0x69, 0x73, 0x3b, 0x43, 0x69, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0xf9, 0x69, 0x73,
+0x68, 0x69, 0x3b, 0x4c, 0x75, 0x73, 0xf2, 0x6c, 0x6f, 0x3b, 0x4d, 0xf9, 0x75, 0x79, 0xe0, 0x3b, 0x4c, 0x75, 0x6d, 0xf9,
+0x6e, 0x67, 0xf9, 0x6c, 0xf9, 0x3b, 0x4c, 0x75, 0x66, 0x75, 0x69, 0x6d, 0x69, 0x3b, 0x4b, 0x61, 0x62, 0xe0, 0x6c, 0xe0,
+0x73, 0x68, 0xec, 0x70, 0xf9, 0x3b, 0x4c, 0xf9, 0x73, 0x68, 0xec, 0x6b, 0xe0, 0x3b, 0x4c, 0x75, 0x74, 0x6f, 0x6e, 0x67,
+0x6f, 0x6c, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x67, 0xf9, 0x64, 0x69, 0x3b, 0x4b, 0x61, 0x73, 0x77, 0xe8, 0x6b, 0xe8, 0x73,
+0xe8, 0x3b, 0x43, 0x69, 0x73, 0x77, 0xe0, 0x3b, 0x43, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b,
+0x4b, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x43, 0x3b, 0x4a, 0x61, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b,
+0x4d, 0xe4, 0x65, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x3b, 0x4a, 0x75, 0x6c, 0x3b,
+0x41, 0x75, 0x67, 0x3b, 0x53, 0x65, 0x70, 0x3b, 0x4f, 0x6b, 0x74, 0x3b, 0x4e, 0x6f, 0x76, 0x3b, 0x44, 0x65, 0x7a, 0x3b,
+0x4a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x46, 0x65, 0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x4d, 0xe4, 0x65, 0x72, 0x7a,
+0x3b, 0x41, 0x62, 0x72, 0xeb, 0x6c, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c,
+0x69, 0x3b, 0x41, 0x75, 0x67, 0x75, 0x73, 0x74, 0x3b, 0x53, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4f,
+0x6b, 0x74, 0x6f, 0x62, 0x65, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x3b, 0x44, 0x65, 0x7a, 0x65,
+0x6d, 0x62, 0x65, 0x72, 0x3b, 0x4a, 0x61, 0x6e, 0x2e, 0x3b, 0x46, 0x65, 0x62, 0x2e, 0x3b, 0x4d, 0xe4, 0x65, 0x2e, 0x3b,
+0x41, 0x62, 0x72, 0x2e, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x4a, 0x75, 0x6e, 0x69, 0x3b, 0x4a, 0x75, 0x6c, 0x69, 0x3b, 0x41,
+0x75, 0x67, 0x2e, 0x3b, 0x53, 0x65, 0x70, 0x2e, 0x3b, 0x4f, 0x6b, 0x74, 0x2e, 0x3b, 0x4e, 0x6f, 0x76, 0x2e, 0x3b, 0x44,
+0x65, 0x7a, 0x2e, 0x3b, 0x6e, 0xf9, 0x6d, 0x3b, 0x6b, 0x268, 0x7a, 0x3b, 0x74, 0x268, 0x64, 0x3b, 0x74, 0x61, 0x61, 0x3b,
+0x73, 0x65, 0x65, 0x3b, 0x6e, 0x7a, 0x75, 0x3b, 0x64, 0x75, 0x6d, 0x3b, 0x66, 0x254, 0x65, 0x3b, 0x64, 0x7a, 0x75, 0x3b,
+0x6c, 0x254, 0x6d, 0x3b, 0x6b, 0x61, 0x61, 0x3b, 0x66, 0x77, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300,
+0x6e, 0xf9, 0x6d, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6b, 0x197, 0x300, 0x7a, 0xf9, 0x294, 0x3b, 0x6e,
+0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x74, 0x197, 0x300, 0x64, 0x289, 0x300, 0x67, 0x68, 0xe0, 0x3b, 0x6e, 0x64, 0x7a,
+0x254, 0x300, 0x14b, 0x254, 0x300, 0x74, 0x1ce, 0x61, 0x66, 0x289, 0x304, 0x67, 0x68, 0x101, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300,
+0x14b, 0xe8, 0x73, 0xe8, 0x65, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x6e, 0x7a, 0xf9, 0x67, 0x68, 0xf2,
+0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x64, 0xf9, 0x6d, 0x6c, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300,
+0x14b, 0x254, 0x300, 0x6b, 0x77, 0xee, 0x66, 0x254, 0x300, 0x65, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b, 0x254, 0x300, 0x74,
+0x197, 0x300, 0x66, 0x289, 0x300, 0x67, 0x68, 0xe0, 0x64, 0x7a, 0x75, 0x67, 0x68, 0xf9, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300,
+0x14b, 0x254, 0x300, 0x67, 0x68, 0x1d4, 0x75, 0x77, 0x65, 0x6c, 0x254, 0x300, 0x6d, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300, 0x14b,
+0x254, 0x300, 0x63, 0x68, 0x77, 0x61, 0x294, 0xe0, 0x6b, 0x61, 0x61, 0x20, 0x77, 0x6f, 0x3b, 0x6e, 0x64, 0x7a, 0x254, 0x300,
+0x14b, 0xe8, 0x66, 0x77, 0xf2, 0x6f, 0x3b, 0x6e, 0x3b, 0x6b, 0x3b, 0x74, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x6b,
+0x3b, 0x66, 0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x63, 0x3b, 0x66, 0x3b, 0x6b, 0x254, 0x6e, 0x3b, 0x6d, 0x61, 0x63, 0x3b, 0x6d,
+0x61, 0x74, 0x3b, 0x6d, 0x74, 0x6f, 0x3b, 0x6d, 0x70, 0x75, 0x3b, 0x68, 0x69, 0x6c, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x68,
+0x69, 0x6b, 0x3b, 0x64, 0x69, 0x70, 0x3b, 0x62, 0x69, 0x6f, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x6c, 0x69, 0x253, 0x3b, 0x4b,
+0x254, 0x6e, 0x64, 0x254, 0x14b, 0x3b, 0x4d, 0xe0, 0x63, 0x25b, 0x302, 0x6c, 0x3b, 0x4d, 0xe0, 0x74, 0xf9, 0x6d, 0x62, 0x3b,
+0x4d, 0xe0, 0x74, 0x6f, 0x70, 0x3b, 0x4d, 0x300, 0x70, 0x75, 0x79, 0x25b, 0x3b, 0x48, 0xec, 0x6c, 0xf2, 0x6e, 0x64, 0x25b,
+0x300, 0x3b, 0x4e, 0x6a, 0xe8, 0x62, 0xe0, 0x3b, 0x48, 0xec, 0x6b, 0x61, 0x14b, 0x3b, 0x44, 0xec, 0x70, 0x254, 0x300, 0x73,
+0x3b, 0x42, 0xec, 0xf2, 0xf4, 0x6d, 0x3b, 0x4d, 0xe0, 0x79, 0x25b, 0x73, 0xe8, 0x70, 0x3b, 0x4c, 0xec, 0x62, 0x75, 0x79,
+0x20, 0x6c, 0x69, 0x20, 0x144, 0x79, 0xe8, 0x65, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x68,
+0x3b, 0x6e, 0x3b, 0x68, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x6d, 0x3b, 0x6c, 0x3b, 0x64, 0x69, 0x3b, 0x14b, 0x67, 0x254, 0x6e,
+0x3b, 0x73, 0x254, 0x14b, 0x3b, 0x64, 0x69, 0x253, 0x3b, 0x65, 0x6d, 0x69, 0x3b, 0x65, 0x73, 0x254, 0x3b, 0x6d, 0x61, 0x64,
+0x3b, 0x64, 0x69, 0x14b, 0x3b, 0x6e, 0x79, 0x25b, 0x74, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x74, 0x69, 0x6e, 0x3b, 0x65, 0x6c,
+0xe1, 0x3b, 0x64, 0x69, 0x6d, 0x254, 0x301, 0x64, 0x69, 0x3b, 0x14b, 0x67, 0x254, 0x6e, 0x64, 0x25b, 0x3b, 0x73, 0x254, 0x14b,
+0x25b, 0x3b, 0x64, 0x69, 0x253, 0xe1, 0x253, 0xe1, 0x3b, 0x65, 0x6d, 0x69, 0x61, 0x73, 0x65, 0x6c, 0x65, 0x3b, 0x65, 0x73,
+0x254, 0x70, 0x25b, 0x73, 0x254, 0x70, 0x25b, 0x3b, 0x6d, 0x61, 0x64, 0x69, 0x253, 0x25b, 0x301, 0x64, 0xed, 0x253, 0x25b, 0x301,
+0x3b, 0x64, 0x69, 0x14b, 0x67, 0x69, 0x6e, 0x64, 0x69, 0x3b, 0x6e, 0x79, 0x25b, 0x74, 0x25b, 0x6b, 0x69, 0x3b, 0x6d, 0x61,
+0x79, 0xe9, 0x73, 0x25b, 0x301, 0x3b, 0x74, 0x69, 0x6e, 0xed, 0x6e, 0xed, 0x3b, 0x65, 0x6c, 0xe1, 0x14b, 0x67, 0x25b, 0x301,
+0x3b, 0x64, 0x3b, 0x14b, 0x3b, 0x73, 0x3b, 0x64, 0x3b, 0x65, 0x3b, 0x65, 0x3b, 0x6d, 0x3b, 0x64, 0x3b, 0x6e, 0x3b, 0x6d,
+0x3b, 0x74, 0x3b, 0x65, 0x3b, 0x53, 0x61, 0x3b, 0x46, 0x65, 0x3b, 0x4d, 0x61, 0x3b, 0x41, 0x62, 0x3b, 0x4d, 0x65, 0x3b,
+0x53, 0x75, 0x3b, 0x53, 0xfa, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x3b, 0x4f, 0x6b, 0x3b, 0x4e, 0x6f, 0x3b, 0x44, 0x65,
+0x3b, 0x53, 0x61, 0x6e, 0x76, 0x69, 0x65, 0x3b, 0x46, 0xe9, 0x62, 0x69, 0x72, 0x69, 0x65, 0x3b, 0x4d, 0x61, 0x72, 0x73,
+0x3b, 0x41, 0x62, 0x75, 0x72, 0x69, 0x6c, 0x3b, 0x4d, 0x65, 0x65, 0x3b, 0x53, 0x75, 0x65, 0x14b, 0x3b, 0x53, 0xfa, 0x75,
+0x79, 0x65, 0x65, 0x3b, 0x55, 0x74, 0x3b, 0x53, 0x65, 0x74, 0x74, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x4f, 0x6b, 0x74,
+0x6f, 0x62, 0x61, 0x72, 0x3b, 0x4e, 0x6f, 0x76, 0x65, 0x6d, 0x62, 0x61, 0x72, 0x3b, 0x44, 0x69, 0x73, 0x61, 0x6d, 0x62,
+0x61, 0x72, 0x3b, 0x53, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x55, 0x3b, 0x53,
+0x3b, 0x4f, 0x3b, 0x4e, 0x3b, 0x44, 0x3b, 0x6e, 0x67, 0x6f, 0x3b, 0x6e, 0x67, 0x62, 0x3b, 0x6e, 0x67, 0x6c, 0x3b, 0x6e,
+0x67, 0x6e, 0x3b, 0x6e, 0x67, 0x74, 0x3b, 0x6e, 0x67, 0x73, 0x3b, 0x6e, 0x67, 0x7a, 0x3b, 0x6e, 0x67, 0x6d, 0x3b, 0x6e,
+0x67, 0x65, 0x3b, 0x6e, 0x67, 0x61, 0x3b, 0x6e, 0x67, 0x61, 0x64, 0x3b, 0x6e, 0x67, 0x61, 0x62, 0x3b, 0x6e, 0x67, 0x254,
+0x6e, 0x20, 0x6f, 0x73, 0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x62, 0x25b, 0x30c, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20,
+0x6c, 0xe1, 0x6c, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6e, 0x79, 0x69, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e,
+0x20, 0x74, 0xe1, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x73, 0x61, 0x6d, 0x259, 0x6e, 0x61, 0x3b, 0x6e, 0x67,
+0x254, 0x6e, 0x20, 0x7a, 0x61, 0x6d, 0x67, 0x62, 0xe1, 0x6c, 0x61, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x6d, 0x77, 0x6f,
+0x6d, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x65, 0x62, 0x75, 0x6c, 0xfa, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77,
+0xf3, 0x6d, 0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x20, 0x61, 0x69, 0x20, 0x64, 0x7a, 0x69, 0xe1,
+0x3b, 0x6e, 0x67, 0x254, 0x6e, 0x20, 0x61, 0x77, 0xf3, 0x6d, 0x20, 0x61, 0x69, 0x20, 0x62, 0x25b, 0x30c, 0x3b, 0x6f, 0x3b,
+0x62, 0x3b, 0x6c, 0x3b, 0x6e, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x7a, 0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x61, 0x3b, 0x64, 0x3b,
+0x62, 0x3b, 0x14b, 0x31, 0x3b, 0x14b, 0x32, 0x3b, 0x14b, 0x33, 0x3b, 0x14b, 0x34, 0x3b, 0x14b, 0x35, 0x3b, 0x14b, 0x36, 0x3b,
+0x14b, 0x37, 0x3b, 0x14b, 0x38, 0x3b, 0x14b, 0x39, 0x3b, 0x14b, 0x31, 0x30, 0x3b, 0x14b, 0x31, 0x31, 0x3b, 0x14b, 0x31, 0x32,
+0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x20, 0x6e, 0x74, 0x254, 0x301, 0x6e, 0x74, 0x254, 0x3b, 0x14b, 0x77, 0xed, 0xed,
+0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x62, 0x25b, 0x301, 0x25b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x72,
+0xe1, 0xe1, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed,
+0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74,
+0xe1, 0x61, 0x66, 0x254, 0x6b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x62, 0x25b,
+0x25b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x72, 0x61, 0x61, 0x3b, 0x14b, 0x77,
+0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x74, 0xe1, 0x61, 0x6e, 0x69, 0x6e, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61,
+0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b, 0x6b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e, 0x74, 0x25b,
+0x6b, 0x20, 0x64, 0x69, 0x20, 0x62, 0x254, 0x301, 0x6b, 0x3b, 0x14b, 0x77, 0xed, 0xed, 0x20, 0x61, 0x6b, 0x1dd, 0x20, 0x6e,
+0x74, 0x25b, 0x6b, 0x20, 0x64, 0x69, 0x20, 0x62, 0x25b, 0x301, 0x25b, 0x3b, 0x4b, 0x77, 0x61, 0x3b, 0x55, 0x6e, 0x61, 0x3b,
+0x52, 0x61, 0x72, 0x3b, 0x43, 0x68, 0x65, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x4d, 0x6f, 0x63, 0x3b, 0x53, 0x61, 0x62, 0x3b,
+0x4e, 0x61, 0x6e, 0x3b, 0x54, 0x69, 0x73, 0x3b, 0x4b, 0x75, 0x6d, 0x3b, 0x4d, 0x6f, 0x6a, 0x3b, 0x59, 0x65, 0x6c, 0x3b,
+0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72,
+0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e, 0x61, 0x79, 0x65, 0x6c, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
+0x6f, 0x20, 0x75, 0x6e, 0x65, 0x72, 0x61, 0x72, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75,
+0x6e, 0x65, 0x63, 0x68, 0x65, 0x73, 0x68, 0x65, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x75, 0x6e,
+0x65, 0x74, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x74, 0x68, 0x61, 0x6e,
+0x75, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x63, 0x68, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20,
+0x73, 0x61, 0x62, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6e, 0x61, 0x6e, 0x65, 0x3b, 0x4d,
+0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x74, 0x69, 0x73, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77,
+0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75, 0x6d, 0x69,
+0x20, 0x6e, 0x61, 0x20, 0x6d, 0x6f, 0x6a, 0x61, 0x3b, 0x4d, 0x77, 0x65, 0x72, 0x69, 0x20, 0x77, 0x6f, 0x20, 0x6b, 0x75,
+0x6d, 0x69, 0x20, 0x6e, 0x61, 0x20, 0x79, 0x65, 0x6c, 0x2019, 0x6c, 0x69, 0x3b, 0x4b, 0x3b, 0x55, 0x3b, 0x52, 0x3b, 0x43,
+0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x59, 0x3b, 0x46, 0x4c, 0x4f,
+0x3b, 0x43, 0x4c, 0x41, 0x3b, 0x43, 0x4b, 0x49, 0x3b, 0x46, 0x4d, 0x46, 0x3b, 0x4d, 0x41, 0x44, 0x3b, 0x4d, 0x42, 0x49,
+0x3b, 0x4d, 0x4c, 0x49, 0x3b, 0x4d, 0x41, 0x4d, 0x3b, 0x46, 0x44, 0x45, 0x3b, 0x46, 0x4d, 0x55, 0x3b, 0x46, 0x47, 0x57,
+0x3b, 0x46, 0x59, 0x55, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4c, 0x6f, 0x6f, 0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61, 0x6b,
+0x6c, 0x61, 0x14b, 0x6e, 0x65, 0x3b, 0x43, 0x6f, 0x6b, 0x63, 0x77, 0x61, 0x6b, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69,
+0x20, 0x4d, 0x61, 0x72, 0x66, 0x6f, 0x6f, 0x3b, 0x4d, 0x61, 0x64, 0x1dd, 0x1dd, 0x75, 0x75, 0x74, 0x1dd, 0x62, 0x69, 0x6a,
+0x61, 0x14b, 0x3b, 0x4d, 0x61, 0x6d, 0x1dd, 0x14b, 0x67, 0x77, 0xe3, 0x61, 0x66, 0x61, 0x68, 0x62, 0x69, 0x69, 0x3b, 0x4d,
+0x61, 0x6d, 0x1dd, 0x14b, 0x67, 0x77, 0xe3, 0x61, 0x6c, 0x69, 0x69, 0x3b, 0x4d, 0x61, 0x64, 0x1dd, 0x6d, 0x62, 0x69, 0x69,
+0x3b, 0x46, 0x129, 0x69, 0x20, 0x44, 0x1dd, 0x253, 0x6c, 0x69, 0x69, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x4d, 0x75, 0x6e, 0x64,
+0x61, 0x14b, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x47, 0x77, 0x61, 0x68, 0x6c, 0x6c, 0x65, 0x3b, 0x46, 0x129, 0x69, 0x20, 0x59,
+0x75, 0x72, 0x75, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x46, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b,
+0x45, 0x3b, 0x55, 0x3b, 0x57, 0x3b, 0x59, 0x3b, 0x6e, 0x67, 0x31, 0x3b, 0x6e, 0x67, 0x32, 0x3b, 0x6e, 0x67, 0x33, 0x3b,
+0x6e, 0x67, 0x34, 0x3b, 0x6e, 0x67, 0x35, 0x3b, 0x6e, 0x67, 0x36, 0x3b, 0x6e, 0x67, 0x37, 0x3b, 0x6e, 0x67, 0x38, 0x3b,
+0x6e, 0x67, 0x39, 0x3b, 0x6e, 0x67, 0x31, 0x30, 0x3b, 0x6e, 0x67, 0x31, 0x31, 0x3b, 0x6b, 0x72, 0x69, 0x73, 0x3b, 0x6e,
+0x67, 0x77, 0x25b, 0x6e, 0x20, 0x6d, 0x61, 0x74, 0xe1, 0x68, 0x72, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144,
+0x6d, 0x62, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x6c, 0x61, 0x6c, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e,
+0x20, 0x144, 0x6e, 0x61, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x144, 0x74, 0x61, 0x6e, 0x3b, 0x6e, 0x67, 0x77, 0x25b,
+0x6e, 0x20, 0x144, 0x74, 0x75, 0xf3, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x68, 0x25b, 0x6d, 0x62, 0x75, 0x25b, 0x72,
+0xed, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x6c, 0x254, 0x6d, 0x62, 0x69, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20,
+0x72, 0x25b, 0x62, 0x76, 0x75, 0xe2, 0x3b, 0x6e, 0x67, 0x77, 0x25b, 0x6e, 0x20, 0x77, 0x75, 0x6d, 0x3b, 0x6e, 0x67, 0x77,
+0x25b, 0x6e, 0x20, 0x77, 0x75, 0x6d, 0x20, 0x6e, 0x61, 0x76, 0x1d4, 0x72, 0x3b, 0x6b, 0x72, 0xed, 0x73, 0x69, 0x6d, 0x69,
+0x6e, 0x3b, 0x54, 0x69, 0x6f, 0x70, 0x3b, 0x50, 0x25b, 0x74, 0x3b, 0x44, 0x75, 0x254, 0x331, 0x254, 0x331, 0x3b, 0x47, 0x75,
+0x61, 0x6b, 0x3b, 0x44, 0x75, 0xe4, 0x3b, 0x4b, 0x6f, 0x72, 0x3b, 0x50, 0x61, 0x79, 0x3b, 0x54, 0x68, 0x6f, 0x6f, 0x3b,
+0x54, 0x25b, 0x25b, 0x3b, 0x4c, 0x61, 0x61, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x54, 0x69, 0x64, 0x3b, 0x54, 0x69, 0x6f, 0x70,
+0x20, 0x74, 0x68, 0x61, 0x72, 0x20, 0x70, 0x25b, 0x74, 0x3b, 0x50, 0x25b, 0x74, 0x3b, 0x44, 0x75, 0x254, 0x331, 0x254, 0x331,
+0x14b, 0x3b, 0x47, 0x75, 0x61, 0x6b, 0x3b, 0x44, 0x75, 0xe4, 0x74, 0x3b, 0x4b, 0x6f, 0x72, 0x6e, 0x79, 0x6f, 0x6f, 0x74,
+0x3b, 0x50, 0x61, 0x79, 0x20, 0x79, 0x69, 0x65, 0x331, 0x74, 0x6e, 0x69, 0x3b, 0x54, 0x68, 0x6f, 0x331, 0x6f, 0x331, 0x72,
+0x3b, 0x54, 0x25b, 0x25b, 0x72, 0x3b, 0x4c, 0x61, 0x61, 0x74, 0x68, 0x3b, 0x4b, 0x75, 0x72, 0x3b, 0x54, 0x69, 0x6f, 0x331,
+0x70, 0x20, 0x69, 0x6e, 0x20, 0x64, 0x69, 0x331, 0x69, 0x331, 0x74, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x44, 0x3b, 0x47, 0x3b,
+0x44, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x422, 0x43e, 0x445, 0x441,
+0x3b, 0x41e, 0x43b, 0x443, 0x43d, 0x3b, 0x41a, 0x43b, 0x43d, 0x3b, 0x41c, 0x441, 0x443, 0x3b, 0x42b, 0x430, 0x43c, 0x3b, 0x411, 0x44d,
+0x441, 0x3b, 0x41e, 0x442, 0x439, 0x3b, 0x410, 0x442, 0x440, 0x3b, 0x411, 0x43b, 0x495, 0x3b, 0x410, 0x43b, 0x442, 0x3b, 0x421, 0x44d,
+0x442, 0x3b, 0x410, 0x445, 0x441, 0x3b, 0x442, 0x43e, 0x445, 0x441, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x43e, 0x43b, 0x443, 0x43d,
+0x43d, 0x44c, 0x443, 0x3b, 0x43a, 0x443, 0x43b, 0x443, 0x43d, 0x20, 0x442, 0x443, 0x442, 0x430, 0x440, 0x3b, 0x43c, 0x443, 0x443, 0x441,
+0x20, 0x443, 0x441, 0x442, 0x430, 0x440, 0x3b, 0x44b, 0x430, 0x43c, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x431, 0x44d, 0x441, 0x20, 0x44b,
+0x439, 0x430, 0x3b, 0x43e, 0x442, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x430, 0x442, 0x44b, 0x440, 0x434, 0x44c, 0x44b, 0x445, 0x20, 0x44b,
+0x439, 0x430, 0x3b, 0x431, 0x430, 0x43b, 0x430, 0x495, 0x430, 0x43d, 0x20, 0x44b, 0x439, 0x430, 0x3b, 0x430, 0x43b, 0x442, 0x44b, 0x43d,
+0x43d, 0x44c, 0x44b, 0x3b, 0x441, 0x44d, 0x442, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x3b, 0x430, 0x445, 0x441, 0x44b, 0x43d, 0x43d, 0x44c,
+0x44b, 0x3b, 0x422, 0x3b, 0x41e, 0x3b, 0x41a, 0x3b, 0x41c, 0x3b, 0x42b, 0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x410, 0x3b, 0x411, 0x3b,
+0x410, 0x3b, 0x421, 0x3b, 0x410, 0x3b, 0x422, 0x43e, 0x445, 0x441, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x3b, 0x41e, 0x43b, 0x443, 0x43d,
0x43d, 0x44c, 0x443, 0x3b, 0x41a, 0x443, 0x43b, 0x443, 0x43d, 0x20, 0x442, 0x443, 0x442, 0x430, 0x440, 0x3b, 0x41c, 0x443, 0x443, 0x441,
0x20, 0x443, 0x441, 0x442, 0x430, 0x440, 0x3b, 0x42b, 0x430, 0x43c, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x411, 0x44d, 0x441, 0x20,
0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x41e, 0x442, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x410, 0x442, 0x44b, 0x440, 0x434, 0x44c, 0x44b,
0x445, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b, 0x411, 0x430, 0x43b, 0x430, 0x495, 0x430, 0x43d, 0x20, 0x44b, 0x439, 0x44b, 0x43d, 0x3b,
-0x410, 0x43b, 0x442, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x421, 0x44d, 0x442, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x3b, 0x410, 0x445,
-0x441, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x422, 0x3b, 0x41e, 0x3b, 0x41a, 0x3b, 0x41c, 0x3b, 0x42b, 0x3b, 0x411, 0x3b, 0x41e,
-0x3b, 0x410, 0x3b, 0x411, 0x3b, 0x410, 0x3b, 0x421, 0x3b, 0x410, 0x3b, 0x4d, 0x75, 0x70, 0x3b, 0x4d, 0x77, 0x69, 0x3b, 0x4d,
-0x73, 0x68, 0x3b, 0x4d, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x67, 0x3b, 0x4d, 0x75, 0x6a, 0x3b, 0x4d, 0x73, 0x70, 0x3b, 0x4d,
-0x70, 0x67, 0x3b, 0x4d, 0x79, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x3b, 0x4d, 0x75, 0x73, 0x3b, 0x4d, 0x75, 0x68, 0x3b, 0x4d,
-0x75, 0x70, 0x61, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x6c, 0x77, 0x61, 0x3b, 0x4d, 0x77, 0x69, 0x74, 0x6f, 0x70, 0x65, 0x3b,
-0x4d, 0x75, 0x73, 0x68, 0x65, 0x6e, 0x64, 0x65, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4d, 0x75, 0x73, 0x68, 0x65,
-0x6e, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x67, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x75, 0x6a, 0x69, 0x6d, 0x62, 0x69, 0x3b, 0x4d,
-0x75, 0x73, 0x68, 0x69, 0x70, 0x65, 0x70, 0x6f, 0x3b, 0x4d, 0x75, 0x70, 0x75, 0x67, 0x75, 0x74, 0x6f, 0x3b, 0x4d, 0x75,
-0x6e, 0x79, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x68, 0x75, 0x3b, 0x4d, 0x75, 0x73, 0x6f, 0x6e, 0x67, 0x61,
-0x6e, 0x64, 0x65, 0x6d, 0x62, 0x77, 0x65, 0x3b, 0x4d, 0x75, 0x68, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0xa5a8, 0xa56a, 0xa583, 0x20,
-0xa51e, 0xa56e, 0x3b, 0xa552, 0xa561, 0xa59d, 0xa595, 0x3b, 0xa57e, 0xa5ba, 0x3b, 0xa5a2, 0xa595, 0x3b, 0xa591, 0xa571, 0x3b, 0x36, 0x3b, 0x37,
-0x3b, 0xa5db, 0xa515, 0x3b, 0xa562, 0xa54c, 0x3b, 0xa56d, 0xa583, 0x3b, 0xa51e, 0xa60b, 0xa554, 0xa57f, 0x20, 0xa578, 0xa583, 0xa5cf, 0x3b, 0xa5a8,
-0xa56a, 0xa571, 0x20, 0xa5cf, 0xa56e, 0x3b, 0x6c, 0x75, 0x75, 0x6b, 0x61, 0x6f, 0x20, 0x6b, 0x65, 0x6d, 0xe3, 0x3b, 0x253, 0x61,
-0x6e, 0x64, 0x61, 0x253, 0x75, 0x3b, 0x76, 0x254, 0x254, 0x3b, 0x66, 0x75, 0x6c, 0x75, 0x3b, 0x67, 0x6f, 0x6f, 0x3b, 0x36,
-0x3b, 0x37, 0x3b, 0x6b, 0x254, 0x6e, 0x64, 0x65, 0x3b, 0x73, 0x61, 0x61, 0x68, 0x3b, 0x67, 0x61, 0x6c, 0x6f, 0x3b, 0x6b,
-0x65, 0x6e, 0x70, 0x6b, 0x61, 0x74, 0x6f, 0x20, 0x253, 0x6f, 0x6c, 0x6f, 0x6c, 0x254, 0x3b, 0x6c, 0x75, 0x75, 0x6b, 0x61,
-0x6f, 0x20, 0x6c, 0x254, 0x6d, 0x61, 0x3b, 0x4a, 0x65, 0x6e, 0x3b, 0x48, 0x6f, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41,
-0x62, 0x72, 0x3b, 0x4d, 0x65, 0x69, 0x3b, 0x42, 0x72, 0xe1, 0x3b, 0x48, 0x65, 0x69, 0x3b, 0xd6, 0x69, 0x67, 0x3b, 0x48,
-0x65, 0x72, 0x3b, 0x57, 0xed, 0x6d, 0x3b, 0x57, 0x69, 0x6e, 0x3b, 0x43, 0x68, 0x72, 0x3b, 0x4a, 0x65, 0x6e, 0x6e, 0x65,
-0x72, 0x3b, 0x48, 0x6f, 0x72, 0x6e, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x65, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c,
-0x6c, 0x65, 0x3b, 0x4d, 0x65, 0x69, 0x6a, 0x65, 0x3b, 0x42, 0x72, 0xe1, 0x10d, 0x65, 0x74, 0x3b, 0x48, 0x65, 0x69, 0x77,
-0x65, 0x74, 0x3b, 0xd6, 0x69, 0x67, 0x161, 0x74, 0x65, 0x3b, 0x48, 0x65, 0x72, 0x62, 0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65,
-0x74, 0x3b, 0x57, 0xed, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x57, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0xe1, 0x6e, 0x65,
-0x74, 0x3b, 0x43, 0x68, 0x72, 0x69, 0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x4a, 0x3b, 0x48, 0x3b, 0x4d, 0x3b,
-0x41, 0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x48, 0x3b, 0xd6, 0x3b, 0x48, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x43, 0x3b, 0x6f, 0x2e,
-0x31, 0x3b, 0x6f, 0x2e, 0x32, 0x3b, 0x6f, 0x2e, 0x33, 0x3b, 0x6f, 0x2e, 0x34, 0x3b, 0x6f, 0x2e, 0x35, 0x3b, 0x6f, 0x2e,
-0x36, 0x3b, 0x6f, 0x2e, 0x37, 0x3b, 0x6f, 0x2e, 0x38, 0x3b, 0x6f, 0x2e, 0x39, 0x3b, 0x6f, 0x2e, 0x31, 0x30, 0x3b, 0x6f,
-0x2e, 0x31, 0x31, 0x3b, 0x6f, 0x2e, 0x31, 0x32, 0x3b, 0x70, 0x69, 0x6b, 0xed, 0x74, 0xed, 0x6b, 0xed, 0x74, 0x69, 0x65,
-0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0xed, 0x20, 0xfa, 0x20, 0x6b, 0x75, 0x74, 0xfa, 0x61, 0x6e, 0x3b, 0x73, 0x69, 0x25b, 0x79,
-0x25b, 0x301, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x6e, 0x64, 0xed, 0x25b, 0x3b, 0x254, 0x6e,
-0x73, 0xfa, 0x6d, 0x62, 0x254, 0x6c, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1, 0x74,
-0xfa, 0x25b, 0x3b, 0x6d, 0x65, 0x73, 0x69, 0x14b, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe9, 0x6e,
-0x69, 0x65, 0x3b, 0x65, 0x6e, 0x73, 0x69, 0x6c, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74,
-0xe1, 0x6e, 0x75, 0x25b, 0x3b, 0x254, 0x73, 0x254, 0x6e, 0x3b, 0x65, 0x66, 0x75, 0x74, 0x65, 0x3b, 0x70, 0x69, 0x73, 0x75,
-0x79, 0xfa, 0x3b, 0x69, 0x6d, 0x25b, 0x14b, 0x20, 0x69, 0x20, 0x70, 0x75, 0x254, 0x73, 0x3b, 0x69, 0x6d, 0x25b, 0x14b, 0x20,
-0x69, 0x20, 0x70, 0x75, 0x74, 0xfa, 0x6b, 0x2c, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xed, 0x25b,
-0x3b, 0x6d, 0x61, 0x6b, 0x61, 0x6e, 0x64, 0x69, 0x6b, 0x25b, 0x3b, 0x70, 0x69, 0x6c, 0x254, 0x6e, 0x64, 0x254, 0x301, 0x3b,
-0x58, 0x69, 0x6e, 0x3b, 0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b,
-0x58, 0x75, 0x6e, 0x3b, 0x58, 0x6e, 0x74, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x63, 0x68, 0x3b,
-0x50, 0x61, 0x79, 0x3b, 0x41, 0x76, 0x69, 0x3b, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65,
-0x72, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x7a, 0x75, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x75, 0x3b,
-0x78, 0x75, 0x6e, 0x75, 0x3b, 0x78, 0x75, 0x6e, 0x65, 0x74, 0x75, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x73,
-0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x70, 0x61, 0x79,
-0x61, 0x72, 0x65, 0x73, 0x3b, 0x61, 0x76, 0x69, 0x65, 0x6e, 0x74, 0x75, 0x3b, 0x58, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41,
-0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x78, 0x69, 0x6e,
-0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x78, 0x75, 0x6e,
-0x3b, 0x78, 0x6e, 0x74, 0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x63, 0x68, 0x3b, 0x70, 0x61, 0x79,
-0x3b, 0x61, 0x76, 0x69, 0x3b, 0x64, 0x65, 0x20, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65,
-0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x7a, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72,
-0x69, 0x6c, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x79, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x78, 0x75, 0x6e, 0x75, 0x3b, 0x64,
-0x65, 0x20, 0x78, 0x75, 0x6e, 0x65, 0x74, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x64, 0x65,
-0x20, 0x73, 0x65, 0x74, 0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72, 0x65,
-0x3b, 0x64, 0x65, 0x20, 0x70, 0x61, 0x79, 0x61, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x2019, 0x61, 0x76, 0x69, 0x65, 0x6e, 0x74,
-0x75, 0x3b, 0x4e, 0x64, 0x75, 0x14b, 0x6d, 0x62, 0x69, 0x20, 0x53, 0x61, 0x14b, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20,
-0x50, 0x25b, 0x301, 0x70, 0xe1, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x74, 0xe1, 0x74, 0x3b, 0x50,
-0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x6b, 0x77, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b,
-0x20, 0x50, 0x61, 0x74, 0x61, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x6e,
-0x74, 0xfa, 0x6b, 0xfa, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x53, 0x61, 0x61, 0x6d, 0x62, 0xe1, 0x3b, 0x50, 0x25b,
-0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x66, 0x254, 0x6d, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20,
-0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x70, 0x66, 0xfa, 0xa78b, 0xfa, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x25b,
-0x67, 0x25b, 0x301, 0x6d, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x6d, 0x254, 0x301,
-0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x70, 0xe1, 0x3b, 0x70, 0x61, 0x6d, 0x62,
-0x61, 0x3b, 0x77, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x6d, 0x62, 0x69, 0x79, 0x254, 0x20, 0x6d, 0x25b, 0x6e, 0x64, 0x6f, 0x14b,
-0x67, 0x254, 0x3b, 0x4e, 0x79, 0x254, 0x6c, 0x254, 0x6d, 0x62, 0x254, 0x14b, 0x67, 0x254, 0x3b, 0x4d, 0x254, 0x6e, 0x254, 0x20,
-0x14b, 0x67, 0x62, 0x61, 0x6e, 0x6a, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x14b, 0x67, 0x77, 0x25b, 0x20, 0x14b, 0x67, 0x62, 0x61,
-0x6e, 0x6a, 0x61, 0x3b, 0x6b, 0x75, 0x14b, 0x67, 0x77, 0x25b, 0x3b, 0x66, 0x25b, 0x3b, 0x6e, 0x6a, 0x61, 0x70, 0x69, 0x3b,
-0x6e, 0x79, 0x75, 0x6b, 0x75, 0x6c, 0x3b, 0x31, 0x31, 0x3b, 0x253, 0x75, 0x6c, 0x253, 0x75, 0x73, 0x25b, 0x3b, 0x6d, 0x62,
-0x65, 0x67, 0x74, 0x75, 0x67, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62, 0xec, 0x3b, 0x69, 0x6d, 0x65,
-0x67, 0x20, 0x6d, 0x62, 0x259, 0x14b, 0x63, 0x68, 0x75, 0x62, 0x69, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6e, 0x67, 0x77,
-0x259, 0x300, 0x74, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63,
-0x68, 0x69, 0x69, 0x62, 0x254, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9, 0x6d, 0x62, 0x259, 0x300, 0x14b,
-0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x6b, 0x61, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x75,
-0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x74, 0xe8, 0x73, 0x69, 0x2bc, 0x65, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x7a,
-0xf2, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20,
-0x6d, 0x62, 0x65, 0x67, 0x74, 0x75, 0x67, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62, 0xec, 0x3b, 0x69,
-0x6d, 0x65, 0x67, 0x20, 0x6d, 0x62, 0x259, 0x14b, 0x63, 0x68, 0x75, 0x62, 0x69, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6e,
-0x67, 0x77, 0x259, 0x300, 0x74, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20,
-0x69, 0x63, 0x68, 0x69, 0x69, 0x62, 0x254, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9, 0x6d, 0x62, 0x259,
-0x300, 0x14b, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x6b, 0x61, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20,
-0x6b, 0x75, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x74, 0xe8, 0x73, 0x69, 0x2bc, 0x65, 0x3b, 0x69, 0x6d, 0x259, 0x67,
-0x20, 0x7a, 0xf2, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x3b, 0x4d, 0x31, 0x3b,
-0x41, 0x32, 0x3b, 0x4d, 0x33, 0x3b, 0x4e, 0x34, 0x3b, 0x46, 0x35, 0x3b, 0x49, 0x36, 0x3b, 0x41, 0x37, 0x3b, 0x49, 0x38,
-0x3b, 0x4b, 0x39, 0x3b, 0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x65,
-0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x6c, 0xf9, 0x6d, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6b, 0xe0, 0x67, 0x20, 0x6e, 0x67,
-0x77, 0xf3, 0x14b, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6c, 0x65, 0x70, 0x79, 0xe8, 0x20, 0x73, 0x68, 0xfa, 0x6d, 0x3b, 0x73,
-0x61, 0x14b, 0x20, 0x63, 0xff, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x63, 0xff, 0xf3,
-0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6e, 0x6a, 0xff, 0x6f, 0x6c, 0xe1, 0x2bc, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x79, 0x25b,
-0x300, 0x62, 0x20, 0x74, 0x79, 0x25b, 0x300, 0x62, 0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6d,
-0x62, 0x289, 0x300, 0x14b, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6e, 0x67, 0x77, 0x254, 0x300, 0x2bc, 0x20, 0x6d, 0x62, 0xff, 0x25b,
-0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0xe0, 0x14b, 0x61, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0xe1, 0x2bc, 0x3b, 0x73, 0x61,
-0x14b, 0x20, 0x6d, 0x65, 0x6a, 0x77, 0x6f, 0x14b, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6c, 0xf9, 0x6d, 0x3b, 0x57, 0x69,
-0xf3, 0x74, 0x68, 0x65, 0x21f, 0x69, 0x6b, 0x61, 0x20, 0x57, 0xed, 0x3b, 0x54, 0x68, 0x69, 0x79, 0xf3, 0x21f, 0x65, 0x79,
-0x75, 0x14b, 0x6b, 0x61, 0x20, 0x57, 0xed, 0x3b, 0x49, 0x161, 0x74, 0xe1, 0x77, 0x69, 0x10d, 0x68, 0x61, 0x79, 0x61, 0x7a,
-0x61, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x50, 0x21f, 0x65, 0x17e, 0xed, 0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68,
-0x61, 0x14b, 0x77, 0xe1, 0x70, 0x65, 0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x57, 0xed, 0x70, 0x61, 0x7a, 0x75, 0x6b,
-0x21f, 0x61, 0x2d, 0x77, 0x61, 0x161, 0x74, 0xe9, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x70, 0x21f, 0xe1, 0x73,
-0x61, 0x70, 0x61, 0x20, 0x57, 0xed, 0x3b, 0x57, 0x61, 0x73, 0xfa, 0x74, 0x21f, 0x75, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x10c,
-0x68, 0x61, 0x14b, 0x77, 0xe1, 0x70, 0x65, 0x1e7, 0x69, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1, 0x70,
-0x65, 0x2d, 0x6b, 0x61, 0x73, 0x6e, 0xe1, 0x20, 0x57, 0xed, 0x3b, 0x57, 0x61, 0x6e, 0xed, 0x79, 0x65, 0x74, 0x75, 0x20,
-0x57, 0xed, 0x3b, 0x54, 0x21f, 0x61, 0x68, 0xe9, 0x6b, 0x61, 0x70, 0x161, 0x75, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x6a9, 0x627,
-0x646, 0x648, 0x648, 0x646, 0x6cc, 0x20, 0x62f, 0x648, 0x648, 0x6d5, 0x645, 0x3b, 0x634, 0x648, 0x628, 0x627, 0x62a, 0x3b, 0x626, 0x627,
-0x632, 0x627, 0x631, 0x3b, 0x646, 0x6cc, 0x633, 0x627, 0x646, 0x3b, 0x626, 0x627, 0x6cc, 0x627, 0x631, 0x3b, 0x62d, 0x648, 0x632, 0x6d5,
-0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x62a, 0x6d5, 0x645, 0x648, 0x648, 0x632, 0x3b, 0x626, 0x627, 0x628, 0x3b, 0x626, 0x6d5, 0x6cc, 0x644,
-0x648, 0x648, 0x644, 0x3b, 0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x3b, 0x62a, 0x634, 0x631,
-0x6cc, 0x646, 0x6cc, 0x20, 0x62f, 0x648, 0x648, 0x6d5, 0x645, 0x3b, 0x6a9, 0x627, 0x646, 0x648, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9,
-0x6d5, 0x645, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x11b, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d,
+0x410, 0x43b, 0x442, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x421, 0x44d, 0x442, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x3b, 0x430, 0x445,
+0x441, 0x44b, 0x43d, 0x43d, 0x44c, 0x44b, 0x3b, 0x4d, 0x75, 0x70, 0x3b, 0x4d, 0x77, 0x69, 0x3b, 0x4d, 0x73, 0x68, 0x3b, 0x4d,
+0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x67, 0x3b, 0x4d, 0x75, 0x6a, 0x3b, 0x4d, 0x73, 0x70, 0x3b, 0x4d, 0x70, 0x67, 0x3b, 0x4d,
+0x79, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x3b, 0x4d, 0x75, 0x73, 0x3b, 0x4d, 0x75, 0x68, 0x3b, 0x4d, 0x75, 0x70, 0x61, 0x6c,
+0x61, 0x6e, 0x67, 0x75, 0x6c, 0x77, 0x61, 0x3b, 0x4d, 0x77, 0x69, 0x74, 0x6f, 0x70, 0x65, 0x3b, 0x4d, 0x75, 0x73, 0x68,
+0x65, 0x6e, 0x64, 0x65, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x69, 0x3b, 0x4d, 0x75, 0x73, 0x68, 0x65, 0x6e, 0x64, 0x65, 0x20,
+0x4d, 0x61, 0x67, 0x61, 0x6c, 0x69, 0x3b, 0x4d, 0x75, 0x6a, 0x69, 0x6d, 0x62, 0x69, 0x3b, 0x4d, 0x75, 0x73, 0x68, 0x69,
+0x70, 0x65, 0x70, 0x6f, 0x3b, 0x4d, 0x75, 0x70, 0x75, 0x67, 0x75, 0x74, 0x6f, 0x3b, 0x4d, 0x75, 0x6e, 0x79, 0x65, 0x6e,
+0x73, 0x65, 0x3b, 0x4d, 0x6f, 0x6b, 0x68, 0x75, 0x3b, 0x4d, 0x75, 0x73, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x64, 0x65, 0x6d,
+0x62, 0x77, 0x65, 0x3b, 0x4d, 0x75, 0x68, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0xa5a8, 0xa56a, 0xa583, 0x20, 0xa51e, 0xa56e, 0x3b, 0xa552,
+0xa561, 0xa59d, 0xa595, 0x3b, 0xa57e, 0xa5ba, 0x3b, 0xa5a2, 0xa595, 0x3b, 0xa591, 0xa571, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0xa5db, 0xa515, 0x3b,
+0xa562, 0xa54c, 0x3b, 0xa56d, 0xa583, 0x3b, 0xa51e, 0xa60b, 0xa554, 0xa57f, 0x20, 0xa578, 0xa583, 0xa5cf, 0x3b, 0xa5a8, 0xa56a, 0xa571, 0x20, 0xa5cf,
+0xa56e, 0x3b, 0x6c, 0x75, 0x75, 0x6b, 0x61, 0x6f, 0x20, 0x6b, 0x65, 0x6d, 0xe3, 0x3b, 0x253, 0x61, 0x6e, 0x64, 0x61, 0x253,
+0x75, 0x3b, 0x76, 0x254, 0x254, 0x3b, 0x66, 0x75, 0x6c, 0x75, 0x3b, 0x67, 0x6f, 0x6f, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x6b,
+0x254, 0x6e, 0x64, 0x65, 0x3b, 0x73, 0x61, 0x61, 0x68, 0x3b, 0x67, 0x61, 0x6c, 0x6f, 0x3b, 0x6b, 0x65, 0x6e, 0x70, 0x6b,
+0x61, 0x74, 0x6f, 0x20, 0x253, 0x6f, 0x6c, 0x6f, 0x6c, 0x254, 0x3b, 0x6c, 0x75, 0x75, 0x6b, 0x61, 0x6f, 0x20, 0x6c, 0x254,
+0x6d, 0x61, 0x3b, 0x4a, 0x65, 0x6e, 0x3b, 0x48, 0x6f, 0x72, 0x3b, 0x4d, 0xe4, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d,
+0x65, 0x69, 0x3b, 0x42, 0x72, 0xe1, 0x3b, 0x48, 0x65, 0x69, 0x3b, 0xd6, 0x69, 0x67, 0x3b, 0x48, 0x65, 0x72, 0x3b, 0x57,
+0xed, 0x6d, 0x3b, 0x57, 0x69, 0x6e, 0x3b, 0x43, 0x68, 0x72, 0x3b, 0x4a, 0x65, 0x6e, 0x6e, 0x65, 0x72, 0x3b, 0x48, 0x6f,
+0x72, 0x6e, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0x72, 0x7a, 0x65, 0x3b, 0x41, 0x62, 0x72, 0x69, 0x6c, 0x6c, 0x65, 0x3b, 0x4d,
+0x65, 0x69, 0x6a, 0x65, 0x3b, 0x42, 0x72, 0xe1, 0x10d, 0x65, 0x74, 0x3b, 0x48, 0x65, 0x69, 0x77, 0x65, 0x74, 0x3b, 0xd6,
+0x69, 0x67, 0x161, 0x74, 0x65, 0x3b, 0x48, 0x65, 0x72, 0x62, 0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x57, 0xed,
+0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x57, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x43, 0x68,
+0x72, 0x69, 0x161, 0x74, 0x6d, 0xe1, 0x6e, 0x65, 0x74, 0x3b, 0x4a, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b,
+0x42, 0x3b, 0x48, 0x3b, 0xd6, 0x3b, 0x48, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x43, 0x3b, 0x6f, 0x2e, 0x31, 0x3b, 0x6f, 0x2e,
+0x32, 0x3b, 0x6f, 0x2e, 0x33, 0x3b, 0x6f, 0x2e, 0x34, 0x3b, 0x6f, 0x2e, 0x35, 0x3b, 0x6f, 0x2e, 0x36, 0x3b, 0x6f, 0x2e,
+0x37, 0x3b, 0x6f, 0x2e, 0x38, 0x3b, 0x6f, 0x2e, 0x39, 0x3b, 0x6f, 0x2e, 0x31, 0x30, 0x3b, 0x6f, 0x2e, 0x31, 0x31, 0x3b,
+0x6f, 0x2e, 0x31, 0x32, 0x3b, 0x70, 0x69, 0x6b, 0xed, 0x74, 0xed, 0x6b, 0xed, 0x74, 0x69, 0x65, 0x2c, 0x20, 0x6f, 0xf3,
+0x6c, 0xed, 0x20, 0xfa, 0x20, 0x6b, 0x75, 0x74, 0xfa, 0x61, 0x6e, 0x3b, 0x73, 0x69, 0x25b, 0x79, 0x25b, 0x301, 0x2c, 0x20,
+0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x6e, 0x64, 0xed, 0x25b, 0x3b, 0x254, 0x6e, 0x73, 0xfa, 0x6d, 0x62,
+0x254, 0x6c, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1, 0x74, 0xfa, 0x25b, 0x3b, 0x6d,
+0x65, 0x73, 0x69, 0x14b, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe9, 0x6e, 0x69, 0x65, 0x3b, 0x65,
+0x6e, 0x73, 0x69, 0x6c, 0x2c, 0x20, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xe1, 0x6e, 0x75, 0x25b,
+0x3b, 0x254, 0x73, 0x254, 0x6e, 0x3b, 0x65, 0x66, 0x75, 0x74, 0x65, 0x3b, 0x70, 0x69, 0x73, 0x75, 0x79, 0xfa, 0x3b, 0x69,
+0x6d, 0x25b, 0x14b, 0x20, 0x69, 0x20, 0x70, 0x75, 0x254, 0x73, 0x3b, 0x69, 0x6d, 0x25b, 0x14b, 0x20, 0x69, 0x20, 0x70, 0x75,
+0x74, 0xfa, 0x6b, 0x2c, 0x6f, 0xf3, 0x6c, 0x69, 0x20, 0xfa, 0x20, 0x6b, 0xe1, 0x74, 0xed, 0x25b, 0x3b, 0x6d, 0x61, 0x6b,
+0x61, 0x6e, 0x64, 0x69, 0x6b, 0x25b, 0x3b, 0x70, 0x69, 0x6c, 0x254, 0x6e, 0x64, 0x254, 0x301, 0x3b, 0x58, 0x69, 0x6e, 0x3b,
+0x46, 0x65, 0x62, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x41, 0x62, 0x72, 0x3b, 0x4d, 0x61, 0x79, 0x3b, 0x58, 0x75, 0x6e, 0x3b,
+0x58, 0x6e, 0x74, 0x3b, 0x41, 0x67, 0x6f, 0x3b, 0x53, 0x65, 0x74, 0x3b, 0x4f, 0x63, 0x68, 0x3b, 0x50, 0x61, 0x79, 0x3b,
+0x41, 0x76, 0x69, 0x3b, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72, 0x75, 0x3b, 0x6d,
+0x61, 0x72, 0x7a, 0x75, 0x3b, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x6d, 0x61, 0x79, 0x75, 0x3b, 0x78, 0x75, 0x6e, 0x75,
+0x3b, 0x78, 0x75, 0x6e, 0x65, 0x74, 0x75, 0x3b, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x73, 0x65, 0x74, 0x69, 0x65,
+0x6d, 0x62, 0x72, 0x65, 0x3b, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x70, 0x61, 0x79, 0x61, 0x72, 0x65, 0x73,
+0x3b, 0x61, 0x76, 0x69, 0x65, 0x6e, 0x74, 0x75, 0x3b, 0x58, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x58,
+0x3b, 0x58, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x4f, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x78, 0x69, 0x6e, 0x3b, 0x66, 0x65, 0x62,
+0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x61, 0x62, 0x72, 0x3b, 0x6d, 0x61, 0x79, 0x3b, 0x78, 0x75, 0x6e, 0x3b, 0x78, 0x6e, 0x74,
+0x3b, 0x61, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x74, 0x3b, 0x6f, 0x63, 0x68, 0x3b, 0x70, 0x61, 0x79, 0x3b, 0x61, 0x76, 0x69,
+0x3b, 0x64, 0x65, 0x20, 0x78, 0x69, 0x6e, 0x65, 0x72, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x66, 0x65, 0x62, 0x72, 0x65, 0x72,
+0x75, 0x3b, 0x64, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x7a, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x62, 0x72, 0x69, 0x6c, 0x3b, 0x64,
+0x65, 0x20, 0x6d, 0x61, 0x79, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x78, 0x75, 0x6e, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x78, 0x75,
+0x6e, 0x65, 0x74, 0x75, 0x3b, 0x64, 0x2019, 0x61, 0x67, 0x6f, 0x73, 0x74, 0x75, 0x3b, 0x64, 0x65, 0x20, 0x73, 0x65, 0x74,
+0x69, 0x65, 0x6d, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x2019, 0x6f, 0x63, 0x68, 0x6f, 0x62, 0x72, 0x65, 0x3b, 0x64, 0x65, 0x20,
+0x70, 0x61, 0x79, 0x61, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x2019, 0x61, 0x76, 0x69, 0x65, 0x6e, 0x74, 0x75, 0x3b, 0x4e, 0x64,
+0x75, 0x14b, 0x6d, 0x62, 0x69, 0x20, 0x53, 0x61, 0x14b, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x70,
+0xe1, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x74, 0xe1, 0x74, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b,
+0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x6b, 0x77, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x61, 0x74,
+0x61, 0x61, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x6e, 0x74, 0xfa, 0x6b, 0xfa,
+0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x53, 0x61, 0x61, 0x6d, 0x62, 0xe1, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20,
+0x50, 0x25b, 0x301, 0x6e, 0x25b, 0x301, 0x66, 0x254, 0x6d, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x50, 0x25b, 0x301, 0x6e,
+0x25b, 0x301, 0x70, 0x66, 0xfa, 0xa78b, 0xfa, 0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x25b, 0x67, 0x25b, 0x301, 0x6d,
+0x3b, 0x50, 0x25b, 0x73, 0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x6d, 0x254, 0x301, 0x3b, 0x50, 0x25b, 0x73,
+0x61, 0x14b, 0x20, 0x4e, 0x74, 0x73, 0x254, 0x30c, 0x70, 0x70, 0xe1, 0x3b, 0x70, 0x61, 0x6d, 0x62, 0x61, 0x3b, 0x77, 0x61,
+0x6e, 0x6a, 0x61, 0x3b, 0x6d, 0x62, 0x69, 0x79, 0x254, 0x20, 0x6d, 0x25b, 0x6e, 0x64, 0x6f, 0x14b, 0x67, 0x254, 0x3b, 0x4e,
+0x79, 0x254, 0x6c, 0x254, 0x6d, 0x62, 0x254, 0x14b, 0x67, 0x254, 0x3b, 0x4d, 0x254, 0x6e, 0x254, 0x20, 0x14b, 0x67, 0x62, 0x61,
+0x6e, 0x6a, 0x61, 0x3b, 0x4e, 0x79, 0x61, 0x14b, 0x67, 0x77, 0x25b, 0x20, 0x14b, 0x67, 0x62, 0x61, 0x6e, 0x6a, 0x61, 0x3b,
+0x6b, 0x75, 0x14b, 0x67, 0x77, 0x25b, 0x3b, 0x66, 0x25b, 0x3b, 0x6e, 0x6a, 0x61, 0x70, 0x69, 0x3b, 0x6e, 0x79, 0x75, 0x6b,
+0x75, 0x6c, 0x3b, 0x31, 0x31, 0x3b, 0x253, 0x75, 0x6c, 0x253, 0x75, 0x73, 0x25b, 0x3b, 0x6d, 0x62, 0x65, 0x67, 0x74, 0x75,
+0x67, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62, 0xec, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0x6d, 0x62,
+0x259, 0x14b, 0x63, 0x68, 0x75, 0x62, 0x69, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6e, 0x67, 0x77, 0x259, 0x300, 0x74, 0x3b,
+0x69, 0x6d, 0x259, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x69, 0x62,
+0x254, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9, 0x6d, 0x62, 0x259, 0x300, 0x14b, 0x3b, 0x69, 0x6d, 0x259,
+0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x6b, 0x61, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x75, 0x64, 0x3b, 0x69, 0x6d,
+0x259, 0x67, 0x20, 0x74, 0xe8, 0x73, 0x69, 0x2bc, 0x65, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x7a, 0xf2, 0x3b, 0x69, 0x6d,
+0x259, 0x67, 0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6d, 0x62, 0x65, 0x67,
+0x74, 0x75, 0x67, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20, 0xe0, 0x62, 0xf9, 0x62, 0xec, 0x3b, 0x69, 0x6d, 0x65, 0x67, 0x20,
+0x6d, 0x62, 0x259, 0x14b, 0x63, 0x68, 0x75, 0x62, 0x69, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6e, 0x67, 0x77, 0x259, 0x300,
+0x74, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x66, 0x6f, 0x67, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69,
+0x69, 0x62, 0x254, 0x64, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0xe0, 0x64, 0xf9, 0x6d, 0x62, 0x259, 0x300, 0x14b, 0x3b, 0x69,
+0x6d, 0x259, 0x67, 0x20, 0x69, 0x63, 0x68, 0x69, 0x6b, 0x61, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x75, 0x64, 0x3b,
+0x69, 0x6d, 0x259, 0x67, 0x20, 0x74, 0xe8, 0x73, 0x69, 0x2bc, 0x65, 0x3b, 0x69, 0x6d, 0x259, 0x67, 0x20, 0x7a, 0xf2, 0x3b,
+0x69, 0x6d, 0x259, 0x67, 0x20, 0x6b, 0x72, 0x69, 0x7a, 0x6d, 0x65, 0x64, 0x3b, 0x4d, 0x31, 0x3b, 0x41, 0x32, 0x3b, 0x4d,
+0x33, 0x3b, 0x4e, 0x34, 0x3b, 0x46, 0x35, 0x3b, 0x49, 0x36, 0x3b, 0x41, 0x37, 0x3b, 0x49, 0x38, 0x3b, 0x4b, 0x39, 0x3b,
+0x31, 0x30, 0x3b, 0x31, 0x31, 0x3b, 0x31, 0x32, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0x25b, 0x300,
+0x25b, 0x20, 0x6c, 0xf9, 0x6d, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6b, 0xe0, 0x67, 0x20, 0x6e, 0x67, 0x77, 0xf3, 0x14b, 0x3b,
+0x73, 0x61, 0x14b, 0x20, 0x6c, 0x65, 0x70, 0x79, 0xe8, 0x20, 0x73, 0x68, 0xfa, 0x6d, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x63,
+0xff, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x63, 0xff, 0xf3, 0x3b, 0x73, 0x61, 0x14b,
+0x20, 0x6e, 0x6a, 0xff, 0x6f, 0x6c, 0xe1, 0x2bc, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x74, 0x79, 0x25b, 0x300, 0x62, 0x20, 0x74,
+0x79, 0x25b, 0x300, 0x62, 0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6d, 0x62, 0x289, 0x300, 0x14b,
+0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6e, 0x67, 0x77, 0x254, 0x300, 0x2bc, 0x20, 0x6d, 0x62, 0xff, 0x25b, 0x3b, 0x73, 0x61, 0x14b,
+0x20, 0x74, 0xe0, 0x14b, 0x61, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0xe1, 0x2bc, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6d, 0x65,
+0x6a, 0x77, 0x6f, 0x14b, 0xf3, 0x3b, 0x73, 0x61, 0x14b, 0x20, 0x6c, 0xf9, 0x6d, 0x3b, 0x57, 0x69, 0xf3, 0x74, 0x68, 0x65,
+0x21f, 0x69, 0x6b, 0x61, 0x20, 0x57, 0xed, 0x3b, 0x54, 0x68, 0x69, 0x79, 0xf3, 0x21f, 0x65, 0x79, 0x75, 0x14b, 0x6b, 0x61,
+0x20, 0x57, 0xed, 0x3b, 0x49, 0x161, 0x74, 0xe1, 0x77, 0x69, 0x10d, 0x68, 0x61, 0x79, 0x61, 0x7a, 0x61, 0x14b, 0x20, 0x57,
+0xed, 0x3b, 0x50, 0x21f, 0x65, 0x17e, 0xed, 0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1,
+0x70, 0x65, 0x74, 0x21f, 0x6f, 0x20, 0x57, 0xed, 0x3b, 0x57, 0xed, 0x70, 0x61, 0x7a, 0x75, 0x6b, 0x21f, 0x61, 0x2d, 0x77,
+0x61, 0x161, 0x74, 0xe9, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x70, 0x21f, 0xe1, 0x73, 0x61, 0x70, 0x61, 0x20,
+0x57, 0xed, 0x3b, 0x57, 0x61, 0x73, 0xfa, 0x74, 0x21f, 0x75, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77,
+0xe1, 0x70, 0x65, 0x1e7, 0x69, 0x20, 0x57, 0xed, 0x3b, 0x10c, 0x68, 0x61, 0x14b, 0x77, 0xe1, 0x70, 0x65, 0x2d, 0x6b, 0x61,
+0x73, 0x6e, 0xe1, 0x20, 0x57, 0xed, 0x3b, 0x57, 0x61, 0x6e, 0xed, 0x79, 0x65, 0x74, 0x75, 0x20, 0x57, 0xed, 0x3b, 0x54,
+0x21f, 0x61, 0x68, 0xe9, 0x6b, 0x61, 0x70, 0x161, 0x75, 0x14b, 0x20, 0x57, 0xed, 0x3b, 0x6a9, 0x627, 0x646, 0x648, 0x648, 0x646,
+0x6cc, 0x20, 0x62f, 0x648, 0x648, 0x6d5, 0x645, 0x3b, 0x634, 0x648, 0x628, 0x627, 0x62a, 0x3b, 0x626, 0x627, 0x632, 0x627, 0x631, 0x3b,
+0x646, 0x6cc, 0x633, 0x627, 0x646, 0x3b, 0x626, 0x627, 0x6cc, 0x627, 0x631, 0x3b, 0x62d, 0x648, 0x632, 0x6d5, 0x6cc, 0x631, 0x627, 0x646,
+0x3b, 0x62a, 0x6d5, 0x645, 0x648, 0x648, 0x632, 0x3b, 0x626, 0x627, 0x628, 0x3b, 0x626, 0x6d5, 0x6cc, 0x644, 0x648, 0x648, 0x644, 0x3b,
+0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x3b, 0x62a, 0x634, 0x631, 0x6cc, 0x646, 0x6cc, 0x20,
+0x62f, 0x648, 0x648, 0x6d5, 0x645, 0x3b, 0x6a9, 0x627, 0x646, 0x648, 0x646, 0x6cc, 0x20, 0x6cc, 0x6d5, 0x6a9, 0x6d5, 0x645, 0x3b, 0x6a9,
+0x3b, 0x634, 0x3b, 0x626, 0x3b, 0x646, 0x3b, 0x626, 0x3b, 0x62d, 0x3b, 0x62a, 0x3b, 0x626, 0x3b, 0x626, 0x3b, 0x62a, 0x3b, 0x62a,
+0x3b, 0x6a9, 0x3b, 0x6a, 0x61, 0x6e, 0x3b, 0x66, 0x65, 0x62, 0x3b, 0x6d, 0x11b, 0x72, 0x3b, 0x61, 0x70, 0x72, 0x3b, 0x6d,
0x61, 0x6a, 0x3b, 0x6a, 0x75, 0x6e, 0x3b, 0x6a, 0x75, 0x6c, 0x3b, 0x61, 0x77, 0x67, 0x3b, 0x73, 0x65, 0x70, 0x3b, 0x6f,
0x6b, 0x74, 0x3b, 0x6e, 0x6f, 0x77, 0x3b, 0x64, 0x65, 0x63, 0x3b, 0x6a, 0x61, 0x6e, 0x75, 0x61, 0x72, 0x3b, 0x66, 0x65,
0x62, 0x72, 0x75, 0x61, 0x72, 0x3b, 0x6d, 0x11b, 0x72, 0x63, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x3b, 0x6d, 0x61, 0x6a,
@@ -3789,18 +3805,23 @@ static const ushort months_data[] = {
0x6d, 0x11b, 0x72, 0x63, 0x61, 0x3b, 0x61, 0x70, 0x72, 0x79, 0x6c, 0x61, 0x3b, 0x6d, 0x65, 0x6a, 0x65, 0x3b, 0x6a, 0x75,
0x6e, 0x69, 0x6a, 0x61, 0x3b, 0x6a, 0x75, 0x6c, 0x69, 0x6a, 0x61, 0x3b, 0x61, 0x77, 0x67, 0x75, 0x73, 0x74, 0x61, 0x3b,
0x73, 0x65, 0x70, 0x74, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x6f, 0x6b, 0x74, 0x6f, 0x62, 0x72, 0x61, 0x3b, 0x6e, 0x6f,
-0x77, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x75, 0x111, 0x111, 0xe2,
-0x69, 0x76, 0x65, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x75, 0x6f, 0x76, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b,
-0x6e, 0x6a, 0x75, 0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x63, 0x75, 0xe1, 0x14b, 0x75, 0x69, 0x6d, 0xe1,
-0xe1, 0x6e, 0x75, 0x3b, 0x76, 0x79, 0x65, 0x73, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x65, 0x73, 0x69, 0x6d,
-0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x70, 0x6f, 0x72,
-0x67, 0x65, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x10d, 0x6f, 0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x72,
-0x6f, 0x6f, 0x76, 0x76, 0xe2, 0x64, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x73, 0x6b, 0x61, 0x6d, 0x6d, 0xe2, 0x6d, 0xe1,
-0xe1, 0x6e, 0x75, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x62c, 0x627, 0x646, 0x6a4,
-0x6cc, 0x6d5, 0x3b, 0x641, 0x626, 0x6a4, 0x631, 0x6cc, 0x6d5, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x6a4, 0x631, 0x6cc, 0x644,
-0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x659, 0x623, 0x646, 0x3b, 0x62c, 0x648, 0x659, 0x644, 0x627, 0x3b, 0x622, 0x6af, 0x648,
-0x633, 0x62a, 0x3b, 0x633, 0x626, 0x67e, 0x62a, 0x627, 0x645, 0x631, 0x3b, 0x626, 0x648, 0x6a9, 0x62a, 0x648, 0x6a4, 0x631, 0x3b, 0x646,
-0x648, 0x6a4, 0x627, 0x645, 0x631, 0x3b, 0x62f, 0x626, 0x633, 0x627, 0x645, 0x631, 0x3b
+0x77, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x64, 0x65, 0x63, 0x65, 0x6d, 0x62, 0x72, 0x61, 0x3b, 0x75, 0x111, 0x69, 0x76,
+0x3b, 0x6b, 0x75, 0x6f, 0x76, 0xe2, 0x3b, 0x6e, 0x6a, 0x75, 0x68, 0x10d, 0xe2, 0x3b, 0x63, 0x75, 0xe1, 0x14b, 0x75, 0x69,
+0x3b, 0x76, 0x79, 0x65, 0x73, 0x69, 0x3b, 0x6b, 0x65, 0x73, 0x69, 0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e, 0x69, 0x3b, 0x70,
+0x6f, 0x72, 0x67, 0x65, 0x3b, 0x10d, 0x6f, 0x68, 0x10d, 0xe2, 0x3b, 0x72, 0x6f, 0x6f, 0x76, 0x76, 0xe2, 0x64, 0x3b, 0x73,
+0x6b, 0x61, 0x6d, 0x6d, 0xe2, 0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0xe2, 0x3b, 0x75, 0x111, 0x111, 0xe2, 0x69, 0x76, 0x65,
+0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x75, 0x6f, 0x76, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6e, 0x6a, 0x75,
+0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x63, 0x75, 0xe1, 0x14b, 0x75, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75,
+0x3b, 0x76, 0x79, 0x65, 0x73, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x6b, 0x65, 0x73, 0x69, 0x6d, 0xe1, 0xe1, 0x6e,
+0x75, 0x3b, 0x73, 0x79, 0x65, 0x69, 0x6e, 0x69, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x70, 0x6f, 0x72, 0x67, 0x65, 0x6d,
+0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x10d, 0x6f, 0x68, 0x10d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x72, 0x6f, 0x6f, 0x76,
+0x76, 0xe2, 0x64, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x73, 0x6b, 0x61, 0x6d, 0x6d, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75,
+0x3b, 0x6a, 0x75, 0x6f, 0x76, 0x6c, 0xe2, 0x6d, 0xe1, 0xe1, 0x6e, 0x75, 0x3b, 0x55, 0x3b, 0x4b, 0x3b, 0x4e, 0x4a, 0x3b,
+0x43, 0x3b, 0x56, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x50, 0x3b, 0x10c, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 0x62c, 0x627,
+0x646, 0x6a4, 0x6cc, 0x6d5, 0x3b, 0x641, 0x626, 0x6a4, 0x631, 0x6cc, 0x6d5, 0x3b, 0x645, 0x627, 0x631, 0x633, 0x3b, 0x622, 0x6a4, 0x631,
+0x6cc, 0x644, 0x3b, 0x645, 0x626, 0x6cc, 0x3b, 0x62c, 0x648, 0x659, 0x623, 0x646, 0x3b, 0x62c, 0x648, 0x659, 0x644, 0x627, 0x3b, 0x622,
+0x6af, 0x648, 0x633, 0x62a, 0x3b, 0x633, 0x626, 0x67e, 0x62a, 0x627, 0x645, 0x631, 0x3b, 0x626, 0x648, 0x6a9, 0x62a, 0x648, 0x6a4, 0x631,
+0x3b, 0x646, 0x648, 0x6a4, 0x627, 0x645, 0x631, 0x3b, 0x62f, 0x626, 0x633, 0x627, 0x645, 0x631, 0x3b
};
static const ushort days_data[] = {
@@ -3813,169 +3834,170 @@ static const ushort days_data[] = {
0x3b, 0x51, 0x69, 0x62, 0x3b, 0x52, 0x6f, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x53, 0x61, 0x6e,
0x3b, 0x44, 0x69, 0x6c, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x57, 0x69, 0x69, 0x78, 0x61, 0x74, 0x61, 0x3b, 0x51, 0x69, 0x62,
0x78, 0x61, 0x74, 0x61, 0x3b, 0x52, 0x6f, 0x6f, 0x62, 0x69, 0x69, 0x3b, 0x4b, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b,
-0x4a, 0x69, 0x6d, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x53, 0x61, 0x6e, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x53, 0x6f, 0x2e, 0x3b,
-0x4d, 0x61, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x57, 0x6f, 0x2e, 0x3b, 0x44, 0x6f, 0x2e, 0x3b, 0x56, 0x72, 0x2e, 0x3b,
-0x53, 0x61, 0x2e, 0x3b, 0x53, 0x6f, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x44,
-0x69, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x57, 0x6f, 0x65, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x6f, 0x6e, 0x64,
-0x65, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x56, 0x72, 0x79, 0x64, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x74, 0x65, 0x72, 0x64, 0x61,
-0x67, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x44, 0x69, 0x65, 0x3b,
-0x48, 0xeb, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0xeb, 0x72, 0x3b, 0x45, 0x6e, 0x6a, 0x3b, 0x50, 0x72, 0x65, 0x3b,
-0x53, 0x68, 0x74, 0x3b, 0x45, 0x20, 0x64, 0x69, 0x65, 0x6c, 0x3b, 0x45, 0x20, 0x68, 0xeb, 0x6e, 0xeb, 0x3b, 0x45, 0x20,
-0x6d, 0x61, 0x72, 0x74, 0xeb, 0x3b, 0x45, 0x20, 0x6d, 0xeb, 0x72, 0x6b, 0x75, 0x72, 0xeb, 0x3b, 0x45, 0x20, 0x65, 0x6e,
-0x6a, 0x74, 0x65, 0x3b, 0x45, 0x20, 0x70, 0x72, 0x65, 0x6d, 0x74, 0x65, 0x3b, 0x45, 0x20, 0x73, 0x68, 0x74, 0x75, 0x6e,
-0xeb, 0x3b, 0x44, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x65, 0x20, 0x64, 0x69,
-0x65, 0x6c, 0x3b, 0x65, 0x20, 0x68, 0xeb, 0x6e, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x74, 0xeb, 0x3b, 0x65, 0x20,
-0x6d, 0xeb, 0x72, 0x6b, 0x75, 0x72, 0xeb, 0x3b, 0x65, 0x20, 0x65, 0x6e, 0x6a, 0x74, 0x65, 0x3b, 0x65, 0x20, 0x70, 0x72,
-0x65, 0x6d, 0x74, 0x65, 0x3b, 0x65, 0x20, 0x73, 0x68, 0x74, 0x75, 0x6e, 0xeb, 0x3b, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230, 0x129e,
-0x3b, 0x121b, 0x12ad, 0x1230, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c,
-0x3b, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230, 0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x129e, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235,
-0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c, 0x3b, 0x12a5, 0x3b, 0x1230, 0x3b, 0x121b, 0x3b, 0x1228, 0x3b, 0x1210, 0x3b, 0x12d3,
-0x3b, 0x1245, 0x3b, 0x627, 0x644, 0x623, 0x62d, 0x62f, 0x3b, 0x627, 0x644, 0x627, 0x62b, 0x646, 0x64a, 0x646, 0x3b, 0x627, 0x644, 0x62b,
-0x644, 0x627, 0x62b, 0x627, 0x621, 0x3b, 0x627, 0x644, 0x623, 0x631, 0x628, 0x639, 0x627, 0x621, 0x3b, 0x627, 0x644, 0x62e, 0x645, 0x64a,
-0x633, 0x3b, 0x627, 0x644, 0x62c, 0x645, 0x639, 0x629, 0x3b, 0x627, 0x644, 0x633, 0x628, 0x62a, 0x3b, 0x62d, 0x3b, 0x646, 0x3b, 0x62b,
-0x3b, 0x631, 0x3b, 0x62e, 0x3b, 0x62c, 0x3b, 0x633, 0x3b, 0x56f, 0x56b, 0x580, 0x3b, 0x565, 0x580, 0x56f, 0x3b, 0x565, 0x580, 0x584,
-0x3b, 0x579, 0x580, 0x584, 0x3b, 0x570, 0x576, 0x563, 0x3b, 0x578, 0x582, 0x580, 0x3b, 0x577, 0x562, 0x569, 0x3b, 0x56f, 0x56b, 0x580,
-0x561, 0x56f, 0x56b, 0x3b, 0x565, 0x580, 0x56f, 0x578, 0x582, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x565, 0x580, 0x565, 0x584, 0x577,
-0x561, 0x562, 0x569, 0x56b, 0x3b, 0x579, 0x578, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x570, 0x56b, 0x576, 0x563,
-0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x578, 0x582, 0x580, 0x562, 0x561, 0x569, 0x3b, 0x577, 0x561, 0x562, 0x561, 0x569, 0x3b, 0x53f,
-0x580, 0x3b, 0x535, 0x56f, 0x3b, 0x535, 0x580, 0x3b, 0x549, 0x580, 0x3b, 0x540, 0x563, 0x3b, 0x548, 0x582, 0x3b, 0x547, 0x562, 0x3b,
-0x53f, 0x3b, 0x535, 0x3b, 0x535, 0x3b, 0x549, 0x3b, 0x540, 0x3b, 0x548, 0x582, 0x3b, 0x547, 0x3b, 0x9f0, 0x9ac, 0x9bf, 0x3b, 0x9b8,
-0x9cb, 0x9ae, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, 0x9aa, 0x9a4,
-0x9bf, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x3b, 0x9a6, 0x9c7, 0x993, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b8,
-0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be,
-0x9f0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x9ac,
-0x9be, 0x9f0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x42, 0x2e, 0x3b, 0x42, 0x2e, 0x45, 0x2e, 0x3b, 0xc7, 0x2e,
-0x41, 0x2e, 0x3b, 0xc7, 0x2e, 0x3b, 0x43, 0x2e, 0x41, 0x2e, 0x3b, 0x43, 0x2e, 0x3b, 0x15e, 0x2e, 0x3b, 0x62, 0x61, 0x7a,
-0x61, 0x72, 0x3b, 0x62, 0x61, 0x7a, 0x61, 0x72, 0x20, 0x65, 0x72, 0x74, 0x259, 0x73, 0x69, 0x3b, 0xe7, 0x259, 0x72, 0x15f,
-0x259, 0x6e, 0x62, 0x259, 0x20, 0x61, 0x78, 0x15f, 0x61, 0x6d, 0x131, 0x3b, 0xe7, 0x259, 0x72, 0x15f, 0x259, 0x6e, 0x62, 0x259,
-0x3b, 0x63, 0xfc, 0x6d, 0x259, 0x20, 0x61, 0x78, 0x15f, 0x61, 0x6d, 0x131, 0x3b, 0x63, 0xfc, 0x6d, 0x259, 0x3b, 0x15f, 0x259,
-0x6e, 0x62, 0x259, 0x3b, 0x431, 0x430, 0x437, 0x430, 0x440, 0x3b, 0x431, 0x430, 0x437, 0x430, 0x440, 0x20, 0x435, 0x440, 0x442, 0x4d9,
-0x441, 0x438, 0x3b, 0x447, 0x4d9, 0x440, 0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x20, 0x430, 0x445, 0x448, 0x430, 0x43c, 0x44b, 0x3b, 0x447,
-0x4d9, 0x440, 0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x3b, 0x4b9, 0x4af, 0x43c, 0x4d9, 0x20, 0x430, 0x445, 0x448, 0x430, 0x43c, 0x44b, 0x3b,
-0x4b9, 0x4af, 0x43c, 0x4d9, 0x3b, 0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x3b, 0x49, 0x67, 0x2e, 0x3b, 0x41, 0x6c, 0x2e, 0x3b, 0x41,
-0x72, 0x2e, 0x3b, 0x41, 0x7a, 0x2e, 0x3b, 0x4f, 0x67, 0x2e, 0x3b, 0x4f, 0x72, 0x2e, 0x3b, 0x4c, 0x72, 0x2e, 0x3b, 0x49,
-0x67, 0x61, 0x6e, 0x64, 0x65, 0x61, 0x3b, 0x41, 0x73, 0x74, 0x65, 0x6c, 0x65, 0x68, 0x65, 0x6e, 0x61, 0x3b, 0x41, 0x73,
-0x74, 0x65, 0x61, 0x72, 0x74, 0x65, 0x61, 0x3b, 0x41, 0x73, 0x74, 0x65, 0x61, 0x7a, 0x6b, 0x65, 0x6e, 0x61, 0x3b, 0x4f,
-0x73, 0x74, 0x65, 0x67, 0x75, 0x6e, 0x61, 0x3b, 0x4f, 0x73, 0x74, 0x69, 0x72, 0x61, 0x6c, 0x61, 0x3b, 0x4c, 0x61, 0x72,
-0x75, 0x6e, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x4f, 0x3b, 0x4f, 0x3b, 0x4c,
-0x3b, 0x69, 0x67, 0x2e, 0x3b, 0x61, 0x6c, 0x2e, 0x3b, 0x61, 0x72, 0x2e, 0x3b, 0x61, 0x7a, 0x2e, 0x3b, 0x6f, 0x67, 0x2e,
-0x3b, 0x6f, 0x72, 0x2e, 0x3b, 0x6c, 0x72, 0x2e, 0x3b, 0x69, 0x67, 0x61, 0x6e, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74,
-0x65, 0x6c, 0x65, 0x68, 0x65, 0x6e, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x61, 0x72, 0x74, 0x65, 0x61, 0x3b, 0x61, 0x73,
-0x74, 0x65, 0x61, 0x7a, 0x6b, 0x65, 0x6e, 0x61, 0x3b, 0x6f, 0x73, 0x74, 0x65, 0x67, 0x75, 0x6e, 0x61, 0x3b, 0x6f, 0x73,
-0x74, 0x69, 0x72, 0x61, 0x6c, 0x61, 0x3b, 0x6c, 0x61, 0x72, 0x75, 0x6e, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x9b0, 0x9ac, 0x9bf,
-0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd,
-0x9aa, 0x9a4, 0x9bf, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x3b, 0x9b0, 0x9ac, 0x9bf, 0x9ac, 0x9be, 0x9b0,
-0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c1, 0x9a7,
-0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd,
-0x9b0, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x3b, 0x9ae, 0x3b, 0x9ac,
-0x9c1, 0x3b, 0x9ac, 0x9c3, 0x3b, 0x9b6, 0x9c1, 0x3b, 0x9b6, 0x3b, 0x9b0, 0x9ac, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x9ae,
-0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9b0, 0x3b,
-0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, 0x9ac, 0x9be, 0x9b0,
-0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0x3b, 0xf58, 0xf72, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42,
-0xf0b, 0x3b, 0xf55, 0xf74, 0xf62, 0xf0b, 0x3b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0x3b, 0xf49, 0xf72,
-0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58, 0xf72, 0xf42, 0xf0b,
-0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b,
-0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf42,
-0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b,
-0x3b, 0xf5f, 0xfb3, 0x3b, 0xf58, 0xf72, 0xf62, 0x3b, 0xf63, 0xfb7, 0xf42, 0x3b, 0xf55, 0xf74, 0xf62, 0x3b, 0xf66, 0xf44, 0xfb6, 0x3b,
-0xf66, 0xfa4, 0xf7a, 0xf53, 0x3b, 0xf49, 0xf72, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x65, 0x75, 0x2e,
-0x3b, 0x4d, 0x65, 0x72, 0x2e, 0x3b, 0x59, 0x61, 0x6f, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x2e, 0x3b, 0x53, 0x61, 0x64, 0x2e,
-0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68, 0x3b, 0x4d, 0x65, 0x72, 0x63,
-0x2bc, 0x68, 0x65, 0x72, 0x3b, 0x59, 0x61, 0x6f, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x53, 0x61, 0x64,
-0x6f, 0x72, 0x6e, 0x3b, 0x53, 0x75, 0x3b, 0x4c, 0x3b, 0x4d, 0x7a, 0x3b, 0x4d, 0x63, 0x3b, 0x59, 0x3b, 0x47, 0x3b, 0x53,
-0x61, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b,
-0x441, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44f, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x43d, 0x438, 0x43a,
-0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x44f, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x44a,
-0x440, 0x442, 0x44a, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x44a, 0x43a, 0x3b, 0x441, 0x44a, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x3b,
-0x43f, 0x3b, 0x432, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a, 0x1039, 0x1002, 0x1014, 0x103d,
-0x1031, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a, 0x1039, 0x101c, 0x102c, 0x3b, 0x1021, 0x1004, 0x103a, 0x1039, 0x1002, 0x102b, 0x3b, 0x1017, 0x102f, 0x1012,
-0x1039, 0x1013, 0x101f, 0x1030, 0x1038, 0x3b, 0x1000, 0x103c, 0x102c, 0x101e, 0x1015, 0x1010, 0x1031, 0x1038, 0x3b, 0x101e, 0x1031, 0x102c, 0x1000, 0x103c,
-0x102c, 0x3b, 0x1005, 0x1014, 0x1031, 0x3b, 0x1010, 0x3b, 0x1010, 0x3b, 0x1021, 0x3b, 0x1017, 0x3b, 0x1000, 0x3b, 0x101e, 0x3b, 0x1005, 0x3b,
-0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x430, 0x45e, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x446, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431,
-0x3b, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b, 0x44f, 0x3b, 0x43f, 0x430, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b, 0x430, 0x43a, 0x3b,
-0x430, 0x45e, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x435, 0x440, 0x430, 0x434, 0x430, 0x3b, 0x447, 0x430, 0x446, 0x432, 0x435,
-0x440, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x456, 0x446, 0x430, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x3b, 0x43f,
-0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x17a2, 0x17b6, 0x1791, 0x17b7, 0x178f, 0x17d2, 0x1799, 0x3b, 0x1785,
-0x17d0, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2, 0x1782, 0x17b6, 0x179a, 0x3b, 0x1796, 0x17bb, 0x1792, 0x3b, 0x1796, 0x17d2, 0x179a, 0x17a0,
-0x179f, 0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x179f, 0x17bb, 0x1780, 0x17d2, 0x179a, 0x3b, 0x179f, 0x17c5, 0x179a, 0x17cd, 0x3b, 0x17a2, 0x17b6,
-0x3b, 0x1785, 0x3b, 0x17a2, 0x3b, 0x1796, 0x17bb, 0x3b, 0x1796, 0x17d2, 0x179a, 0x3b, 0x179f, 0x17bb, 0x3b, 0x179f, 0x3b, 0x64, 0x67, 0x2e,
-0x3b, 0x64, 0x6c, 0x2e, 0x3b, 0x64, 0x74, 0x2e, 0x3b, 0x64, 0x63, 0x2e, 0x3b, 0x64, 0x6a, 0x2e, 0x3b, 0x64, 0x76, 0x2e,
-0x3b, 0x64, 0x73, 0x2e, 0x3b, 0x64, 0x69, 0x75, 0x6d, 0x65, 0x6e, 0x67, 0x65, 0x3b, 0x64, 0x69, 0x6c, 0x6c, 0x75, 0x6e,
-0x73, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x65, 0x63, 0x72, 0x65, 0x73, 0x3b, 0x64,
-0x69, 0x6a, 0x6f, 0x75, 0x73, 0x3b, 0x64, 0x69, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x73, 0x73,
-0x61, 0x62, 0x74, 0x65, 0x3b, 0x64, 0x67, 0x3b, 0x64, 0x6c, 0x3b, 0x64, 0x74, 0x3b, 0x64, 0x63, 0x3b, 0x64, 0x6a, 0x3b,
-0x64, 0x76, 0x3b, 0x64, 0x73, 0x3b, 0x5468, 0x65e5, 0x3b, 0x5468, 0x4e00, 0x3b, 0x5468, 0x4e8c, 0x3b, 0x5468, 0x4e09, 0x3b, 0x5468, 0x56db,
-0x3b, 0x5468, 0x4e94, 0x3b, 0x5468, 0x516d, 0x3b, 0x661f, 0x671f, 0x65e5, 0x3b, 0x661f, 0x671f, 0x4e00, 0x3b, 0x661f, 0x671f, 0x4e8c, 0x3b, 0x661f,
-0x671f, 0x4e09, 0x3b, 0x661f, 0x671f, 0x56db, 0x3b, 0x661f, 0x671f, 0x4e94, 0x3b, 0x661f, 0x671f, 0x516d, 0x3b, 0x65e5, 0x3b, 0x4e00, 0x3b, 0x4e8c,
-0x3b, 0x4e09, 0x3b, 0x56db, 0x3b, 0x4e94, 0x3b, 0x516d, 0x3b, 0x9031, 0x65e5, 0x3b, 0x9031, 0x4e00, 0x3b, 0x9031, 0x4e8c, 0x3b, 0x9031, 0x4e09,
-0x3b, 0x9031, 0x56db, 0x3b, 0x9031, 0x4e94, 0x3b, 0x9031, 0x516d, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74,
-0x6f, 0x3b, 0x73, 0x72, 0x69, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x3b, 0x6e, 0x65,
-0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75,
-0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74,
-0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b,
-0x75, 0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0x55, 0x3b, 0x53, 0x3b, 0x10c, 0x3b,
-0x50, 0x3b, 0x53, 0x3b, 0x6e, 0x65, 0x3b, 0x70, 0x6f, 0x3b, 0xfa, 0x74, 0x3b, 0x73, 0x74, 0x3b, 0x10d, 0x74, 0x3b, 0x70,
-0xe1, 0x3b, 0x73, 0x6f, 0x3b, 0x6e, 0x65, 0x64, 0x11b, 0x6c, 0x65, 0x3b, 0x70, 0x6f, 0x6e, 0x64, 0x11b, 0x6c, 0xed, 0x3b,
-0xfa, 0x74, 0x65, 0x72, 0xfd, 0x3b, 0x73, 0x74, 0x159, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x74, 0x76, 0x72, 0x74, 0x65, 0x6b,
-0x3b, 0x70, 0xe1, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0xda, 0x3b,
-0x53, 0x3b, 0x10c, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x73, 0xf8, 0x6e, 0x3b, 0x6d, 0x61, 0x6e, 0x3b, 0x74, 0x69, 0x72, 0x3b,
-0x6f, 0x6e, 0x73, 0x3b, 0x74, 0x6f, 0x72, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0xf8, 0x72, 0x3b, 0x73, 0xf8, 0x6e, 0x64,
-0x61, 0x67, 0x3b, 0x6d, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x69, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e,
-0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b,
-0x6c, 0xf8, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x4c,
-0x3b, 0x73, 0xf8, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x6e, 0x2e, 0x3b, 0x74, 0x69, 0x72, 0x2e, 0x3b, 0x6f, 0x6e, 0x73, 0x2e,
-0x3b, 0x74, 0x6f, 0x72, 0x2e, 0x3b, 0x66, 0x72, 0x65, 0x2e, 0x3b, 0x6c, 0xf8, 0x72, 0x2e, 0x3b, 0x7a, 0x6f, 0x3b, 0x6d,
-0x61, 0x3b, 0x64, 0x69, 0x3b, 0x77, 0x6f, 0x3b, 0x64, 0x6f, 0x3b, 0x76, 0x72, 0x3b, 0x7a, 0x61, 0x3b, 0x7a, 0x6f, 0x6e,
-0x64, 0x61, 0x67, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x64, 0x69, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b,
-0x77, 0x6f, 0x65, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x64, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x76,
-0x72, 0x69, 0x6a, 0x64, 0x61, 0x67, 0x3b, 0x7a, 0x61, 0x74, 0x65, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x5a, 0x3b, 0x4d, 0x3b,
-0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x5a, 0x3b, 0x53, 0x75, 0x6e, 0x2e, 0x3b, 0x4d, 0x6f, 0x6e, 0x2e, 0x3b,
-0x54, 0x75, 0x65, 0x2e, 0x3b, 0x57, 0x65, 0x64, 0x2e, 0x3b, 0x54, 0x68, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x69, 0x2e, 0x3b,
-0x53, 0x61, 0x74, 0x2e, 0x3b, 0x53, 0x75, 0x2e, 0x3b, 0x4d, 0x2e, 0x3b, 0x54, 0x75, 0x2e, 0x3b, 0x57, 0x2e, 0x3b, 0x54,
-0x68, 0x2e, 0x3b, 0x46, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x50, 0x3b, 0x45, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b,
-0x52, 0x3b, 0x4c, 0x3b, 0x70, 0xfc, 0x68, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x65, 0x73, 0x6d, 0x61, 0x73, 0x70, 0xe4,
-0x65, 0x76, 0x3b, 0x74, 0x65, 0x69, 0x73, 0x69, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6b, 0x6f, 0x6c, 0x6d, 0x61, 0x70, 0xe4,
-0x65, 0x76, 0x3b, 0x6e, 0x65, 0x6c, 0x6a, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x72, 0x65, 0x65, 0x64, 0x65, 0x3b, 0x6c,
-0x61, 0x75, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x73, 0x75, 0x6e, 0x3b, 0x6d, 0xe1, 0x6e, 0x3b, 0x74, 0xfd, 0x73, 0x3b, 0x6d,
-0x69, 0x6b, 0x3b, 0x68, 0xf3, 0x73, 0x3b, 0x66, 0x72, 0xed, 0x3b, 0x6c, 0x65, 0x79, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75,
-0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, 0x6e, 0x61, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x74, 0xfd, 0x73, 0x64,
-0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0x6b, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x68, 0xf3, 0x73, 0x64, 0x61,
-0x67, 0x75, 0x72, 0x3b, 0x66, 0x72, 0xed, 0x67, 0x67, 0x6a, 0x61, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6c, 0x65, 0x79,
-0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x46,
-0x3b, 0x4c, 0x3b, 0x73, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0x74, 0xfd, 0x73, 0x2e, 0x3b, 0x6d, 0x69,
-0x6b, 0x2e, 0x3b, 0x68, 0xf3, 0x73, 0x2e, 0x3b, 0x66, 0x72, 0xed, 0x2e, 0x3b, 0x6c, 0x65, 0x79, 0x2e, 0x3b, 0x73, 0x75,
-0x3b, 0x6d, 0x61, 0x3b, 0x74, 0x69, 0x3b, 0x6b, 0x65, 0x3b, 0x74, 0x6f, 0x3b, 0x70, 0x65, 0x3b, 0x6c, 0x61, 0x3b, 0x73,
-0x75, 0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x74,
-0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76, 0x69, 0x69, 0x6b, 0x6b, 0x6f, 0x3b, 0x74,
-0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x70, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x6c, 0x61, 0x75,
-0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x50, 0x3b, 0x4c, 0x3b,
-0x73, 0x75, 0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x61, 0x6e, 0x74, 0x61,
-0x69, 0x6e, 0x61, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76,
-0x69, 0x69, 0x6b, 0x6b, 0x6f, 0x6e, 0x61, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x70, 0x65,
-0x72, 0x6a, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6c, 0x61, 0x75, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61,
-0x3b, 0x64, 0x69, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x65, 0x72, 0x2e,
-0x3b, 0x6a, 0x65, 0x75, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e, 0x3b, 0x73, 0x61, 0x6d, 0x2e, 0x3b, 0x64, 0x69, 0x6d, 0x61,
-0x6e, 0x63, 0x68, 0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72,
-0x63, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x6a, 0x65, 0x75, 0x64, 0x69, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x69,
-0x3b, 0x73, 0x61, 0x6d, 0x65, 0x64, 0x69, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x56, 0x3b,
-0x53, 0x3b, 0x73, 0x69, 0x3b, 0x6d, 0x6f, 0x3b, 0x74, 0x69, 0x3b, 0x77, 0x6f, 0x3b, 0x74, 0x6f, 0x3b, 0x66, 0x72, 0x3b,
-0x73, 0x6f, 0x3b, 0x73, 0x6e, 0x65, 0x69, 0x6e, 0x3b, 0x6d, 0x6f, 0x61, 0x6e, 0x64, 0x65, 0x69, 0x3b, 0x74, 0x69, 0x69,
-0x73, 0x64, 0x65, 0x69, 0x3b, 0x77, 0x6f, 0x61, 0x6e, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x74, 0x6f, 0x6e, 0x67, 0x65, 0x72,
-0x73, 0x64, 0x65, 0x69, 0x3b, 0x66, 0x72, 0x65, 0x65, 0x64, 0x3b, 0x73, 0x6e, 0x65, 0x6f, 0x6e, 0x3b, 0x44, 0x69, 0x44,
-0x3b, 0x44, 0x69, 0x4c, 0x3b, 0x44, 0x69, 0x4d, 0x3b, 0x44, 0x69, 0x43, 0x3b, 0x44, 0x69, 0x61, 0x3b, 0x44, 0x69, 0x68,
-0x3b, 0x44, 0x69, 0x53, 0x3b, 0x44, 0x69, 0x44, 0xf2, 0x6d, 0x68, 0x6e, 0x61, 0x69, 0x63, 0x68, 0x3b, 0x44, 0x69, 0x4c,
-0x75, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x4d, 0xe0, 0x69, 0x72, 0x74, 0x3b, 0x44, 0x69, 0x43, 0x69, 0x61, 0x64, 0x61,
-0x69, 0x6e, 0x3b, 0x44, 0x69, 0x61, 0x72, 0x44, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x68, 0x41, 0x6f, 0x69, 0x6e,
-0x65, 0x3b, 0x44, 0x69, 0x53, 0x61, 0x74, 0x68, 0x61, 0x69, 0x72, 0x6e, 0x65, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b,
-0x43, 0x3b, 0x41, 0x3b, 0x48, 0x3b, 0x53, 0x3b, 0x44, 0x6f, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b,
-0x4d, 0xe9, 0x72, 0x3b, 0x58, 0x6f, 0x76, 0x3b, 0x56, 0x65, 0x6e, 0x3b, 0x53, 0xe1, 0x62, 0x3b, 0x44, 0x6f, 0x6d, 0x69,
-0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0xe9, 0x72, 0x63,
-0x6f, 0x72, 0x65, 0x73, 0x3b, 0x58, 0x6f, 0x76, 0x65, 0x73, 0x3b, 0x56, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x53, 0xe1,
-0x62, 0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64,
-0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0xe9, 0x72, 0x3b, 0x78, 0x6f, 0x76, 0x3b,
-0x76, 0x65, 0x6e, 0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x73,
-0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0xe9, 0x72, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x3b, 0x78, 0x6f, 0x76,
-0x65, 0x73, 0x3b, 0x76, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x10d9, 0x10d5, 0x10d8,
+0x4a, 0x69, 0x6d, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x53, 0x61, 0x6e, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x44, 0x3b, 0x57, 0x3b,
+0x51, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x53, 0x6f, 0x2e, 0x3b, 0x4d, 0x61, 0x2e, 0x3b, 0x44, 0x69,
+0x2e, 0x3b, 0x57, 0x6f, 0x2e, 0x3b, 0x44, 0x6f, 0x2e, 0x3b, 0x56, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x53, 0x6f,
+0x6e, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x69, 0x6e, 0x73, 0x64, 0x61, 0x67,
+0x3b, 0x57, 0x6f, 0x65, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x61, 0x67, 0x3b,
+0x56, 0x72, 0x79, 0x64, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x74, 0x65, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x53, 0x3b, 0x4d, 0x3b,
+0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x44, 0x69, 0x65, 0x3b, 0x48, 0xeb, 0x6e, 0x3b, 0x4d, 0x61,
+0x72, 0x3b, 0x4d, 0xeb, 0x72, 0x3b, 0x45, 0x6e, 0x6a, 0x3b, 0x50, 0x72, 0x65, 0x3b, 0x53, 0x68, 0x74, 0x3b, 0x45, 0x20,
+0x64, 0x69, 0x65, 0x6c, 0x3b, 0x45, 0x20, 0x68, 0xeb, 0x6e, 0xeb, 0x3b, 0x45, 0x20, 0x6d, 0x61, 0x72, 0x74, 0xeb, 0x3b,
+0x45, 0x20, 0x6d, 0xeb, 0x72, 0x6b, 0x75, 0x72, 0xeb, 0x3b, 0x45, 0x20, 0x65, 0x6e, 0x6a, 0x74, 0x65, 0x3b, 0x45, 0x20,
+0x70, 0x72, 0x65, 0x6d, 0x74, 0x65, 0x3b, 0x45, 0x20, 0x73, 0x68, 0x74, 0x75, 0x6e, 0xeb, 0x3b, 0x44, 0x3b, 0x48, 0x3b,
+0x4d, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x65, 0x20, 0x64, 0x69, 0x65, 0x6c, 0x3b, 0x65, 0x20, 0x68,
+0xeb, 0x6e, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x74, 0xeb, 0x3b, 0x65, 0x20, 0x6d, 0xeb, 0x72, 0x6b, 0x75, 0x72,
+0xeb, 0x3b, 0x65, 0x20, 0x65, 0x6e, 0x6a, 0x74, 0x65, 0x3b, 0x65, 0x20, 0x70, 0x72, 0x65, 0x6d, 0x74, 0x65, 0x3b, 0x65,
+0x20, 0x73, 0x68, 0x74, 0x75, 0x6e, 0xeb, 0x3b, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230, 0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x3b, 0x1228,
+0x1261, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245, 0x12f3, 0x121c, 0x3b, 0x12a5, 0x1211, 0x12f5, 0x3b, 0x1230,
+0x129e, 0x3b, 0x121b, 0x12ad, 0x1230, 0x129e, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1210, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1265, 0x3b, 0x1245,
+0x12f3, 0x121c, 0x3b, 0x12a5, 0x3b, 0x1230, 0x3b, 0x121b, 0x3b, 0x1228, 0x3b, 0x1210, 0x3b, 0x12d3, 0x3b, 0x1245, 0x3b, 0x627, 0x644, 0x623,
+0x62d, 0x62f, 0x3b, 0x627, 0x644, 0x627, 0x62b, 0x646, 0x64a, 0x646, 0x3b, 0x627, 0x644, 0x62b, 0x644, 0x627, 0x62b, 0x627, 0x621, 0x3b,
+0x627, 0x644, 0x623, 0x631, 0x628, 0x639, 0x627, 0x621, 0x3b, 0x627, 0x644, 0x62e, 0x645, 0x64a, 0x633, 0x3b, 0x627, 0x644, 0x62c, 0x645,
+0x639, 0x629, 0x3b, 0x627, 0x644, 0x633, 0x628, 0x62a, 0x3b, 0x62d, 0x3b, 0x646, 0x3b, 0x62b, 0x3b, 0x631, 0x3b, 0x62e, 0x3b, 0x62c,
+0x3b, 0x633, 0x3b, 0x56f, 0x56b, 0x580, 0x3b, 0x565, 0x580, 0x56f, 0x3b, 0x565, 0x580, 0x584, 0x3b, 0x579, 0x580, 0x584, 0x3b, 0x570,
+0x576, 0x563, 0x3b, 0x578, 0x582, 0x580, 0x3b, 0x577, 0x562, 0x569, 0x3b, 0x56f, 0x56b, 0x580, 0x561, 0x56f, 0x56b, 0x3b, 0x565, 0x580,
+0x56f, 0x578, 0x582, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x565, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x579,
+0x578, 0x580, 0x565, 0x584, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b, 0x570, 0x56b, 0x576, 0x563, 0x577, 0x561, 0x562, 0x569, 0x56b, 0x3b,
+0x578, 0x582, 0x580, 0x562, 0x561, 0x569, 0x3b, 0x577, 0x561, 0x562, 0x561, 0x569, 0x3b, 0x53f, 0x3b, 0x535, 0x3b, 0x535, 0x3b, 0x549,
+0x3b, 0x540, 0x3b, 0x548, 0x3b, 0x547, 0x3b, 0x9f0, 0x9ac, 0x9bf, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2,
+0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x3b,
+0x9b6, 0x9a8, 0x9bf, 0x3b, 0x9a6, 0x9c7, 0x993, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ae, 0x999,
+0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd, 0x9aa,
+0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9f0, 0x9ac, 0x9be, 0x9f0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be,
+0x9f0, 0x3b, 0x42, 0x2e, 0x3b, 0x42, 0x2e, 0x45, 0x2e, 0x3b, 0xc7, 0x2e, 0x41, 0x2e, 0x3b, 0xc7, 0x2e, 0x3b, 0x43, 0x2e,
+0x41, 0x2e, 0x3b, 0x43, 0x2e, 0x3b, 0x15e, 0x2e, 0x3b, 0x62, 0x61, 0x7a, 0x61, 0x72, 0x3b, 0x62, 0x61, 0x7a, 0x61, 0x72,
+0x20, 0x65, 0x72, 0x74, 0x259, 0x73, 0x69, 0x3b, 0xe7, 0x259, 0x72, 0x15f, 0x259, 0x6e, 0x62, 0x259, 0x20, 0x61, 0x78, 0x15f,
+0x61, 0x6d, 0x131, 0x3b, 0xe7, 0x259, 0x72, 0x15f, 0x259, 0x6e, 0x62, 0x259, 0x3b, 0x63, 0xfc, 0x6d, 0x259, 0x20, 0x61, 0x78,
+0x15f, 0x61, 0x6d, 0x131, 0x3b, 0x63, 0xfc, 0x6d, 0x259, 0x3b, 0x15f, 0x259, 0x6e, 0x62, 0x259, 0x3b, 0x411, 0x2e, 0x3b, 0x411,
+0x2e, 0x415, 0x2e, 0x3b, 0x427, 0x2e, 0x410, 0x2e, 0x3b, 0x427, 0x2e, 0x3b, 0x4b8, 0x2e, 0x410, 0x2e, 0x3b, 0x4b8, 0x2e, 0x3b,
+0x428, 0x2e, 0x3b, 0x431, 0x430, 0x437, 0x430, 0x440, 0x3b, 0x431, 0x430, 0x437, 0x430, 0x440, 0x20, 0x435, 0x440, 0x442, 0x4d9, 0x441,
+0x438, 0x3b, 0x447, 0x4d9, 0x440, 0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x20, 0x430, 0x445, 0x448, 0x430, 0x43c, 0x44b, 0x3b, 0x447, 0x4d9,
+0x440, 0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x3b, 0x4b9, 0x4af, 0x43c, 0x4d9, 0x20, 0x430, 0x445, 0x448, 0x430, 0x43c, 0x44b, 0x3b, 0x4b9,
+0x4af, 0x43c, 0x4d9, 0x3b, 0x448, 0x4d9, 0x43d, 0x431, 0x4d9, 0x3b, 0x69, 0x67, 0x2e, 0x3b, 0x61, 0x6c, 0x2e, 0x3b, 0x61, 0x72,
+0x2e, 0x3b, 0x61, 0x7a, 0x2e, 0x3b, 0x6f, 0x67, 0x2e, 0x3b, 0x6f, 0x72, 0x2e, 0x3b, 0x6c, 0x72, 0x2e, 0x3b, 0x49, 0x67,
+0x61, 0x6e, 0x64, 0x65, 0x61, 0x3b, 0x41, 0x73, 0x74, 0x65, 0x6c, 0x65, 0x68, 0x65, 0x6e, 0x61, 0x3b, 0x41, 0x73, 0x74,
+0x65, 0x61, 0x72, 0x74, 0x65, 0x61, 0x3b, 0x41, 0x73, 0x74, 0x65, 0x61, 0x7a, 0x6b, 0x65, 0x6e, 0x61, 0x3b, 0x4f, 0x73,
+0x74, 0x65, 0x67, 0x75, 0x6e, 0x61, 0x3b, 0x4f, 0x73, 0x74, 0x69, 0x72, 0x61, 0x6c, 0x61, 0x3b, 0x4c, 0x61, 0x72, 0x75,
+0x6e, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x49, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x4f, 0x3b, 0x4f, 0x3b, 0x4c, 0x3b,
+0x69, 0x67, 0x61, 0x6e, 0x64, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x6c, 0x65, 0x68, 0x65, 0x6e, 0x61, 0x3b, 0x61,
+0x73, 0x74, 0x65, 0x61, 0x72, 0x74, 0x65, 0x61, 0x3b, 0x61, 0x73, 0x74, 0x65, 0x61, 0x7a, 0x6b, 0x65, 0x6e, 0x61, 0x3b,
+0x6f, 0x73, 0x74, 0x65, 0x67, 0x75, 0x6e, 0x61, 0x3b, 0x6f, 0x73, 0x74, 0x69, 0x72, 0x61, 0x6c, 0x61, 0x3b, 0x6c, 0x61,
+0x72, 0x75, 0x6e, 0x62, 0x61, 0x74, 0x61, 0x3b, 0x9b0, 0x9ac, 0x9bf, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997,
+0x9b2, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0,
+0x3b, 0x9b6, 0x9a8, 0x9bf, 0x3b, 0x9b0, 0x9ac, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae,
+0x999, 0x9cd, 0x997, 0x9b2, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b7, 0x9cd,
+0x9aa, 0x9a4, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac,
+0x9be, 0x9b0, 0x3b, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x3b, 0x9ae, 0x3b, 0x9ac, 0x9c1, 0x3b, 0x9ac, 0x9c3, 0x3b, 0x9b6, 0x9c1, 0x3b, 0x9b6,
+0x3b, 0x9b0, 0x9ac, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b8, 0x9cb, 0x9ae, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ae, 0x999, 0x9cd, 0x997, 0x9b2,
+0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c1, 0x9a7, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9ac, 0x9c3, 0x9b9, 0x9b8, 0x9cd, 0x9aa, 0x9a4, 0x9bf, 0x9ac,
+0x9be, 0x9b0, 0x3b, 0x9b6, 0x9c1, 0x995, 0x9cd, 0x9b0, 0x9ac, 0x9be, 0x9b0, 0x3b, 0x9b6, 0x9a8, 0x9bf, 0x9ac, 0x9be, 0x9b0, 0x3b, 0xf5f,
+0xfb3, 0xf0b, 0x3b, 0xf58, 0xf72, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62, 0xf0b, 0x3b, 0xf66, 0xf44,
+0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0x3b, 0xf49, 0xf72, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f, 0xfb3, 0xf0b,
+0xf56, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b,
+0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42,
+0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54,
+0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0x3b, 0xf58, 0xf72, 0xf62, 0x3b, 0xf63,
+0xfb7, 0xf42, 0x3b, 0xf55, 0xf74, 0xf62, 0x3b, 0xf66, 0xf44, 0xfb6, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0x3b, 0xf49, 0xf72, 0x3b, 0x53,
+0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x65, 0x75, 0x2e, 0x3b, 0x4d, 0x65, 0x72, 0x2e, 0x3b, 0x59, 0x61, 0x6f,
+0x75, 0x3b, 0x47, 0x77, 0x65, 0x2e, 0x3b, 0x53, 0x61, 0x64, 0x2e, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b,
+0x4d, 0x65, 0x75, 0x72, 0x7a, 0x68, 0x3b, 0x4d, 0x65, 0x72, 0x63, 0x2bc, 0x68, 0x65, 0x72, 0x3b, 0x59, 0x61, 0x6f, 0x75,
+0x3b, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x53, 0x61, 0x64, 0x6f, 0x72, 0x6e, 0x3b, 0x53, 0x75, 0x3b, 0x4c, 0x3b,
+0x4d, 0x7a, 0x3b, 0x4d, 0x63, 0x3b, 0x59, 0x3b, 0x47, 0x3b, 0x53, 0x61, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x432,
+0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44f,
+0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b,
+0x441, 0x440, 0x44f, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x44a, 0x440, 0x442, 0x44a, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x44a,
+0x43a, 0x3b, 0x441, 0x44a, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x432, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f,
+0x3b, 0x441, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a, 0x1039, 0x1002, 0x1014, 0x103d, 0x1031, 0x3b, 0x1010, 0x1014, 0x1004, 0x103a, 0x1039, 0x101c, 0x102c,
+0x3b, 0x1021, 0x1004, 0x103a, 0x1039, 0x1002, 0x102b, 0x3b, 0x1017, 0x102f, 0x1012, 0x1039, 0x1013, 0x101f, 0x1030, 0x1038, 0x3b, 0x1000, 0x103c, 0x102c,
+0x101e, 0x1015, 0x1010, 0x1031, 0x1038, 0x3b, 0x101e, 0x1031, 0x102c, 0x1000, 0x103c, 0x102c, 0x3b, 0x1005, 0x1014, 0x1031, 0x3b, 0x1010, 0x3b, 0x1010,
+0x3b, 0x1021, 0x3b, 0x1017, 0x3b, 0x1000, 0x3b, 0x101e, 0x3b, 0x1005, 0x3b, 0x43d, 0x434, 0x3b, 0x43f, 0x43d, 0x3b, 0x430, 0x45e, 0x3b,
+0x441, 0x440, 0x3b, 0x447, 0x446, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b, 0x44f, 0x3b,
+0x43f, 0x430, 0x43d, 0x44f, 0x434, 0x437, 0x435, 0x43b, 0x430, 0x43a, 0x3b, 0x430, 0x45e, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441,
+0x435, 0x440, 0x430, 0x434, 0x430, 0x3b, 0x447, 0x430, 0x446, 0x432, 0x435, 0x440, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x456, 0x446, 0x430,
+0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x430, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b,
+0x441, 0x3b, 0x17a2, 0x17b6, 0x1791, 0x17b7, 0x178f, 0x17d2, 0x1799, 0x3b, 0x1785, 0x17d0, 0x1793, 0x17d2, 0x1791, 0x3b, 0x17a2, 0x1784, 0x17d2, 0x1782,
+0x17b6, 0x179a, 0x3b, 0x1796, 0x17bb, 0x1792, 0x3b, 0x1796, 0x17d2, 0x179a, 0x17a0, 0x179f, 0x17d2, 0x1794, 0x178f, 0x17b7, 0x17cd, 0x3b, 0x179f, 0x17bb,
+0x1780, 0x17d2, 0x179a, 0x3b, 0x179f, 0x17c5, 0x179a, 0x17cd, 0x3b, 0x17a2, 0x3b, 0x1785, 0x3b, 0x17a2, 0x3b, 0x1796, 0x3b, 0x1796, 0x3b, 0x179f,
+0x3b, 0x179f, 0x3b, 0x64, 0x67, 0x2e, 0x3b, 0x64, 0x6c, 0x2e, 0x3b, 0x64, 0x74, 0x2e, 0x3b, 0x64, 0x63, 0x2e, 0x3b, 0x64,
+0x6a, 0x2e, 0x3b, 0x64, 0x76, 0x2e, 0x3b, 0x64, 0x73, 0x2e, 0x3b, 0x64, 0x69, 0x75, 0x6d, 0x65, 0x6e, 0x67, 0x65, 0x3b,
+0x64, 0x69, 0x6c, 0x6c, 0x75, 0x6e, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x72, 0x74, 0x73, 0x3b, 0x64, 0x69, 0x6d, 0x65,
+0x63, 0x72, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x6a, 0x6f, 0x75, 0x73, 0x3b, 0x64, 0x69, 0x76, 0x65, 0x6e, 0x64, 0x72, 0x65,
+0x73, 0x3b, 0x64, 0x69, 0x73, 0x73, 0x61, 0x62, 0x74, 0x65, 0x3b, 0x64, 0x67, 0x3b, 0x64, 0x6c, 0x3b, 0x64, 0x74, 0x3b,
+0x64, 0x63, 0x3b, 0x64, 0x6a, 0x3b, 0x64, 0x76, 0x3b, 0x64, 0x73, 0x3b, 0x5468, 0x65e5, 0x3b, 0x5468, 0x4e00, 0x3b, 0x5468, 0x4e8c,
+0x3b, 0x5468, 0x4e09, 0x3b, 0x5468, 0x56db, 0x3b, 0x5468, 0x4e94, 0x3b, 0x5468, 0x516d, 0x3b, 0x661f, 0x671f, 0x65e5, 0x3b, 0x661f, 0x671f, 0x4e00,
+0x3b, 0x661f, 0x671f, 0x4e8c, 0x3b, 0x661f, 0x671f, 0x4e09, 0x3b, 0x661f, 0x671f, 0x56db, 0x3b, 0x661f, 0x671f, 0x4e94, 0x3b, 0x661f, 0x671f, 0x516d,
+0x3b, 0x65e5, 0x3b, 0x4e00, 0x3b, 0x4e8c, 0x3b, 0x4e09, 0x3b, 0x56db, 0x3b, 0x4e94, 0x3b, 0x516d, 0x3b, 0x9031, 0x65e5, 0x3b, 0x9031, 0x4e00,
+0x3b, 0x9031, 0x4e8c, 0x3b, 0x9031, 0x4e09, 0x3b, 0x9031, 0x56db, 0x3b, 0x9031, 0x4e94, 0x3b, 0x9031, 0x516d, 0x3b, 0x6e, 0x65, 0x64, 0x3b,
+0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x69, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b,
+0x73, 0x75, 0x62, 0x3b, 0x6e, 0x65, 0x64, 0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x6a, 0x65,
+0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b,
+0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74,
+0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x75, 0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x4e, 0x3b, 0x50, 0x3b,
+0x55, 0x3b, 0x53, 0x3b, 0x10c, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x6e, 0x65, 0x3b, 0x70, 0x6f, 0x3b, 0xfa, 0x74, 0x3b, 0x73,
+0x74, 0x3b, 0x10d, 0x74, 0x3b, 0x70, 0xe1, 0x3b, 0x73, 0x6f, 0x3b, 0x6e, 0x65, 0x64, 0x11b, 0x6c, 0x65, 0x3b, 0x70, 0x6f,
+0x6e, 0x64, 0x11b, 0x6c, 0xed, 0x3b, 0xfa, 0x74, 0x65, 0x72, 0xfd, 0x3b, 0x73, 0x74, 0x159, 0x65, 0x64, 0x61, 0x3b, 0x10d,
+0x74, 0x76, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0xe1, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b,
+0x4e, 0x3b, 0x50, 0x3b, 0xda, 0x3b, 0x53, 0x3b, 0x10c, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x73, 0xf8, 0x6e, 0x3b, 0x6d, 0x61,
+0x6e, 0x3b, 0x74, 0x69, 0x72, 0x3b, 0x6f, 0x6e, 0x73, 0x3b, 0x74, 0x6f, 0x72, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0xf8,
+0x72, 0x3b, 0x73, 0xf8, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x69, 0x72, 0x73,
+0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66,
+0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0xf8, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4f,
+0x3b, 0x54, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x73, 0xf8, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x6e, 0x2e, 0x3b, 0x74, 0x69, 0x72,
+0x2e, 0x3b, 0x6f, 0x6e, 0x73, 0x2e, 0x3b, 0x74, 0x6f, 0x72, 0x2e, 0x3b, 0x66, 0x72, 0x65, 0x2e, 0x3b, 0x6c, 0xf8, 0x72,
+0x2e, 0x3b, 0x7a, 0x6f, 0x3b, 0x6d, 0x61, 0x3b, 0x64, 0x69, 0x3b, 0x77, 0x6f, 0x3b, 0x64, 0x6f, 0x3b, 0x76, 0x72, 0x3b,
+0x7a, 0x61, 0x3b, 0x7a, 0x6f, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x64, 0x69,
+0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x77, 0x6f, 0x65, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x64, 0x6f, 0x6e, 0x64, 0x65,
+0x72, 0x64, 0x61, 0x67, 0x3b, 0x76, 0x72, 0x69, 0x6a, 0x64, 0x61, 0x67, 0x3b, 0x7a, 0x61, 0x74, 0x65, 0x72, 0x64, 0x61,
+0x67, 0x3b, 0x5a, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x56, 0x3b, 0x5a, 0x3b, 0x53, 0x75, 0x6e, 0x2e,
+0x3b, 0x4d, 0x6f, 0x6e, 0x2e, 0x3b, 0x54, 0x75, 0x65, 0x2e, 0x3b, 0x57, 0x65, 0x64, 0x2e, 0x3b, 0x54, 0x68, 0x75, 0x2e,
+0x3b, 0x46, 0x72, 0x69, 0x2e, 0x3b, 0x53, 0x61, 0x74, 0x2e, 0x3b, 0x53, 0x75, 0x2e, 0x3b, 0x4d, 0x2e, 0x3b, 0x54, 0x75,
+0x2e, 0x3b, 0x57, 0x2e, 0x3b, 0x54, 0x68, 0x2e, 0x3b, 0x46, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x50, 0x3b, 0x45, 0x3b,
+0x54, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x52, 0x3b, 0x4c, 0x3b, 0x70, 0xfc, 0x68, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x65,
+0x73, 0x6d, 0x61, 0x73, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x74, 0x65, 0x69, 0x73, 0x69, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6b,
+0x6f, 0x6c, 0x6d, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x6e, 0x65, 0x6c, 0x6a, 0x61, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x72,
+0x65, 0x65, 0x64, 0x65, 0x3b, 0x6c, 0x61, 0x75, 0x70, 0xe4, 0x65, 0x76, 0x3b, 0x73, 0x75, 0x6e, 0x3b, 0x6d, 0xe1, 0x6e,
+0x3b, 0x74, 0xfd, 0x73, 0x3b, 0x6d, 0x69, 0x6b, 0x3b, 0x68, 0xf3, 0x73, 0x3b, 0x66, 0x72, 0xed, 0x3b, 0x6c, 0x65, 0x79,
+0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, 0x6e, 0x61, 0x64, 0x61, 0x67, 0x75,
+0x72, 0x3b, 0x74, 0xfd, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0x6b, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72,
+0x3b, 0x68, 0xf3, 0x73, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0x72, 0xed, 0x67, 0x67, 0x6a, 0x61, 0x64, 0x61, 0x67,
+0x75, 0x72, 0x3b, 0x6c, 0x65, 0x79, 0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54,
+0x3b, 0x4d, 0x3b, 0x48, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x73, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0x74,
+0xfd, 0x73, 0x2e, 0x3b, 0x6d, 0x69, 0x6b, 0x2e, 0x3b, 0x68, 0xf3, 0x73, 0x2e, 0x3b, 0x66, 0x72, 0xed, 0x2e, 0x3b, 0x6c,
+0x65, 0x79, 0x2e, 0x3b, 0x73, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x74, 0x69, 0x3b, 0x6b, 0x65, 0x3b, 0x74, 0x6f, 0x3b, 0x70,
+0x65, 0x3b, 0x6c, 0x61, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x6d, 0x61, 0x61, 0x6e, 0x61,
+0x6e, 0x74, 0x61, 0x69, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76, 0x69,
+0x69, 0x6b, 0x6b, 0x6f, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61, 0x69, 0x3b, 0x70, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x74,
+0x61, 0x69, 0x3b, 0x6c, 0x61, 0x75, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x54, 0x3b, 0x4b, 0x3b,
+0x54, 0x3b, 0x50, 0x3b, 0x4c, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6d, 0x61,
+0x61, 0x6e, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b,
+0x6b, 0x65, 0x73, 0x6b, 0x69, 0x76, 0x69, 0x69, 0x6b, 0x6b, 0x6f, 0x6e, 0x61, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x74, 0x61,
+0x69, 0x6e, 0x61, 0x3b, 0x70, 0x65, 0x72, 0x6a, 0x61, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x6c, 0x61, 0x75, 0x61,
+0x6e, 0x74, 0x61, 0x69, 0x6e, 0x61, 0x3b, 0x64, 0x69, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72,
+0x2e, 0x3b, 0x6d, 0x65, 0x72, 0x2e, 0x3b, 0x6a, 0x65, 0x75, 0x2e, 0x3b, 0x76, 0x65, 0x6e, 0x2e, 0x3b, 0x73, 0x61, 0x6d,
+0x2e, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72,
+0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x63, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x6a, 0x65, 0x75, 0x64, 0x69, 0x3b, 0x76, 0x65,
+0x6e, 0x64, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x65, 0x64, 0x69, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b,
+0x4d, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x73, 0x69, 0x3b, 0x6d, 0x6f, 0x3b, 0x74, 0x69, 0x3b, 0x77, 0x6f, 0x3b,
+0x74, 0x6f, 0x3b, 0x66, 0x72, 0x3b, 0x73, 0x6f, 0x3b, 0x73, 0x6e, 0x65, 0x69, 0x6e, 0x3b, 0x6d, 0x6f, 0x61, 0x6e, 0x64,
+0x65, 0x69, 0x3b, 0x74, 0x69, 0x69, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x77, 0x6f, 0x61, 0x6e, 0x73, 0x64, 0x65, 0x69, 0x3b,
+0x74, 0x6f, 0x6e, 0x67, 0x65, 0x72, 0x73, 0x64, 0x65, 0x69, 0x3b, 0x66, 0x72, 0x65, 0x65, 0x64, 0x3b, 0x73, 0x6e, 0x65,
+0x6f, 0x6e, 0x3b, 0x44, 0x69, 0x44, 0x3b, 0x44, 0x69, 0x4c, 0x3b, 0x44, 0x69, 0x4d, 0x3b, 0x44, 0x69, 0x43, 0x3b, 0x44,
+0x69, 0x61, 0x3b, 0x44, 0x69, 0x68, 0x3b, 0x44, 0x69, 0x53, 0x3b, 0x44, 0x69, 0x44, 0xf2, 0x6d, 0x68, 0x6e, 0x61, 0x69,
+0x63, 0x68, 0x3b, 0x44, 0x69, 0x4c, 0x75, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x4d, 0xe0, 0x69, 0x72, 0x74, 0x3b, 0x44,
+0x69, 0x43, 0x69, 0x61, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0x69, 0x61, 0x72, 0x44, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44,
+0x69, 0x68, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x44, 0x69, 0x53, 0x61, 0x74, 0x68, 0x61, 0x69, 0x72, 0x6e, 0x65, 0x3b,
+0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x48, 0x3b, 0x53, 0x3b, 0x44, 0x6f, 0x6d, 0x2e, 0x3b, 0x4c,
+0x75, 0x6e, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x2e, 0x3b, 0x4d, 0xe9, 0x72, 0x2e, 0x3b, 0x58, 0x6f, 0x76, 0x2e, 0x3b, 0x56,
+0x65, 0x6e, 0x2e, 0x3b, 0x53, 0xe1, 0x62, 0x2e, 0x3b, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e,
+0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0xe9, 0x72, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x3b, 0x58, 0x6f,
+0x76, 0x65, 0x73, 0x3b, 0x56, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x53, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b,
+0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e,
+0x73, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0xe9, 0x72, 0x2e, 0x3b, 0x78, 0x6f, 0x76, 0x2e, 0x3b, 0x76, 0x65, 0x6e,
+0x2e, 0x3b, 0x73, 0xe1, 0x62, 0x2e, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x73, 0x3b,
+0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0xe9, 0x72, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x3b, 0x78, 0x6f, 0x76, 0x65,
+0x73, 0x3b, 0x76, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x64, 0x2e, 0x3b, 0x6c,
+0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x6d, 0x2e, 0x3b, 0x78, 0x2e, 0x3b, 0x76, 0x2e, 0x3b, 0x73, 0x2e, 0x3b, 0x10d9, 0x10d5, 0x10d8,
0x3b, 0x10dd, 0x10e0, 0x10e8, 0x3b, 0x10e1, 0x10d0, 0x10db, 0x3b, 0x10dd, 0x10d7, 0x10ee, 0x3b, 0x10ee, 0x10e3, 0x10d7, 0x3b, 0x10de, 0x10d0, 0x10e0,
0x3b, 0x10e8, 0x10d0, 0x10d1, 0x3b, 0x10d9, 0x10d5, 0x10d8, 0x10e0, 0x10d0, 0x3b, 0x10dd, 0x10e0, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b,
0x10e1, 0x10d0, 0x10db, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b, 0x10dd, 0x10d7, 0x10ee, 0x10e8, 0x10d0, 0x10d1, 0x10d0, 0x10d7, 0x10d8, 0x3b,
@@ -4004,266 +4026,277 @@ static const ushort days_data[] = {
0xab8, 0xacb, 0xaae, 0xab5, 0xabe, 0xab0, 0x3b, 0xaae, 0xa82, 0xa97, 0xab3, 0xab5, 0xabe, 0xab0, 0x3b, 0xaac, 0xac1, 0xaa7, 0xab5, 0xabe,
0xab0, 0x3b, 0xa97, 0xac1, 0xab0, 0xac1, 0xab5, 0xabe, 0xab0, 0x3b, 0xab6, 0xac1, 0xa95, 0xacd, 0xab0, 0xab5, 0xabe, 0xab0, 0x3b, 0xab6,
0xaa8, 0xabf, 0xab5, 0xabe, 0xab0, 0x3b, 0xab0, 0x3b, 0xab8, 0xacb, 0x3b, 0xaae, 0xa82, 0x3b, 0xaac, 0xac1, 0x3b, 0xa97, 0xac1, 0x3b,
-0xab6, 0xac1, 0x3b, 0xab6, 0x3b, 0x4c, 0x68, 0x3b, 0x4c, 0x69, 0x3b, 0x54, 0x61, 0x3b, 0x4c, 0x72, 0x3b, 0x41, 0x6c, 0x3b,
-0x4a, 0x75, 0x3b, 0x41, 0x73, 0x3b, 0x4c, 0x61, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x4c, 0x69, 0x74, 0x69, 0x6e, 0x69, 0x6e,
-0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x4c, 0x61, 0x72, 0x61, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d,
-0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x6d, 0x61, 0x2bc, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x61, 0x72, 0x3b, 0x4c, 0x3b,
-0x4c, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d0, 0x5f3, 0x3b, 0x5d9,
-0x5d5, 0x5dd, 0x20, 0x5d1, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d2, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d3, 0x5f3, 0x3b,
-0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d4, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d5, 0x5f3, 0x3b, 0x5e9, 0x5d1, 0x5ea, 0x3b, 0x5d9, 0x5d5,
-0x5dd, 0x20, 0x5e8, 0x5d0, 0x5e9, 0x5d5, 0x5df, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20,
-0x5e9, 0x5dc, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e8, 0x5d1, 0x5d9, 0x5e2, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20,
-0x5d7, 0x5de, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9,
-0x5d1, 0x5ea, 0x3b, 0x5d0, 0x5f3, 0x3b, 0x5d1, 0x5f3, 0x3b, 0x5d2, 0x5f3, 0x3b, 0x5d3, 0x5f3, 0x3b, 0x5d4, 0x5f3, 0x3b, 0x5d5, 0x5f3,
-0x3b, 0x5e9, 0x5f3, 0x3b, 0x930, 0x935, 0x93f, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927,
-0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b, 0x930, 0x935, 0x93f, 0x935,
-0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941,
-0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e,
-0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x930, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b,
-0x917, 0x941, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x3b, 0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x7a, 0x65, 0x3b, 0x43, 0x73,
-0x3b, 0x50, 0x3b, 0x53, 0x7a, 0x6f, 0x3b, 0x76, 0x61, 0x73, 0xe1, 0x72, 0x6e, 0x61, 0x70, 0x3b, 0x68, 0xe9, 0x74, 0x66,
-0x151, 0x3b, 0x6b, 0x65, 0x64, 0x64, 0x3b, 0x73, 0x7a, 0x65, 0x72, 0x64, 0x61, 0x3b, 0x63, 0x73, 0xfc, 0x74, 0xf6, 0x72,
-0x74, 0xf6, 0x6b, 0x3b, 0x70, 0xe9, 0x6e, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x7a, 0x6f, 0x6d, 0x62, 0x61, 0x74, 0x3b, 0x56,
-0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x7a, 0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b, 0x53, 0x7a, 0x3b, 0x73, 0x75, 0x6e, 0x2e,
-0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0xfe, 0x72, 0x69, 0x2e, 0x3b, 0x6d, 0x69, 0xf0, 0x2e, 0x3b, 0x66, 0x69, 0x6d, 0x2e,
-0x3b, 0x66, 0xf6, 0x73, 0x2e, 0x3b, 0x6c, 0x61, 0x75, 0x2e, 0x3b, 0x73, 0x75, 0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75,
-0x72, 0x3b, 0x6d, 0xe1, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0xfe, 0x72, 0x69, 0xf0, 0x6a, 0x75, 0x64, 0x61,
-0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0xf0, 0x76, 0x69, 0x6b, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0x69, 0x6d,
-0x6d, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0xf6, 0x73, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b,
-0x6c, 0x61, 0x75, 0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0xde, 0x3b, 0x4d, 0x3b,
-0x46, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4d, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52, 0x61,
-0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4d, 0x69, 0x6e, 0x67, 0x67, 0x75,
-0x3b, 0x53, 0x65, 0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b,
-0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x3b, 0x4d, 0x3b, 0x53,
-0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x44, 0x6f, 0x6d, 0x68, 0x3b, 0x4c, 0x75, 0x61, 0x6e,
-0x3b, 0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x43, 0xe9, 0x61, 0x64, 0x3b, 0x44, 0xe9, 0x61, 0x72, 0x3b, 0x41, 0x6f, 0x69,
-0x6e, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x68, 0x3b, 0x44, 0xe9, 0x20, 0x44, 0x6f, 0x6d, 0x68, 0x6e, 0x61, 0x69, 0x67, 0x68,
-0x3b, 0x44, 0xe9, 0x20, 0x4c, 0x75, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x20, 0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x44,
-0xe9, 0x20, 0x43, 0xe9, 0x61, 0x64, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x61, 0x72, 0x64, 0x61, 0x6f, 0x69, 0x6e,
-0x3b, 0x44, 0xe9, 0x20, 0x68, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x44, 0xe9, 0x20, 0x53, 0x61, 0x74, 0x68, 0x61, 0x69,
-0x72, 0x6e, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x44, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d,
-0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x72, 0x3b, 0x67, 0x69, 0x6f, 0x3b, 0x76, 0x65, 0x6e,
-0x3b, 0x73, 0x61, 0x62, 0x3b, 0x44, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x63, 0x61, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x64, 0xec,
-0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x64, 0xec, 0x3b, 0x4d, 0x65, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x64, 0xec, 0x3b, 0x47,
-0x69, 0x6f, 0x76, 0x65, 0x64, 0xec, 0x3b, 0x56, 0x65, 0x6e, 0x65, 0x72, 0x64, 0xec, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x74,
-0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x65,
-0x6e, 0x69, 0x63, 0x61, 0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x64, 0xec, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x64, 0xec, 0x3b,
-0x6d, 0x65, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x64, 0xec, 0x3b, 0x67, 0x69, 0x6f, 0x76, 0x65, 0x64, 0xec, 0x3b, 0x76, 0x65,
-0x6e, 0x65, 0x72, 0x64, 0xec, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x65e5, 0x3b, 0x6708, 0x3b, 0x706b, 0x3b, 0x6c34,
-0x3b, 0x6728, 0x3b, 0x91d1, 0x3b, 0x571f, 0x3b, 0x65e5, 0x66dc, 0x65e5, 0x3b, 0x6708, 0x66dc, 0x65e5, 0x3b, 0x706b, 0x66dc, 0x65e5, 0x3b, 0x6c34,
-0x66dc, 0x65e5, 0x3b, 0x6728, 0x66dc, 0x65e5, 0x3b, 0x91d1, 0x66dc, 0x65e5, 0x3b, 0x571f, 0x66dc, 0x65e5, 0x3b, 0xcad, 0xcbe, 0xca8, 0xcc1, 0x3b,
-0xcb8, 0xccb, 0xcae, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0x3b, 0xcac, 0xcc1, 0xca7, 0x3b, 0xc97, 0xcc1, 0xcb0, 0xcc1, 0x3b, 0xcb6, 0xcc1,
-0xc95, 0xccd, 0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, 0x3b, 0xcad, 0xcbe, 0xca8, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb8, 0xccb, 0xcae, 0xcb5,
-0xcbe, 0xcb0, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcac, 0xcc1, 0xca7, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xc97, 0xcc1,
-0xcb0, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd, 0xcb0, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, 0xcb5, 0xcbe,
-0xcb0, 0x3b, 0xcad, 0xcbe, 0x3b, 0xcb8, 0xccb, 0x3b, 0xcae, 0xc82, 0x3b, 0xcac, 0xcc1, 0x3b, 0xc97, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0x3b,
-0xcb6, 0x3b, 0x622, 0x62a, 0x6be, 0x648, 0x627, 0x631, 0x3b, 0x698, 0x654, 0x646, 0x65b, 0x62f, 0x655, 0x631, 0x648, 0x627, 0x631, 0x3b,
-0x628, 0x648, 0x65a, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x62f, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x631, 0x65b, 0x66e, 0x6ea,
-0x633, 0x648, 0x627, 0x631, 0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b, 0x628, 0x679, 0x648, 0x627, 0x631, 0x3b, 0x627, 0x64e, 0x62a, 0x6be,
-0x648, 0x627, 0x631, 0x3b, 0x698, 0x654, 0x646, 0x65b, 0x62f, 0x631, 0x655, 0x631, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x65a, 0x645,
-0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x62f, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x631, 0x65b, 0x66e, 0x6ea, 0x633, 0x648, 0x627, 0x631,
-0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b, 0x628, 0x679, 0x648, 0x627, 0x631, 0x3b, 0x627, 0x3b, 0x698, 0x3b, 0x628, 0x3b, 0x628, 0x3b,
-0x628, 0x3b, 0x62c, 0x3b, 0x628, 0x3b, 0x416, 0x441, 0x3b, 0x414, 0x441, 0x3b, 0x421, 0x441, 0x3b, 0x421, 0x440, 0x3b, 0x411, 0x441,
-0x3b, 0x416, 0x43c, 0x3b, 0x421, 0x431, 0x3b, 0x416, 0x435, 0x43a, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x414, 0x4af, 0x439, 0x441,
-0x435, 0x43d, 0x431, 0x456, 0x3b, 0x421, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x421, 0x4d9, 0x440, 0x441, 0x435, 0x43d,
-0x431, 0x456, 0x3b, 0x411, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x416, 0x4b1, 0x43c, 0x430, 0x3b, 0x421, 0x435, 0x43d,
-0x431, 0x456, 0x3b, 0x416, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x421, 0x3b, 0x411, 0x3b, 0x416, 0x3b, 0x421, 0x3b, 0x436, 0x435, 0x43a,
-0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x434, 0x4af, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x435, 0x439, 0x441, 0x435,
-0x43d, 0x431, 0x456, 0x3b, 0x441, 0x4d9, 0x440, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x431, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431,
-0x456, 0x3b, 0x436, 0x4b1, 0x43c, 0x430, 0x3b, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x63, 0x79, 0x75, 0x2e, 0x3b, 0x6d, 0x62,
-0x65, 0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74, 0x75, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x67, 0x6e,
-0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0x3b, 0x4b, 0x75, 0x20, 0x63, 0x79, 0x75, 0x6d, 0x77, 0x65, 0x72, 0x75, 0x3b,
-0x4b, 0x75, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x62, 0x69,
-0x72, 0x69, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20,
-0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4b, 0x75, 0x77,
-0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x75, 0x3b, 0x436, 0x435, 0x43a, 0x2e, 0x3b, 0x434, 0x4af, 0x439,
-0x2e, 0x3b, 0x448, 0x435, 0x439, 0x448, 0x2e, 0x3b, 0x448, 0x430, 0x440, 0x448, 0x2e, 0x3b, 0x431, 0x435, 0x439, 0x448, 0x2e, 0x3b,
-0x436, 0x443, 0x43c, 0x430, 0x3b, 0x438, 0x448, 0x43c, 0x2e, 0x3b, 0x436, 0x435, 0x43a, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x434,
-0x4af, 0x439, 0x448, 0x4e9, 0x43c, 0x431, 0x4af, 0x3b, 0x448, 0x435, 0x439, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x448, 0x430, 0x440,
-0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x431, 0x435, 0x439, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b,
-0x438, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x416, 0x3b, 0x414, 0x3b, 0x428, 0x3b, 0x428, 0x3b, 0x411, 0x3b, 0x416, 0x3b, 0x418,
-0x3b, 0xc77c, 0x3b, 0xc6d4, 0x3b, 0xd654, 0x3b, 0xc218, 0x3b, 0xbaa9, 0x3b, 0xae08, 0x3b, 0xd1a0, 0x3b, 0xc77c, 0xc694, 0xc77c, 0x3b, 0xc6d4,
-0xc694, 0xc77c, 0x3b, 0xd654, 0xc694, 0xc77c, 0x3b, 0xc218, 0xc694, 0xc77c, 0x3b, 0xbaa9, 0xc694, 0xc77c, 0x3b, 0xae08, 0xc694, 0xc77c, 0x3b, 0xd1a0,
-0xc694, 0xc77c, 0x3b, 0x63, 0x75, 0x2e, 0x3b, 0x6d, 0x62, 0x65, 0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74, 0x75,
-0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x67, 0x6e, 0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0x3b, 0x4b, 0x75, 0x20,
-0x77, 0x2019, 0x69, 0x6e, 0x64, 0x77, 0x69, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b,
-0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67,
-0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, 0x20,
-0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61,
-0x6e, 0x64, 0x61, 0x74, 0x75, 0x3b, 0xead, 0xeb2, 0xe97, 0xeb4, 0xe94, 0x3b, 0xe88, 0xeb1, 0xe99, 0x3b, 0xead, 0xeb1, 0xe87, 0xe84,
-0xeb2, 0xe99, 0x3b, 0xe9e, 0xeb8, 0xe94, 0x3b, 0xe9e, 0xeb0, 0xeab, 0xeb1, 0xe94, 0x3b, 0xeaa, 0xeb8, 0xe81, 0x3b, 0xec0, 0xeaa, 0xebb,
-0xeb2, 0x3b, 0xea7, 0xeb1, 0xe99, 0xead, 0xeb2, 0xe97, 0xeb4, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe88, 0xeb1, 0xe99, 0x3b, 0xea7, 0xeb1,
-0xe99, 0xead, 0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe9e, 0xeb8, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe9e, 0xeb0,
-0xeab, 0xeb1, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xeaa, 0xeb8, 0xe81, 0x3b, 0xea7, 0xeb1, 0xe99, 0xec0, 0xeaa, 0xebb, 0xeb2, 0x3b, 0xead,
-0x3b, 0xe88, 0x3b, 0xead, 0x3b, 0xe9e, 0x3b, 0xe9e, 0xeab, 0x3b, 0xeaa, 0xeb8, 0x3b, 0xeaa, 0x3b, 0x31, 0x3b, 0x32, 0x3b, 0x33,
-0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x53, 0x76, 0x3b, 0x50, 0x72, 0x3b, 0x4f, 0x74, 0x3b, 0x54, 0x72,
-0x3b, 0x43, 0x65, 0x3b, 0x50, 0x6b, 0x3b, 0x53, 0x65, 0x3b, 0x53, 0x76, 0x113, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b,
-0x50, 0x69, 0x72, 0x6d, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x4f, 0x74, 0x72, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x54,
-0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x43, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61,
-0x3b, 0x50, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x53, 0x65, 0x73, 0x74, 0x64, 0x69, 0x65, 0x6e,
-0x61, 0x3b, 0x53, 0x3b, 0x50, 0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x73, 0x76, 0x113, 0x74,
-0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x6f, 0x74, 0x72, 0x64,
-0x69, 0x65, 0x6e, 0x61, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x63, 0x65, 0x74, 0x75, 0x72,
-0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x73, 0x65,
-0x73, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x65, 0x79, 0x65, 0x3b, 0x79, 0x62, 0x6f, 0x3b, 0x6d, 0x62, 0x6c, 0x3b,
-0x6d, 0x73, 0x74, 0x3b, 0x6d, 0x69, 0x6e, 0x3b, 0x6d, 0x74, 0x6e, 0x3b, 0x6d, 0x70, 0x73, 0x3b, 0x65, 0x79, 0x65, 0x6e,
-0x67, 0x61, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x79, 0x61, 0x6d, 0x62, 0x6f, 0x3b,
-0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x6d, 0x6f,
-0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74, 0x6f, 0x3b, 0x6d, 0x6f, 0x6b, 0x254,
-0x6c, 0x254, 0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0xe9, 0x69, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79,
-0x61, 0x20, 0x6d, 0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x6d, 0x70, 0x254, 0x301, 0x73, 0x254, 0x3b, 0x65, 0x3b, 0x79, 0x3b,
-0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x70, 0x3b, 0x73, 0x6b, 0x3b, 0x70, 0x72, 0x3b, 0x61, 0x6e, 0x3b, 0x74,
-0x72, 0x3b, 0x6b, 0x74, 0x3b, 0x70, 0x6e, 0x3b, 0x161, 0x74, 0x3b, 0x73, 0x65, 0x6b, 0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e,
-0x69, 0x73, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x61, 0x6e, 0x74, 0x72, 0x61,
-0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x74, 0x72, 0x65, 0x10d, 0x69, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b,
-0x6b, 0x65, 0x74, 0x76, 0x69, 0x72, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x70, 0x65, 0x6e, 0x6b, 0x74,
-0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x161, 0x65, 0x161, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b,
-0x53, 0x3b, 0x50, 0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x160, 0x3b, 0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f,
-0x43e, 0x43d, 0x2e, 0x3b, 0x432, 0x442, 0x2e, 0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435,
-0x442, 0x2e, 0x3b, 0x441, 0x430, 0x431, 0x2e, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434,
-0x435, 0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b,
-0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x43e, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x43e, 0x43a, 0x3b, 0x441, 0x430, 0x431, 0x43e, 0x442,
-0x430, 0x3b, 0x41, 0x6c, 0x61, 0x68, 0x3b, 0x41, 0x6c, 0x61, 0x74, 0x73, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x6c, 0x61,
-0x72, 0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x3b, 0x5a, 0x6f, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x3b, 0x41, 0x6c, 0x61, 0x68,
-0x61, 0x64, 0x79, 0x3b, 0x41, 0x6c, 0x61, 0x74, 0x73, 0x69, 0x6e, 0x61, 0x69, 0x6e, 0x79, 0x3b, 0x54, 0x61, 0x6c, 0x61,
-0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x6f, 0x62, 0x69, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x61, 0x6d, 0x69, 0x73,
-0x79, 0x3b, 0x5a, 0x6f, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x6f, 0x74, 0x73, 0x79, 0x3b, 0x41, 0x3b, 0x41, 0x3b,
-0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x5a, 0x3b, 0x41, 0x3b, 0x41, 0x68, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x3b, 0x53, 0x65,
-0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b, 0x68, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x41, 0x68,
-0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75,
-0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75,
-0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd7c, 0x3b,
-0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd7e, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd7b, 0x3b, 0xd35, 0xd4d,
-0xd2f, 0xd3e, 0xd34, 0xd02, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0x3b, 0xd36, 0xd28, 0xd3f, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd31,
-0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1a, 0xd4a,
-0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35,
-0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d,
-0x200c, 0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1e, 0xd3e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a,
-0xd4a, 0x3b, 0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd31, 0xd3e,
-0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1a, 0xd4a, 0xd35,
-0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd4d, 0xd2f,
-0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a,
-0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b, 0xd2c,
-0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0x3b, 0x126, 0x61, 0x64, 0x3b, 0x54, 0x6e, 0x65, 0x3b,
-0x54, 0x6c, 0x69, 0x3b, 0x45, 0x72, 0x62, 0x3b, 0x126, 0x61, 0x6d, 0x3b, 0x120, 0x69, 0x6d, 0x3b, 0x53, 0x69, 0x62, 0x3b,
-0x49, 0x6c, 0x2d, 0x126, 0x61, 0x64, 0x64, 0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6e, 0x65, 0x6a, 0x6e, 0x3b, 0x49, 0x74, 0x2d,
-0x54, 0x6c, 0x69, 0x65, 0x74, 0x61, 0x3b, 0x4c, 0x2d, 0x45, 0x72, 0x62, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x6c, 0x2d, 0x126,
-0x61, 0x6d, 0x69, 0x73, 0x3b, 0x49, 0x6c, 0x2d, 0x120, 0x69, 0x6d, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x73, 0x2d, 0x53, 0x69,
-0x62, 0x74, 0x3b, 0x126, 0x64, 0x3b, 0x54, 0x6e, 0x3b, 0x54, 0x6c, 0x3b, 0x45, 0x72, 0x3b, 0x126, 0x6d, 0x3b, 0x120, 0x6d,
-0x3b, 0x53, 0x62, 0x3b, 0x126, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x45, 0x3b, 0x126, 0x3b, 0x120, 0x3b, 0x53, 0x3b, 0x930, 0x935,
-0x93f, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b,
-0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e,
-0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917,
-0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935,
-0x93e, 0x930, 0x3b, 0x41d, 0x44f, 0x3b, 0x414, 0x430, 0x3b, 0x41c, 0x44f, 0x3b, 0x41b, 0x445, 0x3b, 0x41f, 0x4af, 0x3b, 0x411, 0x430,
-0x3b, 0x411, 0x44f, 0x3b, 0x43d, 0x44f, 0x43c, 0x3b, 0x434, 0x430, 0x432, 0x430, 0x430, 0x3b, 0x43c, 0x44f, 0x433, 0x43c, 0x430, 0x440,
-0x3b, 0x43b, 0x445, 0x430, 0x433, 0x432, 0x430, 0x3b, 0x43f, 0x4af, 0x440, 0x44d, 0x432, 0x3b, 0x431, 0x430, 0x430, 0x441, 0x430, 0x43d,
-0x3b, 0x431, 0x44f, 0x43c, 0x431, 0x430, 0x3b, 0x906, 0x907, 0x924, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932,
-0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x92c, 0x93f, 0x939, 0x940, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b,
-0x906, 0x907, 0x924, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x92c,
-0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x939, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x941,
-0x915, 0x94d, 0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x906, 0x3b, 0x938, 0x94b, 0x3b, 0x92e,
-0x3b, 0x92c, 0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x3b, 0xb30, 0xb2c, 0xb3f, 0x3b, 0xb38, 0xb4b, 0xb2e, 0x3b,
-0xb2e, 0xb19, 0xb4d, 0xb17, 0xb33, 0x3b, 0xb2c, 0xb41, 0xb27, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30,
-0x3b, 0xb36, 0xb28, 0xb3f, 0x3b, 0xb30, 0xb2c, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb38, 0xb4b, 0xb2e, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2e,
-0xb19, 0xb4d, 0xb17, 0xb33, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2c, 0xb41, 0xb27, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0xb2c,
-0xb3e, 0xb30, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb36, 0xb28, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb30,
-0x3b, 0xb38, 0xb4b, 0x3b, 0xb2e, 0x3b, 0xb2c, 0xb41, 0x3b, 0xb17, 0xb41, 0x3b, 0xb36, 0xb41, 0x3b, 0xb36, 0x3b, 0x6cc, 0x6a9, 0x634,
-0x646, 0x628, 0x647, 0x3b, 0x62f, 0x648, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x633, 0x647, 0x200c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x686,
-0x647, 0x627, 0x631, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x67e, 0x646, 0x62c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x62c, 0x645, 0x639, 0x647,
-0x3b, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x3b,
-0x6e, 0x69, 0x65, 0x64, 0x7a, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x77, 0x74, 0x2e, 0x3b, 0x15b, 0x72, 0x2e, 0x3b,
-0x63, 0x7a, 0x77, 0x2e, 0x3b, 0x70, 0x74, 0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x3b, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69,
-0x65, 0x6c, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x61, 0x142, 0x65, 0x6b, 0x3b, 0x77, 0x74, 0x6f,
-0x72, 0x65, 0x6b, 0x3b, 0x15b, 0x72, 0x6f, 0x64, 0x61, 0x3b, 0x63, 0x7a, 0x77, 0x61, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70,
-0x69, 0x105, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0x57, 0x3b, 0x15a,
-0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x73, 0x65, 0x67, 0x3b, 0x74, 0x65, 0x72, 0x3b, 0x71,
-0x75, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x3b, 0x73, 0x65, 0x78, 0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e,
-0x67, 0x6f, 0x3b, 0x73, 0x65, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72,
-0xe7, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72,
-0x61, 0x3b, 0x71, 0x75, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61,
-0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b,
-0x51, 0x3b, 0x51, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x67, 0x75,
-0x6e, 0x64, 0x61, 0x3b, 0x74, 0x65, 0x72, 0xe7, 0x61, 0x3b, 0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x3b, 0x71, 0x75, 0x69,
-0x6e, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0xa10, 0xa24, 0x3b,
-0xa38, 0xa4b, 0xa2e, 0x3b, 0xa2e, 0xa70, 0xa17, 0xa32, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0x3b, 0xa35, 0xa40, 0xa30, 0x3b, 0xa38, 0xa3c,
-0xa41, 0xa71, 0xa15, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa3f, 0xa71, 0xa1a, 0xa30, 0x3b, 0xa10, 0xa24, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38,
-0xa4b, 0xa2e, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2e, 0xa70, 0xa17, 0xa32, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0xa35, 0xa3e,
-0xa30, 0x3b, 0xa35, 0xa40, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38,
-0xa3c, 0xa28, 0xa3f, 0xa71, 0xa1a, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa10, 0x3b, 0xa38, 0xa4b, 0x3b, 0xa2e, 0xa70, 0x3b, 0xa2c, 0xa41,
-0xa71, 0x3b, 0xa35, 0xa40, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0x3b, 0xa38, 0xa3c, 0x3b, 0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x67e,
-0x6cc, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644, 0x3b, 0x628, 0x64f, 0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b,
-0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1, 0x3b, 0x44, 0x6f, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61,
-0x72, 0x3b, 0x4d, 0x69, 0xe9, 0x3b, 0x4a, 0x75, 0x65, 0x3b, 0x56, 0x69, 0x65, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x44, 0x6f,
-0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d,
-0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x4a, 0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x56, 0x69, 0x65, 0x72,
-0x6e, 0x65, 0x73, 0x3b, 0x53, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x4a,
-0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x75, 0x3b, 0x67, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x65, 0x3b, 0x67, 0x69,
-0x65, 0x3b, 0x76, 0x65, 0x3b, 0x73, 0x6f, 0x3b, 0x64, 0x75, 0x6d, 0x65, 0x6e, 0x67, 0x69, 0x61, 0x3b, 0x67, 0x6c, 0x69,
-0x6e, 0x64, 0x65, 0x73, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x73, 0x65, 0x6d, 0x6e, 0x61,
-0x3b, 0x67, 0x69, 0x65, 0x76, 0x67, 0x69, 0x61, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x69, 0x3b, 0x73, 0x6f,
-0x6e, 0x64, 0x61, 0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x75,
-0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x69, 0x65, 0x2e, 0x3b, 0x6a, 0x6f,
-0x69, 0x3b, 0x76, 0x69, 0x6e, 0x2e, 0x3b, 0x73, 0xe2, 0x6d, 0x2e, 0x3b, 0x64, 0x75, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x103,
-0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x21b, 0x69, 0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x75, 0x72, 0x69,
-0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x65, 0x72, 0x69, 0x3b, 0x73, 0xe2, 0x6d, 0x62, 0x103, 0x74, 0x103, 0x3b,
-0x44, 0x75, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0x65, 0x3b, 0x4a, 0x6f, 0x69, 0x3b,
-0x56, 0x69, 0x6e, 0x3b, 0x53, 0xe2, 0x6d, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x61, 0x3b, 0x4d, 0x69, 0x3b, 0x4a, 0x3b,
-0x56, 0x3b, 0x53, 0x3b, 0x432, 0x441, 0x3b, 0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f,
-0x442, 0x3b, 0x441, 0x431, 0x3b, 0x432, 0x43e, 0x441, 0x43a, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x435, 0x3b, 0x43f, 0x43e, 0x43d,
-0x435, 0x434, 0x435, 0x43b, 0x44c, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435,
-0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x433, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x430, 0x3b, 0x441,
-0x443, 0x431, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x412, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421,
-0x3b, 0x42, 0x6b, 0x31, 0x3b, 0x42, 0x6b, 0x32, 0x3b, 0x42, 0x6b, 0x33, 0x3b, 0x42, 0x6b, 0x34, 0x3b, 0x42, 0x6b, 0x35,
-0x3b, 0x4c, 0xe2, 0x70, 0x3b, 0x4c, 0xe2, 0x79, 0x3b, 0x42, 0x69, 0x6b, 0x75, 0x61, 0x2d, 0xf4, 0x6b, 0x6f, 0x3b, 0x42,
-0xef, 0x6b, 0x75, 0x61, 0x2d, 0xfb, 0x73, 0x65, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x70, 0x74, 0xe2, 0x3b, 0x42,
-0xef, 0x6b, 0x75, 0x61, 0x2d, 0x75, 0x73, 0xef, 0xf6, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x6f, 0x6b, 0xfc, 0x3b,
-0x4c, 0xe2, 0x70, 0xf4, 0x73, 0xf6, 0x3b, 0x4c, 0xe2, 0x79, 0x65, 0x6e, 0x67, 0x61, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x54,
-0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x59, 0x3b, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e,
-0x3b, 0x441, 0x440, 0x435, 0x3b, 0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434,
-0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a,
-0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430,
-0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x443, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f,
-0x3b, 0x441, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x65, 0x3b, 0x10d,
-0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75, 0x62, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70,
-0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x65,
-0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75,
-0x62, 0x6f, 0x74, 0x61, 0x3b, 0x425, 0x446, 0x431, 0x3b, 0x41a, 0x440, 0x441, 0x3b, 0x414, 0x446, 0x433, 0x3b, 0x4d4, 0x440, 0x442,
-0x3b, 0x426, 0x43f, 0x440, 0x3b, 0x41c, 0x440, 0x431, 0x3b, 0x421, 0x431, 0x442, 0x3b, 0x425, 0x443, 0x44b, 0x446, 0x430, 0x443, 0x431,
-0x43e, 0x43d, 0x3b, 0x41a, 0x44a, 0x443, 0x44b, 0x440, 0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x414, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b,
-0x4d4, 0x440, 0x442, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x426, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x41c, 0x430,
-0x439, 0x440, 0x4d5, 0x43c, 0x431, 0x43e, 0x43d, 0x3b, 0x421, 0x430, 0x431, 0x430, 0x442, 0x3b, 0x425, 0x3b, 0x41a, 0x3b, 0x414, 0x3b,
-0x4d4, 0x3b, 0x426, 0x3b, 0x41c, 0x3b, 0x421, 0x3b, 0x445, 0x446, 0x431, 0x3b, 0x43a, 0x440, 0x441, 0x3b, 0x434, 0x446, 0x433, 0x3b,
-0x4d5, 0x440, 0x442, 0x3b, 0x446, 0x43f, 0x440, 0x3b, 0x43c, 0x440, 0x431, 0x3b, 0x441, 0x431, 0x442, 0x3b, 0x445, 0x443, 0x44b, 0x446,
-0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x43a, 0x44a, 0x443, 0x44b, 0x440, 0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x434, 0x44b, 0x446, 0x446,
-0x4d5, 0x433, 0x3b, 0x4d5, 0x440, 0x442, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x446, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5, 0x43c,
-0x3b, 0x43c, 0x430, 0x439, 0x440, 0x4d5, 0x43c, 0x431, 0x43e, 0x43d, 0x3b, 0x441, 0x430, 0x431, 0x430, 0x442, 0x3b, 0x53, 0x76, 0x6f,
-0x3b, 0x4d, 0x75, 0x76, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x3b, 0x43, 0x68, 0x69, 0x74, 0x3b, 0x43, 0x68, 0x69, 0x6e, 0x3b,
-0x43, 0x68, 0x69, 0x73, 0x3b, 0x4d, 0x75, 0x67, 0x3b, 0x53, 0x76, 0x6f, 0x6e, 0x64, 0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x68,
-0x75, 0x72, 0x6f, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b,
-0x43, 0x68, 0x69, 0x6e, 0x61, 0x3b, 0x43, 0x68, 0x69, 0x73, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x75, 0x67, 0x6f, 0x76,
-0x65, 0x72, 0x61, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0xd89, 0xdbb,
-0xdd2, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4, 0x3b, 0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b,
-0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3, 0xdca, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0x3b, 0xd89, 0xdbb, 0xdd2,
-0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4, 0xdbb, 0xdd4, 0xdc0, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6,
-0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3, 0xdca, 0xdb4, 0xdad, 0xdd2, 0xdb1, 0xdca, 0xdaf, 0xdcf, 0x3b,
-0xdc3, 0xdd2, 0xd9a, 0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0xdc3, 0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xd89,
-0x3b, 0xdc3, 0x3b, 0xd85, 0x3b, 0xdb6, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0x3b, 0xdc3, 0xdd2, 0x3b, 0xdc3, 0xdd9, 0x3b, 0x6e, 0x65,
-0x3b, 0x70, 0x6f, 0x3b, 0x75, 0x74, 0x3b, 0x73, 0x74, 0x3b, 0x161, 0x74, 0x3b, 0x70, 0x69, 0x3b, 0x73, 0x6f, 0x3b, 0x6e,
-0x65, 0x64, 0x65, 0x13e, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x6c, 0x6f, 0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x6f,
-0x6b, 0x3b, 0x73, 0x74, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x161, 0x74, 0x76, 0x72, 0x74, 0x6f, 0x6b, 0x3b, 0x70, 0x69, 0x61,
-0x74, 0x6f, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x75, 0x3b, 0x73, 0x3b, 0x161,
-0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f, 0x6e, 0x3b, 0x74, 0x6f, 0x72, 0x3b, 0x73, 0x72, 0x65,
-0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x6f, 0x62, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61,
-0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x65, 0x6b, 0x3b, 0x74, 0x6f, 0x72, 0x65, 0x6b, 0x3b, 0x73, 0x72,
-0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f,
-0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e,
-0x65, 0x64, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x74, 0x6f, 0x72, 0x2e, 0x3b, 0x73, 0x72, 0x65, 0x2e, 0x3b, 0x10d,
-0x65, 0x74, 0x2e, 0x3b, 0x70, 0x65, 0x74, 0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x3b, 0x41, 0x78, 0x64, 0x3b, 0x49, 0x73,
-0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0x62, 0x3b, 0x4b, 0x68, 0x61, 0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x53, 0x61,
-0x62, 0x3b, 0x41, 0x78, 0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x61, 0x64,
-0x6f, 0x3b, 0x41, 0x72, 0x62, 0x61, 0x63, 0x6f, 0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x3b, 0x4a, 0x69, 0x6d,
-0x63, 0x6f, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x69, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x4b, 0x3b, 0x4a,
+0xab6, 0xac1, 0x3b, 0xab6, 0x3b, 0x4c, 0x61, 0x68, 0x3b, 0x4c, 0x69, 0x74, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x4c, 0x61, 0x72,
+0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x3b, 0x4c, 0x61, 0x68, 0x61, 0x64, 0x69, 0x3b,
+0x4c, 0x69, 0x74, 0x69, 0x6e, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x4c, 0x61, 0x72, 0x61, 0x62,
+0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x6d, 0x61, 0x2bc, 0x61, 0x3b, 0x41, 0x73,
+0x61, 0x62, 0x61, 0x72, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x5d9,
+0x5d5, 0x5dd, 0x20, 0x5d0, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d1, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d2, 0x5f3, 0x3b,
+0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d3, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d4, 0x5f3, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d5, 0x5f3,
+0x3b, 0x5e9, 0x5d1, 0x5ea, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e8, 0x5d0, 0x5e9, 0x5d5, 0x5df, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9,
+0x5e0, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5dc, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e8, 0x5d1, 0x5d9,
+0x5e2, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5d7, 0x5de, 0x5d9, 0x5e9, 0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d9, 0x5e9,
+0x5d9, 0x3b, 0x5d9, 0x5d5, 0x5dd, 0x20, 0x5e9, 0x5d1, 0x5ea, 0x3b, 0x5d0, 0x5f3, 0x3b, 0x5d1, 0x5f3, 0x3b, 0x5d2, 0x5f3, 0x3b, 0x5d3,
+0x5f3, 0x3b, 0x5d4, 0x5f3, 0x3b, 0x5d5, 0x5f3, 0x3b, 0x5e9, 0x5f3, 0x3b, 0x930, 0x935, 0x93f, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e,
+0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936,
+0x928, 0x93f, 0x3b, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917,
+0x932, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b,
+0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x930, 0x3b, 0x938, 0x94b,
+0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x917, 0x941, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x3b, 0x56, 0x3b, 0x48, 0x3b, 0x4b,
+0x3b, 0x53, 0x7a, 0x65, 0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b, 0x53, 0x7a, 0x6f, 0x3b, 0x76, 0x61, 0x73, 0xe1, 0x72, 0x6e,
+0x61, 0x70, 0x3b, 0x68, 0xe9, 0x74, 0x66, 0x151, 0x3b, 0x6b, 0x65, 0x64, 0x64, 0x3b, 0x73, 0x7a, 0x65, 0x72, 0x64, 0x61,
+0x3b, 0x63, 0x73, 0xfc, 0x74, 0xf6, 0x72, 0x74, 0xf6, 0x6b, 0x3b, 0x70, 0xe9, 0x6e, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x7a,
+0x6f, 0x6d, 0x62, 0x61, 0x74, 0x3b, 0x56, 0x3b, 0x48, 0x3b, 0x4b, 0x3b, 0x53, 0x7a, 0x3b, 0x43, 0x73, 0x3b, 0x50, 0x3b,
+0x53, 0x7a, 0x3b, 0x73, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0xe1, 0x6e, 0x2e, 0x3b, 0xfe, 0x72, 0x69, 0x2e, 0x3b, 0x6d, 0x69,
+0xf0, 0x2e, 0x3b, 0x66, 0x69, 0x6d, 0x2e, 0x3b, 0x66, 0xf6, 0x73, 0x2e, 0x3b, 0x6c, 0x61, 0x75, 0x2e, 0x3b, 0x73, 0x75,
+0x6e, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0xe1, 0x6e, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0xfe,
+0x72, 0x69, 0xf0, 0x6a, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6d, 0x69, 0xf0, 0x76, 0x69, 0x6b, 0x75, 0x64, 0x61,
+0x67, 0x75, 0x72, 0x3b, 0x66, 0x69, 0x6d, 0x6d, 0x74, 0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x66, 0xf6, 0x73, 0x74,
+0x75, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x6c, 0x61, 0x75, 0x67, 0x61, 0x72, 0x64, 0x61, 0x67, 0x75, 0x72, 0x3b, 0x53,
+0x3b, 0x4d, 0x3b, 0xde, 0x3b, 0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b, 0x4c, 0x3b, 0x4d, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6e,
+0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b, 0x61, 0x6d, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62,
+0x3b, 0x4d, 0x69, 0x6e, 0x67, 0x67, 0x75, 0x3b, 0x53, 0x65, 0x6e, 0x69, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61,
+0x3b, 0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x3b, 0x53, 0x61,
+0x62, 0x74, 0x75, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x44, 0x6f,
+0x6d, 0x68, 0x3b, 0x4c, 0x75, 0x61, 0x6e, 0x3b, 0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x43, 0xe9, 0x61, 0x64, 0x3b, 0x44,
+0xe9, 0x61, 0x72, 0x3b, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x68, 0x3b, 0x44, 0xe9, 0x20, 0x44, 0x6f,
+0x6d, 0x68, 0x6e, 0x61, 0x69, 0x67, 0x68, 0x3b, 0x44, 0xe9, 0x20, 0x4c, 0x75, 0x61, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x20,
+0x4d, 0xe1, 0x69, 0x72, 0x74, 0x3b, 0x44, 0xe9, 0x20, 0x43, 0xe9, 0x61, 0x64, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0xe9,
+0x61, 0x72, 0x64, 0x61, 0x6f, 0x69, 0x6e, 0x3b, 0x44, 0xe9, 0x20, 0x68, 0x41, 0x6f, 0x69, 0x6e, 0x65, 0x3b, 0x44, 0xe9,
+0x20, 0x53, 0x61, 0x74, 0x68, 0x61, 0x69, 0x72, 0x6e, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x44, 0x3b,
+0x41, 0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x72, 0x3b,
+0x67, 0x69, 0x6f, 0x3b, 0x76, 0x65, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x63, 0x61,
+0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x64, 0xec, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x64, 0xec, 0x3b, 0x6d, 0x65, 0x72, 0x63,
+0x6f, 0x6c, 0x65, 0x64, 0xec, 0x3b, 0x67, 0x69, 0x6f, 0x76, 0x65, 0x64, 0xec, 0x3b, 0x76, 0x65, 0x6e, 0x65, 0x72, 0x64,
+0xec, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56,
+0x3b, 0x53, 0x3b, 0x65e5, 0x3b, 0x6708, 0x3b, 0x706b, 0x3b, 0x6c34, 0x3b, 0x6728, 0x3b, 0x91d1, 0x3b, 0x571f, 0x3b, 0x65e5, 0x66dc, 0x65e5,
+0x3b, 0x6708, 0x66dc, 0x65e5, 0x3b, 0x706b, 0x66dc, 0x65e5, 0x3b, 0x6c34, 0x66dc, 0x65e5, 0x3b, 0x6728, 0x66dc, 0x65e5, 0x3b, 0x91d1, 0x66dc, 0x65e5,
+0x3b, 0x571f, 0x66dc, 0x65e5, 0x3b, 0xcad, 0xcbe, 0xca8, 0xcc1, 0x3b, 0xcb8, 0xccb, 0xcae, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0x3b, 0xcac,
+0xcc1, 0xca7, 0x3b, 0xc97, 0xcc1, 0xcb0, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd, 0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, 0x3b, 0xcad, 0xcbe,
+0xca8, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb8, 0xccb, 0xcae, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcae, 0xc82, 0xc97, 0xcb3, 0xcb5, 0xcbe, 0xcb0,
+0x3b, 0xcac, 0xcc1, 0xca7, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xc97, 0xcc1, 0xcb0, 0xcc1, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xcc1, 0xc95, 0xccd,
+0xcb0, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcb6, 0xca8, 0xcbf, 0xcb5, 0xcbe, 0xcb0, 0x3b, 0xcad, 0xcbe, 0x3b, 0xcb8, 0xccb, 0x3b, 0xcae, 0xc82,
+0x3b, 0xcac, 0xcc1, 0x3b, 0xc97, 0xcc1, 0x3b, 0xcb6, 0xcc1, 0x3b, 0xcb6, 0x3b, 0x622, 0x62a, 0x6be, 0x648, 0x627, 0x631, 0x3b, 0x698,
+0x654, 0x646, 0x65b, 0x62f, 0x655, 0x631, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x65a, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648,
+0x62f, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x631, 0x65b, 0x66e, 0x6ea, 0x633, 0x648, 0x627, 0x631, 0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b,
+0x628, 0x679, 0x648, 0x627, 0x631, 0x3b, 0x627, 0x64e, 0x62a, 0x6be, 0x648, 0x627, 0x631, 0x3b, 0x698, 0x654, 0x646, 0x65b, 0x62f, 0x631,
+0x655, 0x631, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x65a, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x628, 0x648, 0x62f, 0x648, 0x627, 0x631,
+0x3b, 0x628, 0x631, 0x65b, 0x66e, 0x6ea, 0x633, 0x648, 0x627, 0x631, 0x3b, 0x62c, 0x64f, 0x645, 0x6c1, 0x3b, 0x628, 0x679, 0x648, 0x627,
+0x631, 0x3b, 0x627, 0x3b, 0x698, 0x3b, 0x628, 0x3b, 0x628, 0x3b, 0x628, 0x3b, 0x62c, 0x3b, 0x628, 0x3b, 0x416, 0x441, 0x3b, 0x414,
+0x441, 0x3b, 0x421, 0x441, 0x3b, 0x421, 0x440, 0x3b, 0x411, 0x441, 0x3b, 0x416, 0x43c, 0x3b, 0x421, 0x431, 0x3b, 0x416, 0x435, 0x43a,
+0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x414, 0x4af, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x421, 0x435, 0x439, 0x441, 0x435,
+0x43d, 0x431, 0x456, 0x3b, 0x421, 0x4d9, 0x440, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x411, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431,
+0x456, 0x3b, 0x416, 0x4b1, 0x43c, 0x430, 0x3b, 0x421, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x416, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x421,
+0x3b, 0x411, 0x3b, 0x416, 0x3b, 0x421, 0x3b, 0x436, 0x435, 0x43a, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x434, 0x4af, 0x439, 0x441,
+0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x441, 0x4d9, 0x440, 0x441, 0x435, 0x43d,
+0x431, 0x456, 0x3b, 0x431, 0x435, 0x439, 0x441, 0x435, 0x43d, 0x431, 0x456, 0x3b, 0x436, 0x4b1, 0x43c, 0x430, 0x3b, 0x441, 0x435, 0x43d,
+0x431, 0x456, 0x3b, 0x63, 0x79, 0x75, 0x2e, 0x3b, 0x6d, 0x62, 0x65, 0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74,
+0x75, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x67, 0x6e, 0x75, 0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0x3b, 0x4b, 0x75,
+0x20, 0x63, 0x79, 0x75, 0x6d, 0x77, 0x65, 0x72, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65,
+0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61,
+0x74, 0x61, 0x74, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20,
+0x67, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x4b, 0x75, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74,
+0x75, 0x3b, 0x436, 0x435, 0x43a, 0x2e, 0x3b, 0x434, 0x4af, 0x439, 0x2e, 0x3b, 0x448, 0x435, 0x439, 0x448, 0x2e, 0x3b, 0x448, 0x430,
+0x440, 0x448, 0x2e, 0x3b, 0x431, 0x435, 0x439, 0x448, 0x2e, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x438, 0x448, 0x43c, 0x2e, 0x3b,
+0x436, 0x435, 0x43a, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x434, 0x4af, 0x439, 0x448, 0x4e9, 0x43c, 0x431, 0x4af, 0x3b, 0x448, 0x435,
+0x439, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x448, 0x430, 0x440, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x431, 0x435, 0x439, 0x448,
+0x435, 0x43c, 0x431, 0x438, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x438, 0x448, 0x435, 0x43c, 0x431, 0x438, 0x3b, 0x416, 0x3b, 0x414,
+0x3b, 0x428, 0x3b, 0x428, 0x3b, 0x411, 0x3b, 0x416, 0x3b, 0x418, 0x3b, 0xc77c, 0x3b, 0xc6d4, 0x3b, 0xd654, 0x3b, 0xc218, 0x3b, 0xbaa9,
+0x3b, 0xae08, 0x3b, 0xd1a0, 0x3b, 0xc77c, 0xc694, 0xc77c, 0x3b, 0xc6d4, 0xc694, 0xc77c, 0x3b, 0xd654, 0xc694, 0xc77c, 0x3b, 0xc218, 0xc694, 0xc77c,
+0x3b, 0xbaa9, 0xc694, 0xc77c, 0x3b, 0xae08, 0xc694, 0xc77c, 0x3b, 0xd1a0, 0xc694, 0xc77c, 0x3b, 0x63, 0x75, 0x2e, 0x3b, 0x6d, 0x62, 0x65,
+0x2e, 0x3b, 0x6b, 0x61, 0x62, 0x2e, 0x3b, 0x67, 0x74, 0x75, 0x2e, 0x3b, 0x6b, 0x61, 0x6e, 0x2e, 0x3b, 0x67, 0x6e, 0x75,
+0x2e, 0x3b, 0x67, 0x6e, 0x64, 0x2e, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x2019, 0x69, 0x6e, 0x64, 0x77, 0x69, 0x3b, 0x4b, 0x75,
+0x20, 0x77, 0x61, 0x20, 0x6d, 0x62, 0x65, 0x72, 0x65, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x6b, 0x61, 0x62, 0x69,
+0x72, 0x69, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4b, 0x75, 0x20, 0x77,
+0x61, 0x20, 0x6b, 0x61, 0x6e, 0x65, 0x3b, 0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b,
+0x4b, 0x75, 0x20, 0x77, 0x61, 0x20, 0x67, 0x61, 0x74, 0x61, 0x6e, 0x64, 0x61, 0x74, 0x75, 0x3b, 0xead, 0xeb2, 0xe97, 0xeb4,
+0xe94, 0x3b, 0xe88, 0xeb1, 0xe99, 0x3b, 0xead, 0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99, 0x3b, 0xe9e, 0xeb8, 0xe94, 0x3b, 0xe9e, 0xeb0, 0xeab,
+0xeb1, 0xe94, 0x3b, 0xeaa, 0xeb8, 0xe81, 0x3b, 0xec0, 0xeaa, 0xebb, 0xeb2, 0x3b, 0xea7, 0xeb1, 0xe99, 0xead, 0xeb2, 0xe97, 0xeb4, 0xe94,
+0x3b, 0xea7, 0xeb1, 0xe99, 0xe88, 0xeb1, 0xe99, 0x3b, 0xea7, 0xeb1, 0xe99, 0xead, 0xeb1, 0xe87, 0xe84, 0xeb2, 0xe99, 0x3b, 0xea7, 0xeb1,
+0xe99, 0xe9e, 0xeb8, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xe9e, 0xeb0, 0xeab, 0xeb1, 0xe94, 0x3b, 0xea7, 0xeb1, 0xe99, 0xeaa, 0xeb8, 0xe81,
+0x3b, 0xea7, 0xeb1, 0xe99, 0xec0, 0xeaa, 0xebb, 0xeb2, 0x3b, 0xead, 0xeb2, 0x3b, 0xe88, 0x3b, 0xead, 0x3b, 0xe9e, 0x3b, 0xe9e, 0xeab,
+0x3b, 0xeaa, 0xeb8, 0x3b, 0xeaa, 0x3b, 0x53, 0x76, 0x113, 0x74, 0x64, 0x2e, 0x3b, 0x50, 0x69, 0x72, 0x6d, 0x64, 0x2e, 0x3b,
+0x4f, 0x74, 0x72, 0x64, 0x2e, 0x3b, 0x54, 0x72, 0x65, 0x161, 0x64, 0x2e, 0x3b, 0x43, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64,
+0x2e, 0x3b, 0x50, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x2e, 0x3b, 0x53, 0x65, 0x73, 0x74, 0x64, 0x2e, 0x3b, 0x53, 0x76, 0x113,
+0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x50, 0x69, 0x72, 0x6d, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x4f, 0x74, 0x72,
+0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x54, 0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x43, 0x65, 0x74, 0x75,
+0x72, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x50, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x53,
+0x65, 0x73, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x53, 0x3b, 0x50, 0x3b, 0x4f, 0x3b, 0x54, 0x3b, 0x43, 0x3b, 0x50,
+0x3b, 0x53, 0x3b, 0x73, 0x76, 0x113, 0x74, 0x64, 0x2e, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x64, 0x2e, 0x3b, 0x6f, 0x74, 0x72,
+0x64, 0x2e, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64, 0x2e, 0x3b, 0x63, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64, 0x2e, 0x3b, 0x70,
+0x69, 0x65, 0x6b, 0x74, 0x64, 0x2e, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x64, 0x2e, 0x3b, 0x73, 0x76, 0x113, 0x74, 0x64, 0x69,
+0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x72, 0x6d, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x6f, 0x74, 0x72, 0x64, 0x69, 0x65,
+0x6e, 0x61, 0x3b, 0x74, 0x72, 0x65, 0x161, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x63, 0x65, 0x74, 0x75, 0x72, 0x74, 0x64,
+0x69, 0x65, 0x6e, 0x61, 0x3b, 0x70, 0x69, 0x65, 0x6b, 0x74, 0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x74,
+0x64, 0x69, 0x65, 0x6e, 0x61, 0x3b, 0x65, 0x79, 0x65, 0x3b, 0x79, 0x62, 0x6f, 0x3b, 0x6d, 0x62, 0x6c, 0x3b, 0x6d, 0x73,
+0x74, 0x3b, 0x6d, 0x69, 0x6e, 0x3b, 0x6d, 0x74, 0x6e, 0x3b, 0x6d, 0x70, 0x73, 0x3b, 0x65, 0x79, 0x65, 0x6e, 0x67, 0x61,
+0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x79, 0x61, 0x6d, 0x62, 0x6f, 0x3b, 0x6d, 0x6f,
+0x6b, 0x254, 0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x62, 0x61, 0x6c, 0xe9, 0x3b, 0x6d, 0x6f, 0x6b, 0x254,
+0x6c, 0x254, 0x20, 0x6d, 0x77, 0x61, 0x20, 0x6d, 0xed, 0x73, 0xe1, 0x74, 0x6f, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254,
+0x20, 0x79, 0x61, 0x20, 0x6d, 0xed, 0x6e, 0xe9, 0x69, 0x3b, 0x6d, 0x6f, 0x6b, 0x254, 0x6c, 0x254, 0x20, 0x79, 0x61, 0x20,
+0x6d, 0xed, 0x74, 0xe1, 0x6e, 0x6f, 0x3b, 0x6d, 0x70, 0x254, 0x301, 0x73, 0x254, 0x3b, 0x65, 0x3b, 0x79, 0x3b, 0x6d, 0x3b,
+0x6d, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x70, 0x3b, 0x73, 0x6b, 0x3b, 0x70, 0x72, 0x3b, 0x61, 0x6e, 0x3b, 0x74, 0x72, 0x3b,
+0x6b, 0x74, 0x3b, 0x70, 0x6e, 0x3b, 0x161, 0x74, 0x3b, 0x73, 0x65, 0x6b, 0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73,
+0x3b, 0x70, 0x69, 0x72, 0x6d, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x61, 0x6e, 0x74, 0x72, 0x61, 0x64, 0x69,
+0x65, 0x6e, 0x69, 0x73, 0x3b, 0x74, 0x72, 0x65, 0x10d, 0x69, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x6b, 0x65,
+0x74, 0x76, 0x69, 0x72, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x70, 0x65, 0x6e, 0x6b, 0x74, 0x61, 0x64,
+0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x161, 0x65, 0x161, 0x74, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x69, 0x73, 0x3b, 0x53, 0x3b,
+0x50, 0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x4b, 0x3b, 0x50, 0x3b, 0x160, 0x3b, 0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, 0x43e, 0x43d,
+0x2e, 0x3b, 0x432, 0x442, 0x43e, 0x2e, 0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, 0x442,
+0x2e, 0x3b, 0x441, 0x430, 0x431, 0x2e, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435,
+0x43b, 0x43d, 0x438, 0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447,
+0x435, 0x442, 0x432, 0x440, 0x442, 0x43e, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x43e, 0x43a, 0x3b, 0x441, 0x430, 0x431, 0x43e, 0x442, 0x430,
+0x3b, 0x43d, 0x435, 0x434, 0x2e, 0x3b, 0x43f, 0x43e, 0x43d, 0x2e, 0x3b, 0x432, 0x442, 0x2e, 0x3b, 0x441, 0x440, 0x435, 0x2e, 0x3b,
+0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f, 0x435, 0x442, 0x2e, 0x3b, 0x441, 0x430, 0x431, 0x2e, 0x3b, 0x41, 0x6c, 0x61, 0x68, 0x3b,
+0x41, 0x6c, 0x61, 0x74, 0x73, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x3b,
+0x5a, 0x6f, 0x6d, 0x3b, 0x41, 0x73, 0x61, 0x62, 0x3b, 0x41, 0x6c, 0x61, 0x68, 0x61, 0x64, 0x79, 0x3b, 0x41, 0x6c, 0x61,
+0x74, 0x73, 0x69, 0x6e, 0x61, 0x69, 0x6e, 0x79, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72,
+0x6f, 0x62, 0x69, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x6b, 0x61, 0x6d, 0x69, 0x73, 0x79, 0x3b, 0x5a, 0x6f, 0x6d, 0x61, 0x3b,
+0x41, 0x73, 0x61, 0x62, 0x6f, 0x74, 0x73, 0x79, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x5a,
+0x3b, 0x41, 0x3b, 0x41, 0x68, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x3b, 0x52, 0x61, 0x62, 0x3b, 0x4b,
+0x68, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x41, 0x68, 0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69,
+0x6e, 0x3b, 0x53, 0x65, 0x6c, 0x61, 0x73, 0x61, 0x3b, 0x52, 0x61, 0x62, 0x75, 0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x73,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x75, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x53, 0x3b,
+0x52, 0x3b, 0x4b, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd7c, 0x3b, 0xd24, 0xd3f, 0xd19, 0xd4d, 0xd15, 0xd7e, 0x3b,
+0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd7b, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd02, 0x3b, 0xd35, 0xd46,
+0xd33, 0xd4d, 0xd33, 0xd3f, 0x3b, 0xd36, 0xd28, 0xd3f, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd31, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24,
+0xd3f, 0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0x200c,
+0xd1a, 0x3b, 0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d,
+0x200c, 0xd1a, 0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f,
+0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1e, 0xd3e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b, 0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d,
+0xd2f, 0xd3e, 0x3b, 0xd35, 0xd46, 0x3b, 0xd36, 0x3b, 0xd1e, 0xd3e, 0xd2f, 0xd31, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd24, 0xd3f,
+0xd19, 0xd4d, 0xd15, 0xd33, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1a, 0xd4a, 0xd35, 0xd4d, 0xd35, 0xd3e, 0xd34, 0xd4d, 0xd1a, 0x3b,
+0xd2c, 0xd41, 0xd27, 0xd28, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0xd34, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a,
+0x3b, 0xd35, 0xd46, 0xd33, 0xd4d, 0xd33, 0xd3f, 0xd2f, 0xd3e, 0xd34, 0xd4d, 0x200c, 0xd1a, 0x3b, 0xd36, 0xd28, 0xd3f, 0xd2f, 0xd3e, 0xd34,
+0xd4d, 0x200c, 0xd1a, 0x3b, 0xd1e, 0x3b, 0xd24, 0xd3f, 0x3b, 0xd1a, 0xd4a, 0x3b, 0xd2c, 0xd41, 0x3b, 0xd35, 0xd4d, 0xd2f, 0xd3e, 0x3b,
+0xd35, 0xd46, 0x3b, 0xd36, 0x3b, 0x126, 0x61, 0x64, 0x3b, 0x54, 0x6e, 0x65, 0x3b, 0x54, 0x6c, 0x69, 0x3b, 0x45, 0x72, 0x62,
+0x3b, 0x126, 0x61, 0x6d, 0x3b, 0x120, 0x69, 0x6d, 0x3b, 0x53, 0x69, 0x62, 0x3b, 0x49, 0x6c, 0x2d, 0x126, 0x61, 0x64, 0x64,
+0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6e, 0x65, 0x6a, 0x6e, 0x3b, 0x49, 0x74, 0x2d, 0x54, 0x6c, 0x69, 0x65, 0x74, 0x61, 0x3b,
+0x4c, 0x2d, 0x45, 0x72, 0x62, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x6c, 0x2d, 0x126, 0x61, 0x6d, 0x69, 0x73, 0x3b, 0x49, 0x6c,
+0x2d, 0x120, 0x69, 0x6d, 0x67, 0x127, 0x61, 0x3b, 0x49, 0x73, 0x2d, 0x53, 0x69, 0x62, 0x74, 0x3b, 0x126, 0x64, 0x3b, 0x54,
+0x6e, 0x3b, 0x54, 0x6c, 0x3b, 0x45, 0x72, 0x3b, 0x126, 0x6d, 0x3b, 0x120, 0x6d, 0x3b, 0x53, 0x62, 0x3b, 0x126, 0x64, 0x3b,
+0x54, 0x3b, 0x54, 0x6c, 0x3b, 0x45, 0x72, 0x3b, 0x126, 0x6d, 0x3b, 0x120, 0x6d, 0x3b, 0x53, 0x62, 0x3b, 0x930, 0x935, 0x93f,
+0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x3b, 0x92c, 0x941, 0x927, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x3b, 0x936,
+0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b, 0x930, 0x935, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935,
+0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x935, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941,
+0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e,
+0x930, 0x3b, 0x41d, 0x44f, 0x3b, 0x414, 0x430, 0x3b, 0x41c, 0x44f, 0x3b, 0x41b, 0x445, 0x3b, 0x41f, 0x4af, 0x3b, 0x411, 0x430, 0x3b,
+0x411, 0x44f, 0x3b, 0x43d, 0x44f, 0x43c, 0x3b, 0x434, 0x430, 0x432, 0x430, 0x430, 0x3b, 0x43c, 0x44f, 0x433, 0x43c, 0x430, 0x440, 0x3b,
+0x43b, 0x445, 0x430, 0x433, 0x432, 0x430, 0x3b, 0x43f, 0x4af, 0x440, 0x44d, 0x432, 0x3b, 0x431, 0x430, 0x430, 0x441, 0x430, 0x43d, 0x3b,
+0x431, 0x44f, 0x43c, 0x431, 0x430, 0x3b, 0x906, 0x907, 0x924, 0x3b, 0x938, 0x94b, 0x92e, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x3b,
+0x92c, 0x941, 0x927, 0x3b, 0x92c, 0x93f, 0x939, 0x93f, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x3b, 0x906,
+0x907, 0x924, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x919, 0x94d, 0x917, 0x932, 0x92c, 0x93e,
+0x930, 0x3b, 0x92c, 0x941, 0x927, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x939, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915,
+0x94d, 0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x906, 0x3b, 0x938, 0x94b, 0x3b, 0x92e, 0x3b,
+0x92c, 0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x936, 0x941, 0x3b, 0x936, 0x3b, 0xb30, 0xb2c, 0xb3f, 0x3b, 0xb38, 0xb4b, 0xb2e, 0x3b, 0xb2e,
+0xb19, 0xb4d, 0xb17, 0xb33, 0x3b, 0xb2c, 0xb41, 0xb27, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0x3b,
+0xb36, 0xb28, 0xb3f, 0x3b, 0xb30, 0xb2c, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb38, 0xb4b, 0xb2e, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2e, 0xb19,
+0xb4d, 0xb17, 0xb33, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb2c, 0xb41, 0xb27, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb17, 0xb41, 0xb30, 0xb41, 0xb2c, 0xb3e,
+0xb30, 0x3b, 0xb36, 0xb41, 0xb15, 0xb4d, 0xb30, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb36, 0xb28, 0xb3f, 0xb2c, 0xb3e, 0xb30, 0x3b, 0xb30, 0x3b,
+0xb38, 0xb4b, 0x3b, 0xb2e, 0x3b, 0xb2c, 0xb41, 0x3b, 0xb17, 0xb41, 0x3b, 0xb36, 0xb41, 0x3b, 0xb36, 0x3b, 0x6cc, 0x6a9, 0x634, 0x646,
+0x628, 0x647, 0x3b, 0x62f, 0x648, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x633, 0x647, 0x200c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x686, 0x647,
+0x627, 0x631, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x67e, 0x646, 0x62c, 0x634, 0x646, 0x628, 0x647, 0x3b, 0x62c, 0x645, 0x639, 0x647, 0x3b,
+0x634, 0x646, 0x628, 0x647, 0x3b, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x3b, 0x6e,
+0x69, 0x65, 0x64, 0x7a, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x77, 0x74, 0x2e, 0x3b, 0x15b, 0x72, 0x2e, 0x3b, 0x63,
+0x7a, 0x77, 0x2e, 0x3b, 0x70, 0x74, 0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x3b, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x65,
+0x6c, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x69, 0x65, 0x64, 0x7a, 0x69, 0x61, 0x142, 0x65, 0x6b, 0x3b, 0x77, 0x74, 0x6f, 0x72,
+0x65, 0x6b, 0x3b, 0x15b, 0x72, 0x6f, 0x64, 0x61, 0x3b, 0x63, 0x7a, 0x77, 0x61, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0x69,
+0x105, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x4e, 0x3b, 0x50, 0x3b, 0x57, 0x3b, 0x15a, 0x3b,
+0x43, 0x3b, 0x50, 0x3b, 0x53, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x15b, 0x3b, 0x63, 0x3b, 0x70, 0x3b, 0x73, 0x3b,
+0x64, 0x6f, 0x6d, 0x3b, 0x73, 0x65, 0x67, 0x3b, 0x74, 0x65, 0x72, 0x3b, 0x71, 0x75, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x3b,
+0x73, 0x65, 0x78, 0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x67, 0x75,
+0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0xe7, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72,
+0x61, 0x3b, 0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x6e, 0x74,
+0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x78, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x69, 0x72, 0x61, 0x3b,
+0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x51, 0x3b, 0x51, 0x3b, 0x53, 0x3b, 0x53,
+0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x73, 0x65, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x3b, 0x74, 0x65, 0x72,
+0xe7, 0x61, 0x3b, 0x71, 0x75, 0x61, 0x72, 0x74, 0x61, 0x3b, 0x71, 0x75, 0x69, 0x6e, 0x74, 0x61, 0x3b, 0x73, 0x65, 0x78,
+0x74, 0x61, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0xa10, 0xa24, 0x3b, 0xa38, 0xa4b, 0xa2e, 0x3b, 0xa2e, 0xa70, 0xa17,
+0xa32, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0x3b, 0xa35, 0xa40, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0x3b, 0xa38, 0xa3c,
+0xa28, 0xa3f, 0xa71, 0xa1a, 0xa30, 0x3b, 0xa10, 0xa24, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa4b, 0xa2e, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2e,
+0xa70, 0xa17, 0xa32, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa2c, 0xa41, 0xa71, 0xa27, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa35, 0xa40, 0xa30, 0xa35, 0xa3e,
+0xa30, 0x3b, 0xa38, 0xa3c, 0xa41, 0xa71, 0xa15, 0xa30, 0xa35, 0xa3e, 0xa30, 0x3b, 0xa38, 0xa3c, 0xa28, 0xa3f, 0xa71, 0xa1a, 0xa30, 0xa35,
+0xa3e, 0xa30, 0x3b, 0xa10, 0x3b, 0xa38, 0xa4b, 0x3b, 0xa2e, 0xa70, 0x3b, 0xa2c, 0xa41, 0xa71, 0x3b, 0xa35, 0xa40, 0x3b, 0xa38, 0xa3c,
+0xa41, 0xa71, 0x3b, 0xa38, 0xa3c, 0x3b, 0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x67e, 0x6cc, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644,
+0x3b, 0x628, 0x64f, 0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641,
+0x62a, 0x6c1, 0x3b, 0x44, 0x6f, 0x6d, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0xe9, 0x3b, 0x4a,
+0x75, 0x65, 0x3b, 0x56, 0x69, 0x65, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x4c,
+0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65,
+0x73, 0x3b, 0x4a, 0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x56, 0x69, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0xe1, 0x62,
+0x61, 0x64, 0x6f, 0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x58, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x75,
+0x3b, 0x67, 0x6c, 0x69, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x65, 0x3b, 0x67, 0x69, 0x65, 0x3b, 0x76, 0x65, 0x3b, 0x73, 0x6f,
+0x3b, 0x64, 0x75, 0x6d, 0x65, 0x6e, 0x67, 0x69, 0x61, 0x3b, 0x67, 0x6c, 0x69, 0x6e, 0x64, 0x65, 0x73, 0x64, 0x69, 0x3b,
+0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x73, 0x65, 0x6d, 0x6e, 0x61, 0x3b, 0x67, 0x69, 0x65, 0x76, 0x67, 0x69,
+0x61, 0x3b, 0x76, 0x65, 0x6e, 0x64, 0x65, 0x72, 0x64, 0x69, 0x3b, 0x73, 0x6f, 0x6e, 0x64, 0x61, 0x3b, 0x44, 0x3b, 0x47,
+0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x47, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x64, 0x75, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e,
+0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x69, 0x65, 0x2e, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x2e, 0x3b,
+0x73, 0xe2, 0x6d, 0x2e, 0x3b, 0x64, 0x75, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x103, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x3b, 0x6d,
+0x61, 0x72, 0x21b, 0x69, 0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x75, 0x72, 0x69, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69,
+0x6e, 0x65, 0x72, 0x69, 0x3b, 0x73, 0xe2, 0x6d, 0x62, 0x103, 0x74, 0x103, 0x3b, 0x44, 0x75, 0x6d, 0x3b, 0x4c, 0x75, 0x6e,
+0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0x65, 0x3b, 0x4a, 0x6f, 0x69, 0x3b, 0x56, 0x69, 0x6e, 0x3b, 0x53, 0xe2, 0x6d,
+0x3b, 0x44, 0x3b, 0x4c, 0x3b, 0x4d, 0x61, 0x3b, 0x4d, 0x69, 0x3b, 0x4a, 0x3b, 0x56, 0x3b, 0x53, 0x3b, 0x432, 0x441, 0x3b,
+0x43f, 0x43d, 0x3b, 0x432, 0x442, 0x3b, 0x441, 0x440, 0x3b, 0x447, 0x442, 0x3b, 0x43f, 0x442, 0x3b, 0x441, 0x431, 0x3b, 0x432, 0x43e,
+0x441, 0x43a, 0x440, 0x435, 0x441, 0x435, 0x43d, 0x44c, 0x435, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x43b, 0x44c, 0x43d, 0x438,
+0x43a, 0x3b, 0x432, 0x442, 0x43e, 0x440, 0x43d, 0x438, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432,
+0x435, 0x440, 0x433, 0x3b, 0x43f, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x430, 0x3b, 0x441, 0x443, 0x431, 0x431, 0x43e, 0x442, 0x430, 0x3b,
+0x412, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421, 0x3b, 0x42, 0x6b, 0x31, 0x3b, 0x42, 0x6b,
+0x32, 0x3b, 0x42, 0x6b, 0x33, 0x3b, 0x42, 0x6b, 0x34, 0x3b, 0x42, 0x6b, 0x35, 0x3b, 0x4c, 0xe2, 0x70, 0x3b, 0x4c, 0xe2,
+0x79, 0x3b, 0x42, 0x69, 0x6b, 0x75, 0x61, 0x2d, 0xf4, 0x6b, 0x6f, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0xfb, 0x73,
+0x65, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x70, 0x74, 0xe2, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x75, 0x73,
+0xef, 0xf6, 0x3b, 0x42, 0xef, 0x6b, 0x75, 0x61, 0x2d, 0x6f, 0x6b, 0xfc, 0x3b, 0x4c, 0xe2, 0x70, 0xf4, 0x73, 0xf6, 0x3b,
+0x4c, 0xe2, 0x79, 0x65, 0x6e, 0x67, 0x61, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x50, 0x3b,
+0x59, 0x3b, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e, 0x3b, 0x441, 0x440, 0x435, 0x3b, 0x447, 0x435,
+0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d,
+0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x3b,
+0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442,
+0x430, 0x3b, 0x43d, 0x3b, 0x43f, 0x3b, 0x443, 0x3b, 0x441, 0x3b, 0x447, 0x3b, 0x43f, 0x3b, 0x441, 0x3b, 0x43d, 0x435, 0x434, 0x2e,
+0x3b, 0x43f, 0x43e, 0x43d, 0x2e, 0x3b, 0x443, 0x442, 0x2e, 0x3b, 0x441, 0x440, 0x2e, 0x3b, 0x447, 0x435, 0x442, 0x2e, 0x3b, 0x43f,
+0x435, 0x442, 0x2e, 0x3b, 0x441, 0x443, 0x431, 0x2e, 0x3b, 0x43d, 0x435, 0x434, 0x458, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d,
+0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434,
+0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431,
+0x43e, 0x442, 0x430, 0x3b, 0x6e, 0x65, 0x64, 0x2e, 0x3b, 0x70, 0x6f, 0x6e, 0x2e, 0x3b, 0x75, 0x74, 0x2e, 0x3b, 0x73, 0x72,
+0x2e, 0x3b, 0x10d, 0x65, 0x74, 0x2e, 0x3b, 0x70, 0x65, 0x74, 0x2e, 0x3b, 0x73, 0x75, 0x62, 0x2e, 0x3b, 0x6e, 0x65, 0x64,
+0x6a, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b, 0x3b, 0x75, 0x74, 0x6f,
+0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x69, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74, 0x61, 0x6b,
+0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x65, 0x64, 0x3b, 0x70, 0x6f,
+0x6e, 0x3b, 0x75, 0x74, 0x6f, 0x3b, 0x73, 0x72, 0x65, 0x3b, 0x10d, 0x65, 0x74, 0x3b, 0x70, 0x65, 0x74, 0x3b, 0x73, 0x75,
+0x62, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x6b,
+0x3b, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x6b, 0x3b, 0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65, 0x74, 0x76, 0x72, 0x74,
+0x61, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x61, 0x6b, 0x3b, 0x73, 0x75, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x425, 0x446, 0x431, 0x3b,
+0x41a, 0x440, 0x441, 0x3b, 0x414, 0x446, 0x433, 0x3b, 0x4d4, 0x440, 0x442, 0x3b, 0x426, 0x43f, 0x440, 0x3b, 0x41c, 0x440, 0x431, 0x3b,
+0x421, 0x431, 0x442, 0x3b, 0x425, 0x443, 0x44b, 0x446, 0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x41a, 0x44a, 0x443, 0x44b, 0x440, 0x438,
+0x441, 0x4d5, 0x440, 0x3b, 0x414, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x4d4, 0x440, 0x442, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b,
+0x426, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x41c, 0x430, 0x439, 0x440, 0x4d5, 0x43c, 0x431, 0x43e, 0x43d, 0x3b, 0x421,
+0x430, 0x431, 0x430, 0x442, 0x3b, 0x425, 0x3b, 0x41a, 0x3b, 0x414, 0x3b, 0x4d4, 0x3b, 0x426, 0x3b, 0x41c, 0x3b, 0x421, 0x3b, 0x445,
+0x446, 0x431, 0x3b, 0x43a, 0x440, 0x441, 0x3b, 0x434, 0x446, 0x433, 0x3b, 0x4d5, 0x440, 0x442, 0x3b, 0x446, 0x43f, 0x440, 0x3b, 0x43c,
+0x440, 0x431, 0x3b, 0x441, 0x431, 0x442, 0x3b, 0x445, 0x443, 0x44b, 0x446, 0x430, 0x443, 0x431, 0x43e, 0x43d, 0x3b, 0x43a, 0x44a, 0x443,
+0x44b, 0x440, 0x438, 0x441, 0x4d5, 0x440, 0x3b, 0x434, 0x44b, 0x446, 0x446, 0x4d5, 0x433, 0x3b, 0x4d5, 0x440, 0x442, 0x44b, 0x446, 0x446,
+0x4d5, 0x433, 0x3b, 0x446, 0x44b, 0x43f, 0x43f, 0x4d5, 0x440, 0x4d5, 0x43c, 0x3b, 0x43c, 0x430, 0x439, 0x440, 0x4d5, 0x43c, 0x431, 0x43e,
+0x43d, 0x3b, 0x441, 0x430, 0x431, 0x430, 0x442, 0x3b, 0x53, 0x76, 0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x3b, 0x43, 0x68, 0x70, 0x3b,
+0x43, 0x68, 0x74, 0x3b, 0x43, 0x68, 0x6e, 0x3b, 0x43, 0x68, 0x73, 0x3b, 0x4d, 0x75, 0x67, 0x3b, 0x53, 0x76, 0x6f, 0x6e,
+0x64, 0x6f, 0x3b, 0x4d, 0x75, 0x76, 0x68, 0x75, 0x72, 0x6f, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43,
+0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x3b, 0x43, 0x68, 0x69, 0x73, 0x68, 0x61, 0x6e,
+0x75, 0x3b, 0x4d, 0x75, 0x67, 0x6f, 0x76, 0x65, 0x72, 0x61, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43,
+0x3b, 0x43, 0x3b, 0x4d, 0x3b, 0xd89, 0xdbb, 0xdd2, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4,
+0x3b, 0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3, 0xdca, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0x3b,
+0xdc3, 0xdd9, 0xdb1, 0x3b, 0xd89, 0xdbb, 0xdd2, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdb3, 0xdd4, 0xdaf, 0xdcf, 0x3b, 0xd85, 0xd9f, 0xdc4, 0xdbb,
+0xdd4, 0xdc0, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdaf, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0xdc4, 0xdc3, 0xdca, 0xdb4,
+0xdad, 0xdd2, 0xdb1, 0xdca, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdd2, 0xd9a, 0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xdc3, 0xdd9, 0xdb1, 0xdc3,
+0xdd4, 0xdbb, 0xdcf, 0xdaf, 0xdcf, 0x3b, 0xd89, 0x3b, 0xdc3, 0x3b, 0xd85, 0x3b, 0xdb6, 0x3b, 0xdb6, 0xdca, 0x200d, 0xdbb, 0x3b, 0xdc3,
+0xdd2, 0x3b, 0xdc3, 0xdd9, 0x3b, 0x6e, 0x65, 0x3b, 0x70, 0x6f, 0x3b, 0x75, 0x74, 0x3b, 0x73, 0x74, 0x3b, 0x161, 0x74, 0x3b,
+0x70, 0x69, 0x3b, 0x73, 0x6f, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x13e, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x6c, 0x6f,
+0x6b, 0x3b, 0x75, 0x74, 0x6f, 0x72, 0x6f, 0x6b, 0x3b, 0x73, 0x74, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x161, 0x74, 0x76, 0x72,
+0x74, 0x6f, 0x6b, 0x3b, 0x70, 0x69, 0x61, 0x74, 0x6f, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b,
+0x70, 0x3b, 0x75, 0x3b, 0x73, 0x3b, 0x161, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x65, 0x64, 0x2e, 0x3b, 0x70, 0x6f, 0x6e,
+0x2e, 0x3b, 0x74, 0x6f, 0x72, 0x2e, 0x3b, 0x73, 0x72, 0x65, 0x2e, 0x3b, 0x10d, 0x65, 0x74, 0x2e, 0x3b, 0x70, 0x65, 0x74,
+0x2e, 0x3b, 0x73, 0x6f, 0x62, 0x2e, 0x3b, 0x6e, 0x65, 0x64, 0x65, 0x6c, 0x6a, 0x61, 0x3b, 0x70, 0x6f, 0x6e, 0x65, 0x64,
+0x65, 0x6c, 0x6a, 0x65, 0x6b, 0x3b, 0x74, 0x6f, 0x72, 0x65, 0x6b, 0x3b, 0x73, 0x72, 0x65, 0x64, 0x61, 0x3b, 0x10d, 0x65,
+0x74, 0x72, 0x74, 0x65, 0x6b, 0x3b, 0x70, 0x65, 0x74, 0x65, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e,
+0x3b, 0x70, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x10d, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x41, 0x78, 0x64, 0x3b, 0x49, 0x73, 0x6e,
+0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x72, 0x62, 0x3b, 0x4b, 0x68, 0x61, 0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x53, 0x61, 0x62,
+0x3b, 0x41, 0x78, 0x61, 0x64, 0x3b, 0x49, 0x73, 0x6e, 0x69, 0x69, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x61, 0x64, 0x6f,
+0x3b, 0x41, 0x72, 0x62, 0x61, 0x63, 0x6f, 0x3b, 0x4b, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x3b, 0x4a, 0x69, 0x6d, 0x63,
+0x6f, 0x3b, 0x53, 0x61, 0x62, 0x74, 0x69, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x4b, 0x68, 0x3b, 0x4a,
0x3b, 0x53, 0x3b, 0x64, 0x6f, 0x6d, 0x2e, 0x3b, 0x6c, 0x75, 0x6e, 0x2e, 0x3b, 0x6d, 0x61, 0x72, 0x2e, 0x3b, 0x6d, 0x69,
0xe9, 0x2e, 0x3b, 0x6a, 0x75, 0x65, 0x2e, 0x3b, 0x76, 0x69, 0x65, 0x2e, 0x3b, 0x73, 0xe1, 0x62, 0x2e, 0x3b, 0x64, 0x6f,
0x6d, 0x69, 0x6e, 0x67, 0x6f, 0x3b, 0x6c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d,
@@ -4272,45 +4305,40 @@ static const ushort days_data[] = {
0x3b, 0x76, 0x3b, 0x73, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61,
0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b,
0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
-0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x79, 0x3b, 0x6b, 0x3b, 0x70, 0x3b, 0x74, 0x3b, 0x69, 0x3b, 0x74, 0x3b, 0x73, 0x3b, 0x79,
-0x65, 0x6e, 0x3b, 0x6b, 0x77, 0x61, 0x3b, 0x70, 0x69, 0x6c, 0x3b, 0x74, 0x61, 0x74, 0x3b, 0x69, 0x6e, 0x65, 0x3b, 0x74,
-0x61, 0x6e, 0x3b, 0x73, 0x69, 0x74, 0x3b, 0x73, 0x69, 0x6b, 0x75, 0x20, 0x79, 0x61, 0x20, 0x79, 0x65, 0x6e, 0x67, 0x61,
-0x3b, 0x73, 0x69, 0x6b, 0x75, 0x20, 0x79, 0x61, 0x20, 0x6b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x73, 0x69, 0x6b, 0x75,
-0x20, 0x79, 0x61, 0x20, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x73, 0x69, 0x6b, 0x75, 0x20, 0x79, 0x61, 0x20, 0x74, 0x61, 0x74,
-0x75, 0x3b, 0x73, 0x69, 0x6b, 0x75, 0x20, 0x79, 0x61, 0x20, 0x69, 0x6e, 0x65, 0x3b, 0x73, 0x69, 0x6b, 0x75, 0x20, 0x79,
-0x61, 0x20, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x73, 0x69, 0x6b, 0x75, 0x20, 0x79, 0x61, 0x20, 0x73, 0x69, 0x74, 0x61, 0x3b,
-0x73, 0xf6, 0x6e, 0x3b, 0x6d, 0xe5, 0x6e, 0x3b, 0x74, 0x69, 0x73, 0x3b, 0x6f, 0x6e, 0x73, 0x3b, 0x74, 0x6f, 0x72, 0x73,
-0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0xf6, 0x72, 0x3b, 0x73, 0xf6, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0xe5, 0x6e, 0x64,
-0x61, 0x67, 0x3b, 0x74, 0x69, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72,
-0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0xf6, 0x72, 0x64, 0x61, 0x67, 0x3b, 0xb9e,
-0xbbe, 0xbaf, 0xbbf, 0x2e, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbb5, 0xbcd, 0x2e, 0x3b, 0xbaa, 0xbc1, 0xba4,
-0x2e, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0x2e, 0x3b, 0xbb5, 0xbc6, 0xbb3, 0xbcd, 0x2e, 0x3b, 0xb9a, 0xba9, 0xbbf, 0x3b, 0xb9e, 0xbbe,
-0xbaf, 0xbbf, 0xbb1, 0xbc1, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb9a, 0xbc6, 0xbb5, 0xbcd, 0xbb5, 0xbbe, 0xbaf,
-0xbcd, 0x3b, 0xbaa, 0xbc1, 0xba4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0xbb4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbc6, 0xbb3, 0xbcd,
-0xbb3, 0xbbf, 0x3b, 0xb9a, 0xba9, 0xbbf, 0x3b, 0xb9e, 0xbbe, 0x3b, 0xba4, 0xbbf, 0x3b, 0xb9a, 0xbc6, 0x3b, 0xbaa, 0xbc1, 0x3b, 0xbb5,
-0xbbf, 0x3b, 0xbb5, 0xbc6, 0x3b, 0xb9a, 0x3b, 0xc06, 0xc26, 0xc3f, 0x3b, 0xc38, 0xc4b, 0xc2e, 0x3b, 0xc2e, 0xc02, 0xc17, 0xc33, 0x3b,
-0xc2c, 0xc41, 0xc27, 0x3b, 0xc17, 0xc41, 0xc30, 0xc41, 0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0x3b, 0xc36, 0xc28, 0xc3f, 0x3b, 0xc06,
-0xc26, 0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc38, 0xc4b, 0xc2e, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc2e, 0xc02, 0xc17, 0xc33, 0xc35,
-0xc3e, 0xc30, 0xc02, 0x3b, 0xc2c, 0xc41, 0xc27, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc17, 0xc41, 0xc30, 0xc41, 0xc35, 0xc3e, 0xc30, 0xc02,
-0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc28, 0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc06,
-0x3b, 0xc38, 0xc4b, 0x3b, 0xc2e, 0x3b, 0xc2c, 0xc41, 0x3b, 0xc17, 0xc41, 0x3b, 0xc36, 0xc41, 0x3b, 0xc36, 0x3b, 0xe2d, 0xe32, 0x2e,
-0x3b, 0xe08, 0x2e, 0x3b, 0xe2d, 0x2e, 0x3b, 0xe1e, 0x2e, 0x3b, 0xe1e, 0xe24, 0x2e, 0x3b, 0xe28, 0x2e, 0x3b, 0xe2a, 0x2e, 0x3b,
-0xe27, 0xe31, 0xe19, 0xe2d, 0xe32, 0xe17, 0xe34, 0xe15, 0xe22, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe08, 0xe31, 0xe19, 0xe17, 0xe23, 0xe4c,
-0x3b, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe31, 0xe07, 0xe04, 0xe32, 0xe23, 0x3b, 0xe27, 0xe31, 0xe19, 0xe1e, 0xe38, 0xe18, 0x3b, 0xe27, 0xe31,
-0xe19, 0xe1e, 0xe24, 0xe2b, 0xe31, 0xe2a, 0xe1a, 0xe14, 0xe35, 0x3b, 0xe27, 0xe31, 0xe19, 0xe28, 0xe38, 0xe01, 0xe23, 0xe4c, 0x3b, 0xe27,
-0xe31, 0xe19, 0xe40, 0xe2a, 0xe32, 0xe23, 0xe4c, 0x3b, 0xe2d, 0xe32, 0x3b, 0xe08, 0x3b, 0xe2d, 0x3b, 0xe1e, 0x3b, 0xe1e, 0xe24, 0x3b,
-0xe28, 0x3b, 0xe2a, 0x3b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf58, 0xf72, 0xf42, 0xf0b,
-0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b,
-0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49,
-0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58,
-0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42,
-0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66,
-0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf49, 0xf72, 0x3b, 0xf5f, 0xfb3, 0x3b,
-0xf58, 0xf72, 0xf42, 0x3b, 0xf63, 0xfb7, 0xf42, 0x3b, 0xf55, 0xf74, 0xf62, 0x3b, 0xf66, 0xf44, 0xf66, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53,
-0x3b, 0x1230, 0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b, 0x1220, 0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1283, 0x1219,
-0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1220, 0x3b, 0x1228, 0x3b, 0x1283, 0x3b,
-0x12d3, 0x3b, 0x1240, 0x3b, 0x1230, 0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b, 0x1230, 0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5,
-0x3b, 0x1213, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d, 0x3b, 0x53, 0x101, 0x70, 0x3b, 0x4d, 0x14d, 0x6e,
+0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x73, 0xf6, 0x6e, 0x3b, 0x6d, 0xe5, 0x6e, 0x3b, 0x74, 0x69, 0x73, 0x3b, 0x6f, 0x6e, 0x73,
+0x3b, 0x74, 0x6f, 0x72, 0x73, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0xf6, 0x72, 0x3b, 0x73, 0xf6, 0x6e, 0x64, 0x61, 0x67,
+0x3b, 0x6d, 0xe5, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x69, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61,
+0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0xf6, 0x72,
+0x64, 0x61, 0x67, 0x3b, 0xb9e, 0xbbe, 0xbaf, 0xbbf, 0x2e, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0x2e, 0x3b, 0xb9a, 0xbc6, 0xbb5, 0xbcd,
+0x2e, 0x3b, 0xbaa, 0xbc1, 0xba4, 0x2e, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0x2e, 0x3b, 0xbb5, 0xbc6, 0xbb3, 0xbcd, 0x2e, 0x3b, 0xb9a,
+0xba9, 0xbbf, 0x3b, 0xb9e, 0xbbe, 0xbaf, 0xbbf, 0xbb1, 0xbc1, 0x3b, 0xba4, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb9a, 0xbc6,
+0xbb5, 0xbcd, 0xbb5, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0xbaa, 0xbc1, 0xba4, 0xba9, 0xbcd, 0x3b, 0xbb5, 0xbbf, 0xbaf, 0xbbe, 0xbb4, 0xba9, 0xbcd,
+0x3b, 0xbb5, 0xbc6, 0xbb3, 0xbcd, 0xbb3, 0xbbf, 0x3b, 0xb9a, 0xba9, 0xbbf, 0x3b, 0xb9e, 0xbbe, 0x3b, 0xba4, 0xbbf, 0x3b, 0xb9a, 0xbc6,
+0x3b, 0xbaa, 0xbc1, 0x3b, 0xbb5, 0xbbf, 0x3b, 0xbb5, 0xbc6, 0x3b, 0xb9a, 0x3b, 0xc06, 0xc26, 0xc3f, 0x3b, 0xc38, 0xc4b, 0xc2e, 0x3b,
+0xc2e, 0xc02, 0xc17, 0xc33, 0x3b, 0xc2c, 0xc41, 0xc27, 0x3b, 0xc17, 0xc41, 0xc30, 0xc41, 0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0x3b,
+0xc36, 0xc28, 0xc3f, 0x3b, 0xc06, 0xc26, 0xc3f, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc38, 0xc4b, 0xc2e, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b,
+0xc2e, 0xc02, 0xc17, 0xc33, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc2c, 0xc41, 0xc27, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc17, 0xc41, 0xc30,
+0xc41, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc41, 0xc15, 0xc4d, 0xc30, 0xc35, 0xc3e, 0xc30, 0xc02, 0x3b, 0xc36, 0xc28, 0xc3f, 0xc35,
+0xc3e, 0xc30, 0xc02, 0x3b, 0xc06, 0x3b, 0xc38, 0xc4b, 0x3b, 0xc2e, 0x3b, 0xc2c, 0xc41, 0x3b, 0xc17, 0xc41, 0x3b, 0xc36, 0xc41, 0x3b,
+0xc36, 0x3b, 0xe2d, 0xe32, 0x2e, 0x3b, 0xe08, 0x2e, 0x3b, 0xe2d, 0x2e, 0x3b, 0xe1e, 0x2e, 0x3b, 0xe1e, 0xe24, 0x2e, 0x3b, 0xe28,
+0x2e, 0x3b, 0xe2a, 0x2e, 0x3b, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe32, 0xe17, 0xe34, 0xe15, 0xe22, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe08,
+0xe31, 0xe19, 0xe17, 0xe23, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe2d, 0xe31, 0xe07, 0xe04, 0xe32, 0xe23, 0x3b, 0xe27, 0xe31, 0xe19, 0xe1e,
+0xe38, 0xe18, 0x3b, 0xe27, 0xe31, 0xe19, 0xe1e, 0xe24, 0xe2b, 0xe31, 0xe2a, 0xe1a, 0xe14, 0xe35, 0x3b, 0xe27, 0xe31, 0xe19, 0xe28, 0xe38,
+0xe01, 0xe23, 0xe4c, 0x3b, 0xe27, 0xe31, 0xe19, 0xe40, 0xe2a, 0xe32, 0xe23, 0xe4c, 0x3b, 0xe2d, 0xe32, 0x3b, 0xe08, 0x3b, 0xe2d, 0x3b,
+0xe1e, 0x3b, 0xe1e, 0xe24, 0x3b, 0xe28, 0x3b, 0xe2a, 0x3b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b,
+0x3b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf63, 0xfb7, 0xf42, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf55, 0xf74, 0xf62,
+0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b,
+0xf42, 0xf5f, 0xf60, 0xf0b, 0xf49, 0xf72, 0xf0b, 0xf58, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf5f, 0xfb3, 0xf0b, 0xf56, 0xf0b, 0x3b,
+0xf42, 0xf5f, 0xf60, 0xf0b, 0xf58, 0xf72, 0xf42, 0xf0b, 0xf51, 0xf58, 0xf62, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf63, 0xfb7, 0xf42,
+0xf0b, 0xf54, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf55, 0xf74, 0xf62, 0xf0b, 0xf56, 0xf74, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b,
+0xf54, 0xf0b, 0xf66, 0xf44, 0xf66, 0xf0b, 0x3b, 0xf42, 0xf5f, 0xf60, 0xf0b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0xf0b, 0xf54, 0xf0b, 0x3b, 0xf49,
+0xf72, 0x3b, 0xf5f, 0xfb3, 0x3b, 0xf58, 0xf72, 0xf42, 0x3b, 0xf63, 0xfb7, 0xf42, 0x3b, 0xf55, 0xf74, 0xf62, 0x3b, 0xf66, 0xf44, 0xf66,
+0x3b, 0xf66, 0xfa4, 0xf7a, 0xf53, 0x3b, 0x1230, 0x1295, 0x3b, 0x1230, 0x1291, 0x3b, 0x1230, 0x1209, 0x3b, 0x1228, 0x1261, 0x3b, 0x1213, 0x1219,
+0x3b, 0x12d3, 0x122d, 0x3b, 0x1240, 0x12f3, 0x3b, 0x1230, 0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b, 0x1230, 0x1209, 0x1235, 0x3b,
+0x1228, 0x1261, 0x12d5, 0x3b, 0x1213, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d, 0x3b, 0x1230, 0x3b, 0x1230, 0x3b,
+0x1220, 0x3b, 0x1228, 0x3b, 0x1213, 0x3b, 0x12d3, 0x3b, 0x1240, 0x3b, 0x1230, 0x1295, 0x1260, 0x1275, 0x3b, 0x1230, 0x1291, 0x12ed, 0x3b, 0x1220,
+0x1209, 0x1235, 0x3b, 0x1228, 0x1261, 0x12d5, 0x3b, 0x1283, 0x1219, 0x1235, 0x3b, 0x12d3, 0x122d, 0x1262, 0x3b, 0x1240, 0x12f3, 0x121d, 0x3b, 0x1230,
+0x3b, 0x1230, 0x3b, 0x1230, 0x3b, 0x1228, 0x3b, 0x1213, 0x3b, 0x12d3, 0x3b, 0x1240, 0x3b, 0x53, 0x101, 0x70, 0x3b, 0x4d, 0x14d, 0x6e,
0x3b, 0x54, 0x16b, 0x73, 0x3b, 0x50, 0x75, 0x6c, 0x3b, 0x54, 0x75, 0x2bb, 0x61, 0x3b, 0x46, 0x61, 0x6c, 0x3b, 0x54, 0x6f,
0x6b, 0x3b, 0x53, 0x101, 0x70, 0x61, 0x74, 0x65, 0x3b, 0x4d, 0x14d, 0x6e, 0x69, 0x74, 0x65, 0x3b, 0x54, 0x16b, 0x73, 0x69,
0x74, 0x65, 0x3b, 0x50, 0x75, 0x6c, 0x65, 0x6c, 0x75, 0x6c, 0x75, 0x3b, 0x54, 0x75, 0x2bb, 0x61, 0x70, 0x75, 0x6c, 0x65,
@@ -4329,554 +4357,620 @@ static const ushort days_data[] = {
0x6d5, 0x3b, 0x64a, 0x6d5, 0x643, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x62f, 0x6c8, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x633,
0x6d5, 0x64a, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x686, 0x627, 0x631, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x67e, 0x6d5, 0x64a,
0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x62c, 0x6c8, 0x645, 0x6d5, 0x3b, 0x634, 0x6d5, 0x646, 0x628, 0x6d5, 0x3b, 0x64a, 0x3b, 0x62f,
-0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x3b, 0x41d, 0x434, 0x3b, 0x41f, 0x43d, 0x3b, 0x412, 0x442, 0x3b,
-0x421, 0x440, 0x3b, 0x427, 0x442, 0x3b, 0x41f, 0x442, 0x3b, 0x421, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x456, 0x43b, 0x44f, 0x3b, 0x43f,
-0x43e, 0x43d, 0x435, 0x434, 0x456, 0x43b, 0x43e, 0x43a, 0x3b, 0x432, 0x456, 0x432, 0x442, 0x43e, 0x440, 0x43e, 0x43a, 0x3b, 0x441, 0x435,
-0x440, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x3b, 0x43f, 0x2bc, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x44f,
-0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x41d, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b,
-0x421, 0x3b, 0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x633, 0x648, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644, 0x3b,
-0x628, 0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1,
-0x3b, 0x59, 0x61, 0x3b, 0x44, 0x75, 0x3b, 0x53, 0x65, 0x3b, 0x43, 0x68, 0x3b, 0x50, 0x61, 0x3b, 0x4a, 0x75, 0x3b, 0x53,
-0x68, 0x3b, 0x79, 0x61, 0x6b, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x64, 0x75, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61,
-0x3b, 0x73, 0x65, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x63, 0x68, 0x6f, 0x72, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61,
-0x3b, 0x70, 0x61, 0x79, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x73, 0x68, 0x61, 0x6e,
-0x62, 0x61, 0x3b, 0x59, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x6cc, 0x2e, 0x3b,
-0x62f, 0x2e, 0x3b, 0x633, 0x2e, 0x3b, 0x686, 0x2e, 0x3b, 0x67e, 0x2e, 0x3b, 0x62c, 0x2e, 0x3b, 0x634, 0x2e, 0x3b, 0x42f, 0x43a,
-0x448, 0x3b, 0x414, 0x443, 0x448, 0x3b, 0x421, 0x435, 0x448, 0x3b, 0x427, 0x43e, 0x440, 0x3b, 0x41f, 0x430, 0x439, 0x3b, 0x416, 0x443,
-0x43c, 0x3b, 0x428, 0x430, 0x43d, 0x3b, 0x44f, 0x43a, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x434, 0x443, 0x448, 0x430, 0x43d, 0x431,
-0x430, 0x3b, 0x441, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x447, 0x43e, 0x440, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x43f,
-0x430, 0x439, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x42f,
-0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x416, 0x3b, 0x428, 0x3b, 0x43, 0x4e, 0x3b, 0x54, 0x68, 0x20, 0x32,
-0x3b, 0x54, 0x68, 0x20, 0x33, 0x3b, 0x54, 0x68, 0x20, 0x34, 0x3b, 0x54, 0x68, 0x20, 0x35, 0x3b, 0x54, 0x68, 0x20, 0x36,
-0x3b, 0x54, 0x68, 0x20, 0x37, 0x3b, 0x43, 0x68, 0x1ee7, 0x20, 0x4e, 0x68, 0x1ead, 0x74, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x48,
-0x61, 0x69, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x42, 0x61, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x54, 0x1b0, 0x3b, 0x54, 0x68, 0x1ee9,
-0x20, 0x4e, 0x103, 0x6d, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x53, 0xe1, 0x75, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x42, 0x1ea3, 0x79,
-0x3b, 0x43, 0x4e, 0x3b, 0x54, 0x32, 0x3b, 0x54, 0x33, 0x3b, 0x54, 0x34, 0x3b, 0x54, 0x35, 0x3b, 0x54, 0x36, 0x3b, 0x54,
-0x37, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49,
-0x61, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x53, 0x75, 0x6c, 0x3b,
-0x44, 0x79, 0x64, 0x64, 0x20, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x61, 0x77, 0x72, 0x74,
-0x68, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x65, 0x72, 0x63, 0x68, 0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20,
-0x49, 0x61, 0x75, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64,
-0x20, 0x53, 0x61, 0x64, 0x77, 0x72, 0x6e, 0x3b, 0x53, 0x3b, 0x4c, 0x6c, 0x3b, 0x4d, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x47,
-0x3b, 0x53, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b,
-0x49, 0x61, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a,
-0xe9, 0x3b, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd,
-0x301, 0x62, 0x1ecd, 0x3b, 0x1eb8, 0x74, 0xec, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9, 0x301, 0x74, 0x61, 0x3b, 0x1ecc, 0x6a, 0x1ecd,
-0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301,
-0x20, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301,
-0x62, 0x1ecd, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x1eb8, 0x74, 0xec, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0x62, 0xe1,
-0x6d, 0x1eb9, 0x301, 0x74, 0x61, 0x3b, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a, 0xe9, 0x3b, 0xcc, 0x73, 0x25b, 0x301, 0x67,
-0x75, 0x6e, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x62, 0x254, 0x3b, 0x190, 0x74, 0xec,
-0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x25b, 0x301, 0x74, 0x61, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b,
-0x186, 0x6a, 0x254, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75,
-0x6e, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x62, 0x254, 0x3b, 0x186, 0x6a, 0x254, 0x301,
-0x20, 0x190, 0x74, 0xec, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xc0, 0x62, 0xe1, 0x6d, 0x25b, 0x301, 0x74, 0x61, 0x3b, 0x53,
-0x6f, 0x6e, 0x3b, 0x4d, 0x73, 0x6f, 0x3b, 0x42, 0x69, 0x6c, 0x3b, 0x54, 0x68, 0x61, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x48,
-0x6c, 0x61, 0x3b, 0x4d, 0x67, 0x71, 0x3b, 0x49, 0x53, 0x6f, 0x6e, 0x74, 0x6f, 0x3b, 0x55, 0x4d, 0x73, 0x6f, 0x6d, 0x62,
-0x75, 0x6c, 0x75, 0x6b, 0x6f, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x55, 0x4c, 0x77,
-0x65, 0x73, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, 0x75, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x55,
-0x4c, 0x77, 0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x55, 0x4d, 0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f,
-0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x48, 0x3b, 0x4d, 0x3b, 0x73, 0xf8, 0x6e, 0x3b, 0x6d,
-0xe5, 0x6e, 0x3b, 0x74, 0x79, 0x73, 0x3b, 0x6f, 0x6e, 0x73, 0x3b, 0x74, 0x6f, 0x72, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c,
-0x61, 0x75, 0x3b, 0x73, 0xf8, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0xe5, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x79, 0x73,
-0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66,
-0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0x61, 0x75, 0x72, 0x64, 0x61, 0x67, 0x3b, 0x73, 0xf8, 0x2e, 0x3b, 0x6d, 0xe5,
-0x2e, 0x3b, 0x74, 0x79, 0x2e, 0x3b, 0x6f, 0x6e, 0x2e, 0x3b, 0x74, 0x6f, 0x2e, 0x3b, 0x66, 0x72, 0x2e, 0x3b, 0x6c, 0x61,
-0x2e, 0x3b, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e, 0x3b, 0x441, 0x440, 0x438, 0x3b, 0x447, 0x435,
-0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d,
-0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a, 0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434,
-0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435, 0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431,
-0x43e, 0x442, 0x430, 0x3b, 0x4a, 0x65, 0x64, 0x3b, 0x4a, 0x65, 0x6c, 0x3b, 0x4a, 0x65, 0x6d, 0x3b, 0x4a, 0x65, 0x72, 0x63,
-0x3b, 0x4a, 0x65, 0x72, 0x64, 0x3b, 0x4a, 0x65, 0x68, 0x3b, 0x4a, 0x65, 0x73, 0x3b, 0x4a, 0x65, 0x64, 0x6f, 0x6f, 0x6e,
-0x65, 0x65, 0x3b, 0x4a, 0x65, 0x6c, 0x68, 0x65, 0x69, 0x6e, 0x3b, 0x4a, 0x65, 0x6d, 0x61, 0x79, 0x72, 0x74, 0x3b, 0x4a,
-0x65, 0x72, 0x63, 0x65, 0x61, 0x6e, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x65, 0x69, 0x6e, 0x3b, 0x4a, 0x65, 0x68, 0x65, 0x69,
-0x6e, 0x65, 0x79, 0x3b, 0x4a, 0x65, 0x73, 0x61, 0x72, 0x6e, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d,
-0x74, 0x68, 0x3b, 0x4d, 0x68, 0x72, 0x3b, 0x59, 0x6f, 0x77, 0x3b, 0x47, 0x77, 0x65, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x64,
-0x79, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x64, 0x79, 0x20, 0x4c, 0x75, 0x6e, 0x3b, 0x64, 0x79, 0x20, 0x4d, 0x65, 0x75, 0x72,
-0x74, 0x68, 0x3b, 0x64, 0x79, 0x20, 0x4d, 0x65, 0x72, 0x68, 0x65, 0x72, 0x3b, 0x64, 0x79, 0x20, 0x59, 0x6f, 0x77, 0x3b,
-0x64, 0x79, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x79, 0x20, 0x53, 0x61, 0x64, 0x6f, 0x72, 0x6e, 0x3b,
-0x4b, 0x77, 0x65, 0x3b, 0x44, 0x77, 0x6f, 0x3b, 0x42, 0x65, 0x6e, 0x3b, 0x57, 0x75, 0x6b, 0x3b, 0x59, 0x61, 0x77, 0x3b,
-0x46, 0x69, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x3b, 0x4b, 0x77, 0x65, 0x73, 0x69, 0x64, 0x61, 0x3b, 0x44, 0x77, 0x6f, 0x77,
-0x64, 0x61, 0x3b, 0x42, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x3b, 0x57, 0x75, 0x6b, 0x75, 0x64, 0x61, 0x3b, 0x59, 0x61, 0x77,
-0x64, 0x61, 0x3b, 0x46, 0x69, 0x64, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x65, 0x6e, 0x65, 0x64, 0x61, 0x3b, 0x4b, 0x3b, 0x44,
-0x3b, 0x42, 0x3b, 0x57, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x906, 0x926, 0x93f, 0x924, 0x94d, 0x92f, 0x935, 0x93e, 0x930,
-0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e,
-0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915, 0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936,
-0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x1ee4, 0x6b, 0x61, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x3b, 0x54, 0x69, 0x75, 0x3b, 0x57, 0x65,
-0x6e, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x3b, 0x46, 0x72, 0x61, 0x1ecb, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x4d, 0x62, 0x1ecd, 0x73, 0x1ecb,
-0x20, 0x1ee4, 0x6b, 0x61, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x64, 0x65, 0x3b, 0x54, 0x69, 0x75, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x57,
-0x65, 0x6e, 0x65, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x46, 0x72, 0x61, 0x1ecb,
-0x64, 0x65, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x1ecd, 0x64, 0x65, 0x65, 0x3b, 0x57, 0x6b, 0x79, 0x3b, 0x57, 0x6b, 0x77, 0x3b,
-0x57, 0x6b, 0x6c, 0x3b, 0x57, 0x74, 0x169, 0x3b, 0x57, 0x6b, 0x6e, 0x3b, 0x57, 0x74, 0x6e, 0x3b, 0x57, 0x74, 0x68, 0x3b,
-0x57, 0x61, 0x20, 0x6b, 0x79, 0x75, 0x6d, 0x77, 0x61, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x77, 0x61, 0x6d, 0x62, 0x129, 0x6c,
-0x129, 0x6c, 0x79, 0x61, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61,
-0x74, 0x169, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f,
-0x3b, 0x57, 0x61, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x169, 0x3b, 0x59, 0x3b, 0x57, 0x3b, 0x45, 0x3b,
-0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
-0x6d, 0x69, 0x65, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x65,
-0x6e, 0x69, 0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x61, 0x72, 0x73, 0x3b, 0x6d, 0x69,
-0x65, 0x72, 0x63, 0x75, 0x73, 0x3b, 0x6a, 0x6f, 0x69, 0x62, 0x65, 0x3b, 0x76, 0x69, 0x6e, 0x61, 0x72, 0x73, 0x3b, 0x73,
-0x61, 0x62, 0x69, 0x64, 0x65, 0x3b, 0x6b, 0x254, 0x73, 0x3b, 0x64, 0x7a, 0x6f, 0x3b, 0x62, 0x6c, 0x61, 0x3b, 0x6b, 0x75,
-0x256, 0x3b, 0x79, 0x61, 0x77, 0x3b, 0x66, 0x69, 0x256, 0x3b, 0x6d, 0x65, 0x6d, 0x3b, 0x6b, 0x254, 0x73, 0x69, 0x256, 0x61,
-0x3b, 0x64, 0x7a, 0x6f, 0x256, 0x61, 0x3b, 0x62, 0x6c, 0x61, 0x256, 0x61, 0x3b, 0x6b, 0x75, 0x256, 0x61, 0x3b, 0x79, 0x61,
-0x77, 0x6f, 0x256, 0x61, 0x3b, 0x66, 0x69, 0x256, 0x61, 0x3b, 0x6d, 0x65, 0x6d, 0x6c, 0x65, 0x256, 0x61, 0x3b, 0x6b, 0x3b,
-0x64, 0x3b, 0x62, 0x3b, 0x6b, 0x3b, 0x79, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x4c, 0x50, 0x3b, 0x50, 0x31, 0x3b, 0x50, 0x32,
-0x3b, 0x50, 0x33, 0x3b, 0x50, 0x34, 0x3b, 0x50, 0x35, 0x3b, 0x50, 0x36, 0x3b, 0x4c, 0x101, 0x70, 0x75, 0x6c, 0x65, 0x3b,
-0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x61, 0x68, 0x69, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x75, 0x61, 0x3b, 0x50, 0x6f, 0x2bb,
-0x61, 0x6b, 0x6f, 0x6c, 0x75, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x68, 0x101, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x69, 0x6d,
-0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6f, 0x6e, 0x6f, 0x3b, 0x4c, 0x69, 0x6e, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61,
-0x72, 0x3b, 0x4d, 0x69, 0x79, 0x3b, 0x48, 0x75, 0x77, 0x3b, 0x42, 0x69, 0x79, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4c, 0x69,
-0x6e, 0x67, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69,
-0x79, 0x65, 0x72, 0x6b, 0x75, 0x6c, 0x65, 0x73, 0x3b, 0x48, 0x75, 0x77, 0x65, 0x62, 0x65, 0x73, 0x3b, 0x42, 0x69, 0x79,
-0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x64, 0x6f, 0x3b, 0x53, 0x75, 0x2e, 0x3b, 0x4d, 0xe4, 0x2e,
-0x3b, 0x5a, 0x69, 0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e,
-0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x74, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0xe4, 0x6e, 0x74, 0x69, 0x67, 0x3b, 0x5a, 0x69, 0x69,
-0x73, 0x63, 0x68, 0x74, 0x69, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x75, 0x63, 0x68, 0x3b, 0x44, 0x75, 0x6e, 0x73,
-0x63, 0x68, 0x74, 0x69, 0x67, 0x3b, 0x46, 0x72, 0x69, 0x69, 0x74, 0x69, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68,
-0x74, 0x69, 0x67, 0x3b, 0xa46d, 0xa18f, 0x3b, 0xa18f, 0xa2cd, 0x3b, 0xa18f, 0xa44d, 0x3b, 0xa18f, 0xa315, 0x3b, 0xa18f, 0xa1d6, 0x3b, 0xa18f,
-0xa26c, 0x3b, 0xa18f, 0xa0d8, 0x3b, 0xa46d, 0xa18f, 0xa44d, 0x3b, 0xa18f, 0xa282, 0xa2cd, 0x3b, 0xa18f, 0xa282, 0xa44d, 0x3b, 0xa18f, 0xa282, 0xa315,
-0x3b, 0xa18f, 0xa282, 0xa1d6, 0x3b, 0xa18f, 0xa282, 0xa26c, 0x3b, 0xa18f, 0xa282, 0xa0d8, 0x3b, 0xa18f, 0x3b, 0xa2cd, 0x3b, 0xa44d, 0x3b, 0xa315,
-0x3b, 0xa1d6, 0x3b, 0xa26c, 0x3b, 0xa0d8, 0x3b, 0x73, 0x6f, 0x74, 0x6e, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x3b, 0x6d, 0x61, 0x14b,
+0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x62c, 0x3b, 0x634, 0x3b, 0x43d, 0x435, 0x434, 0x456, 0x43b, 0x44f, 0x3b, 0x43f, 0x43e,
+0x43d, 0x435, 0x434, 0x456, 0x43b, 0x43e, 0x43a, 0x3b, 0x432, 0x456, 0x432, 0x442, 0x43e, 0x440, 0x43e, 0x43a, 0x3b, 0x441, 0x435, 0x440,
+0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x3b, 0x43f, 0x2bc, 0x44f, 0x442, 0x43d, 0x438, 0x446, 0x44f, 0x3b,
+0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x41d, 0x3b, 0x41f, 0x3b, 0x412, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x421,
+0x3b, 0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x633, 0x648, 0x645, 0x648, 0x627, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644, 0x3b, 0x628,
+0x62f, 0x6be, 0x3b, 0x62c, 0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1, 0x3b,
+0x627, 0x62a, 0x648, 0x627, 0x631, 0x3b, 0x67e, 0x6cc, 0x631, 0x3b, 0x645, 0x646, 0x6af, 0x644, 0x3b, 0x628, 0x62f, 0x6be, 0x3b, 0x62c,
+0x645, 0x639, 0x631, 0x627, 0x62a, 0x3b, 0x62c, 0x645, 0x639, 0x6c1, 0x3b, 0x6c1, 0x641, 0x62a, 0x6c1, 0x3b, 0x59, 0x61, 0x6b, 0x3b,
+0x44, 0x75, 0x73, 0x68, 0x3b, 0x53, 0x65, 0x73, 0x68, 0x3b, 0x43, 0x68, 0x6f, 0x72, 0x3b, 0x50, 0x61, 0x79, 0x3b, 0x4a,
+0x75, 0x6d, 0x3b, 0x53, 0x68, 0x61, 0x6e, 0x3b, 0x79, 0x61, 0x6b, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x64, 0x75,
+0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x63, 0x68, 0x6f, 0x72,
+0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x70, 0x61, 0x79, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x6a, 0x75, 0x6d,
+0x61, 0x3b, 0x73, 0x68, 0x61, 0x6e, 0x62, 0x61, 0x3b, 0x59, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x43, 0x3b, 0x50, 0x3b, 0x4a,
+0x3b, 0x53, 0x3b, 0x6cc, 0x2e, 0x3b, 0x62f, 0x2e, 0x3b, 0x633, 0x2e, 0x3b, 0x686, 0x2e, 0x3b, 0x67e, 0x2e, 0x3b, 0x62c, 0x2e,
+0x3b, 0x634, 0x2e, 0x3b, 0x42f, 0x43a, 0x448, 0x3b, 0x414, 0x443, 0x448, 0x3b, 0x421, 0x435, 0x448, 0x3b, 0x427, 0x43e, 0x440, 0x3b,
+0x41f, 0x430, 0x439, 0x3b, 0x416, 0x443, 0x43c, 0x3b, 0x428, 0x430, 0x43d, 0x3b, 0x42f, 0x43a, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b,
+0x414, 0x443, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x421, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x427, 0x43e, 0x440, 0x448,
+0x430, 0x43d, 0x431, 0x430, 0x3b, 0x41f, 0x430, 0x439, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x416, 0x443, 0x43c, 0x430, 0x3b, 0x428,
+0x430, 0x43d, 0x431, 0x430, 0x3b, 0x42f, 0x3b, 0x414, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x41f, 0x3b, 0x416, 0x3b, 0x428, 0x3b, 0x44f,
+0x43a, 0x448, 0x3b, 0x434, 0x443, 0x448, 0x3b, 0x441, 0x435, 0x448, 0x3b, 0x447, 0x43e, 0x440, 0x3b, 0x43f, 0x430, 0x439, 0x3b, 0x436,
+0x443, 0x43c, 0x3b, 0x448, 0x430, 0x43d, 0x3b, 0x44f, 0x43a, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x434, 0x443, 0x448, 0x430, 0x43d,
+0x431, 0x430, 0x3b, 0x441, 0x435, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x447, 0x43e, 0x440, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b,
+0x43f, 0x430, 0x439, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b, 0x436, 0x443, 0x43c, 0x430, 0x3b, 0x448, 0x430, 0x43d, 0x431, 0x430, 0x3b,
+0x43, 0x4e, 0x3b, 0x54, 0x68, 0x20, 0x32, 0x3b, 0x54, 0x68, 0x20, 0x33, 0x3b, 0x54, 0x68, 0x20, 0x34, 0x3b, 0x54, 0x68,
+0x20, 0x35, 0x3b, 0x54, 0x68, 0x20, 0x36, 0x3b, 0x54, 0x68, 0x20, 0x37, 0x3b, 0x43, 0x68, 0x1ee7, 0x20, 0x4e, 0x68, 0x1ead,
+0x74, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x48, 0x61, 0x69, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x42, 0x61, 0x3b, 0x54, 0x68, 0x1ee9,
+0x20, 0x54, 0x1b0, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x4e, 0x103, 0x6d, 0x3b, 0x54, 0x68, 0x1ee9, 0x20, 0x53, 0xe1, 0x75, 0x3b,
+0x54, 0x68, 0x1ee9, 0x20, 0x42, 0x1ea3, 0x79, 0x3b, 0x43, 0x4e, 0x3b, 0x54, 0x32, 0x3b, 0x54, 0x33, 0x3b, 0x54, 0x34, 0x3b,
+0x54, 0x35, 0x3b, 0x54, 0x36, 0x3b, 0x54, 0x37, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d, 0x61,
+0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49, 0x61, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x44, 0x79,
+0x64, 0x64, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x44, 0x79, 0x64,
+0x64, 0x20, 0x4d, 0x61, 0x77, 0x72, 0x74, 0x68, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x4d, 0x65, 0x72, 0x63, 0x68, 0x65,
+0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x49, 0x61, 0x75, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x47, 0x77, 0x65, 0x6e,
+0x65, 0x72, 0x3b, 0x44, 0x79, 0x64, 0x64, 0x20, 0x53, 0x61, 0x64, 0x77, 0x72, 0x6e, 0x3b, 0x53, 0x3b, 0x4c, 0x6c, 0x3b,
+0x4d, 0x3b, 0x4d, 0x3b, 0x49, 0x3b, 0x47, 0x3b, 0x53, 0x3b, 0x53, 0x75, 0x6c, 0x3b, 0x4c, 0x6c, 0x75, 0x6e, 0x3b, 0x4d,
+0x61, 0x77, 0x3b, 0x4d, 0x65, 0x72, 0x3b, 0x49, 0x61, 0x75, 0x3b, 0x47, 0x77, 0x65, 0x6e, 0x3b, 0x53, 0x61, 0x64, 0x3b,
+0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a, 0xe9, 0x3b, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd,
+0x301, 0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x62, 0x1ecd, 0x3b, 0x1eb8, 0x74, 0xec, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9,
+0x301, 0x74, 0x61, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x41,
+0x6a, 0xe9, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0xcc, 0x73, 0x1eb9, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301,
+0x72, 0xfa, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x62, 0x1ecd, 0x3b, 0x1ecc, 0x6a, 0x1ecd, 0x301, 0x20, 0x1eb8, 0x74, 0xec, 0x3b, 0x1ecc,
+0x6a, 0x1ecd, 0x301, 0x20, 0xc0, 0x62, 0xe1, 0x6d, 0x1eb9, 0x301, 0x74, 0x61, 0x3b, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x41, 0x6a,
+0xe9, 0x3b, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254,
+0x301, 0x62, 0x254, 0x3b, 0x190, 0x74, 0xec, 0x3b, 0xc0, 0x62, 0xe1, 0x6d, 0x25b, 0x301, 0x74, 0x61, 0x3b, 0x186, 0x6a, 0x254,
+0x301, 0x20, 0xc0, 0xec, 0x6b, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0x41, 0x6a, 0xe9, 0x3b, 0x186, 0x6a, 0x254, 0x301,
+0x20, 0xcc, 0x73, 0x25b, 0x301, 0x67, 0x75, 0x6e, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x72, 0xfa, 0x3b, 0x186, 0x6a, 0x254, 0x301,
+0x62, 0x254, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0x190, 0x74, 0xec, 0x3b, 0x186, 0x6a, 0x254, 0x301, 0x20, 0xc0, 0x62, 0xe1,
+0x6d, 0x25b, 0x301, 0x74, 0x61, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x73, 0x6f, 0x3b, 0x42, 0x69, 0x6c, 0x3b, 0x54, 0x68,
+0x61, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x48, 0x6c, 0x61, 0x3b, 0x4d, 0x67, 0x71, 0x3b, 0x49, 0x53, 0x6f, 0x6e, 0x74, 0x6f,
+0x3b, 0x55, 0x4d, 0x73, 0x6f, 0x6d, 0x62, 0x75, 0x6c, 0x75, 0x6b, 0x6f, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x62,
+0x69, 0x6c, 0x69, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, 0x75, 0x3b, 0x55, 0x4c, 0x77,
+0x65, 0x73, 0x69, 0x6e, 0x65, 0x3b, 0x55, 0x4c, 0x77, 0x65, 0x73, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x55, 0x4d,
+0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x42, 0x3b, 0x54, 0x3b, 0x53, 0x3b, 0x48, 0x3b,
+0x4d, 0x3b, 0x73, 0xf8, 0x6e, 0x3b, 0x6d, 0xe5, 0x6e, 0x3b, 0x74, 0x79, 0x73, 0x3b, 0x6f, 0x6e, 0x73, 0x3b, 0x74, 0x6f,
+0x72, 0x3b, 0x66, 0x72, 0x65, 0x3b, 0x6c, 0x61, 0x75, 0x3b, 0x73, 0xf8, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x6d, 0xe5, 0x6e,
+0x64, 0x61, 0x67, 0x3b, 0x74, 0x79, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x6f, 0x6e, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x74, 0x6f,
+0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x66, 0x72, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x6c, 0x61, 0x75, 0x72, 0x64, 0x61, 0x67,
+0x3b, 0x73, 0xf8, 0x2e, 0x3b, 0x6d, 0xe5, 0x2e, 0x3b, 0x74, 0x79, 0x2e, 0x3b, 0x6f, 0x6e, 0x2e, 0x3b, 0x74, 0x6f, 0x2e,
+0x3b, 0x66, 0x72, 0x2e, 0x3b, 0x6c, 0x61, 0x2e, 0x3b, 0x43d, 0x435, 0x434, 0x3b, 0x43f, 0x43e, 0x43d, 0x3b, 0x443, 0x442, 0x43e,
+0x3b, 0x441, 0x440, 0x438, 0x3b, 0x447, 0x435, 0x442, 0x3b, 0x43f, 0x435, 0x442, 0x3b, 0x441, 0x443, 0x431, 0x3b, 0x43d, 0x435, 0x434,
+0x435, 0x459, 0x430, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x435, 0x459, 0x430, 0x43a, 0x3b, 0x443, 0x442, 0x43e, 0x440, 0x430, 0x43a,
+0x3b, 0x441, 0x440, 0x438, 0x458, 0x435, 0x434, 0x430, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x440, 0x442, 0x430, 0x43a, 0x3b, 0x43f, 0x435,
+0x442, 0x430, 0x43a, 0x3b, 0x441, 0x443, 0x431, 0x43e, 0x442, 0x430, 0x3b, 0x4a, 0x65, 0x64, 0x3b, 0x4a, 0x65, 0x6c, 0x3b, 0x4a,
+0x65, 0x6d, 0x3b, 0x4a, 0x65, 0x72, 0x63, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x3b, 0x4a, 0x65, 0x68, 0x3b, 0x4a, 0x65, 0x73,
+0x3b, 0x4a, 0x65, 0x64, 0x6f, 0x6f, 0x6e, 0x65, 0x65, 0x3b, 0x4a, 0x65, 0x6c, 0x68, 0x65, 0x69, 0x6e, 0x3b, 0x4a, 0x65,
+0x6d, 0x61, 0x79, 0x72, 0x74, 0x3b, 0x4a, 0x65, 0x72, 0x63, 0x65, 0x61, 0x6e, 0x3b, 0x4a, 0x65, 0x72, 0x64, 0x65, 0x69,
+0x6e, 0x3b, 0x4a, 0x65, 0x68, 0x65, 0x69, 0x6e, 0x65, 0x79, 0x3b, 0x4a, 0x65, 0x73, 0x61, 0x72, 0x6e, 0x3b, 0x53, 0x75,
+0x6c, 0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x74, 0x68, 0x3b, 0x4d, 0x68, 0x72, 0x3b, 0x59, 0x6f, 0x77, 0x3b, 0x47, 0x77,
+0x65, 0x3b, 0x53, 0x61, 0x64, 0x3b, 0x64, 0x79, 0x20, 0x53, 0x75, 0x6c, 0x3b, 0x64, 0x79, 0x20, 0x4c, 0x75, 0x6e, 0x3b,
+0x64, 0x79, 0x20, 0x4d, 0x65, 0x75, 0x72, 0x74, 0x68, 0x3b, 0x64, 0x79, 0x20, 0x4d, 0x65, 0x72, 0x68, 0x65, 0x72, 0x3b,
+0x64, 0x79, 0x20, 0x59, 0x6f, 0x77, 0x3b, 0x64, 0x79, 0x20, 0x47, 0x77, 0x65, 0x6e, 0x65, 0x72, 0x3b, 0x64, 0x79, 0x20,
+0x53, 0x61, 0x64, 0x6f, 0x72, 0x6e, 0x3b, 0x4b, 0x77, 0x65, 0x3b, 0x44, 0x77, 0x6f, 0x3b, 0x42, 0x65, 0x6e, 0x3b, 0x57,
+0x75, 0x6b, 0x3b, 0x59, 0x61, 0x77, 0x3b, 0x46, 0x69, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x3b, 0x4b, 0x77, 0x65, 0x73, 0x69,
+0x64, 0x61, 0x3b, 0x44, 0x77, 0x6f, 0x77, 0x64, 0x61, 0x3b, 0x42, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x3b, 0x57, 0x75, 0x6b,
+0x75, 0x64, 0x61, 0x3b, 0x59, 0x61, 0x77, 0x64, 0x61, 0x3b, 0x46, 0x69, 0x64, 0x61, 0x3b, 0x4d, 0x65, 0x6d, 0x65, 0x6e,
+0x65, 0x64, 0x61, 0x3b, 0x4b, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x57, 0x3b, 0x59, 0x3b, 0x46, 0x3b, 0x4d, 0x3b, 0x906, 0x926,
+0x93f, 0x924, 0x94d, 0x92f, 0x935, 0x93e, 0x930, 0x3b, 0x938, 0x94b, 0x92e, 0x935, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x933, 0x93e,
+0x930, 0x3b, 0x92c, 0x941, 0x927, 0x935, 0x93e, 0x930, 0x3b, 0x917, 0x941, 0x930, 0x941, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x941, 0x915,
+0x94d, 0x930, 0x935, 0x93e, 0x930, 0x3b, 0x936, 0x928, 0x93f, 0x935, 0x93e, 0x930, 0x3b, 0x1ee4, 0x6b, 0x61, 0x3b, 0x4d, 0x1ecd, 0x6e,
+0x3b, 0x54, 0x69, 0x75, 0x3b, 0x57, 0x65, 0x6e, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x3b, 0x46, 0x72, 0x61, 0x1ecb, 0x3b, 0x53, 0x61,
+0x74, 0x3b, 0x4d, 0x62, 0x1ecd, 0x73, 0x1ecb, 0x20, 0x1ee4, 0x6b, 0x61, 0x3b, 0x4d, 0x1ecd, 0x6e, 0x64, 0x65, 0x3b, 0x54, 0x69,
+0x75, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x57, 0x65, 0x6e, 0x65, 0x7a, 0x64, 0x65, 0x65, 0x3b, 0x54, 0x1ecd, 0x1ecd, 0x7a, 0x64,
+0x65, 0x65, 0x3b, 0x46, 0x72, 0x61, 0x1ecb, 0x64, 0x65, 0x65, 0x3b, 0x53, 0x61, 0x74, 0x1ecd, 0x64, 0x65, 0x65, 0x3b, 0x57,
+0x6b, 0x79, 0x3b, 0x57, 0x6b, 0x77, 0x3b, 0x57, 0x6b, 0x6c, 0x3b, 0x57, 0x74, 0x169, 0x3b, 0x57, 0x6b, 0x6e, 0x3b, 0x57,
+0x74, 0x6e, 0x3b, 0x57, 0x74, 0x68, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x79, 0x75, 0x6d, 0x77, 0x61, 0x3b, 0x57, 0x61, 0x20,
+0x6b, 0x77, 0x61, 0x6d, 0x62, 0x129, 0x6c, 0x129, 0x6c, 0x79, 0x61, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x65, 0x6c, 0x129, 0x3b,
+0x57, 0x61, 0x20, 0x6b, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x57, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x57, 0x61,
+0x20, 0x6b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x57, 0x61, 0x20, 0x74, 0x68, 0x61, 0x6e, 0x74, 0x68, 0x61, 0x74, 0x169,
+0x3b, 0x59, 0x3b, 0x57, 0x3b, 0x45, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c,
+0x75, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0x65, 0x3b, 0x6a, 0x6f, 0x69, 0x3b, 0x76, 0x69, 0x6e, 0x3b, 0x73,
+0x61, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x65, 0x6e, 0x69, 0x65, 0x3b, 0x6c, 0x75, 0x6e, 0x69, 0x73, 0x3b, 0x6d, 0x61, 0x72,
+0x74, 0x61, 0x72, 0x73, 0x3b, 0x6d, 0x69, 0x65, 0x72, 0x63, 0x75, 0x73, 0x3b, 0x6a, 0x6f, 0x69, 0x62, 0x65, 0x3b, 0x76,
+0x69, 0x6e, 0x61, 0x72, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x69, 0x64, 0x65, 0x3b, 0x6b, 0x254, 0x73, 0x3b, 0x64, 0x7a, 0x6f,
+0x3b, 0x62, 0x6c, 0x61, 0x3b, 0x6b, 0x75, 0x256, 0x3b, 0x79, 0x61, 0x77, 0x3b, 0x66, 0x69, 0x256, 0x3b, 0x6d, 0x65, 0x6d,
+0x3b, 0x6b, 0x254, 0x73, 0x69, 0x256, 0x61, 0x3b, 0x64, 0x7a, 0x6f, 0x256, 0x61, 0x3b, 0x62, 0x6c, 0x61, 0x256, 0x61, 0x3b,
+0x6b, 0x75, 0x256, 0x61, 0x3b, 0x79, 0x61, 0x77, 0x6f, 0x256, 0x61, 0x3b, 0x66, 0x69, 0x256, 0x61, 0x3b, 0x6d, 0x65, 0x6d,
+0x6c, 0x65, 0x256, 0x61, 0x3b, 0x6b, 0x3b, 0x64, 0x3b, 0x62, 0x3b, 0x6b, 0x3b, 0x79, 0x3b, 0x66, 0x3b, 0x6d, 0x3b, 0x4c,
+0x50, 0x3b, 0x50, 0x31, 0x3b, 0x50, 0x32, 0x3b, 0x50, 0x33, 0x3b, 0x50, 0x34, 0x3b, 0x50, 0x35, 0x3b, 0x50, 0x36, 0x3b,
+0x4c, 0x101, 0x70, 0x75, 0x6c, 0x65, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x61, 0x68, 0x69, 0x3b, 0x50, 0x6f, 0x2bb, 0x61,
+0x6c, 0x75, 0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6b, 0x6f, 0x6c, 0x75, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x68, 0x101, 0x3b,
+0x50, 0x6f, 0x2bb, 0x61, 0x6c, 0x69, 0x6d, 0x61, 0x3b, 0x50, 0x6f, 0x2bb, 0x61, 0x6f, 0x6e, 0x6f, 0x3b, 0x4c, 0x69, 0x6e,
+0x3b, 0x4c, 0x75, 0x6e, 0x3b, 0x4d, 0x61, 0x72, 0x3b, 0x4d, 0x69, 0x79, 0x3b, 0x48, 0x75, 0x77, 0x3b, 0x42, 0x69, 0x79,
+0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4c, 0x69, 0x6e, 0x67, 0x67, 0x6f, 0x3b, 0x4c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x4d, 0x61,
+0x72, 0x74, 0x65, 0x73, 0x3b, 0x4d, 0x69, 0x79, 0x65, 0x72, 0x6b, 0x75, 0x6c, 0x65, 0x73, 0x3b, 0x48, 0x75, 0x77, 0x65,
+0x62, 0x65, 0x73, 0x3b, 0x42, 0x69, 0x79, 0x65, 0x72, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x64, 0x6f, 0x3b,
+0x53, 0x75, 0x2e, 0x3b, 0x4d, 0xe4, 0x2e, 0x3b, 0x5a, 0x69, 0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b,
+0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x74, 0x69, 0x67, 0x3b, 0x4d, 0xe4, 0xe4, 0x6e,
+0x74, 0x69, 0x67, 0x3b, 0x5a, 0x69, 0x69, 0x73, 0x63, 0x68, 0x74, 0x69, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x75,
+0x63, 0x68, 0x3b, 0x44, 0x75, 0x6e, 0x73, 0x63, 0x68, 0x74, 0x69, 0x67, 0x3b, 0x46, 0x72, 0x69, 0x69, 0x74, 0x69, 0x67,
+0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68, 0x74, 0x69, 0x67, 0x3b, 0xa46d, 0xa18f, 0x3b, 0xa18f, 0xa2cd, 0x3b, 0xa18f, 0xa44d, 0x3b,
+0xa18f, 0xa315, 0x3b, 0xa18f, 0xa1d6, 0x3b, 0xa18f, 0xa26c, 0x3b, 0xa18f, 0xa0d8, 0x3b, 0xa46d, 0xa18f, 0xa44d, 0x3b, 0xa18f, 0xa282, 0xa2cd, 0x3b,
+0xa18f, 0xa282, 0xa44d, 0x3b, 0xa18f, 0xa282, 0xa315, 0x3b, 0xa18f, 0xa282, 0xa1d6, 0x3b, 0xa18f, 0xa282, 0xa26c, 0x3b, 0xa18f, 0xa282, 0xa0d8, 0x3b,
+0xa18f, 0x3b, 0xa2cd, 0x3b, 0xa44d, 0x3b, 0xa315, 0x3b, 0xa1d6, 0x3b, 0xa26c, 0x3b, 0xa0d8, 0x3b, 0x53, 0xfc, 0x2e, 0x3b, 0x4d, 0x61,
+0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x69, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61,
+0x2e, 0x3b, 0x53, 0xfc, 0x6e, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x61, 0x61, 0x6e, 0x64, 0x61, 0x67, 0x3b, 0x44, 0x69,
+0x6e, 0x67, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x64, 0x64, 0x65, 0x77, 0x65, 0x6b, 0x65, 0x6e, 0x3b, 0x44, 0x75,
+0x6e, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x65, 0x65, 0x64, 0x61, 0x67, 0x3b, 0x53, 0xfc, 0x6e,
+0x6e, 0x61, 0x76, 0x65, 0x6e, 0x64, 0x3b, 0x73, 0x6f, 0x74, 0x6e, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x3b, 0x6d, 0x61, 0x14b,
0x3b, 0x67, 0x61, 0x73, 0x6b, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x3b, 0x6c, 0xe1, 0x76, 0x3b,
0x73, 0x6f, 0x74, 0x6e, 0x61, 0x62, 0x65, 0x61, 0x69, 0x76, 0x69, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73, 0xe1, 0x72, 0x67,
0x61, 0x3b, 0x6d, 0x61, 0x14b, 0x14b, 0x65, 0x62, 0xe1, 0x72, 0x67, 0x61, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x61, 0x76, 0x61,
0x68, 0x6b, 0x6b, 0x75, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x61, 0x73, 0x64, 0x61, 0x74, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x6a,
0x61, 0x64, 0x61, 0x74, 0x3b, 0x6c, 0xe1, 0x76, 0x76, 0x61, 0x72, 0x64, 0x61, 0x74, 0x3b, 0x53, 0x3b, 0x56, 0x3b, 0x4d,
-0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x61, 0x65, 0x6a, 0x6c, 0x65, 0x67, 0x65, 0x3b, 0x6d, 0xe5, 0x61,
-0x6e, 0x74, 0x61, 0x3b, 0x64, 0xe4, 0x6a, 0x73, 0x74, 0x61, 0x3b, 0x67, 0x61, 0x73, 0x6b, 0x65, 0x76, 0x61, 0x68, 0x6b,
-0x6f, 0x65, 0x3b, 0x64, 0xe5, 0x61, 0x72, 0x73, 0x74, 0x61, 0x3b, 0x62, 0x65, 0x61, 0x72, 0x6a, 0x61, 0x64, 0x61, 0x68,
-0x6b, 0x65, 0x3b, 0x6c, 0x61, 0x61, 0x76, 0x61, 0x64, 0x61, 0x68, 0x6b, 0x65, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b,
-0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x43, 0x70, 0x72, 0x3b, 0x43, 0x74, 0x74, 0x3b, 0x43, 0x6d, 0x6e, 0x3b,
-0x43, 0x6d, 0x74, 0x3b, 0x41, 0x72, 0x73, 0x3b, 0x49, 0x63, 0x6d, 0x3b, 0x45, 0x73, 0x74, 0x3b, 0x43, 0x68, 0x75, 0x6d,
-0x61, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43, 0x68, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x6f, 0x3b, 0x43, 0x68, 0x75, 0x6d,
-0x61, 0x69, 0x6e, 0x65, 0x3b, 0x43, 0x68, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69,
-0x73, 0x69, 0x3b, 0x49, 0x63, 0x68, 0x75, 0x6d, 0x61, 0x3b, 0x45, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x43, 0x3b,
-0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x45, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x4a, 0x69, 0x6d, 0x3b,
-0x4b, 0x61, 0x77, 0x3b, 0x4b, 0x61, 0x64, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x4e, 0x67, 0x75, 0x3b,
-0x49, 0x74, 0x75, 0x6b, 0x75, 0x20, 0x6a, 0x61, 0x20, 0x6a, 0x75, 0x6d, 0x77, 0x61, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d,
-0x75, 0x6b, 0x61, 0x20, 0x6a, 0x69, 0x6d, 0x77, 0x65, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61,
-0x20, 0x6b, 0x61, 0x77, 0x69, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x64, 0x61, 0x64,
-0x75, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4b, 0x75, 0x72, 0x61,
-0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x73, 0x61, 0x6e, 0x75, 0x3b, 0x4b, 0x69, 0x66, 0x75, 0x6c, 0x61, 0x20, 0x6e,
-0x67, 0x75, 0x77, 0x6f, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x64,
-0x65, 0x77, 0x3b, 0x61, 0x61, 0x253, 0x3b, 0x6d, 0x61, 0x77, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x6e, 0x61, 0x61, 0x3b, 0x6d,
-0x77, 0x64, 0x3b, 0x68, 0x62, 0x69, 0x3b, 0x64, 0x65, 0x77, 0x6f, 0x3b, 0x61, 0x61, 0x253, 0x6e, 0x64, 0x65, 0x3b, 0x6d,
-0x61, 0x77, 0x62, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x6e, 0x6a, 0x65, 0x73, 0x6c, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x6e, 0x61,
-0x61, 0x73, 0x61, 0x61, 0x6e, 0x64, 0x65, 0x3b, 0x6d, 0x61, 0x77, 0x6e, 0x64, 0x65, 0x3b, 0x68, 0x6f, 0x6f, 0x72, 0x65,
-0x2d, 0x62, 0x69, 0x69, 0x72, 0x3b, 0x64, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6e, 0x3b, 0x6e, 0x3b, 0x6d, 0x3b, 0x68, 0x3b,
-0x4b, 0x4d, 0x41, 0x3b, 0x4e, 0x54, 0x54, 0x3b, 0x4e, 0x4d, 0x4e, 0x3b, 0x4e, 0x4d, 0x54, 0x3b, 0x41, 0x52, 0x54, 0x3b,
-0x4e, 0x4d, 0x41, 0x3b, 0x4e, 0x4d, 0x4d, 0x3b, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61,
-0x74, 0x61, 0x74, 0x169, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74,
-0x61, 0x6e, 0x61, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x74, 0x68, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b,
-0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x74, 0x68, 0x69, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41,
-0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x72, 0x65, 0x3b, 0x4b, 0x75, 0x6e, 0x3b, 0x4f, 0x6e, 0x67, 0x3b, 0x49, 0x6e, 0x65,
-0x3b, 0x49, 0x6c, 0x65, 0x3b, 0x53, 0x61, 0x70, 0x3b, 0x4b, 0x77, 0x65, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20,
-0x65, 0x65, 0x20, 0x61, 0x72, 0x65, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x6b, 0x75, 0x6e,
-0x69, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x6f, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b,
-0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x69, 0x6e, 0x65, 0x74, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f,
-0x74, 0x20, 0x65, 0x65, 0x20, 0x69, 0x6c, 0x65, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x73,
-0x61, 0x70, 0x61, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x6b, 0x77, 0x65, 0x3b, 0x41, 0x3b,
-0x4b, 0x3b, 0x4f, 0x3b, 0x49, 0x3b, 0x49, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x44, 0x69, 0x6d, 0x3b, 0x50, 0x6f, 0x73, 0x3b,
-0x50, 0x69, 0x72, 0x3b, 0x54, 0x61, 0x74, 0x3b, 0x4e, 0x61, 0x69, 0x3b, 0x53, 0x68, 0x61, 0x3b, 0x53, 0x61, 0x62, 0x3b,
-0x44, 0x69, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x6f, 0x73, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x70,
-0x69, 0x72, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x69, 0x3b, 0x43,
-0x68, 0x69, 0x73, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x53, 0x61, 0x62, 0x75, 0x64, 0x75, 0x3b, 0x44, 0x3b, 0x50, 0x3b, 0x43,
-0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x53, 0x69, 0x62,
-0x3b, 0x53, 0x69, 0x74, 0x3b, 0x53, 0x69, 0x6e, 0x3b, 0x53, 0x69, 0x68, 0x3b, 0x4d, 0x67, 0x71, 0x3b, 0x53, 0x6f, 0x6e,
-0x74, 0x6f, 0x3b, 0x4d, 0x76, 0x75, 0x6c, 0x6f, 0x3b, 0x53, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x53, 0x69, 0x74, 0x68,
-0x61, 0x74, 0x68, 0x75, 0x3b, 0x53, 0x69, 0x6e, 0x65, 0x3b, 0x53, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x67,
-0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4d,
-0x3b, 0x49, 0x6a, 0x70, 0x3b, 0x49, 0x6a, 0x74, 0x3b, 0x49, 0x6a, 0x6e, 0x3b, 0x49, 0x6a, 0x74, 0x6e, 0x3b, 0x41, 0x6c,
-0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b,
-0x49, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x49,
-0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a,
-0x75, 0x6d, 0x61, 0x61, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34,
-0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37, 0x3b, 0x31, 0x3b, 0x2d30, 0x2d59, 0x2d30, 0x3b, 0x2d30, 0x2d62, 0x2d4f, 0x3b, 0x2d30, 0x2d59, 0x2d49,
-0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x3b, 0x2d30, 0x2d3d, 0x2d61, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4e, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x3b, 0x2d30,
-0x2d59, 0x2d30, 0x2d4e, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d62, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30,
-0x2d3d, 0x2d55, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d59, 0x2d49, 0x2d4e, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59,
-0x2d49, 0x2d39, 0x2d62, 0x2d30, 0x2d59, 0x3b, 0x61, 0x73, 0x61, 0x3b, 0x61, 0x79, 0x6e, 0x3b, 0x61, 0x73, 0x69, 0x3b, 0x61, 0x6b,
-0x1e5b, 0x3b, 0x61, 0x6b, 0x77, 0x3b, 0x61, 0x73, 0x69, 0x6d, 0x3b, 0x61, 0x73, 0x69, 0x1e0d, 0x3b, 0x61, 0x73, 0x61, 0x6d,
-0x61, 0x73, 0x3b, 0x61, 0x79, 0x6e, 0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x61, 0x6b, 0x1e5b, 0x61,
-0x73, 0x3b, 0x61, 0x6b, 0x77, 0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x1e0d,
-0x79, 0x61, 0x73, 0x3b, 0x59, 0x61, 0x6e, 0x3b, 0x53, 0x61, 0x6e, 0x3b, 0x4b, 0x72, 0x61, 0x1e0d, 0x3b, 0x4b, 0x75, 0x1e93,
-0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x1e0d, 0x69, 0x73, 0x3b, 0x53, 0x61, 0x79, 0x3b, 0x59, 0x61, 0x6e, 0x61, 0x73, 0x73,
-0x3b, 0x53, 0x61, 0x6e, 0x61, 0x73, 0x73, 0x3b, 0x4b, 0x72, 0x61, 0x1e0d, 0x61, 0x73, 0x73, 0x3b, 0x4b, 0x75, 0x1e93, 0x61,
-0x73, 0x73, 0x3b, 0x53, 0x61, 0x6d, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x1e0d, 0x69, 0x73, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61,
-0x79, 0x61, 0x73, 0x73, 0x3b, 0x59, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53,
-0x41, 0x4e, 0x3b, 0x4f, 0x52, 0x4b, 0x3b, 0x4f, 0x4b, 0x42, 0x3b, 0x4f, 0x4b, 0x53, 0x3b, 0x4f, 0x4b, 0x4e, 0x3b, 0x4f,
-0x4b, 0x54, 0x3b, 0x4f, 0x4d, 0x4b, 0x3b, 0x53, 0x61, 0x6e, 0x64, 0x65, 0x3b, 0x4f, 0x72, 0x77, 0x6f, 0x6b, 0x75, 0x62,
-0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4f, 0x72, 0x77, 0x61,
-0x6b, 0x61, 0x73, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x72, 0x77,
-0x61, 0x6b, 0x61, 0x74, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61,
-0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x52, 0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x56,
-0x69, 0x6c, 0x3b, 0x48, 0x69, 0x76, 0x3b, 0x48, 0x69, 0x64, 0x3b, 0x48, 0x69, 0x74, 0x3b, 0x48, 0x69, 0x68, 0x3b, 0x4c,
-0x65, 0x6d, 0x3b, 0x70, 0x61, 0x20, 0x6d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x73, 0x68, 0x61,
-0x68, 0x75, 0x76, 0x69, 0x6c, 0x75, 0x68, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70,
-0x61, 0x20, 0x68, 0x69, 0x64, 0x61, 0x74, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x74, 0x61, 0x79, 0x69, 0x3b, 0x70,
-0x61, 0x20, 0x68, 0x69, 0x68, 0x61, 0x6e, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x73, 0x68, 0x61, 0x68, 0x75, 0x6c, 0x65, 0x6d,
-0x62, 0x65, 0x6c, 0x61, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x57, 0x3b, 0x4a, 0x3b, 0x4a,
-0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49,
-0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6d,
-0x61, 0x74, 0x61, 0x74, 0x75, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
-0x61, 0x6e, 0x75, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b,
-0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49,
-0x3b, 0x4a, 0x3b, 0x6b, 0x61, 0x72, 0x3b, 0x6e, 0x74, 0x25b, 0x3b, 0x74, 0x61, 0x72, 0x3b, 0x61, 0x72, 0x61, 0x3b, 0x61,
-0x6c, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x3b, 0x73, 0x69, 0x62, 0x3b, 0x6b, 0x61, 0x72, 0x69, 0x3b, 0x6e, 0x74, 0x25b, 0x6e,
-0x25b, 0x3b, 0x74, 0x61, 0x72, 0x61, 0x74, 0x61, 0x3b, 0x61, 0x72, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x6d, 0x69,
-0x73, 0x61, 0x3b, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x73, 0x69, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x54,
-0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x4a, 0x3b, 0x53, 0x3b, 0x4b, 0x6d, 0x61, 0x3b, 0x54, 0x61, 0x74, 0x3b, 0x49, 0x6e, 0x65,
-0x3b, 0x54, 0x61, 0x6e, 0x3b, 0x41, 0x72, 0x6d, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x4e, 0x4d, 0x4d, 0x3b, 0x4b, 0x69, 0x75,
-0x6d, 0x69, 0x61, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x69,
-0x6e, 0x65, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x74, 0x68,
-0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4e, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x74, 0x68, 0x69, 0x69,
-0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x13c6, 0x13cd, 0x13ac, 0x3b, 0x13c9,
-0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5, 0x13c1, 0x3b, 0x13e6, 0x13a2, 0x13c1, 0x3b, 0x13c5, 0x13a9, 0x13c1, 0x3b, 0x13e7, 0x13be, 0x13a9, 0x3b, 0x13c8,
-0x13d5, 0x13be, 0x3b, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c6, 0x13cd, 0x13ac, 0x3b, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4,
-0x13b5, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13e6, 0x13a2, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13c5, 0x13a9, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13e7, 0x13be, 0x13a9,
-0x13b6, 0x13cd, 0x13d7, 0x3b, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c8, 0x13d5, 0x13be, 0x3b, 0x13c6, 0x3b, 0x13c9, 0x3b, 0x13d4, 0x3b, 0x13e6, 0x3b,
-0x13c5, 0x3b, 0x13e7, 0x3b, 0x13a4, 0x3b, 0x64, 0x69, 0x6d, 0x3b, 0x6c, 0x69, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x65,
-0x72, 0x3b, 0x7a, 0x65, 0x3b, 0x76, 0x61, 0x6e, 0x3b, 0x73, 0x61, 0x6d, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x73, 0x3b,
-0x6c, 0x69, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x6b, 0x72, 0x65, 0x64, 0x69,
-0x3b, 0x7a, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x61, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x64, 0x69,
-0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x7a, 0x3b, 0x76, 0x3b, 0x73, 0x3b, 0x4c, 0x6c, 0x32, 0x3b, 0x4c,
-0x6c, 0x33, 0x3b, 0x4c, 0x6c, 0x34, 0x3b, 0x4c, 0x6c, 0x35, 0x3b, 0x4c, 0x6c, 0x36, 0x3b, 0x4c, 0x6c, 0x37, 0x3b, 0x4c,
-0x6c, 0x31, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x69,
-0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20,
-0x6c, 0x79, 0x61, 0x6e, 0x63, 0x68, 0x65, 0x63, 0x68, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79,
-0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e,
-0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x6c, 0x69, 0x6e, 0x6a, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61,
-0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x76, 0x69, 0x6c, 0x69,
-0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x69, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x3b, 0x50, 0xed, 0x69, 0x6c,
-0x69, 0x3b, 0x54, 0xe1, 0x61, 0x74, 0x75, 0x3b, 0xcd, 0x6e, 0x65, 0x3b, 0x54, 0xe1, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c,
-0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 0x4d, 0xf3, 0x6f, 0x73, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0xed, 0x69, 0x72,
-0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0xed, 0x6e, 0x65, 0x3b, 0x4a,
-0x75, 0x6d, 0x61, 0x74, 0xe1, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x61, 0x6d, 0xed, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a,
-0x75, 0x6d, 0xe1, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0xf3, 0x6f, 0x73, 0x69, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x45,
-0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x42, 0x61, 0x6c, 0x3b, 0x4c, 0x77, 0x32,
-0x3b, 0x4c, 0x77, 0x33, 0x3b, 0x4c, 0x77, 0x34, 0x3b, 0x4c, 0x77, 0x35, 0x3b, 0x4c, 0x77, 0x36, 0x3b, 0x53, 0x61, 0x62,
-0x62, 0x69, 0x69, 0x74, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x7a, 0x61, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x62, 0x69,
-0x72, 0x69, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x73, 0x61, 0x74, 0x75, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x6e, 0x61,
-0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x74, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4c, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61,
-0x67, 0x61, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x50, 0x61, 0x20,
-0x4d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x6d, 0x6f, 0x3b, 0x50, 0x61,
-0x6c, 0x69, 0x63, 0x68, 0x69, 0x62, 0x75, 0x6c, 0x69, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x74, 0x61, 0x74,
-0x75, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x6e, 0x65, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x73,
-0x61, 0x6e, 0x6f, 0x3b, 0x50, 0x61, 0x63, 0x68, 0x69, 0x62, 0x65, 0x6c, 0x75, 0x73, 0x68, 0x69, 0x3b, 0x64, 0x75, 0x6d,
-0x3b, 0x73, 0x69, 0x67, 0x3b, 0x74, 0x65, 0x72, 0x3b, 0x6b, 0x75, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x3b, 0x73, 0x65, 0x73,
-0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64, 0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x73, 0x69, 0x67, 0x75, 0x6e, 0x64, 0x61,
-0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0x73, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x75, 0x61,
-0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b,
-0x73, 0x65, 0x73, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x64, 0x3b,
-0x73, 0x3b, 0x74, 0x3b, 0x6b, 0x3b, 0x6b, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b,
-0x4b, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4b, 0x49, 0x55, 0x3b, 0x4d, 0x52, 0x41, 0x3b, 0x57, 0x41, 0x49, 0x3b, 0x57, 0x45,
-0x54, 0x3b, 0x57, 0x45, 0x4e, 0x3b, 0x57, 0x54, 0x4e, 0x3b, 0x4a, 0x55, 0x4d, 0x3b, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61,
-0x3b, 0x4d, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x6f, 0x3b, 0x57, 0x61, 0x69, 0x72, 0x69, 0x3b, 0x57, 0x65, 0x74, 0x68,
-0x61, 0x74, 0x75, 0x3b, 0x57, 0x65, 0x6e, 0x61, 0x3b, 0x57, 0x65, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
-0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x4a, 0x3b, 0x4b,
-0x74, 0x73, 0x3b, 0x4b, 0x6f, 0x74, 0x3b, 0x4b, 0x6f, 0x6f, 0x3b, 0x4b, 0x6f, 0x73, 0x3b, 0x4b, 0x6f, 0x61, 0x3b, 0x4b,
-0x6f, 0x6d, 0x3b, 0x4b, 0x6f, 0x6c, 0x3b, 0x4b, 0x6f, 0x74, 0x69, 0x73, 0x61, 0x70, 0x3b, 0x4b, 0x6f, 0x74, 0x61, 0x61,
-0x69, 0x3b, 0x4b, 0x6f, 0x61, 0x65, 0x6e, 0x67, 0x2019, 0x3b, 0x4b, 0x6f, 0x73, 0x6f, 0x6d, 0x6f, 0x6b, 0x3b, 0x4b, 0x6f,
-0x61, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4b, 0x6f, 0x6d, 0x75, 0x75, 0x74, 0x3b, 0x4b, 0x6f, 0x6c, 0x6f, 0x3b,
-0x54, 0x3b, 0x54, 0x3b, 0x4f, 0x3b, 0x53, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x61,
-0x3b, 0x44, 0x65, 0x3b, 0x57, 0x75, 0x3b, 0x44, 0x6f, 0x3b, 0x46, 0x72, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x53, 0x6f, 0x6e,
-0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x6e, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73,
-0x3b, 0x44, 0x65, 0x6e, 0x73, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x57, 0x75, 0x6e, 0x73, 0x74, 0x61,
-0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x44, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65,
-0x73, 0x3b, 0x46, 0x72, 0x61, 0x69, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x74, 0x65, 0x72,
-0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x46,
-0x3b, 0x41, 0x3b, 0x53, 0x75, 0x2e, 0x3b, 0x4d, 0x6f, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x65, 0x2e, 0x3b, 0x44,
-0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b, 0x53, 0x61, 0x2e, 0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68,
-0x3b, 0x4d, 0x6f, 0x6f, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x44, 0x69, 0x6e, 0x6e, 0x73, 0x64, 0x61, 0x61, 0x63,
-0x68, 0x3b, 0x4d, 0x65, 0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x61, 0x61,
-0x63, 0x68, 0x3b, 0x46, 0x72, 0x69, 0x69, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x64, 0x61, 0x61,
-0x63, 0x68, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0xed, 0x6c, 0xed, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x74, 0x75,
-0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x6e, 0x254, 0x3b, 0x41, 0x6c, 0x61,
-0xe1, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0xe1, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0xf3, 0x73, 0x69,
-0x3b, 0x53, 0x61, 0x62, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x3b, 0x4b, 0x75, 0x62, 0x69, 0x3b, 0x4b, 0x75, 0x73, 0x61,
-0x3b, 0x4b, 0x75, 0x6e, 0x61, 0x3b, 0x4b, 0x75, 0x74, 0x61, 0x3b, 0x4d, 0x75, 0x6b, 0x61, 0x3b, 0x53, 0x61, 0x62, 0x69,
-0x69, 0x74, 0x69, 0x3b, 0x42, 0x61, 0x6c, 0x61, 0x7a, 0x61, 0x3b, 0x4f, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x69, 0x6c, 0x69,
-0x3b, 0x4f, 0x77, 0x6f, 0x6b, 0x75, 0x73, 0x61, 0x74, 0x75, 0x3b, 0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4f,
-0x6c, 0x6f, 0x6b, 0x75, 0x74, 0x61, 0x61, 0x6e, 0x75, 0x3b, 0x4f, 0x6c, 0x6f, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61,
-0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x42, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x4a, 0x32, 0x3b, 0x4a, 0x33,
-0x3b, 0x4a, 0x34, 0x3b, 0x4a, 0x35, 0x3b, 0x41, 0x6c, 0x3b, 0x49, 0x6a, 0x3b, 0x4a, 0x31, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
-0x70, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e,
-0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x75, 0x72, 0x77, 0x61, 0x20, 0x77, 0x61, 0x20,
-0x4b, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4d, 0x75, 0x72, 0x77, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x61, 0x74, 0x61, 0x6e,
-0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a,
-0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a,
-0x75, 0x6d, 0x3b, 0x42, 0x61, 0x72, 0x3b, 0x41, 0x61, 0x72, 0x3b, 0x55, 0x6e, 0x69, 0x3b, 0x55, 0x6e, 0x67, 0x3b, 0x4b,
-0x61, 0x6e, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x65, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x61, 0x6b,
-0x61, 0x65, 0x62, 0x61, 0x72, 0x61, 0x73, 0x61, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4e, 0x61, 0x6b,
-0x61, 0x75, 0x6e, 0x69, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x75, 0x6e, 0x67, 0x2019, 0x6f, 0x6e, 0x3b, 0x4e, 0x61, 0x6b, 0x61,
-0x6b, 0x61, 0x6e, 0x79, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x73, 0x61, 0x62, 0x69, 0x74, 0x69, 0x3b, 0x4a, 0x3b, 0x42, 0x3b,
-0x41, 0x3b, 0x55, 0x3b, 0x55, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x41, 0x74, 0x69, 0x3b, 0x41, 0x74,
-0x61, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x6c, 0x6d, 0x3b, 0x41, 0x6c, 0x6a, 0x3b, 0x41, 0x73, 0x73, 0x3b, 0x41, 0x6c,
-0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41,
-0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c, 0x6a, 0x75,
-0x6d, 0x61, 0x3b, 0x41, 0x73, 0x73, 0x61, 0x62, 0x64, 0x75, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4c,
-0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x4a, 0x4d, 0x50, 0x3b, 0x57, 0x55, 0x54, 0x3b, 0x54, 0x41, 0x52, 0x3b, 0x54, 0x41, 0x44,
-0x3b, 0x54, 0x41, 0x4e, 0x3b, 0x54, 0x41, 0x42, 0x3b, 0x4e, 0x47, 0x53, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c,
-0x3b, 0x57, 0x75, 0x6f, 0x6b, 0x20, 0x54, 0x69, 0x63, 0x68, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x72, 0x69, 0x79,
-0x6f, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x64, 0x65, 0x6b, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x6e, 0x67,
-0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x62, 0x69, 0x63, 0x68, 0x3b, 0x4e, 0x67, 0x65, 0x73,
-0x6f, 0x3b, 0x4a, 0x3b, 0x57, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x41, 0x73, 0x61, 0x3b,
-0x41, 0x79, 0x6e, 0x3b, 0x41, 0x73, 0x6e, 0x3b, 0x41, 0x6b, 0x72, 0x3b, 0x41, 0x6b, 0x77, 0x3b, 0x41, 0x73, 0x6d, 0x3b,
-0x41, 0x73, 0x1e0d, 0x3b, 0x41, 0x73, 0x61, 0x6d, 0x61, 0x73, 0x3b, 0x41, 0x79, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69,
-0x6e, 0x61, 0x73, 0x3b, 0x41, 0x6b, 0x72, 0x61, 0x73, 0x3b, 0x41, 0x6b, 0x77, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x6d,
-0x77, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x1e0d, 0x79, 0x61, 0x73, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b,
-0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x41, 0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6c,
-0x61, 0x3b, 0x41, 0x6c, 0x6d, 0x3b, 0x41, 0x6c, 0x7a, 0x3b, 0x41, 0x73, 0x69, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69,
-0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61,
-0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c, 0x7a, 0x75, 0x6d, 0x61,
-0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69, 0x3b, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6d, 0x6e, 0x3b,
-0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
-0x61, 0x70, 0x69, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61,
-0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73,
-0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x32,
-0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x31, 0x3b, 0x930, 0x92c, 0x93f, 0x3b, 0x938, 0x92e, 0x3b,
-0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941, 0x926, 0x3b, 0x92c, 0x93f, 0x938, 0x925, 0x93f, 0x3b, 0x938, 0x941, 0x916, 0x941, 0x930,
-0x3b, 0x938, 0x941, 0x928, 0x93f, 0x3b, 0x930, 0x92c, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e,
-0x902, 0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x941, 0x926, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x938, 0x925, 0x93f, 0x92c,
-0x93e, 0x930, 0x3b, 0x938, 0x941, 0x916, 0x941, 0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x941, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x3b,
-0x930, 0x3b, 0x938, 0x3b, 0x92e, 0x902, 0x3b, 0x92c, 0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x938, 0x941, 0x3b, 0x938, 0x941, 0x3b, 0x43a,
-0x4c0, 0x438, 0x440, 0x430, 0x43d, 0x430, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x43e, 0x440, 0x448, 0x43e, 0x442, 0x430, 0x43d, 0x20, 0x434,
-0x435, 0x3b, 0x448, 0x438, 0x43d, 0x430, 0x440, 0x438, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x43a, 0x445, 0x430, 0x430, 0x440, 0x438, 0x43d,
-0x20, 0x434, 0x435, 0x3b, 0x435, 0x430, 0x440, 0x438, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x43f, 0x4c0, 0x435, 0x440, 0x430, 0x441, 0x43a,
-0x430, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x448, 0x43e, 0x442, 0x20, 0x434, 0x435, 0x3b, 0x43d, 0x434, 0x2de7, 0x487, 0x467, 0x3b, 0x43f,
-0x43d, 0x2de3, 0x435, 0x3b, 0x432, 0x442, 0x43e, 0x2dec, 0x487, 0x3b, 0x441, 0x440, 0x2de3, 0x435, 0x3b, 0x447, 0x435, 0x2de6, 0x487, 0x3b,
-0x43f, 0x467, 0x2de6, 0x487, 0x3b, 0x441, 0xa64b, 0x2de0, 0x487, 0x3b, 0x43d, 0x435, 0x434, 0x463, 0x301, 0x43b, 0x467, 0x3b, 0x43f, 0x43e,
-0x43d, 0x435, 0x434, 0x463, 0x301, 0x43b, 0x44c, 0x43d, 0x438, 0x43a, 0x44a, 0x3b, 0x432, 0x442, 0x43e, 0x301, 0x440, 0x43d, 0x438, 0x43a,
-0x44a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430, 0x300, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x442, 0x43e, 0x301, 0x43a, 0x44a,
-0x3b, 0x43f, 0x467, 0x442, 0x43e, 0x301, 0x43a, 0x44a, 0x3b, 0x441, 0xa64b, 0x431, 0x431, 0x461, 0x301, 0x442, 0x430, 0x3b, 0x4c, 0x75,
-0x6d, 0x3b, 0x4e, 0x6b, 0x6f, 0x3b, 0x4e, 0x64, 0x79, 0x3b, 0x4e, 0x64, 0x67, 0x3b, 0x4e, 0x6a, 0x77, 0x3b, 0x4e, 0x67,
-0x76, 0x3b, 0x4c, 0x75, 0x62, 0x3b, 0x4c, 0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x4e, 0x6b, 0x6f, 0x64, 0x79, 0x61,
-0x3b, 0x4e, 0x64, 0xe0, 0x61, 0x79, 0xe0, 0x3b, 0x4e, 0x64, 0x61, 0x6e, 0x67, 0xf9, 0x3b, 0x4e, 0x6a, 0xf2, 0x77, 0x61,
-0x3b, 0x4e, 0x67, 0xf2, 0x76, 0x79, 0x61, 0x3b, 0x4c, 0x75, 0x62, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x4c, 0x3b, 0x4e, 0x3b,
-0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4c, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0xe9, 0x69, 0x3b, 0x44, 0xeb,
-0x6e, 0x3b, 0x4d, 0xeb, 0x74, 0x3b, 0x44, 0x6f, 0x6e, 0x3b, 0x46, 0x72, 0x65, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x6f,
-0x6e, 0x6e, 0x64, 0x65, 0x67, 0x3b, 0x4d, 0xe9, 0x69, 0x6e, 0x64, 0x65, 0x67, 0x3b, 0x44, 0xeb, 0x6e, 0x73, 0x63, 0x68,
-0x64, 0x65, 0x67, 0x3b, 0x4d, 0xeb, 0x74, 0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44, 0x6f, 0x6e, 0x6e, 0x65, 0x73, 0x63,
-0x68, 0x64, 0x65, 0x67, 0x3b, 0x46, 0x72, 0x65, 0x69, 0x64, 0x65, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68, 0x64,
-0x65, 0x67, 0x3b, 0x53, 0x6f, 0x6e, 0x2e, 0x3b, 0x4d, 0xe9, 0x69, 0x2e, 0x3b, 0x44, 0xeb, 0x6e, 0x2e, 0x3b, 0x4d, 0xeb,
-0x74, 0x2e, 0x3b, 0x44, 0x6f, 0x6e, 0x2e, 0x3b, 0x46, 0x72, 0x65, 0x2e, 0x3b, 0x53, 0x61, 0x6d, 0x2e, 0x3b, 0x6e, 0x74,
-0x73, 0x3b, 0x6b, 0x70, 0x61, 0x3b, 0x67, 0x68, 0x254, 0x3b, 0x74, 0x254, 0x6d, 0x3b, 0x75, 0x6d, 0x65, 0x3b, 0x67, 0x68,
-0x268, 0x3b, 0x64, 0x7a, 0x6b, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x6e, 0x74, 0x73, 0x268, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75,
-0x6b, 0x70, 0xe0, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x67, 0x68, 0x254, 0x65, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x74,
-0x254, 0x300, 0x6d, 0x6c, 0xf2, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x6d, 0xe8, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x67,
-0x68, 0x268, 0x302, 0x6d, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x6e, 0x64, 0x7a, 0x268, 0x6b, 0x254, 0x294, 0x254, 0x3b, 0x6e, 0x3b,
-0x6b, 0x3b, 0x67, 0x3b, 0x74, 0x3b, 0x75, 0x3b, 0x67, 0x3b, 0x64, 0x3b, 0x6e, 0x254, 0x79, 0x3b, 0x6e, 0x6a, 0x61, 0x3b,
-0x75, 0x75, 0x6d, 0x3b, 0x14b, 0x67, 0x65, 0x3b, 0x6d, 0x62, 0x254, 0x3b, 0x6b, 0x254, 0x254, 0x3b, 0x6a, 0x6f, 0x6e, 0x3b,
-0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e, 0x254, 0x302, 0x79, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e, 0x6a, 0x61, 0x14b, 0x67,
-0x75, 0x6d, 0x62, 0x61, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0xfb, 0x6d, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x14b, 0x67,
-0xea, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6d, 0x62, 0x254, 0x6b, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6b, 0x254, 0x254,
-0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6a, 0xf4, 0x6e, 0x3b, 0x6e, 0x3b, 0x6e, 0x3b, 0x75, 0x3b, 0x14b, 0x3b, 0x6d, 0x3b,
-0x6b, 0x3b, 0x6a, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69, 0x3b, 0x41, 0x74,
-0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69,
-0x73, 0x69, 0x3b, 0x41, 0x6c, 0x7a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69, 0x3b, 0x48, 0x3b, 0x54,
-0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x53, 0x3b, 0xe9, 0x74, 0x3b, 0x6d, 0x254, 0x301, 0x73, 0x3b, 0x6b,
-0x77, 0x61, 0x3b, 0x6d, 0x75, 0x6b, 0x3b, 0x14b, 0x67, 0x69, 0x3b, 0x257, 0xf3, 0x6e, 0x3b, 0x65, 0x73, 0x61, 0x3b, 0xe9,
-0x74, 0x69, 0x3b, 0x6d, 0x254, 0x301, 0x73, 0xfa, 0x3b, 0x6b, 0x77, 0x61, 0x73, 0xfa, 0x3b, 0x6d, 0x75, 0x6b, 0x254, 0x301,
-0x73, 0xfa, 0x3b, 0x14b, 0x67, 0x69, 0x73, 0xfa, 0x3b, 0x257, 0xf3, 0x6e, 0x25b, 0x73, 0xfa, 0x3b, 0x65, 0x73, 0x61, 0x253,
-0x61, 0x73, 0xfa, 0x3b, 0x65, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x14b, 0x3b, 0x257, 0x3b, 0x65, 0x3b, 0x44, 0x69,
-0x6d, 0x3b, 0x54, 0x65, 0x6e, 0x3b, 0x54, 0x61, 0x6c, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x41, 0x72,
-0x6a, 0x3b, 0x53, 0x69, 0x62, 0x3b, 0x44, 0x69, 0x6d, 0x61, 0x73, 0x3b, 0x54, 0x65, 0x6e, 0x65, 0x14b, 0x3b, 0x54, 0x61,
-0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x79, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x73, 0x61,
-0x79, 0x3b, 0x41, 0x72, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x53, 0x69, 0x62, 0x69, 0x74, 0x69, 0x3b, 0x44, 0x3b, 0x54, 0x3b,
-0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x53, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x3b,
-0x73, 0x6d, 0x62, 0x3b, 0x73, 0x6d, 0x6c, 0x3b, 0x73, 0x6d, 0x6e, 0x3b, 0x66, 0xfa, 0x6c, 0x3b, 0x73, 0xe9, 0x72, 0x3b,
-0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254,
-0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301, 0x62, 0x25b, 0x30c, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20,
-0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301, 0x6c, 0x25b, 0x301, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d,
-0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301, 0x6e, 0x79, 0x69, 0x3b, 0x66, 0xfa, 0x6c, 0x61, 0x64, 0xe9, 0x3b, 0x73, 0xe9,
-0x72, 0x61, 0x64, 0xe9, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x66, 0x3b, 0x73, 0x3b, 0x73,
-0x254, 0x301, 0x6e, 0x3b, 0x6c, 0x1dd, 0x6e, 0x3b, 0x6d, 0x61, 0x61, 0x3b, 0x6d, 0x25b, 0x6b, 0x3b, 0x6a, 0x1dd, 0x1dd, 0x3b,
-0x6a, 0xfa, 0x6d, 0x3b, 0x73, 0x61, 0x6d, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x1dd, 0x3b, 0x6c, 0x1dd, 0x6e, 0x64, 0xed,
-0x3b, 0x6d, 0x61, 0x61, 0x64, 0xed, 0x3b, 0x6d, 0x25b, 0x6b, 0x72, 0x25b, 0x64, 0xed, 0x3b, 0x6a, 0x1dd, 0x1dd, 0x64, 0xed,
-0x3b, 0x6a, 0xfa, 0x6d, 0x62, 0xe1, 0x3b, 0x73, 0x61, 0x6d, 0x64, 0xed, 0x3b, 0x73, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d,
-0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x73, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a,
-0x74, 0x6e, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x74,
-0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a,
-0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a,
-0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b,
-0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x3b, 0x43, 0x79, 0x61, 0x3b, 0x43, 0x6c, 0x61, 0x3b, 0x43, 0x7a, 0x69, 0x3b,
-0x43, 0x6b, 0x6f, 0x3b, 0x43, 0x6b, 0x61, 0x3b, 0x43, 0x67, 0x61, 0x3b, 0x43, 0x7a, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x2019,
-0x79, 0x61, 0x6b, 0x6b, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x6c, 0x61, 0x61, 0x257, 0x69, 0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x7a,
-0x79, 0x69, 0x69, 0x257, 0x69, 0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x6b, 0x6f, 0x6c, 0x6c, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x6b,
-0x61, 0x6c, 0x64, 0x1dd, 0x253, 0x6c, 0x69, 0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x67, 0x61, 0x69, 0x73, 0x75, 0x75, 0x3b, 0x43,
-0x6f, 0x6d, 0x7a, 0x79, 0x65, 0x253, 0x73, 0x75, 0x75, 0x3b, 0x59, 0x3b, 0x4c, 0x3b, 0x5a, 0x3b, 0x4f, 0x3b, 0x41, 0x3b,
-0x47, 0x3b, 0x45, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x3b, 0x73, 0x6d, 0x62, 0x3b, 0x73, 0x6d,
-0x6c, 0x3b, 0x73, 0x6d, 0x6e, 0x3b, 0x6d, 0x62, 0x73, 0x3b, 0x73, 0x61, 0x73, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254,
-0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20,
-0x6d, 0xe1, 0x62, 0x61, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x6c,
-0x61, 0x6c, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x6e, 0x61, 0x3b,
-0x6d, 0x61, 0x62, 0xe1, 0x67, 0xe1, 0x20, 0x6d, 0xe1, 0x20, 0x73, 0x75, 0x6b, 0x75, 0x6c, 0x3b, 0x73, 0xe1, 0x73, 0x61,
-0x64, 0x69, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x43, 0xe4, 0x14b,
-0x3b, 0x4a, 0x69, 0x65, 0x63, 0x3b, 0x52, 0x25b, 0x77, 0x3b, 0x44, 0x69, 0x254, 0x331, 0x6b, 0x3b, 0x14a, 0x75, 0x61, 0x61,
-0x6e, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65, 0x63, 0x3b, 0x42, 0xe4, 0x6b, 0x25b, 0x6c, 0x3b, 0x43, 0xe4, 0x14b, 0x20, 0x6b,
-0x75, 0x254, 0x74, 0x68, 0x3b, 0x4a, 0x69, 0x65, 0x63, 0x20, 0x6c, 0x61, 0x331, 0x74, 0x3b, 0x52, 0x25b, 0x77, 0x20, 0x6c,
-0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x44, 0x69, 0x254, 0x331, 0x6b, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x14a, 0x75, 0x61,
-0x61, 0x6e, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65, 0x63, 0x20, 0x6c, 0xe4, 0x74, 0x6e,
-0x69, 0x3b, 0x42, 0xe4, 0x6b, 0x25b, 0x6c, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x43, 0x3b, 0x4a, 0x3b, 0x52, 0x3b,
-0x44, 0x3b, 0x14a, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x411, 0x441, 0x3b, 0x411, 0x43d, 0x3b, 0x41e, 0x43f, 0x3b, 0x421, 0x44d, 0x3b,
-0x427, 0x43f, 0x3b, 0x411, 0x44d, 0x3b, 0x421, 0x431, 0x3b, 0x411, 0x430, 0x441, 0x43a, 0x44b, 0x4bb, 0x44b, 0x430, 0x43d, 0x43d, 0x44c,
-0x430, 0x3b, 0x411, 0x44d, 0x43d, 0x438, 0x434, 0x438, 0x44d, 0x43b, 0x438, 0x43d, 0x43d, 0x44c, 0x438, 0x43a, 0x3b, 0x41e, 0x43f, 0x442,
-0x443, 0x43e, 0x440, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x43a, 0x3b, 0x421, 0x44d, 0x440, 0x44d, 0x434, 0x44d, 0x3b, 0x427, 0x44d, 0x43f,
-0x43f, 0x438, 0x44d, 0x440, 0x3b, 0x411, 0x44d, 0x44d, 0x442, 0x438, 0x4a5, 0x441, 0x44d, 0x3b, 0x421, 0x443, 0x431, 0x443, 0x43e, 0x442,
-0x430, 0x3b, 0x411, 0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x421, 0x3b, 0x427, 0x3b, 0x411, 0x3b, 0x421, 0x3b, 0x4d, 0x75, 0x6c, 0x3b,
-0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b,
-0x4a, 0x6d, 0x6f, 0x3b, 0x4d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75,
-0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c,
-0x61, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d,
-0x6f, 0x73, 0x69, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x3b, 0xa55e, 0xa54c,
-0xa535, 0x3b, 0xa5f3, 0xa5e1, 0xa609, 0x3b, 0xa55a, 0xa55e, 0xa55a, 0x3b, 0xa549, 0xa55e, 0xa552, 0x3b, 0xa549, 0xa524, 0xa546, 0xa562, 0x3b, 0xa549,
-0xa524, 0xa540, 0xa56e, 0x3b, 0xa53b, 0xa52c, 0xa533, 0x3b, 0x6c, 0x61, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x74, 0x25b, 0x25b, 0x6e, 0x25b,
-0x25b, 0x3b, 0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x69, 0x6d, 0x69, 0x73,
-0x61, 0x3b, 0x61, 0x69, 0x6a, 0x69, 0x6d, 0x61, 0x3b, 0x73, 0x69, 0x253, 0x69, 0x74, 0x69, 0x3b, 0x53, 0x75, 0x6e, 0x3b,
-0x4d, 0xe4, 0x6e, 0x3b, 0x5a, 0x69, 0x161, 0x3b, 0x4d, 0x69, 0x74, 0x3b, 0x46, 0x72, 0xf3, 0x3b, 0x46, 0x72, 0x69, 0x3b,
-0x53, 0x61, 0x6d, 0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0xe4, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x5a,
-0x69, 0x161, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x74, 0x74, 0x77, 0x75, 0x10d, 0x3b, 0x46, 0x72, 0xf3, 0x6e, 0x74, 0x61,
-0x67, 0x3b, 0x46, 0x72, 0x69, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x161, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x3b, 0x4d,
-0x3b, 0x5a, 0x3b, 0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b, 0x53, 0x3b, 0x73, 0x64, 0x3b, 0x6d, 0x64, 0x3b, 0x6d, 0x77, 0x3b,
-0x65, 0x74, 0x3b, 0x6b, 0x6c, 0x3b, 0x66, 0x6c, 0x3b, 0x73, 0x73, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x25b, 0x3b,
-0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65, 0x3b, 0x6d, 0x75, 0xe1, 0x6e, 0x79, 0xe1, 0x14b, 0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65,
-0x3b, 0x6d, 0x65, 0x74, 0xfa, 0x6b, 0x70, 0xed, 0xe1, 0x70, 0x25b, 0x3b, 0x6b, 0xfa, 0x70, 0xe9, 0x6c, 0x69, 0x6d, 0x65,
-0x74, 0xfa, 0x6b, 0x70, 0x69, 0x61, 0x70, 0x25b, 0x3b, 0x66, 0x65, 0x6c, 0xe9, 0x74, 0x65, 0x3b, 0x73, 0xe9, 0x73, 0x65,
-0x6c, 0xe9, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x65, 0x3b, 0x6b, 0x3b, 0x66, 0x3b, 0x73, 0x3b, 0x64, 0x6f, 0x6d,
-0x3b, 0x6c, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x69, 0xe9, 0x3b, 0x78, 0x75, 0x65, 0x3b, 0x76, 0x69, 0x65,
-0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x6c, 0x6c, 0x75, 0x6e, 0x65, 0x73, 0x3b,
-0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0x69, 0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x78, 0x75, 0x65,
-0x76, 0x65, 0x73, 0x3b, 0x76, 0x69, 0x65, 0x6e, 0x72, 0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x53,
-0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0xc1, 0x70, 0x74, 0x61, 0x20, 0x4d, 0x254,
-0x301, 0x6e, 0x64, 0x69, 0x3b, 0x57, 0x25b, 0x301, 0x6e, 0x25b, 0x73, 0x25b, 0x64, 0x25b, 0x3b, 0x54, 0x254, 0x301, 0x73, 0x25b,
-0x64, 0x25b, 0x3b, 0x46, 0x25b, 0x6c, 0xe2, 0x79, 0x25b, 0x64, 0x25b, 0x3b, 0x53, 0xe1, 0x73, 0x69, 0x64, 0x25b, 0x3b, 0x53,
-0x254, 0x301, 0x3b, 0x4d, 0x254, 0x301, 0x3b, 0xc1, 0x4d, 0x3b, 0x57, 0x25b, 0x301, 0x3b, 0x54, 0x254, 0x301, 0x3b, 0x46, 0x25b,
-0x3b, 0x53, 0xe1, 0x3b, 0x73, 0x254, 0x6e, 0x64, 0x69, 0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64,
-0x69, 0x3b, 0x6d, 0x25b, 0x72, 0x6b, 0x25b, 0x72, 0x25b, 0x64, 0x69, 0x3b, 0x79, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x61, 0x14b,
-0x64, 0x25b, 0x72, 0x25b, 0x64, 0x69, 0x3b, 0x6d, 0x254, 0x6e, 0x254, 0x20, 0x73, 0x254, 0x6e, 0x64, 0x69, 0x3b, 0x73, 0x6f,
-0x3b, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x25b, 0x3b, 0x79, 0x65, 0x3b, 0x76, 0x61, 0x3b, 0x6d, 0x73, 0x3b, 0x41,
-0x6e, 0x65, 0x67, 0x20, 0x31, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x32, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x33, 0x3b,
-0x41, 0x6e, 0x65, 0x67, 0x20, 0x34, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x35, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x36,
-0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x37, 0x3b, 0x41, 0x31, 0x3b, 0x41, 0x32, 0x3b, 0x41, 0x33, 0x3b, 0x41, 0x34, 0x3b,
-0x41, 0x35, 0x3b, 0x41, 0x36, 0x3b, 0x41, 0x37, 0x3b, 0x6c, 0x79, 0x25b, 0x2bc, 0x25b, 0x301, 0x20, 0x73, 0x1e85, 0xed, 0x14b,
-0x74, 0xe8, 0x3b, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x62, 0x254, 0x301, 0x254, 0x6e,
-0x74, 0xe8, 0x20, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x74, 0x73, 0xe8, 0x74, 0x73, 0x25b,
-0x300, 0x25b, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x62, 0x254, 0x301, 0x254, 0x6e, 0x74, 0xe8, 0x20, 0x74, 0x73,
-0x65, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6d, 0xe0,
-0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0xe0, 0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b,
-0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77, 0x61, 0x6b, 0x21f, 0x61, 0x14b, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77,
-0x61, 0x14b, 0x17e, 0x69, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x6e, 0x75, 0x14b, 0x70, 0x61, 0x3b, 0x41, 0x14b, 0x70,
-0xe9, 0x74, 0x75, 0x79, 0x61, 0x6d, 0x6e, 0x69, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x74, 0x6f, 0x70, 0x61, 0x3b,
-0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x7a, 0x61, 0x70, 0x74, 0x61, 0x14b, 0x3b, 0x4f, 0x77, 0xe1, 0x14b, 0x67, 0x79, 0x75,
-0x17e, 0x61, 0x17e, 0x61, 0x70, 0x69, 0x3b, 0x41, 0x3b, 0x57, 0x3b, 0x4e, 0x3b, 0x59, 0x3b, 0x54, 0x3b, 0x5a, 0x3b, 0x4f,
-0x3b, 0x2d30, 0x2d59, 0x2d30, 0x2d4e, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d62, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4f, 0x2d30, 0x2d59,
-0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4e, 0x2d61, 0x2d30, 0x2d59,
-0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x2d62, 0x2d30, 0x2d59, 0x3b, 0x6cc, 0x6d5, 0x6a9, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x62f, 0x648,
-0x648, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x633, 0x6ce, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x686, 0x648, 0x627, 0x631, 0x634,
-0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x67e, 0x6ce, 0x646, 0x62c, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x6be, 0x6d5, 0x6cc, 0x646, 0x6cc,
-0x3b, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x6cc, 0x3b, 0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x6be, 0x3b, 0x634,
-0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x70, 0xf3, 0x6e, 0x3b, 0x77, 0x61, 0x142, 0x3b, 0x73, 0x72, 0x6a, 0x3b, 0x73, 0x74, 0x77,
-0x3b, 0x70, 0x11b, 0x74, 0x3b, 0x73, 0x6f, 0x62, 0x3b, 0x6e, 0x6a, 0x65, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e,
-0x6a, 0x65, 0x17a, 0x65, 0x6c, 0x65, 0x3b, 0x77, 0x61, 0x142, 0x74, 0x6f, 0x72, 0x61, 0x3b, 0x73, 0x72, 0x6a, 0x6f, 0x64,
-0x61, 0x3b, 0x73, 0x74, 0x77, 0xf3, 0x72, 0x74, 0x6b, 0x3b, 0x70, 0x11b, 0x74, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74,
-0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x6a, 0x65, 0x3b,
-0x70, 0xf3, 0x6e, 0x3b, 0x77, 0x75, 0x74, 0x3b, 0x73, 0x72, 0x6a, 0x3b, 0x161, 0x74, 0x77, 0x3b, 0x70, 0x6a, 0x61, 0x3b,
-0x73, 0x6f, 0x62, 0x3b, 0x6e, 0x6a, 0x65, 0x64, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e, 0x64, 0x17a, 0x65, 0x6c,
-0x61, 0x3b, 0x77, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x3b, 0x73, 0x72, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x161, 0x74, 0x77, 0xf3,
-0x72, 0x74, 0x6b, 0x3b, 0x70, 0x6a, 0x61, 0x74, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70,
-0x3b, 0x77, 0x3b, 0x73, 0x3b, 0x161, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x70, 0x61, 0x3b, 0x76, 0x75, 0x3b, 0x6d, 0x61, 0x3b,
-0x6b, 0x6f, 0x3b, 0x74, 0x75, 0x3b, 0x76, 0xe1, 0x3b, 0x6c, 0xe1, 0x3b, 0x70, 0x61, 0x73, 0x65, 0x70, 0x65, 0x69, 0x76,
-0x69, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73, 0x61, 0x72, 0x67, 0xe2, 0x3b, 0x6d, 0x61, 0x6a, 0x65, 0x62, 0x61, 0x72, 0x67,
-0xe2, 0x3b, 0x6b, 0x6f, 0x73, 0x6b, 0x6f, 0x6b, 0x6b, 0x6f, 0x3b, 0x74, 0x75, 0x6f, 0x72, 0xe2, 0x73, 0x74, 0xe2, 0x68,
-0x3b, 0x76, 0xe1, 0x73, 0x74, 0x75, 0x70, 0x70, 0x65, 0x69, 0x76, 0x69, 0x3b, 0x6c, 0xe1, 0x76, 0x75, 0x72, 0x64, 0xe2,
-0x68, 0x3b, 0x70, 0x61, 0x73, 0x65, 0x70, 0x65, 0x65, 0x69, 0x76, 0x69, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73, 0x61, 0x61,
-0x72, 0x67, 0xe2, 0x3b, 0x6d, 0x61, 0x6a, 0x65, 0x62, 0x61, 0x61, 0x72, 0x67, 0xe2, 0x3b, 0x6b, 0x6f, 0x73, 0x6b, 0x6f,
-0x68, 0x6f, 0x3b, 0x74, 0x75, 0x6f, 0x72, 0xe2, 0x73, 0x74, 0x75, 0x76, 0x3b, 0x76, 0xe1, 0x73, 0x74, 0x75, 0x70, 0x70,
-0x65, 0x65, 0x69, 0x76, 0x69, 0x3b, 0x6c, 0xe1, 0x76, 0x75, 0x72, 0x64, 0x75, 0x76, 0x3b, 0x50, 0x3b, 0x56, 0x3b, 0x4d,
-0x3b, 0x4b, 0x3b, 0x54, 0x3b, 0x56, 0x3b, 0x4c, 0x3b
+0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x44, 0x3b, 0x47, 0x3b, 0x44, 0x3b, 0x42,
+0x3b, 0x4c, 0x3b, 0x73, 0x6f, 0x74, 0x6e, 0x61, 0x62, 0x65, 0x61, 0x69, 0x76, 0x69, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73,
+0xe1, 0x72, 0x67, 0x67, 0x61, 0x3b, 0x6d, 0x61, 0x14b, 0x14b, 0x65, 0x62, 0xe1, 0x72, 0x67, 0x67, 0x61, 0x3b, 0x67, 0x61,
+0x73, 0x6b, 0x61, 0x76, 0x61, 0x68, 0x6b, 0x75, 0x3b, 0x64, 0x75, 0x6f, 0x72, 0x61, 0x73, 0x74, 0x61, 0x67, 0x61, 0x3b,
+0x62, 0x65, 0x61, 0x72, 0x6a, 0x61, 0x64, 0x61, 0x67, 0x61, 0x3b, 0x6c, 0xe1, 0x76, 0x76, 0x61, 0x72, 0x64, 0x61, 0x67,
+0x61, 0x3b, 0x43, 0x70, 0x72, 0x3b, 0x43, 0x74, 0x74, 0x3b, 0x43, 0x6d, 0x6e, 0x3b, 0x43, 0x6d, 0x74, 0x3b, 0x41, 0x72,
+0x73, 0x3b, 0x49, 0x63, 0x6d, 0x3b, 0x45, 0x73, 0x74, 0x3b, 0x43, 0x68, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x72, 0x69, 0x3b,
+0x43, 0x68, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x6f, 0x3b, 0x43, 0x68, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x43,
+0x68, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x63, 0x68,
+0x75, 0x6d, 0x61, 0x3b, 0x45, 0x73, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b, 0x43, 0x3b,
+0x41, 0x3b, 0x49, 0x3b, 0x45, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x4a, 0x69, 0x6d, 0x3b, 0x4b, 0x61, 0x77, 0x3b, 0x4b, 0x61,
+0x64, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x4b, 0x61, 0x73, 0x3b, 0x4e, 0x67, 0x75, 0x3b, 0x49, 0x74, 0x75, 0x6b, 0x75, 0x20,
+0x6a, 0x61, 0x20, 0x6a, 0x75, 0x6d, 0x77, 0x61, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6a, 0x69,
+0x6d, 0x77, 0x65, 0x72, 0x69, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x77, 0x69, 0x3b,
+0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x64, 0x61, 0x64, 0x75, 0x3b, 0x4b, 0x75, 0x72, 0x61,
+0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4b, 0x75, 0x72, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x20, 0x6b,
+0x61, 0x73, 0x61, 0x6e, 0x75, 0x3b, 0x4b, 0x69, 0x66, 0x75, 0x6c, 0x61, 0x20, 0x6e, 0x67, 0x75, 0x77, 0x6f, 0x3b, 0x4a,
+0x3b, 0x4a, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x64, 0x65, 0x77, 0x3b, 0x61, 0x61, 0x253,
+0x3b, 0x6d, 0x61, 0x77, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x6e, 0x61, 0x61, 0x3b, 0x6d, 0x77, 0x64, 0x3b, 0x68, 0x62, 0x69,
+0x3b, 0x64, 0x65, 0x77, 0x6f, 0x3b, 0x61, 0x61, 0x253, 0x6e, 0x64, 0x65, 0x3b, 0x6d, 0x61, 0x77, 0x62, 0x61, 0x61, 0x72,
+0x65, 0x3b, 0x6e, 0x6a, 0x65, 0x73, 0x6c, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x6e, 0x61, 0x61, 0x73, 0x61, 0x61, 0x6e, 0x64,
+0x65, 0x3b, 0x6d, 0x61, 0x77, 0x6e, 0x64, 0x65, 0x3b, 0x68, 0x6f, 0x6f, 0x72, 0x65, 0x2d, 0x62, 0x69, 0x69, 0x72, 0x3b,
+0x64, 0x3b, 0x61, 0x3b, 0x6d, 0x3b, 0x6e, 0x3b, 0x6e, 0x3b, 0x6d, 0x3b, 0x68, 0x3b, 0x4b, 0x4d, 0x41, 0x3b, 0x4e, 0x54,
+0x54, 0x3b, 0x4e, 0x4d, 0x4e, 0x3b, 0x4e, 0x4d, 0x54, 0x3b, 0x41, 0x52, 0x54, 0x3b, 0x4e, 0x4d, 0x41, 0x3b, 0x4e, 0x4d,
+0x4d, 0x3b, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x169, 0x3b, 0x4e,
+0x6a, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x61, 0x3b, 0x41, 0x72,
+0x61, 0x6d, 0x69, 0x74, 0x68, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x6d,
+0x6f, 0x74, 0x68, 0x69, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x41,
+0x72, 0x65, 0x3b, 0x4b, 0x75, 0x6e, 0x3b, 0x4f, 0x6e, 0x67, 0x3b, 0x49, 0x6e, 0x65, 0x3b, 0x49, 0x6c, 0x65, 0x3b, 0x53,
+0x61, 0x70, 0x3b, 0x4b, 0x77, 0x65, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x61, 0x72, 0x65,
+0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x6b, 0x75, 0x6e, 0x69, 0x3b, 0x4d, 0x64, 0x65, 0x72,
+0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x6f, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74,
+0x20, 0x65, 0x65, 0x20, 0x69, 0x6e, 0x65, 0x74, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x69,
+0x6c, 0x65, 0x3b, 0x4d, 0x64, 0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x73, 0x61, 0x70, 0x61, 0x3b, 0x4d, 0x64,
+0x65, 0x72, 0x6f, 0x74, 0x20, 0x65, 0x65, 0x20, 0x6b, 0x77, 0x65, 0x3b, 0x41, 0x3b, 0x4b, 0x3b, 0x4f, 0x3b, 0x49, 0x3b,
+0x49, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x44, 0x69, 0x6d, 0x3b, 0x50, 0x6f, 0x73, 0x3b, 0x50, 0x69, 0x72, 0x3b, 0x54, 0x61,
+0x74, 0x3b, 0x4e, 0x61, 0x69, 0x3b, 0x53, 0x68, 0x61, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x44, 0x69, 0x6d, 0x69, 0x6e, 0x67,
+0x75, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x6f, 0x73, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x43, 0x68,
+0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x69, 0x3b, 0x43, 0x68, 0x69, 0x73, 0x68, 0x61, 0x6e,
+0x75, 0x3b, 0x53, 0x61, 0x62, 0x75, 0x64, 0x75, 0x3b, 0x44, 0x3b, 0x50, 0x3b, 0x43, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x53,
+0x3b, 0x53, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x76, 0x75, 0x3b, 0x53, 0x69, 0x62, 0x3b, 0x53, 0x69, 0x74, 0x3b, 0x53,
+0x69, 0x6e, 0x3b, 0x53, 0x69, 0x68, 0x3b, 0x4d, 0x67, 0x71, 0x3b, 0x53, 0x6f, 0x6e, 0x74, 0x6f, 0x3b, 0x4d, 0x76, 0x75,
+0x6c, 0x6f, 0x3b, 0x53, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x53, 0x69, 0x74, 0x68, 0x61, 0x74, 0x68, 0x75, 0x3b, 0x53,
+0x69, 0x6e, 0x65, 0x3b, 0x53, 0x69, 0x68, 0x6c, 0x61, 0x6e, 0x75, 0x3b, 0x4d, 0x67, 0x71, 0x69, 0x62, 0x65, 0x6c, 0x6f,
+0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x49, 0x6a, 0x70, 0x3b, 0x49,
+0x6a, 0x74, 0x3b, 0x49, 0x6a, 0x6e, 0x3b, 0x49, 0x6a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b,
+0x49, 0x6a, 0x6d, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x74,
+0x61, 0x74, 0x75, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x74, 0x61,
+0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x49,
+0x6a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b, 0x36, 0x3b, 0x37,
+0x3b, 0x31, 0x3b, 0x2d30, 0x2d59, 0x2d30, 0x3b, 0x2d30, 0x2d62, 0x2d4f, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x3b, 0x2d30,
+0x2d3d, 0x2d61, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4e, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x3b, 0x2d30, 0x2d59, 0x2d30, 0x2d4e, 0x2d30, 0x2d59, 0x3b,
+0x2d30, 0x2d62, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x2d30, 0x2d59, 0x3b, 0x2d30,
+0x2d3d, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d59, 0x2d49, 0x2d4e, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x2d62, 0x2d30, 0x2d59, 0x3b,
+0x61, 0x73, 0x61, 0x3b, 0x61, 0x79, 0x6e, 0x3b, 0x61, 0x73, 0x69, 0x3b, 0x61, 0x6b, 0x1e5b, 0x3b, 0x61, 0x6b, 0x77, 0x3b,
+0x61, 0x73, 0x69, 0x6d, 0x3b, 0x61, 0x73, 0x69, 0x1e0d, 0x3b, 0x61, 0x73, 0x61, 0x6d, 0x61, 0x73, 0x3b, 0x61, 0x79, 0x6e,
+0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x61, 0x6b, 0x1e5b, 0x61, 0x73, 0x3b, 0x61, 0x6b, 0x77, 0x61,
+0x73, 0x3b, 0x61, 0x73, 0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x61, 0x73, 0x69, 0x1e0d, 0x79, 0x61, 0x73, 0x3b, 0x59, 0x61,
+0x6e, 0x3b, 0x53, 0x61, 0x6e, 0x3b, 0x4b, 0x72, 0x61, 0x1e0d, 0x3b, 0x4b, 0x75, 0x1e93, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53,
+0x1e0d, 0x69, 0x73, 0x3b, 0x53, 0x61, 0x79, 0x3b, 0x59, 0x61, 0x6e, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x6e, 0x61, 0x73,
+0x73, 0x3b, 0x4b, 0x72, 0x61, 0x1e0d, 0x61, 0x73, 0x73, 0x3b, 0x4b, 0x75, 0x1e93, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x6d,
+0x61, 0x73, 0x73, 0x3b, 0x53, 0x1e0d, 0x69, 0x73, 0x61, 0x73, 0x73, 0x3b, 0x53, 0x61, 0x79, 0x61, 0x73, 0x73, 0x3b, 0x59,
+0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x53, 0x41, 0x4e, 0x3b, 0x4f, 0x52, 0x4b,
+0x3b, 0x4f, 0x4b, 0x42, 0x3b, 0x4f, 0x4b, 0x53, 0x3b, 0x4f, 0x4b, 0x4e, 0x3b, 0x4f, 0x4b, 0x54, 0x3b, 0x4f, 0x4d, 0x4b,
+0x3b, 0x53, 0x61, 0x6e, 0x64, 0x65, 0x3b, 0x4f, 0x72, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x61, 0x6e, 0x7a, 0x61, 0x3b, 0x4f,
+0x72, 0x77, 0x61, 0x6b, 0x61, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x73, 0x68, 0x61, 0x74,
+0x75, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x6e, 0x61, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6b, 0x61, 0x74, 0x61, 0x61,
+0x6e, 0x6f, 0x3b, 0x4f, 0x72, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x53, 0x3b, 0x4b, 0x3b, 0x52,
+0x3b, 0x53, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x4d, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x56, 0x69, 0x6c, 0x3b, 0x48, 0x69, 0x76,
+0x3b, 0x48, 0x69, 0x64, 0x3b, 0x48, 0x69, 0x74, 0x3b, 0x48, 0x69, 0x68, 0x3b, 0x4c, 0x65, 0x6d, 0x3b, 0x70, 0x61, 0x20,
+0x6d, 0x75, 0x6c, 0x75, 0x6e, 0x67, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x73, 0x68, 0x61, 0x68, 0x75, 0x76, 0x69, 0x6c, 0x75,
+0x68, 0x61, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x64, 0x61,
+0x74, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x74, 0x61, 0x79, 0x69, 0x3b, 0x70, 0x61, 0x20, 0x68, 0x69, 0x68, 0x61,
+0x6e, 0x75, 0x3b, 0x70, 0x61, 0x20, 0x73, 0x68, 0x61, 0x68, 0x75, 0x6c, 0x65, 0x6d, 0x62, 0x65, 0x6c, 0x61, 0x3b, 0x4d,
+0x3b, 0x4a, 0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x48, 0x3b, 0x57, 0x3b, 0x4a, 0x3b, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74,
+0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x79, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x75,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x75, 0x3b, 0x41, 0x6c,
+0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f,
+0x73, 0x69, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x3b, 0x6b, 0x61, 0x72,
+0x3b, 0x6e, 0x74, 0x25b, 0x3b, 0x74, 0x61, 0x72, 0x3b, 0x61, 0x72, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x3b, 0x6a, 0x75, 0x6d,
+0x3b, 0x73, 0x69, 0x62, 0x3b, 0x6b, 0x61, 0x72, 0x69, 0x3b, 0x6e, 0x74, 0x25b, 0x6e, 0x25b, 0x3b, 0x74, 0x61, 0x72, 0x61,
+0x74, 0x61, 0x3b, 0x61, 0x72, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x6c, 0x61, 0x6d, 0x69, 0x73, 0x61, 0x3b, 0x6a, 0x75, 0x6d,
+0x61, 0x3b, 0x73, 0x69, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x4a,
+0x3b, 0x53, 0x3b, 0x4b, 0x6d, 0x61, 0x3b, 0x54, 0x61, 0x74, 0x3b, 0x49, 0x6e, 0x65, 0x3b, 0x54, 0x61, 0x6e, 0x3b, 0x41,
+0x72, 0x6d, 0x3b, 0x4d, 0x61, 0x61, 0x3b, 0x4e, 0x4d, 0x4d, 0x3b, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4e, 0x6a,
+0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4e, 0x6a, 0x75, 0x6d, 0x61, 0x69, 0x6e, 0x65, 0x3b, 0x4e, 0x6a, 0x75,
+0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x74, 0x68, 0x69, 0x3b, 0x4e, 0x6a, 0x75, 0x6d,
+0x61, 0x61, 0x3b, 0x4e, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x74, 0x68, 0x69, 0x69, 0x3b, 0x4b, 0x3b, 0x4e, 0x3b, 0x4e,
+0x3b, 0x4e, 0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4e, 0x3b, 0x13c6, 0x13cd, 0x13ac, 0x3b, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5, 0x13c1,
+0x3b, 0x13e6, 0x13a2, 0x13c1, 0x3b, 0x13c5, 0x13a9, 0x13c1, 0x3b, 0x13e7, 0x13be, 0x13a9, 0x3b, 0x13c8, 0x13d5, 0x13be, 0x3b, 0x13a4, 0x13be, 0x13d9,
+0x13d3, 0x13c6, 0x13cd, 0x13ac, 0x3b, 0x13a4, 0x13be, 0x13d9, 0x13d3, 0x13c9, 0x13c5, 0x13af, 0x3b, 0x13d4, 0x13b5, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13e6,
+0x13a2, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13c5, 0x13a9, 0x13c1, 0x13a2, 0x13a6, 0x3b, 0x13e7, 0x13be, 0x13a9, 0x13b6, 0x13cd, 0x13d7, 0x3b, 0x13a4, 0x13be,
+0x13d9, 0x13d3, 0x13c8, 0x13d5, 0x13be, 0x3b, 0x13c6, 0x3b, 0x13c9, 0x3b, 0x13d4, 0x3b, 0x13e6, 0x3b, 0x13c5, 0x3b, 0x13e7, 0x3b, 0x13a4, 0x3b,
+0x64, 0x69, 0x6d, 0x3b, 0x6c, 0x69, 0x6e, 0x3b, 0x6d, 0x61, 0x72, 0x3b, 0x6d, 0x65, 0x72, 0x3b, 0x7a, 0x65, 0x3b, 0x76,
+0x61, 0x6e, 0x3b, 0x73, 0x61, 0x6d, 0x3b, 0x64, 0x69, 0x6d, 0x61, 0x6e, 0x73, 0x3b, 0x6c, 0x69, 0x6e, 0x64, 0x69, 0x3b,
+0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x65, 0x72, 0x6b, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x7a, 0x65, 0x64, 0x69, 0x3b,
+0x76, 0x61, 0x6e, 0x64, 0x72, 0x65, 0x64, 0x69, 0x3b, 0x73, 0x61, 0x6d, 0x64, 0x69, 0x3b, 0x64, 0x3b, 0x6c, 0x3b, 0x6d,
+0x3b, 0x6d, 0x3b, 0x7a, 0x3b, 0x76, 0x3b, 0x73, 0x3b, 0x4c, 0x6c, 0x32, 0x3b, 0x4c, 0x6c, 0x33, 0x3b, 0x4c, 0x6c, 0x34,
+0x3b, 0x4c, 0x6c, 0x35, 0x3b, 0x4c, 0x6c, 0x36, 0x3b, 0x4c, 0x6c, 0x37, 0x3b, 0x4c, 0x6c, 0x31, 0x3b, 0x4c, 0x69, 0x64,
+0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x70, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c,
+0x79, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x63, 0x68,
+0x65, 0x63, 0x68, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e,
+0x6f, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e, 0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e,
+0x61, 0x20, 0x6c, 0x69, 0x6e, 0x6a, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76, 0x61, 0x20, 0x6c, 0x79, 0x61, 0x6e, 0x6e,
+0x79, 0x61, 0x6e, 0x6f, 0x20, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x76, 0x69, 0x6c, 0x69, 0x3b, 0x4c, 0x69, 0x64, 0x75, 0x76,
+0x61, 0x20, 0x6c, 0x69, 0x74, 0x61, 0x6e, 0x64, 0x69, 0x3b, 0x50, 0xed, 0x69, 0x6c, 0x69, 0x3b, 0x54, 0xe1, 0x61, 0x74,
+0x75, 0x3b, 0xcd, 0x6e, 0x65, 0x3b, 0x54, 0xe1, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b,
+0x4d, 0xf3, 0x6f, 0x73, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0xed, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x74, 0xe1, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0xed, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x61,
+0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x61, 0x6d, 0xed, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0xe1, 0x61, 0x3b, 0x4a,
+0x75, 0x6d, 0x61, 0x6d, 0xf3, 0x6f, 0x73, 0x69, 0x3b, 0x50, 0x3b, 0x54, 0x3b, 0x45, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x49,
+0x3b, 0x4d, 0x3b, 0x53, 0x61, 0x62, 0x3b, 0x42, 0x61, 0x6c, 0x3b, 0x4c, 0x77, 0x32, 0x3b, 0x4c, 0x77, 0x33, 0x3b, 0x4c,
+0x77, 0x34, 0x3b, 0x4c, 0x77, 0x35, 0x3b, 0x4c, 0x77, 0x36, 0x3b, 0x53, 0x61, 0x62, 0x62, 0x69, 0x69, 0x74, 0x69, 0x3b,
+0x42, 0x61, 0x6c, 0x61, 0x7a, 0x61, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x62, 0x69, 0x72, 0x69, 0x3b, 0x4c, 0x77, 0x61,
+0x6b, 0x75, 0x73, 0x61, 0x74, 0x75, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4c, 0x77, 0x61, 0x6b, 0x75,
+0x74, 0x61, 0x61, 0x6e, 0x6f, 0x3b, 0x4c, 0x77, 0x61, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x53, 0x3b, 0x42,
+0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x50, 0x61, 0x20, 0x4d, 0x75, 0x6c, 0x75, 0x6e, 0x67,
+0x75, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x6d, 0x6f, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x62,
+0x75, 0x6c, 0x69, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x50, 0x61, 0x6c, 0x69,
+0x63, 0x68, 0x69, 0x6e, 0x65, 0x3b, 0x50, 0x61, 0x6c, 0x69, 0x63, 0x68, 0x69, 0x73, 0x61, 0x6e, 0x6f, 0x3b, 0x50, 0x61,
+0x63, 0x68, 0x69, 0x62, 0x65, 0x6c, 0x75, 0x73, 0x68, 0x69, 0x3b, 0x64, 0x75, 0x6d, 0x3b, 0x73, 0x69, 0x67, 0x3b, 0x74,
+0x65, 0x72, 0x3b, 0x6b, 0x75, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x3b, 0x73, 0x65, 0x73, 0x3b, 0x73, 0x61, 0x62, 0x3b, 0x64,
+0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x73, 0x69, 0x67, 0x75, 0x6e, 0x64, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b,
+0x74, 0x65, 0x72, 0x73, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x75, 0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65,
+0x72, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x65, 0x73, 0x74, 0x61, 0x2d,
+0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x44, 0x3b, 0x53, 0x3b, 0x54, 0x3b, 0x4b, 0x3b,
+0x4b, 0x3b, 0x53, 0x3b, 0x53, 0x3b, 0x64, 0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x73, 0x69, 0x67, 0x75, 0x6e, 0x64,
+0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x74, 0x65, 0x72, 0x73, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x75,
+0x61, 0x72, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x6b, 0x69, 0x6e, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61,
+0x3b, 0x73, 0x65, 0x73, 0x74, 0x61, 0x2d, 0x66, 0x65, 0x72, 0x61, 0x3b, 0x73, 0x61, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x4b,
+0x49, 0x55, 0x3b, 0x4d, 0x52, 0x41, 0x3b, 0x57, 0x41, 0x49, 0x3b, 0x57, 0x45, 0x54, 0x3b, 0x57, 0x45, 0x4e, 0x3b, 0x57,
+0x54, 0x4e, 0x3b, 0x4a, 0x55, 0x4d, 0x3b, 0x4b, 0x69, 0x75, 0x6d, 0x69, 0x61, 0x3b, 0x4d, 0x75, 0x72, 0x61, 0x6d, 0x75,
+0x6b, 0x6f, 0x3b, 0x57, 0x61, 0x69, 0x72, 0x69, 0x3b, 0x57, 0x65, 0x74, 0x68, 0x61, 0x74, 0x75, 0x3b, 0x57, 0x65, 0x6e,
+0x61, 0x3b, 0x57, 0x65, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x4b, 0x3b,
+0x4d, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x57, 0x3b, 0x4a, 0x3b, 0x4b, 0x74, 0x73, 0x3b, 0x4b, 0x6f, 0x74, 0x3b,
+0x4b, 0x6f, 0x6f, 0x3b, 0x4b, 0x6f, 0x73, 0x3b, 0x4b, 0x6f, 0x61, 0x3b, 0x4b, 0x6f, 0x6d, 0x3b, 0x4b, 0x6f, 0x6c, 0x3b,
+0x4b, 0x6f, 0x74, 0x69, 0x73, 0x61, 0x70, 0x3b, 0x4b, 0x6f, 0x74, 0x61, 0x61, 0x69, 0x3b, 0x4b, 0x6f, 0x61, 0x65, 0x6e,
+0x67, 0x2019, 0x3b, 0x4b, 0x6f, 0x73, 0x6f, 0x6d, 0x6f, 0x6b, 0x3b, 0x4b, 0x6f, 0x61, 0x6e, 0x67, 0x2019, 0x77, 0x61, 0x6e,
+0x3b, 0x4b, 0x6f, 0x6d, 0x75, 0x75, 0x74, 0x3b, 0x4b, 0x6f, 0x6c, 0x6f, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4f, 0x3b, 0x53,
+0x3b, 0x41, 0x3b, 0x4d, 0x3b, 0x4c, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0x61, 0x3b, 0x44, 0x65, 0x3b, 0x57, 0x75, 0x3b,
+0x44, 0x6f, 0x3b, 0x46, 0x72, 0x3b, 0x53, 0x61, 0x74, 0x3b, 0x53, 0x6f, 0x6e, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65,
+0x73, 0x3b, 0x4d, 0x61, 0x6e, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x44, 0x65, 0x6e, 0x73, 0x74, 0x61,
+0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x57, 0x75, 0x6e, 0x73, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b,
+0x44, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x46, 0x72, 0x61, 0x69, 0x74,
+0x61, 0x78, 0x74, 0x73, 0x65, 0x65, 0x73, 0x3b, 0x53, 0x61, 0x74, 0x65, 0x72, 0x74, 0x61, 0x78, 0x74, 0x73, 0x65, 0x65,
+0x73, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x45, 0x3b, 0x57, 0x3b, 0x44, 0x3b, 0x46, 0x3b, 0x41, 0x3b, 0x53, 0x75, 0x2e, 0x3b,
+0x4d, 0x6f, 0x2e, 0x3b, 0x44, 0x69, 0x2e, 0x3b, 0x4d, 0x65, 0x2e, 0x3b, 0x44, 0x75, 0x2e, 0x3b, 0x46, 0x72, 0x2e, 0x3b,
+0x53, 0x61, 0x2e, 0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4d, 0x6f, 0x68, 0x6e, 0x64, 0x61,
+0x61, 0x63, 0x68, 0x3b, 0x44, 0x69, 0x6e, 0x6e, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4d, 0x65, 0x74, 0x77, 0x6f,
+0x63, 0x68, 0x3b, 0x44, 0x75, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x46, 0x72, 0x69, 0x69,
+0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x64, 0x61, 0x61, 0x63, 0x68, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x70, 0xed, 0x6c, 0xed, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x65,
+0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0xe1, 0x6e, 0x254, 0x3b, 0x41, 0x6c, 0x61, 0xe1, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x4a,
+0x75, 0x6d, 0xe1, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0xf3, 0x73, 0x69, 0x3b, 0x53, 0x61, 0x62, 0x69, 0x3b, 0x42,
+0x61, 0x6c, 0x61, 0x3b, 0x4b, 0x75, 0x62, 0x69, 0x3b, 0x4b, 0x75, 0x73, 0x61, 0x3b, 0x4b, 0x75, 0x6e, 0x61, 0x3b, 0x4b,
+0x75, 0x74, 0x61, 0x3b, 0x4d, 0x75, 0x6b, 0x61, 0x3b, 0x53, 0x61, 0x62, 0x69, 0x69, 0x74, 0x69, 0x3b, 0x42, 0x61, 0x6c,
+0x61, 0x7a, 0x61, 0x3b, 0x4f, 0x77, 0x6f, 0x6b, 0x75, 0x62, 0x69, 0x6c, 0x69, 0x3b, 0x4f, 0x77, 0x6f, 0x6b, 0x75, 0x73,
+0x61, 0x74, 0x75, 0x3b, 0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x4f, 0x6c, 0x6f, 0x6b, 0x75, 0x74, 0x61, 0x61,
+0x6e, 0x75, 0x3b, 0x4f, 0x6c, 0x6f, 0x6d, 0x75, 0x6b, 0x61, 0x61, 0x67, 0x61, 0x3b, 0x53, 0x3b, 0x42, 0x3b, 0x42, 0x3b,
+0x53, 0x3b, 0x4b, 0x3b, 0x4b, 0x3b, 0x4d, 0x3b, 0x4a, 0x32, 0x3b, 0x4a, 0x33, 0x3b, 0x4a, 0x34, 0x3b, 0x4a, 0x35, 0x3b,
+0x41, 0x6c, 0x3b, 0x49, 0x6a, 0x3b, 0x4a, 0x31, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x72, 0x69, 0x3b, 0x4a, 0x75,
+0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
+0x61, 0x6e, 0x6f, 0x3b, 0x4d, 0x75, 0x72, 0x77, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4d,
+0x75, 0x72, 0x77, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d,
+0x6f, 0x73, 0x69, 0x3b, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b,
+0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x6d, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x3b, 0x42, 0x61, 0x72, 0x3b,
+0x41, 0x61, 0x72, 0x3b, 0x55, 0x6e, 0x69, 0x3b, 0x55, 0x6e, 0x67, 0x3b, 0x4b, 0x61, 0x6e, 0x3b, 0x53, 0x61, 0x62, 0x3b,
+0x4e, 0x61, 0x6b, 0x61, 0x65, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x65, 0x62, 0x61, 0x72, 0x61, 0x73,
+0x61, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x61, 0x72, 0x65, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x75, 0x6e, 0x69, 0x3b, 0x4e, 0x61,
+0x6b, 0x61, 0x75, 0x6e, 0x67, 0x2019, 0x6f, 0x6e, 0x3b, 0x4e, 0x61, 0x6b, 0x61, 0x6b, 0x61, 0x6e, 0x79, 0x3b, 0x4e, 0x61,
+0x6b, 0x61, 0x73, 0x61, 0x62, 0x69, 0x74, 0x69, 0x3b, 0x4a, 0x3b, 0x42, 0x3b, 0x41, 0x3b, 0x55, 0x3b, 0x55, 0x3b, 0x4b,
+0x3b, 0x53, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x41, 0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41,
+0x6c, 0x6d, 0x3b, 0x41, 0x6c, 0x6a, 0x3b, 0x41, 0x73, 0x73, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74,
+0x69, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41,
+0x6c, 0x68, 0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c, 0x6a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x73, 0x61,
+0x62, 0x64, 0x75, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x4c, 0x3b, 0x53, 0x3b, 0x4a, 0x4d,
+0x50, 0x3b, 0x57, 0x55, 0x54, 0x3b, 0x54, 0x41, 0x52, 0x3b, 0x54, 0x41, 0x44, 0x3b, 0x54, 0x41, 0x4e, 0x3b, 0x54, 0x41,
+0x42, 0x3b, 0x4e, 0x47, 0x53, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x70, 0x69, 0x6c, 0x3b, 0x57, 0x75, 0x6f, 0x6b, 0x20, 0x54,
+0x69, 0x63, 0x68, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x72, 0x69, 0x79, 0x6f, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20,
+0x41, 0x64, 0x65, 0x6b, 0x3b, 0x54, 0x69, 0x63, 0x68, 0x20, 0x41, 0x6e, 0x67, 0x2019, 0x77, 0x65, 0x6e, 0x3b, 0x54, 0x69,
+0x63, 0x68, 0x20, 0x41, 0x62, 0x69, 0x63, 0x68, 0x3b, 0x4e, 0x67, 0x65, 0x73, 0x6f, 0x3b, 0x4a, 0x3b, 0x57, 0x3b, 0x54,
+0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4e, 0x3b, 0x41, 0x73, 0x61, 0x3b, 0x41, 0x79, 0x6e, 0x3b, 0x41, 0x73, 0x6e,
+0x3b, 0x41, 0x6b, 0x72, 0x3b, 0x41, 0x6b, 0x77, 0x3b, 0x41, 0x73, 0x6d, 0x3b, 0x41, 0x73, 0x1e0d, 0x3b, 0x41, 0x73, 0x61,
+0x6d, 0x61, 0x73, 0x3b, 0x41, 0x79, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x41, 0x6b, 0x72,
+0x61, 0x73, 0x3b, 0x41, 0x6b, 0x77, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69, 0x6d, 0x77, 0x61, 0x73, 0x3b, 0x41, 0x73, 0x69,
+0x1e0d, 0x79, 0x61, 0x73, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41,
+0x6c, 0x68, 0x3b, 0x41, 0x74, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x6c, 0x6d, 0x3b, 0x41,
+0x6c, 0x7a, 0x3b, 0x41, 0x73, 0x69, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69,
+0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68,
+0x61, 0x6d, 0x69, 0x69, 0x73, 0x61, 0x3b, 0x41, 0x6c, 0x7a, 0x75, 0x6d, 0x61, 0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69,
+0x3b, 0x4a, 0x70, 0x69, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6d, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68,
+0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x70, 0x69, 0x69, 0x3b, 0x4a, 0x75,
+0x6d, 0x61, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61,
+0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61,
+0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x32, 0x3b, 0x33, 0x3b, 0x34, 0x3b, 0x35, 0x3b,
+0x41, 0x3b, 0x49, 0x3b, 0x31, 0x3b, 0x930, 0x92c, 0x93f, 0x3b, 0x938, 0x92e, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x3b, 0x92c, 0x941,
+0x926, 0x3b, 0x92c, 0x93f, 0x938, 0x925, 0x93f, 0x3b, 0x938, 0x941, 0x916, 0x941, 0x930, 0x3b, 0x938, 0x941, 0x928, 0x93f, 0x3b, 0x930,
+0x92c, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x92e, 0x92c, 0x93e, 0x930, 0x3b, 0x92e, 0x902, 0x917, 0x932, 0x92c, 0x93e, 0x930, 0x3b,
+0x92c, 0x941, 0x926, 0x92c, 0x93e, 0x930, 0x3b, 0x92c, 0x93f, 0x938, 0x925, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x941, 0x916, 0x941,
+0x930, 0x92c, 0x93e, 0x930, 0x3b, 0x938, 0x941, 0x928, 0x93f, 0x92c, 0x93e, 0x930, 0x3b, 0x930, 0x3b, 0x938, 0x3b, 0x92e, 0x902, 0x3b,
+0x92c, 0x941, 0x3b, 0x92c, 0x93f, 0x3b, 0x938, 0x941, 0x3b, 0x938, 0x941, 0x3b, 0x43a, 0x4c0, 0x438, 0x440, 0x430, 0x43d, 0x430, 0x43d,
+0x20, 0x434, 0x435, 0x3b, 0x43e, 0x440, 0x448, 0x43e, 0x442, 0x430, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x448, 0x438, 0x43d, 0x430, 0x440,
+0x438, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x43a, 0x445, 0x430, 0x430, 0x440, 0x438, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x435, 0x430, 0x440,
+0x438, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x43f, 0x4c0, 0x435, 0x440, 0x430, 0x441, 0x43a, 0x430, 0x43d, 0x20, 0x434, 0x435, 0x3b, 0x448,
+0x43e, 0x442, 0x20, 0x434, 0x435, 0x3b, 0x43d, 0x434, 0x2de7, 0x487, 0x467, 0x3b, 0x43f, 0x43d, 0x2de3, 0x435, 0x3b, 0x432, 0x442, 0x43e,
+0x2dec, 0x487, 0x3b, 0x441, 0x440, 0x2de3, 0x435, 0x3b, 0x447, 0x435, 0x2de6, 0x487, 0x3b, 0x43f, 0x467, 0x2de6, 0x487, 0x3b, 0x441, 0xa64b,
+0x2de0, 0x487, 0x3b, 0x43d, 0x435, 0x434, 0x463, 0x301, 0x43b, 0x467, 0x3b, 0x43f, 0x43e, 0x43d, 0x435, 0x434, 0x463, 0x301, 0x43b, 0x44c,
+0x43d, 0x438, 0x43a, 0x44a, 0x3b, 0x432, 0x442, 0x43e, 0x301, 0x440, 0x43d, 0x438, 0x43a, 0x44a, 0x3b, 0x441, 0x440, 0x435, 0x434, 0x430,
+0x300, 0x3b, 0x447, 0x435, 0x442, 0x432, 0x435, 0x440, 0x442, 0x43e, 0x301, 0x43a, 0x44a, 0x3b, 0x43f, 0x467, 0x442, 0x43e, 0x301, 0x43a,
+0x44a, 0x3b, 0x441, 0xa64b, 0x431, 0x431, 0x461, 0x301, 0x442, 0x430, 0x3b, 0x4c, 0x75, 0x6d, 0x3b, 0x4e, 0x6b, 0x6f, 0x3b, 0x4e,
+0x64, 0x79, 0x3b, 0x4e, 0x64, 0x67, 0x3b, 0x4e, 0x6a, 0x77, 0x3b, 0x4e, 0x67, 0x76, 0x3b, 0x4c, 0x75, 0x62, 0x3b, 0x4c,
+0x75, 0x6d, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x4e, 0x6b, 0x6f, 0x64, 0x79, 0x61, 0x3b, 0x4e, 0x64, 0xe0, 0x61, 0x79, 0xe0,
+0x3b, 0x4e, 0x64, 0x61, 0x6e, 0x67, 0xf9, 0x3b, 0x4e, 0x6a, 0xf2, 0x77, 0x61, 0x3b, 0x4e, 0x67, 0xf2, 0x76, 0x79, 0x61,
+0x3b, 0x4c, 0x75, 0x62, 0x69, 0x6e, 0x67, 0x75, 0x3b, 0x4c, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e, 0x3b, 0x4e,
+0x3b, 0x4c, 0x3b, 0x53, 0x6f, 0x6e, 0x3b, 0x4d, 0xe9, 0x69, 0x3b, 0x44, 0xeb, 0x6e, 0x3b, 0x4d, 0xeb, 0x74, 0x3b, 0x44,
+0x6f, 0x6e, 0x3b, 0x46, 0x72, 0x65, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x6f, 0x6e, 0x6e, 0x64, 0x65, 0x67, 0x3b, 0x4d,
+0xe9, 0x69, 0x6e, 0x64, 0x65, 0x67, 0x3b, 0x44, 0xeb, 0x6e, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x3b, 0x4d, 0xeb, 0x74,
+0x74, 0x77, 0x6f, 0x63, 0x68, 0x3b, 0x44, 0x6f, 0x6e, 0x6e, 0x65, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x3b, 0x46, 0x72,
+0x65, 0x69, 0x64, 0x65, 0x67, 0x3b, 0x53, 0x61, 0x6d, 0x73, 0x63, 0x68, 0x64, 0x65, 0x67, 0x3b, 0x53, 0x6f, 0x6e, 0x2e,
+0x3b, 0x4d, 0xe9, 0x69, 0x2e, 0x3b, 0x44, 0xeb, 0x6e, 0x2e, 0x3b, 0x4d, 0xeb, 0x74, 0x2e, 0x3b, 0x44, 0x6f, 0x6e, 0x2e,
+0x3b, 0x46, 0x72, 0x65, 0x2e, 0x3b, 0x53, 0x61, 0x6d, 0x2e, 0x3b, 0x6e, 0x74, 0x73, 0x3b, 0x6b, 0x70, 0x61, 0x3b, 0x67,
+0x68, 0x254, 0x3b, 0x74, 0x254, 0x6d, 0x3b, 0x75, 0x6d, 0x65, 0x3b, 0x67, 0x68, 0x268, 0x3b, 0x64, 0x7a, 0x6b, 0x3b, 0x74,
+0x73, 0x75, 0x294, 0x6e, 0x74, 0x73, 0x268, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x6b, 0x70, 0xe0, 0x3b, 0x74, 0x73, 0x75,
+0x294, 0x75, 0x67, 0x68, 0x254, 0x65, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x74, 0x254, 0x300, 0x6d, 0x6c, 0xf2, 0x3b, 0x74,
+0x73, 0x75, 0x294, 0x75, 0x6d, 0xe8, 0x3b, 0x74, 0x73, 0x75, 0x294, 0x75, 0x67, 0x68, 0x268, 0x302, 0x6d, 0x3b, 0x74, 0x73,
+0x75, 0x294, 0x6e, 0x64, 0x7a, 0x268, 0x6b, 0x254, 0x294, 0x254, 0x3b, 0x6e, 0x3b, 0x6b, 0x3b, 0x67, 0x3b, 0x74, 0x3b, 0x75,
+0x3b, 0x67, 0x3b, 0x64, 0x3b, 0x6e, 0x254, 0x79, 0x3b, 0x6e, 0x6a, 0x61, 0x3b, 0x75, 0x75, 0x6d, 0x3b, 0x14b, 0x67, 0x65,
+0x3b, 0x6d, 0x62, 0x254, 0x3b, 0x6b, 0x254, 0x254, 0x3b, 0x6a, 0x6f, 0x6e, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e, 0x254,
+0x302, 0x79, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6e, 0x6a, 0x61, 0x14b, 0x67, 0x75, 0x6d, 0x62, 0x61, 0x3b, 0x14b, 0x67,
+0x77, 0xe0, 0x20, 0xfb, 0x6d, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x14b, 0x67, 0xea, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20,
+0x6d, 0x62, 0x254, 0x6b, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6b, 0x254, 0x254, 0x3b, 0x14b, 0x67, 0x77, 0xe0, 0x20, 0x6a,
+0xf4, 0x6e, 0x3b, 0x6e, 0x3b, 0x6e, 0x3b, 0x75, 0x3b, 0x14b, 0x3b, 0x6d, 0x3b, 0x6b, 0x3b, 0x6a, 0x3b, 0x41, 0x6c, 0x68,
+0x61, 0x64, 0x69, 0x3b, 0x41, 0x74, 0x69, 0x6e, 0x6e, 0x69, 0x3b, 0x41, 0x74, 0x61, 0x6c, 0x61, 0x61, 0x74, 0x61, 0x3b,
+0x41, 0x6c, 0x61, 0x72, 0x62, 0x61, 0x3b, 0x41, 0x6c, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x41, 0x6c, 0x7a, 0x75,
+0x6d, 0x61, 0x3b, 0x41, 0x73, 0x69, 0x62, 0x74, 0x69, 0x3b, 0x48, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x4c, 0x3b, 0x4d, 0x3b,
+0x5a, 0x3b, 0x53, 0x3b, 0xe9, 0x74, 0x3b, 0x6d, 0x254, 0x301, 0x73, 0x3b, 0x6b, 0x77, 0x61, 0x3b, 0x6d, 0x75, 0x6b, 0x3b,
+0x14b, 0x67, 0x69, 0x3b, 0x257, 0xf3, 0x6e, 0x3b, 0x65, 0x73, 0x61, 0x3b, 0xe9, 0x74, 0x69, 0x3b, 0x6d, 0x254, 0x301, 0x73,
+0xfa, 0x3b, 0x6b, 0x77, 0x61, 0x73, 0xfa, 0x3b, 0x6d, 0x75, 0x6b, 0x254, 0x301, 0x73, 0xfa, 0x3b, 0x14b, 0x67, 0x69, 0x73,
+0xfa, 0x3b, 0x257, 0xf3, 0x6e, 0x25b, 0x73, 0xfa, 0x3b, 0x65, 0x73, 0x61, 0x253, 0x61, 0x73, 0xfa, 0x3b, 0x65, 0x3b, 0x6d,
+0x3b, 0x6b, 0x3b, 0x6d, 0x3b, 0x14b, 0x3b, 0x257, 0x3b, 0x65, 0x3b, 0x44, 0x69, 0x6d, 0x3b, 0x54, 0x65, 0x6e, 0x3b, 0x54,
+0x61, 0x6c, 0x3b, 0x41, 0x6c, 0x61, 0x3b, 0x41, 0x72, 0x61, 0x3b, 0x41, 0x72, 0x6a, 0x3b, 0x53, 0x69, 0x62, 0x3b, 0x44,
+0x69, 0x6d, 0x61, 0x73, 0x3b, 0x54, 0x65, 0x6e, 0x65, 0x14b, 0x3b, 0x54, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b, 0x41, 0x6c,
+0x61, 0x72, 0x62, 0x61, 0x79, 0x3b, 0x41, 0x72, 0x61, 0x6d, 0x69, 0x73, 0x61, 0x79, 0x3b, 0x41, 0x72, 0x6a, 0x75, 0x6d,
+0x61, 0x3b, 0x53, 0x69, 0x62, 0x69, 0x74, 0x69, 0x3b, 0x44, 0x3b, 0x54, 0x3b, 0x54, 0x3b, 0x41, 0x3b, 0x41, 0x3b, 0x41,
+0x3b, 0x53, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x3b, 0x73, 0x6d, 0x62, 0x3b, 0x73, 0x6d, 0x6c,
+0x3b, 0x73, 0x6d, 0x6e, 0x3b, 0x66, 0xfa, 0x6c, 0x3b, 0x73, 0xe9, 0x72, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b,
+0x6d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d,
+0x259, 0x301, 0x62, 0x25b, 0x30c, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259,
+0x301, 0x6c, 0x25b, 0x301, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x259, 0x6c, 0xfa, 0x20, 0x6d, 0x259, 0x301,
+0x6e, 0x79, 0x69, 0x3b, 0x66, 0xfa, 0x6c, 0x61, 0x64, 0xe9, 0x3b, 0x73, 0xe9, 0x72, 0x61, 0x64, 0xe9, 0x3b, 0x73, 0x3b,
+0x6d, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x66, 0x3b, 0x73, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x3b, 0x6c, 0x1dd, 0x6e,
+0x3b, 0x6d, 0x61, 0x61, 0x3b, 0x6d, 0x25b, 0x6b, 0x3b, 0x6a, 0x1dd, 0x1dd, 0x3b, 0x6a, 0xfa, 0x6d, 0x3b, 0x73, 0x61, 0x6d,
+0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x1dd, 0x3b, 0x6c, 0x1dd, 0x6e, 0x64, 0xed, 0x3b, 0x6d, 0x61, 0x61, 0x64, 0xed, 0x3b,
+0x6d, 0x25b, 0x6b, 0x72, 0x25b, 0x64, 0xed, 0x3b, 0x6a, 0x1dd, 0x1dd, 0x64, 0xed, 0x3b, 0x6a, 0xfa, 0x6d, 0x62, 0xe1, 0x3b,
+0x73, 0x61, 0x6d, 0x64, 0xed, 0x3b, 0x73, 0x3b, 0x6c, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b, 0x6a, 0x3b, 0x6a, 0x3b, 0x73, 0x3b,
+0x53, 0x61, 0x62, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a, 0x74, 0x6e, 0x3b, 0x41, 0x72, 0x61, 0x3b,
+0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x53, 0x61, 0x62, 0x61, 0x74, 0x6f, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74,
+0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f,
+0x3b, 0x41, 0x72, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49, 0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75,
+0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x53, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a,
+0x3b, 0x43, 0x79, 0x61, 0x3b, 0x43, 0x6c, 0x61, 0x3b, 0x43, 0x7a, 0x69, 0x3b, 0x43, 0x6b, 0x6f, 0x3b, 0x43, 0x6b, 0x61,
+0x3b, 0x43, 0x67, 0x61, 0x3b, 0x43, 0x7a, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x2019, 0x79, 0x61, 0x6b, 0x6b, 0x65, 0x3b, 0x43,
+0x6f, 0x6d, 0x6c, 0x61, 0x61, 0x257, 0x69, 0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x7a, 0x79, 0x69, 0x69, 0x257, 0x69, 0x69, 0x3b,
+0x43, 0x6f, 0x6d, 0x6b, 0x6f, 0x6c, 0x6c, 0x65, 0x3b, 0x43, 0x6f, 0x6d, 0x6b, 0x61, 0x6c, 0x64, 0x1dd, 0x253, 0x6c, 0x69,
+0x69, 0x3b, 0x43, 0x6f, 0x6d, 0x67, 0x61, 0x69, 0x73, 0x75, 0x75, 0x3b, 0x43, 0x6f, 0x6d, 0x7a, 0x79, 0x65, 0x253, 0x73,
+0x75, 0x75, 0x3b, 0x59, 0x3b, 0x4c, 0x3b, 0x5a, 0x3b, 0x4f, 0x3b, 0x41, 0x3b, 0x47, 0x3b, 0x45, 0x3b, 0x73, 0x254, 0x301,
+0x6e, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x3b, 0x73, 0x6d, 0x62, 0x3b, 0x73, 0x6d, 0x6c, 0x3b, 0x73, 0x6d, 0x6e, 0x3b, 0x6d,
+0x62, 0x73, 0x3b, 0x73, 0x61, 0x73, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x3b, 0x6d, 0x254, 0x301, 0x6e, 0x64, 0x254,
+0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x62, 0x61, 0x3b, 0x73, 0x254,
+0x301, 0x6e, 0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x6c, 0x61, 0x6c, 0x3b, 0x73, 0x254, 0x301, 0x6e,
+0x64, 0x254, 0x20, 0x6d, 0x61, 0x66, 0xfa, 0x20, 0x6d, 0xe1, 0x6e, 0x61, 0x3b, 0x6d, 0x61, 0x62, 0xe1, 0x67, 0xe1, 0x20,
+0x6d, 0xe1, 0x20, 0x73, 0x75, 0x6b, 0x75, 0x6c, 0x3b, 0x73, 0xe1, 0x73, 0x61, 0x64, 0x69, 0x3b, 0x73, 0x3b, 0x6d, 0x3b,
+0x73, 0x3b, 0x73, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x73, 0x3b, 0x43, 0xe4, 0x14b, 0x3b, 0x4a, 0x69, 0x65, 0x63, 0x3b, 0x52,
+0x25b, 0x77, 0x3b, 0x44, 0x69, 0x254, 0x331, 0x6b, 0x3b, 0x14a, 0x75, 0x61, 0x61, 0x6e, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65,
+0x63, 0x3b, 0x42, 0xe4, 0x6b, 0x25b, 0x6c, 0x3b, 0x43, 0xe4, 0x14b, 0x20, 0x6b, 0x75, 0x254, 0x74, 0x68, 0x3b, 0x4a, 0x69,
+0x65, 0x63, 0x20, 0x6c, 0x61, 0x331, 0x74, 0x3b, 0x52, 0x25b, 0x77, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x44, 0x69,
+0x254, 0x331, 0x6b, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x14a, 0x75, 0x61, 0x61, 0x6e, 0x20, 0x6c, 0xe4, 0x74, 0x6e,
+0x69, 0x3b, 0x44, 0x68, 0x69, 0x65, 0x65, 0x63, 0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x42, 0xe4, 0x6b, 0x25b, 0x6c,
+0x20, 0x6c, 0xe4, 0x74, 0x6e, 0x69, 0x3b, 0x43, 0x3b, 0x4a, 0x3b, 0x52, 0x3b, 0x44, 0x3b, 0x14a, 0x3b, 0x44, 0x3b, 0x42,
+0x3b, 0x431, 0x441, 0x3b, 0x431, 0x43d, 0x3b, 0x43e, 0x43f, 0x3b, 0x441, 0x44d, 0x3b, 0x447, 0x43f, 0x3b, 0x431, 0x44d, 0x3b, 0x441,
+0x431, 0x3b, 0x431, 0x430, 0x441, 0x43a, 0x44b, 0x4bb, 0x44b, 0x430, 0x43d, 0x43d, 0x44c, 0x430, 0x3b, 0x431, 0x44d, 0x43d, 0x438, 0x434,
+0x438, 0x44d, 0x43d, 0x43d, 0x44c, 0x438, 0x43a, 0x3b, 0x43e, 0x43f, 0x442, 0x443, 0x43e, 0x440, 0x443, 0x43d, 0x43d, 0x44c, 0x443, 0x43a,
+0x3b, 0x441, 0x44d, 0x440, 0x44d, 0x434, 0x44d, 0x3b, 0x447, 0x44d, 0x43f, 0x43f, 0x438, 0x44d, 0x440, 0x3b, 0x411, 0x44d, 0x44d, 0x442,
+0x438, 0x4a5, 0x441, 0x44d, 0x3b, 0x441, 0x443, 0x431, 0x443, 0x43e, 0x442, 0x430, 0x3b, 0x411, 0x3b, 0x411, 0x3b, 0x41e, 0x3b, 0x421,
+0x3b, 0x427, 0x3b, 0x411, 0x3b, 0x421, 0x3b, 0x4d, 0x75, 0x6c, 0x3b, 0x4a, 0x74, 0x74, 0x3b, 0x4a, 0x6e, 0x6e, 0x3b, 0x4a,
+0x74, 0x6e, 0x3b, 0x41, 0x6c, 0x68, 0x3b, 0x49, 0x6a, 0x75, 0x3b, 0x4a, 0x6d, 0x6f, 0x3b, 0x4d, 0x75, 0x6c, 0x75, 0x6e,
+0x67, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x74, 0x75, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6e, 0x6e, 0x65, 0x3b,
+0x4a, 0x75, 0x6d, 0x61, 0x74, 0x61, 0x6e, 0x6f, 0x3b, 0x41, 0x6c, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x73, 0x69, 0x3b, 0x49,
+0x6a, 0x75, 0x6d, 0x61, 0x61, 0x3b, 0x4a, 0x75, 0x6d, 0x61, 0x6d, 0x6f, 0x73, 0x69, 0x3b, 0x4d, 0x3b, 0x4a, 0x3b, 0x4a,
+0x3b, 0x4a, 0x3b, 0x41, 0x3b, 0x49, 0x3b, 0x4a, 0x3b, 0xa55e, 0xa54c, 0xa535, 0x3b, 0xa5f3, 0xa5e1, 0xa609, 0x3b, 0xa55a, 0xa55e, 0xa55a,
+0x3b, 0xa549, 0xa55e, 0xa552, 0x3b, 0xa549, 0xa524, 0xa546, 0xa562, 0x3b, 0xa549, 0xa524, 0xa540, 0xa56e, 0x3b, 0xa53b, 0xa52c, 0xa533, 0x3b, 0x6c,
+0x61, 0x68, 0x61, 0x64, 0x69, 0x3b, 0x74, 0x25b, 0x25b, 0x6e, 0x25b, 0x25b, 0x3b, 0x74, 0x61, 0x6c, 0x61, 0x74, 0x61, 0x3b,
+0x61, 0x6c, 0x61, 0x62, 0x61, 0x3b, 0x61, 0x69, 0x6d, 0x69, 0x73, 0x61, 0x3b, 0x61, 0x69, 0x6a, 0x69, 0x6d, 0x61, 0x3b,
+0x73, 0x69, 0x253, 0x69, 0x74, 0x69, 0x3b, 0x53, 0x75, 0x6e, 0x3b, 0x4d, 0xe4, 0x6e, 0x3b, 0x5a, 0x69, 0x161, 0x3b, 0x4d,
+0x69, 0x74, 0x3b, 0x46, 0x72, 0xf3, 0x3b, 0x46, 0x72, 0x69, 0x3b, 0x53, 0x61, 0x6d, 0x3b, 0x53, 0x75, 0x6e, 0x6e, 0x74,
+0x61, 0x67, 0x3b, 0x4d, 0xe4, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x5a, 0x69, 0x161, 0x74, 0x61, 0x67, 0x3b, 0x4d, 0x69, 0x74,
+0x74, 0x77, 0x75, 0x10d, 0x3b, 0x46, 0x72, 0xf3, 0x6e, 0x74, 0x61, 0x67, 0x3b, 0x46, 0x72, 0x69, 0x74, 0x61, 0x67, 0x3b,
+0x53, 0x61, 0x6d, 0x161, 0x74, 0x61, 0x67, 0x3b, 0x53, 0x3b, 0x4d, 0x3b, 0x5a, 0x3b, 0x4d, 0x3b, 0x46, 0x3b, 0x46, 0x3b,
+0x53, 0x3b, 0x73, 0x64, 0x3b, 0x6d, 0x64, 0x3b, 0x6d, 0x77, 0x3b, 0x65, 0x74, 0x3b, 0x6b, 0x6c, 0x3b, 0x66, 0x6c, 0x3b,
+0x73, 0x73, 0x3b, 0x73, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x25b, 0x3b, 0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65, 0x3b, 0x6d, 0x75,
+0xe1, 0x6e, 0x79, 0xe1, 0x14b, 0x6d, 0xf3, 0x6e, 0x64, 0x69, 0x65, 0x3b, 0x6d, 0x65, 0x74, 0xfa, 0x6b, 0x70, 0xed, 0xe1,
+0x70, 0x25b, 0x3b, 0x6b, 0xfa, 0x70, 0xe9, 0x6c, 0x69, 0x6d, 0x65, 0x74, 0xfa, 0x6b, 0x70, 0x69, 0x61, 0x70, 0x25b, 0x3b,
+0x66, 0x65, 0x6c, 0xe9, 0x74, 0x65, 0x3b, 0x73, 0xe9, 0x73, 0x65, 0x6c, 0xe9, 0x3b, 0x73, 0x3b, 0x6d, 0x3b, 0x6d, 0x3b,
+0x65, 0x3b, 0x6b, 0x3b, 0x66, 0x3b, 0x73, 0x3b, 0x64, 0x6f, 0x6d, 0x3b, 0x6c, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x72, 0x3b,
+0x6d, 0x69, 0xe9, 0x3b, 0x78, 0x75, 0x65, 0x3b, 0x76, 0x69, 0x65, 0x3b, 0x73, 0xe1, 0x62, 0x3b, 0x64, 0x6f, 0x6d, 0x69,
+0x6e, 0x67, 0x75, 0x3b, 0x6c, 0x6c, 0x75, 0x6e, 0x65, 0x73, 0x3b, 0x6d, 0x61, 0x72, 0x74, 0x65, 0x73, 0x3b, 0x6d, 0x69,
+0xe9, 0x72, 0x63, 0x6f, 0x6c, 0x65, 0x73, 0x3b, 0x78, 0x75, 0x65, 0x76, 0x65, 0x73, 0x3b, 0x76, 0x69, 0x65, 0x6e, 0x72,
+0x65, 0x73, 0x3b, 0x73, 0xe1, 0x62, 0x61, 0x64, 0x75, 0x3b, 0x53, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x4d, 0x254, 0x301,
+0x6e, 0x64, 0x69, 0x3b, 0xc1, 0x70, 0x74, 0x61, 0x20, 0x4d, 0x254, 0x301, 0x6e, 0x64, 0x69, 0x3b, 0x57, 0x25b, 0x301, 0x6e,
+0x25b, 0x73, 0x25b, 0x64, 0x25b, 0x3b, 0x54, 0x254, 0x301, 0x73, 0x25b, 0x64, 0x25b, 0x3b, 0x46, 0x25b, 0x6c, 0xe2, 0x79, 0x25b,
+0x64, 0x25b, 0x3b, 0x53, 0xe1, 0x73, 0x69, 0x64, 0x25b, 0x3b, 0x53, 0x254, 0x301, 0x3b, 0x4d, 0x254, 0x301, 0x3b, 0xc1, 0x4d,
+0x3b, 0x57, 0x25b, 0x301, 0x3b, 0x54, 0x254, 0x301, 0x3b, 0x46, 0x25b, 0x3b, 0x53, 0xe1, 0x3b, 0x73, 0x254, 0x6e, 0x64, 0x69,
+0x3b, 0x6c, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x6d, 0x61, 0x72, 0x64, 0x69, 0x3b, 0x6d, 0x25b, 0x72, 0x6b, 0x25b, 0x72, 0x25b,
+0x64, 0x69, 0x3b, 0x79, 0x65, 0x64, 0x69, 0x3b, 0x76, 0x61, 0x14b, 0x64, 0x25b, 0x72, 0x25b, 0x64, 0x69, 0x3b, 0x6d, 0x254,
+0x6e, 0x254, 0x20, 0x73, 0x254, 0x6e, 0x64, 0x69, 0x3b, 0x73, 0x6f, 0x3b, 0x6c, 0x75, 0x3b, 0x6d, 0x61, 0x3b, 0x6d, 0x25b,
+0x3b, 0x79, 0x65, 0x3b, 0x76, 0x61, 0x3b, 0x6d, 0x73, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x31, 0x3b, 0x41, 0x6e, 0x65,
+0x67, 0x20, 0x32, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x33, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x34, 0x3b, 0x41, 0x6e,
+0x65, 0x67, 0x20, 0x35, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x36, 0x3b, 0x41, 0x6e, 0x65, 0x67, 0x20, 0x37, 0x3b, 0x41,
+0x31, 0x3b, 0x41, 0x32, 0x3b, 0x41, 0x33, 0x3b, 0x41, 0x34, 0x3b, 0x41, 0x35, 0x3b, 0x41, 0x36, 0x3b, 0x41, 0x37, 0x3b,
+0x6c, 0x79, 0x25b, 0x2bc, 0x25b, 0x301, 0x20, 0x73, 0x1e85, 0xed, 0x14b, 0x74, 0xe8, 0x3b, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c,
+0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x62, 0x254, 0x301, 0x254, 0x6e, 0x74, 0xe8, 0x20, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6c,
+0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x74, 0x73, 0xe8, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b,
+0x6d, 0x62, 0x254, 0x301, 0x254, 0x6e, 0x74, 0xe8, 0x20, 0x74, 0x73, 0x65, 0x74, 0x73, 0x25b, 0x300, 0x25b, 0x20, 0x6c, 0x79,
+0x25b, 0x30c, 0x2bc, 0x3b, 0x6d, 0x76, 0x66, 0xf2, 0x20, 0x6d, 0xe0, 0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b,
+0x6d, 0xe0, 0x67, 0x61, 0x20, 0x6c, 0x79, 0x25b, 0x30c, 0x2bc, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77, 0x61, 0x6b,
+0x21f, 0x61, 0x14b, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x77, 0x61, 0x14b, 0x17e, 0x69, 0x3b, 0x41, 0x14b, 0x70, 0xe9,
+0x74, 0x75, 0x6e, 0x75, 0x14b, 0x70, 0x61, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x79, 0x61, 0x6d, 0x6e, 0x69, 0x3b,
+0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x74, 0x6f, 0x70, 0x61, 0x3b, 0x41, 0x14b, 0x70, 0xe9, 0x74, 0x75, 0x7a, 0x61, 0x70,
+0x74, 0x61, 0x14b, 0x3b, 0x4f, 0x77, 0xe1, 0x14b, 0x67, 0x79, 0x75, 0x17e, 0x61, 0x17e, 0x61, 0x70, 0x69, 0x3b, 0x41, 0x3b,
+0x57, 0x3b, 0x4e, 0x3b, 0x59, 0x3b, 0x54, 0x3b, 0x5a, 0x3b, 0x4f, 0x3b, 0x2d30, 0x2d59, 0x2d30, 0x2d4e, 0x2d30, 0x2d59, 0x3b, 0x2d30,
+0x2d62, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4f, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d, 0x2d55, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d3d,
+0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d4e, 0x2d61, 0x2d30, 0x2d59, 0x3b, 0x2d30, 0x2d59, 0x2d49, 0x2d39, 0x2d62, 0x2d30, 0x2d59, 0x3b,
+0x6cc, 0x6d5, 0x6a9, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x62f, 0x648, 0x648, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x633, 0x6ce,
+0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x686, 0x648, 0x627, 0x631, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x67e, 0x6ce, 0x646, 0x62c,
+0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x6be, 0x6d5, 0x6cc, 0x646, 0x6cc, 0x3b, 0x634, 0x6d5, 0x645, 0x645, 0x6d5, 0x3b, 0x6cc, 0x3b,
+0x62f, 0x3b, 0x633, 0x3b, 0x686, 0x3b, 0x67e, 0x3b, 0x6be, 0x3b, 0x634, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x70, 0xf3, 0x6e, 0x3b,
+0x77, 0x61, 0x142, 0x3b, 0x73, 0x72, 0x6a, 0x3b, 0x73, 0x74, 0x77, 0x3b, 0x70, 0x11b, 0x74, 0x3b, 0x73, 0x6f, 0x62, 0x3b,
+0x6e, 0x6a, 0x65, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e, 0x6a, 0x65, 0x17a, 0x65, 0x6c, 0x65, 0x3b, 0x77, 0x61,
+0x142, 0x74, 0x6f, 0x72, 0x61, 0x3b, 0x73, 0x72, 0x6a, 0x6f, 0x64, 0x61, 0x3b, 0x73, 0x74, 0x77, 0xf3, 0x72, 0x74, 0x6b,
+0x3b, 0x70, 0x11b, 0x74, 0x6b, 0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x73,
+0x3b, 0x73, 0x3b, 0x70, 0x3b, 0x73, 0x3b, 0x6e, 0x6a, 0x65, 0x3b, 0x70, 0xf3, 0x6e, 0x3b, 0x77, 0x75, 0x74, 0x3b, 0x73,
+0x72, 0x6a, 0x3b, 0x161, 0x74, 0x77, 0x3b, 0x70, 0x6a, 0x61, 0x3b, 0x73, 0x6f, 0x62, 0x3b, 0x6e, 0x6a, 0x65, 0x64, 0x17a,
+0x65, 0x6c, 0x61, 0x3b, 0x70, 0xf3, 0x6e, 0x64, 0x17a, 0x65, 0x6c, 0x61, 0x3b, 0x77, 0x75, 0x74, 0x6f, 0x72, 0x61, 0x3b,
+0x73, 0x72, 0x6a, 0x65, 0x64, 0x61, 0x3b, 0x161, 0x74, 0x77, 0xf3, 0x72, 0x74, 0x6b, 0x3b, 0x70, 0x6a, 0x61, 0x74, 0x6b,
+0x3b, 0x73, 0x6f, 0x62, 0x6f, 0x74, 0x61, 0x3b, 0x6e, 0x3b, 0x70, 0x3b, 0x77, 0x3b, 0x73, 0x3b, 0x161, 0x3b, 0x70, 0x3b,
+0x73, 0x3b, 0x70, 0x61, 0x73, 0x3b, 0x76, 0x75, 0x6f, 0x3b, 0x6d, 0x61, 0x6a, 0x3b, 0x6b, 0x6f, 0x73, 0x3b, 0x74, 0x75,
+0x6f, 0x3b, 0x76, 0xe1, 0x73, 0x3b, 0x6c, 0xe1, 0x76, 0x3b, 0x70, 0x61, 0x73, 0x65, 0x70, 0x65, 0x69, 0x76, 0x69, 0x3b,
+0x76, 0x75, 0x6f, 0x73, 0x73, 0x61, 0x72, 0x67, 0xe2, 0x3b, 0x6d, 0x61, 0x6a, 0x65, 0x62, 0x61, 0x72, 0x67, 0xe2, 0x3b,
+0x6b, 0x6f, 0x73, 0x6b, 0x6f, 0x6b, 0x6b, 0x6f, 0x3b, 0x74, 0x75, 0x6f, 0x72, 0xe2, 0x73, 0x74, 0xe2, 0x68, 0x3b, 0x76,
+0xe1, 0x73, 0x74, 0x75, 0x70, 0x70, 0x65, 0x69, 0x76, 0x69, 0x3b, 0x6c, 0xe1, 0x76, 0x75, 0x72, 0x64, 0xe2, 0x68, 0x3b,
+0x70, 0x61, 0x73, 0x65, 0x70, 0x65, 0x65, 0x69, 0x76, 0x69, 0x3b, 0x76, 0x75, 0x6f, 0x73, 0x73, 0x61, 0x61, 0x72, 0x67,
+0xe2, 0x3b, 0x6d, 0x61, 0x6a, 0x65, 0x62, 0x61, 0x61, 0x72, 0x67, 0xe2, 0x3b, 0x6b, 0x6f, 0x73, 0x6b, 0x6f, 0x68, 0x6f,
+0x3b, 0x74, 0x75, 0x6f, 0x72, 0xe2, 0x73, 0x74, 0x75, 0x76, 0x3b, 0x76, 0xe1, 0x73, 0x74, 0x75, 0x70, 0x70, 0x65, 0x65,
+0x69, 0x76, 0x69, 0x3b, 0x6c, 0xe1, 0x76, 0x75, 0x72, 0x64, 0x75, 0x76, 0x3b, 0x70, 0x3b, 0x56, 0x3b, 0x4d, 0x3b, 0x4b,
+0x3b, 0x54, 0x3b, 0x56, 0x3b, 0x4c, 0x3b
+};
+
+static const ushort byte_unit_data[] = {
+0x62, 0x79, 0x74, 0x65, 0x73, 0x6b, 0x42, 0x3b, 0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b,
+0x45, 0x42, 0x4b, 0x69, 0x42, 0x3b, 0x4d, 0x69, 0x42, 0x3b, 0x47, 0x69, 0x42, 0x3b, 0x54, 0x69, 0x42, 0x3b, 0x50, 0x69,
+0x42, 0x3b, 0x45, 0x69, 0x42, 0x62, 0x79, 0x74, 0x65, 0x67, 0x72, 0x65, 0x70, 0x65, 0x62, 0x61, 0x6a, 0x74, 0x1263, 0x12ed,
+0x1275, 0x12aa, 0x1263, 0x3b, 0x121c, 0x130b, 0x1263, 0x12ed, 0x1275, 0x3b, 0x130a, 0x1263, 0x3b, 0x1274, 0x122b, 0x1263, 0x12ed, 0x1275, 0x3b, 0x50,
+0x42, 0x3b, 0x45, 0x42, 0x628, 0x627, 0x64a, 0x62a, 0x643, 0x64a, 0x644, 0x648, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x645, 0x64a, 0x63a,
+0x627, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x63a, 0x64a, 0x63a, 0x627, 0x628, 0x627, 0x64a, 0x62a, 0x3b, 0x62a, 0x64a, 0x631, 0x627, 0x628,
+0x627, 0x64a, 0x62a, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x562, 0x561, 0x575, 0x569, 0x565, 0x580, 0x56f, 0x532, 0x3b, 0x544, 0x532,
+0x3b, 0x533, 0x532, 0x3b, 0x54f, 0x532, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x62, 0x61, 0x79, 0x74, 0x62, 0x79, 0x74, 0x65,
+0x2d, 0x61, 0x6b, 0x9ac, 0x9be, 0x987, 0x99f, 0x6f, 0x6b, 0x74, 0x65, 0x64, 0x6f, 0xf9, 0x6b, 0x6f, 0x3b, 0x4d, 0x6f, 0x3b,
+0x47, 0x6f, 0x3b, 0x54, 0x6f, 0x3b, 0x50, 0x6f, 0x3b, 0x45, 0x6f, 0x4b, 0x69, 0x6f, 0x3b, 0x4d, 0x69, 0x6f, 0x3b, 0x47,
+0x69, 0x6f, 0x3b, 0x54, 0x69, 0x6f, 0x3b, 0x50, 0x69, 0x6f, 0x3b, 0x45, 0x69, 0x6f, 0x431, 0x430, 0x439, 0x442, 0x43e, 0x432,
+0x435, 0x1018, 0x102d, 0x102f, 0x1000, 0x103a, 0x431, 0x430, 0x439, 0x442, 0x44b, 0x41a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b,
+0x422, 0x411, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x1794, 0x17c3, 0x5b57, 0x8282, 0x5343, 0x5b57, 0x8282, 0x3b, 0x5146, 0x5b57, 0x8282, 0x3b,
+0x5409, 0x5b57, 0x8282, 0x3b, 0x592a, 0x5b57, 0x8282, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x4f4d, 0x5143, 0x7d44, 0x62, 0x61, 0x6a, 0x74,
+0x6f, 0x76, 0x69, 0x62, 0x61, 0x6a, 0x74, 0x79, 0x62, 0x61, 0x69, 0x64, 0x69, 0x64, 0x62, 0xfd, 0x74, 0x4b, 0x42, 0x3b,
+0x4d, 0x42, 0x3b, 0x47, 0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x74, 0x61, 0x76, 0x75, 0x74, 0x6b,
+0x74, 0x3b, 0x4d, 0x74, 0x3b, 0x47, 0x74, 0x3b, 0x54, 0x74, 0x3b, 0x50, 0x74, 0x3b, 0x45, 0x74, 0x4b, 0x69, 0x74, 0x3b,
+0x4d, 0x69, 0x74, 0x3b, 0x47, 0x69, 0x74, 0x3b, 0x54, 0x69, 0x74, 0x3b, 0x50, 0x69, 0x74, 0x3b, 0x45, 0x69, 0x74, 0x6f,
+0x63, 0x74, 0x65, 0x74, 0x73, 0x62, 0x61, 0x69, 0x64, 0x68, 0x74, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x10d9, 0x10d1, 0x10d0, 0x10d8,
+0x10e2, 0x10d8, 0x3b, 0x10db, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10d2, 0x10d1, 0x10d0, 0x10d8, 0x10e2, 0x10d8, 0x3b, 0x10e2, 0x10d1, 0x10d0,
+0x10d8, 0x10e2, 0x10d8, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x42, 0x79, 0x74, 0x65, 0x73, 0xaac, 0xabe, 0xa87, 0xa9f, 0x5d1, 0x5ea,
+0x5d9, 0x5dd, 0x92c, 0x93e, 0x907, 0x91f, 0x62, 0xe1, 0x6a, 0x74, 0x62, 0xe6, 0x74, 0x69, 0x62, 0x65, 0x61, 0x72, 0x74, 0x61,
+0x30d0, 0x30a4, 0x30c8, 0xcac, 0xcc8, 0xc9f, 0xccd, 0x200c, 0xc97, 0xcb3, 0xcc1, 0xc95, 0xcbf, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xcae, 0xcc6,
+0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xc97, 0xcbf, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0xc9f, 0xcc6, 0x2e, 0xcac, 0xcc8, 0x2e, 0x3b, 0x50,
+0x42, 0x3b, 0x45, 0x42, 0x431, 0x430, 0x439, 0x442, 0x43a, 0x411, 0x3b, 0x4d, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x54, 0x411, 0x3b,
+0x50, 0x411, 0x3b, 0x45, 0x411, 0x4b, 0x69, 0x411, 0x3b, 0x4d, 0x69, 0x411, 0x3b, 0x47, 0x69, 0x411, 0x3b, 0x54, 0x69, 0x411,
+0x3b, 0x50, 0x69, 0x411, 0x3b, 0x45, 0x69, 0x411, 0x43a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x413, 0x411, 0x3b, 0x422, 0x411, 0x3b,
+0x50, 0x42, 0x3b, 0x45, 0x42, 0xbc14, 0xc774, 0xd2b8, 0x62, 0x61, 0x69, 0x74, 0x69, 0x62, 0x61, 0x69, 0x74, 0x61, 0x69, 0x431,
+0x430, 0x458, 0x442, 0x438, 0x62, 0x61, 0x69, 0x74, 0xd2c, 0xd48, 0xd31, 0xd4d, 0xd31, 0xd4d, 0xd15, 0xd3f, 0x2e, 0xd2c, 0xd3f, 0x2e,
+0x3b, 0xd2e, 0xd46, 0x2e, 0xd2c, 0xd48, 0x2e, 0x3b, 0xd1c, 0xd3f, 0x2e, 0xd2c, 0xd48, 0x2e, 0x3b, 0xd1f, 0xd3f, 0xd2c, 0xd3f, 0x3b,
+0x50, 0x42, 0x3b, 0x45, 0x42, 0x628, 0x627, 0x6cc, 0x62a, 0x6a9, 0x6cc, 0x644, 0x648, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x645, 0x6af,
+0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x6af, 0x6cc, 0x6af, 0x627, 0x628, 0x627, 0x6cc, 0x62a, 0x3b, 0x62a, 0x631, 0x627, 0x628, 0x627,
+0x6cc, 0x62a, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0xa2c, 0xa3e, 0xa07, 0xa1f, 0x62, 0x79, 0x21b, 0x69, 0x431, 0x430, 0x458, 0x442,
+0x43e, 0x432, 0x438, 0xdb6, 0xdba, 0xdd2, 0xda7, 0xdca, 0xd9a, 0xdd2, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xdb8, 0xdd9, 0xdb6, 0x20,
+0x7b, 0x30, 0x7d, 0x3b, 0xd9c, 0xdd2, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0xda7, 0xdd9, 0xdb6, 0x20, 0x7b, 0x30, 0x7d, 0x3b,
+0x50, 0x42, 0x3b, 0x45, 0x42, 0x6b, 0x69, 0x6c, 0x6f, 0x62, 0x61, 0x69, 0x74, 0x69, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d,
+0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x47, 0x42, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x74, 0x65, 0x72, 0x61, 0x62, 0x61, 0x69,
+0x74, 0x69, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0xbaa, 0xbc8, 0xb9f, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0xc2c,
+0xc48, 0xc1f, 0xc4d, 0x200c, 0xc32, 0xc41, 0xc15, 0xc47, 0xc2c, 0xc40, 0x3b, 0xc0e, 0xc2e, 0xc4d, 0x200c, 0xc2c, 0xc3f, 0x3b, 0xc1c, 0xc40,
+0xc2c, 0xc40, 0x3b, 0xc1f, 0xc40, 0xc2c, 0xc40, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0xe44, 0xe1a, 0xe15, 0xe4c, 0x70, 0x61, 0x69,
+0x74, 0x69, 0x6b, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30,
+0x7d, 0x3b, 0x47, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x54, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30,
+0x7d, 0x3b, 0x50, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30,
+0x7d, 0x4b, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x4d, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b,
+0x30, 0x7d, 0x3b, 0x47, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x54, 0x69, 0x42, 0x20, 0x2bb, 0x65,
+0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x50, 0x69, 0x42, 0x20, 0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x3b, 0x45, 0x69, 0x42, 0x20,
+0x2bb, 0x65, 0x20, 0x7b, 0x30, 0x7d, 0x62, 0x61, 0xfd, 0x74, 0x431, 0x430, 0x439, 0x442, 0x438, 0x62, 0x65, 0x69, 0x74, 0x69,
+0x61, 0x75, 0x13d7, 0x13d3, 0x13cd, 0x13a6, 0x13b5, 0x13a9, 0x431, 0x430, 0x430, 0x439, 0x442, 0x43a, 0x411, 0x3b, 0x41c, 0x411, 0x3b, 0x47,
+0x42, 0x3b, 0x54, 0x42, 0x3b, 0x50, 0x42, 0x3b, 0x45, 0x42, 0x62, 0x79, 0x74, 0x65, 0x79
};
static const ushort am_data[] = {
0x41, 0x4d, 0x57, 0x44, 0x76, 0x6d, 0x2e, 0x65, 0x20, 0x70, 0x61, 0x72, 0x61, 0x64, 0x69, 0x74, 0x65, 0x73, 0x1325, 0x12cb,
-0x1275, 0x635, 0x9aa, 0x9c2, 0x9f0, 0x9cd, 0x9ac, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0x9aa, 0x9c2, 0x9b0, 0x9cd, 0x9ac, 0x9be, 0x9b9, 0x9cd, 0x9a3,
-0xf66, 0xf94, 0xf0b, 0xf46, 0xf0b, 0x41, 0x2e, 0x4d, 0x2e, 0x43f, 0x440, 0x2e, 0x43e, 0x431, 0x2e, 0x1014, 0x1036, 0x1014, 0x1000, 0x103a,
-0x434, 0x430, 0x20, 0x43f, 0x430, 0x45e, 0x434, 0x43d, 0x44f, 0x1796, 0x17d2, 0x179a, 0x17b9, 0x1780, 0x61, 0x2e, 0x20, 0x6d, 0x2e, 0x4e0a,
-0x5348, 0x64, 0x6f, 0x70, 0x2e, 0x61, 0x2e, 0x6d, 0x2e, 0x61, 0x6d, 0x61, 0x70, 0x2e, 0x6d, 0x76, 0x6f, 0x72, 0x6d, 0x2e,
-0x3c0, 0x2e, 0x3bc, 0x2e, 0x5dc, 0x5e4, 0x5e0, 0x5d4, 0x5f4, 0x5e6, 0x92a, 0x942, 0x930, 0x94d, 0x935, 0x93e, 0x939, 0x94d, 0x928, 0x64,
-0x65, 0x2e, 0x66, 0x2e, 0x68, 0x2e, 0x5348, 0x524d, 0xcaa, 0xcc2, 0xcb0, 0xccd, 0xcb5, 0xcbe, 0xcb9, 0xccd, 0xca8, 0x442, 0x430, 0x4a3,
-0x493, 0x44b, 0x442, 0x430, 0x4a3, 0x43a, 0x44b, 0xc624, 0xc804, 0x5a, 0x2e, 0x4d, 0x55, 0x2e, 0xe81, 0xec8, 0xead, 0xe99, 0xe97, 0xec8,
-0xebd, 0xe87, 0x70, 0x72, 0x69, 0x65, 0x6b, 0x161, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x6e, 0x74, 0x254, 0x301,
-0x6e, 0x67, 0x254, 0x301, 0x70, 0x72, 0x69, 0x65, 0x161, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x440, 0x435, 0x442, 0x43f, 0x43b, 0x430,
-0x434, 0x43d, 0x435, 0x50, 0x47, 0x92e, 0x2e, 0x92a, 0x942, 0x2e, 0x4ae, 0x4e8, 0x63a, 0x2e, 0x645, 0x2e, 0x642, 0x628, 0x644, 0x200c,
+0x1275, 0x635, 0x9aa, 0x9c2, 0x9f0, 0x9cd, 0x9ac, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0x410, 0x41c, 0xf66, 0xf94, 0xf0b, 0xf46, 0xf0b, 0x41, 0x2e,
+0x4d, 0x2e, 0x43f, 0x440, 0x2e, 0x43e, 0x431, 0x2e, 0x1014, 0x1036, 0x1014, 0x1000, 0x103a, 0x61, 0x2e, 0x20, 0x6d, 0x2e, 0x4e0a, 0x5348,
+0x64, 0x6f, 0x70, 0x2e, 0x61, 0x2e, 0x6d, 0x2e, 0x61, 0x6d, 0x61, 0x70, 0x2e, 0x6d, 0x61, 0x74, 0x69, 0x6e, 0x6d, 0x76,
+0x6f, 0x72, 0x6d, 0x2e, 0x3c0, 0x2e, 0x3bc, 0x2e, 0x5dc, 0x5e4, 0x5e0, 0x5d4, 0x5f4, 0x5e6, 0x92a, 0x942, 0x930, 0x94d, 0x935, 0x93e,
+0x939, 0x94d, 0x928, 0x64, 0x65, 0x2e, 0x66, 0x2e, 0x68, 0x2e, 0x5348, 0x524d, 0xcaa, 0xcc2, 0xcb0, 0xccd, 0xcb5, 0xcbe, 0xcb9, 0xccd,
+0xca8, 0x442, 0x430, 0x4a3, 0x43a, 0x44b, 0xc624, 0xc804, 0x5a, 0x2e, 0x4d, 0x55, 0x2e, 0xe81, 0xec8, 0xead, 0xe99, 0xe97, 0xec8, 0xebd,
+0xe87, 0x70, 0x72, 0x69, 0x65, 0x6b, 0x161, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x6e, 0x74, 0x254, 0x301, 0x6e,
+0x67, 0x254, 0x301, 0x70, 0x72, 0x69, 0x65, 0x161, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x440, 0x435, 0x442, 0x43f, 0x43b, 0x430, 0x434,
+0x43d, 0x435, 0x50, 0x47, 0x92e, 0x2e, 0x92a, 0x942, 0x2e, 0x4af, 0x2e, 0x4e9, 0x63a, 0x2e, 0x645, 0x2e, 0x642, 0x628, 0x644, 0x200c,
0x627, 0x632, 0x638, 0x647, 0x631, 0x64, 0x61, 0x20, 0x6d, 0x61, 0x6e, 0x68, 0xe3, 0xa2a, 0xa42, 0x2e, 0xa26, 0xa41, 0x2e, 0x414,
-0x41f, 0x4e, 0x44, 0x43f, 0x440, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x70, 0x72, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e,
-0x65, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x440, 0x430, 0x437, 0x43c, 0x4d5, 0xdb4, 0xdd9, 0x2e, 0xdc0,
-0x2e, 0x73, 0x6e, 0x2e, 0x79, 0x61, 0x20, 0x61, 0x73, 0x75, 0x62, 0x75, 0x79, 0x69, 0x66, 0x6d, 0xbae, 0xbc1, 0xbb1, 0xbcd,
-0xbaa, 0xb95, 0xbb2, 0xbcd, 0x5b, 0x41, 0x4d, 0x5d, 0xe01, 0xe48, 0xe2d, 0xe19, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf66, 0xf94,
-0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b, 0x1295, 0x1309, 0x1206, 0x20, 0x1230, 0x12d3, 0x1270, 0xd6, 0xd6, 0x686, 0x6c8, 0x634, 0x62a, 0x649, 0x646,
-0x20, 0x628, 0x6c7, 0x631, 0x6c7, 0x646, 0x434, 0x43f, 0x642, 0x628, 0x644, 0x20, 0x62f, 0x648, 0x67e, 0x6c1, 0x631, 0x54, 0x4f, 0x53,
-0x41, 0xc0, 0xe1, 0x72, 0x1ecd, 0x300, 0xc0, 0xe1, 0x72, 0x254, 0x300, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x67,
-0x70, 0x72, 0x69, 0x6a, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x41, 0x4e, 0x128, 0x79, 0x61, 0x6b, 0x77, 0x61, 0x6b,
-0x79, 0x61, 0x61, 0x2e, 0x14b, 0x64, 0x69, 0xa3b8, 0xa111, 0x69, 0x111, 0x69, 0x74, 0x62, 0x65, 0x61, 0x69, 0x76, 0x65, 0x74,
-0x4d, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x4c, 0x75, 0x6d, 0x61, 0x20, 0x6c, 0x77, 0x61, 0x20, 0x4b, 0x73, 0x75, 0x62, 0x61,
-0x6b, 0x61, 0x4b, 0x69, 0x72, 0x6f, 0x6b, 0x6f, 0x54, 0x65, 0x73, 0x69, 0x72, 0x61, 0x6e, 0x6b, 0x61, 0x6e, 0x67, 0x2019,
-0x61, 0x6d, 0x61, 0x2d5c, 0x2d49, 0x2d3c, 0x2d30, 0x2d61, 0x2d5c, 0x74, 0x69, 0x66, 0x61, 0x77, 0x74, 0x6e, 0x20, 0x74, 0x75, 0x66,
-0x61, 0x74, 0x70, 0x61, 0x6d, 0x69, 0x6c, 0x61, 0x75, 0x75, 0x74, 0x75, 0x6b, 0x6f, 0x4b, 0x49, 0x13cc, 0x13be, 0x13b4, 0x4d,
-0x75, 0x68, 0x69, 0x54, 0x4f, 0x4f, 0x75, 0x6c, 0x75, 0x63, 0x68, 0x65, 0x6c, 0x6f, 0x52, 0x168, 0x6b, 0x61, 0x72, 0x6f,
-0x6f, 0x6e, 0x1c1, 0x67, 0x6f, 0x61, 0x67, 0x61, 0x73, 0x55, 0x68, 0x72, 0x20, 0x76, 0xf6, 0x72, 0x6d, 0x69, 0x64, 0x64,
-0x61, 0x61, 0x63, 0x68, 0x73, 0x190, 0x6e, 0x6b, 0x61, 0x6b, 0x25b, 0x6e, 0x79, 0xe1, 0x4d, 0x75, 0x6e, 0x6b, 0x79, 0x6f,
-0x69, 0x63, 0x68, 0x65, 0x68, 0x65, 0x61, 0x76, 0x6f, 0x54, 0x61, 0x70, 0x61, 0x72, 0x61, 0x63, 0x68, 0x75, 0x41, 0x64,
-0x64, 0x75, 0x68, 0x61, 0x4f, 0x44, 0x5a, 0x64, 0x61, 0x74, 0x20, 0x61, 0x7a, 0x61, 0x6c, 0x6d, 0x61, 0x6b, 0x65, 0x6f,
-0x92b, 0x941, 0x902, 0x44, 0x69, 0x6e, 0x64, 0x61, 0x6d, 0x6f, 0x69, 0x65, 0x73, 0x61, 0x2e, 0x67, 0x49, 0x20, 0x62, 0x69,
-0x6b, 0x25b, 0x302, 0x67, 0x6c, 0xe0, 0x53, 0x75, 0x62, 0x62, 0x61, 0x61, 0x68, 0x69, 0x69, 0x64, 0x69, 0x253, 0x61, 0x6b,
-0xed, 0x6b, 0xed, 0x72, 0xed, 0x67, 0x73, 0xe1, 0x72, 0xfa, 0x77, 0xe1, 0x77, 0x69, 0x63, 0x68, 0x69, 0x73, 0x68, 0x75,
-0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6d, 0x61, 0x6e, 0xe1, 0x52, 0x57, 0x42d, 0x418, 0x4c, 0x77, 0x61, 0x6d, 0x69, 0x6c, 0x61,
-0x77, 0x75, 0x6b, 0x69, 0x25b, 0x6d, 0x25b, 0x301, 0x25b, 0x6d, 0x64, 0x65, 0x20, 0x6c, 0x61, 0x20, 0x6d, 0x61, 0xf1, 0x61,
-0x6e, 0x61, 0x6d, 0x62, 0x61, 0xa78c, 0x6d, 0x62, 0x61, 0xa78c, 0x6d, 0x62, 0x61, 0x2bc, 0xe1, 0x6d, 0x62, 0x61, 0x2bc, 0x64,
-0x6f, 0x70, 0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x61
+0x41f, 0x4e, 0x44, 0x43f, 0x440, 0x435, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x43f, 0x440, 0x438, 0x458, 0x435, 0x20, 0x43f, 0x43e,
+0x434, 0x43d, 0x435, 0x70, 0x72, 0x69, 0x6a, 0x65, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x70, 0x72, 0x65, 0x20, 0x70, 0x6f,
+0x64, 0x6e, 0x65, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x440, 0x430, 0x437, 0x43c, 0x4d5, 0xdb4, 0xdd9,
+0x2e, 0xdc0, 0x2e, 0x73, 0x6e, 0x2e, 0x41, 0x73, 0x75, 0x62, 0x75, 0x68, 0x69, 0x66, 0x6d, 0xbae, 0xbc1, 0xbb1, 0xbcd, 0xbaa,
+0xb95, 0xbb2, 0xbcd, 0xe01, 0xe48, 0xe2d, 0xe19, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf66, 0xf94, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b,
+0x1295, 0x1309, 0x1206, 0x20, 0x1230, 0x12d3, 0x1270, 0x68, 0x65, 0x6e, 0x67, 0x69, 0x68, 0x65, 0x6e, 0x67, 0x69, 0xd6, 0xd6, 0x686,
+0x6c8, 0x634, 0x62a, 0x649, 0x646, 0x20, 0x628, 0x6c7, 0x631, 0x6c7, 0x646, 0x434, 0x43f, 0x54, 0x4f, 0x422, 0x41e, 0x53, 0x41, 0x79,
+0x62, 0xc0, 0xe1, 0x72, 0x1ecd, 0x300, 0xc0, 0xe1, 0x72, 0x254, 0x300, 0x66, 0x6f, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x67,
+0x70, 0x72, 0x69, 0x6a, 0x65, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x41, 0x4e, 0x128, 0x79, 0x61, 0x6b, 0x77, 0x61, 0x6b, 0x79,
+0x61, 0x61, 0x2e, 0x14b, 0x64, 0x69, 0x61, 0x6d, 0x20, 0x56, 0x6f, 0x72, 0x6d, 0x69, 0x74, 0x74, 0x61, 0x67, 0xa3b8, 0xa111,
+0x69, 0x111, 0x69, 0x74, 0x62, 0x65, 0x61, 0x69, 0x76, 0x65, 0x74, 0x4d, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x4c, 0x75, 0x6d,
+0x61, 0x20, 0x6c, 0x77, 0x61, 0x20, 0x4b, 0x73, 0x75, 0x62, 0x61, 0x6b, 0x61, 0x4b, 0x69, 0x72, 0x6f, 0x6b, 0x6f, 0x54,
+0x65, 0x73, 0x69, 0x72, 0x61, 0x6e, 0x6b, 0x61, 0x6e, 0x67, 0x2019, 0x61, 0x6d, 0x61, 0x2d5c, 0x2d49, 0x2d3c, 0x2d30, 0x2d61, 0x2d5c,
+0x74, 0x69, 0x66, 0x61, 0x77, 0x74, 0x6e, 0x20, 0x74, 0x75, 0x66, 0x61, 0x74, 0x70, 0x61, 0x6d, 0x69, 0x6c, 0x61, 0x75,
+0x75, 0x74, 0x75, 0x6b, 0x6f, 0x4b, 0x49, 0x13cc, 0x13be, 0x13b4, 0x4d, 0x75, 0x68, 0x69, 0x54, 0x4f, 0x4f, 0x75, 0x6c, 0x75,
+0x63, 0x68, 0x65, 0x6c, 0x6f, 0x52, 0x168, 0x6b, 0x61, 0x72, 0x6f, 0x6f, 0x6e, 0x1c1, 0x67, 0x6f, 0x61, 0x67, 0x61, 0x73,
+0x55, 0x68, 0x72, 0x20, 0x76, 0xf6, 0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x61, 0x63, 0x68, 0x73, 0x190, 0x6e, 0x6b, 0x61,
+0x6b, 0x25b, 0x6e, 0x79, 0xe1, 0x4d, 0x75, 0x6e, 0x6b, 0x79, 0x6f, 0x69, 0x63, 0x68, 0x65, 0x68, 0x65, 0x61, 0x76, 0x6f,
+0x54, 0x61, 0x70, 0x61, 0x72, 0x61, 0x63, 0x68, 0x75, 0x41, 0x64, 0x64, 0x75, 0x68, 0x61, 0x4f, 0x44, 0x5a, 0x64, 0x61,
+0x74, 0x20, 0x61, 0x7a, 0x61, 0x6c, 0x6d, 0x61, 0x6b, 0x65, 0x6f, 0x92b, 0x941, 0x902, 0x44, 0x69, 0x6e, 0x64, 0x61, 0x6d,
+0x6f, 0x69, 0x65, 0x73, 0x61, 0x2e, 0x67, 0x49, 0x20, 0x62, 0x69, 0x6b, 0x25b, 0x302, 0x67, 0x6c, 0xe0, 0x53, 0x75, 0x62,
+0x62, 0x61, 0x61, 0x68, 0x69, 0x69, 0x64, 0x69, 0x253, 0x61, 0x6b, 0xed, 0x6b, 0xed, 0x72, 0xed, 0x67, 0x73, 0xe1, 0x72,
+0xfa, 0x77, 0xe1, 0x77, 0x69, 0x63, 0x68, 0x69, 0x73, 0x68, 0x75, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6d, 0x61, 0x6e, 0xe1,
+0x52, 0x57, 0x42d, 0x418, 0x4c, 0x77, 0x61, 0x6d, 0x69, 0x6c, 0x61, 0x77, 0x75, 0x6b, 0x69, 0x25b, 0x6d, 0x25b, 0x301, 0x25b,
+0x6d, 0x64, 0x65, 0x20, 0x6c, 0x61, 0x20, 0x6d, 0x61, 0xf1, 0x61, 0x6e, 0x61, 0x6d, 0x62, 0x61, 0xa78c, 0x6d, 0x62, 0x61,
+0xa78c, 0x6d, 0x62, 0x61, 0x2bc, 0xe1, 0x6d, 0x62, 0x61, 0x2bc, 0x628, 0x2e, 0x646, 0x64, 0x6f, 0x70, 0x6f, 0x142, 0x64, 0x6e,
+0x6a, 0x61, 0x69, 0x70, 0x2e
};
static const ushort pm_data[] = {
0x50, 0x4d, 0x57, 0x42, 0x6e, 0x6d, 0x2e, 0x65, 0x20, 0x70, 0x61, 0x73, 0x64, 0x69, 0x74, 0x65, 0x73, 0x12a8, 0x1230, 0x12d3,
-0x1275, 0x645, 0x985, 0x9aa, 0x9f0, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0x985, 0x9aa, 0x9b0, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0xf55, 0xfb1, 0xf72, 0xf0b,
-0xf46, 0xf0b, 0x47, 0x2e, 0x4d, 0x2e, 0x441, 0x43b, 0x2e, 0x43e, 0x431, 0x2e, 0x100a, 0x1014, 0x1031, 0x43f, 0x430, 0x441, 0x43b, 0x44f,
-0x20, 0x43f, 0x430, 0x45e, 0x434, 0x43d, 0x44f, 0x179b, 0x17d2, 0x1784, 0x17b6, 0x1785, 0x70, 0x2e, 0x20, 0x6d, 0x2e, 0x4e0b, 0x5348, 0x6f,
-0x64, 0x70, 0x2e, 0x70, 0x2e, 0x6d, 0x2e, 0x70, 0x6d, 0x69, 0x70, 0x2e, 0x66, 0x6e, 0x61, 0x63, 0x68, 0x6d, 0x2e, 0x3bc,
-0x2e, 0x3bc, 0x2e, 0x5d0, 0x5d7, 0x5d4, 0x5f4, 0x5e6, 0x905, 0x92a, 0x930, 0x93e, 0x939, 0x94d, 0x928, 0x64, 0x75, 0x2e, 0x65, 0x2e,
-0x68, 0x2e, 0x5348, 0x5f8c, 0xc85, 0xcaa, 0xcb0, 0xcbe, 0xcb9, 0xccd, 0xca8, 0x442, 0x4af, 0x441, 0x43a, 0x456, 0x2f, 0x43a, 0x435, 0x448,
-0x43a, 0x456, 0x442, 0x4af, 0x448, 0x442, 0x4e9, 0x43d, 0x20, 0x43a, 0x438, 0x439, 0x438, 0x43d, 0x43a, 0x438, 0xc624, 0xd6c4, 0x5a, 0x2e,
-0x4d, 0x57, 0x2e, 0xeab, 0xebc, 0xeb1, 0xe87, 0xe97, 0xec8, 0xebd, 0xe87, 0x70, 0x113, 0x63, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65,
-0x6e, 0x101, 0x6d, 0x70, 0xf3, 0x6b, 0x77, 0x61, 0x70, 0x6f, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x43e, 0x43f, 0x43b, 0x430, 0x434,
-0x43d, 0x435, 0x50, 0x54, 0x47, 0x92e, 0x2e, 0x909, 0x2e, 0x4ae, 0x425, 0x63a, 0x2e, 0x648, 0x2e, 0x628, 0x639, 0x62f, 0x627, 0x632,
-0x638, 0x647, 0x631, 0x64, 0x61, 0x20, 0x74, 0x61, 0x72, 0x64, 0x65, 0xa2c, 0xa3e, 0x2e, 0xa26, 0xa41, 0x2e, 0x73, 0x6d, 0x41f,
-0x41f, 0x4c, 0x4b, 0x43f, 0x43e, 0x20, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x70, 0x6f, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x4d5,
-0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x444, 0x4d5, 0x441, 0x442, 0x4d5, 0xdb4, 0x2e, 0xdc0, 0x2e, 0x70, 0x6f,
-0x70, 0x2e, 0x67, 0x6e, 0x2e, 0x79, 0x61, 0x20, 0x6d, 0x75, 0x63, 0x68, 0x61, 0x6e, 0x61, 0x65, 0x6d, 0xbaa, 0xbbf, 0xbb1,
-0xbcd, 0xbaa, 0xb95, 0xbb2, 0xbcd, 0x5b, 0x50, 0x4d, 0x5d, 0xe2b, 0xe25, 0xe31, 0xe07, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22, 0xe07, 0xf55,
-0xfb1, 0xf72, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b, 0x12f5, 0x1215, 0x122d, 0x20, 0x1230, 0x12d3, 0x1275, 0xd6, 0x53, 0x686, 0x6c8, 0x634, 0x62a,
-0x649, 0x646, 0x20, 0x643, 0x6d0, 0x64a, 0x649, 0x646, 0x43f, 0x43f, 0x628, 0x639, 0x62f, 0x20, 0x62f, 0x648, 0x67e, 0x6c1, 0x631, 0x54,
-0x4b, 0x43, 0x48, 0x1ecc, 0x300, 0x73, 0xe1, 0x6e, 0x186, 0x300, 0x73, 0xe1, 0x6e, 0x65, 0x74, 0x74, 0x65, 0x72, 0x6d, 0x69,
-0x64, 0x64, 0x61, 0x67, 0x70, 0x6f, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x43f, 0x43e, 0x43f, 0x43e, 0x434, 0x43d, 0x435, 0x45, 0x57,
-0x92e, 0x2e, 0x928, 0x902, 0x2e, 0x50, 0x2e, 0x4d, 0x2e, 0x128, 0x79, 0x61, 0x77, 0x129, 0x6f, 0x6f, 0x70, 0x2e, 0x263, 0x65,
-0x74, 0x72, 0x254, 0x6e, 0x61, 0x6d, 0x2e, 0xa06f, 0xa2d2, 0x65, 0x61, 0x68, 0x6b, 0x65, 0x74, 0x62, 0x65, 0x61, 0x69, 0x76,
-0x65, 0x74, 0x4d, 0x6f, 0x67, 0x6c, 0x75, 0x6d, 0x61, 0x20, 0x6c, 0x77, 0x61, 0x20, 0x70, 0x6b, 0x69, 0x6b, 0x69, 0x69,
-0x257, 0x65, 0x48, 0x77, 0x61, 0x129, 0x2d, 0x69, 0x6e, 0x129, 0x54, 0x65, 0x69, 0x70, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x6f,
-0x74, 0x6f, 0x2d5c, 0x2d30, 0x2d37, 0x2d33, 0x2d33, 0x2d6f, 0x2d30, 0x2d5c, 0x74, 0x61, 0x64, 0x67, 0x67, 0x2b7, 0x61, 0x74, 0x6e, 0x20,
-0x74, 0x6d, 0x65, 0x64, 0x64, 0x69, 0x74, 0x70, 0x61, 0x6d, 0x75, 0x6e, 0x79, 0x69, 0x6b, 0x79, 0x69, 0x75, 0x6b, 0x6f,
-0x6e, 0x79, 0x69, 0x55, 0x54, 0x13d2, 0x13af, 0x13f1, 0x13a2, 0x13d7, 0x13e2, 0x43, 0x68, 0x69, 0x6c, 0x6f, 0x4d, 0x55, 0x55, 0x61,
-0x6b, 0x61, 0x73, 0x75, 0x62, 0x61, 0x168, 0x47, 0x6b, 0x6f, 0x6f, 0x73, 0x6b, 0x6f, 0x6c, 0x69, 0x6e, 0x79, 0x1c3, 0x75,
-0x69, 0x61, 0x73, 0x55, 0x68, 0x72, 0x20, 0x6e, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x73, 0x190,
-0x6e, 0x64, 0xe1, 0x6d, 0xe2, 0x45, 0x69, 0x67, 0x75, 0x6c, 0x6f, 0x69, 0x63, 0x68, 0x61, 0x6d, 0x74, 0x68, 0x69, 0x45,
-0x62, 0x6f, 0x6e, 0x67, 0x69, 0x41, 0x6c, 0x75, 0x75, 0x6c, 0x61, 0x4f, 0x54, 0x1e0c, 0x65, 0x66, 0x66, 0x69, 0x72, 0x20,
-0x61, 0x7a, 0x61, 0x6e, 0x79, 0x69, 0x61, 0x67, 0x68, 0x75, 0x6f, 0x92c, 0x947, 0x932, 0x93e, 0x938, 0x947, 0x44, 0x69, 0x6c,
-0x6f, 0x6c, 0x6f, 0x6e, 0x6f, 0x6d, 0xeb, 0x74, 0x74, 0x65, 0x73, 0x61, 0x2e, 0x6b, 0x49, 0x20, 0x253, 0x75, 0x67, 0x61,
-0x6a, 0x254, 0x70, 0x5a, 0x61, 0x61, 0x72, 0x69, 0x6b, 0x61, 0x79, 0x20, 0x62, 0x65, 0x62, 0x79, 0xe1, 0x6d, 0x75, 0x6e,
-0x67, 0x259, 0x67, 0xf3, 0x67, 0x259, 0x6c, 0x65, 0x63, 0x25b, 0x25b, 0x301, 0x6e, 0x6b, 0x6f, 0x6d, 0x63, 0x68, 0x6f, 0x63,
-0x68, 0x69, 0x6c, 0x2019, 0x6c, 0x6c, 0x69, 0x6c, 0x6c, 0x69, 0x6b, 0x75, 0x67, 0xfa, 0x54, 0x14a, 0x42d, 0x41a, 0x50, 0x61,
-0x73, 0x68, 0x61, 0x6d, 0x69, 0x68, 0x65, 0x6b, 0x69, 0x73, 0x25b, 0x301, 0x6e, 0x64, 0x25b, 0x64, 0x65, 0x20, 0x6c, 0x61,
-0x20, 0x74, 0x61, 0x72, 0x64, 0x69, 0x14b, 0x6b, 0x61, 0x20, 0x6d, 0x62, 0x254, 0x301, 0x74, 0x20, 0x6e, 0x6a, 0x69, 0x6e,
-0x63, 0x77, 0xf2, 0x6e, 0x7a, 0xe9, 0x6d, 0x77, 0xf3, 0x74, 0x70, 0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x61, 0x70, 0x6f, 0x70,
-0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x75
+0x1275, 0x645, 0x985, 0x9aa, 0x9f0, 0x9be, 0x9b9, 0x9cd, 0x9a3, 0x41f, 0x41c, 0xf55, 0xfb1, 0xf72, 0xf0b, 0xf46, 0xf0b, 0x47, 0x2e, 0x4d,
+0x2e, 0x441, 0x43b, 0x2e, 0x43e, 0x431, 0x2e, 0x100a, 0x1014, 0x1031, 0x70, 0x2e, 0x20, 0x6d, 0x2e, 0x4e0b, 0x5348, 0x6f, 0x64, 0x70,
+0x2e, 0x70, 0x2e, 0x6d, 0x2e, 0x70, 0x6d, 0x69, 0x70, 0x2e, 0x73, 0x6f, 0x69, 0x72, 0x66, 0x6e, 0x61, 0x63, 0x68, 0x6d,
+0x2e, 0x3bc, 0x2e, 0x3bc, 0x2e, 0x5d0, 0x5d7, 0x5d4, 0x5f4, 0x5e6, 0x905, 0x92a, 0x930, 0x93e, 0x939, 0x94d, 0x928, 0x64, 0x75, 0x2e,
+0x65, 0x2e, 0x68, 0x2e, 0x5348, 0x5f8c, 0xc85, 0xcaa, 0xcb0, 0xcbe, 0xcb9, 0xccd, 0xca8, 0x442, 0x4af, 0x448, 0x442, 0x4e9, 0x43d, 0x20,
+0x43a, 0x438, 0x439, 0x438, 0x43d, 0x43a, 0x438, 0xc624, 0xd6c4, 0x5a, 0x2e, 0x4d, 0x57, 0x2e, 0xeab, 0xebc, 0xeb1, 0xe87, 0xe97, 0xec8,
+0xebd, 0xe87, 0x70, 0x113, 0x63, 0x70, 0x75, 0x73, 0x64, 0x69, 0x65, 0x6e, 0x101, 0x6d, 0x70, 0xf3, 0x6b, 0x77, 0x61, 0x70,
+0x6f, 0x70, 0x69, 0x65, 0x74, 0x43f, 0x43e, 0x43f, 0x43b, 0x430, 0x434, 0x43d, 0x435, 0x50, 0x54, 0x47, 0x92e, 0x2e, 0x909, 0x2e,
+0x4af, 0x2e, 0x445, 0x63a, 0x2e, 0x648, 0x2e, 0x628, 0x639, 0x62f, 0x627, 0x632, 0x638, 0x647, 0x631, 0x64, 0x61, 0x20, 0x74, 0x61,
+0x72, 0x64, 0x65, 0xa2c, 0xa3e, 0x2e, 0xa26, 0xa41, 0x2e, 0x41f, 0x41f, 0x4c, 0x4b, 0x43f, 0x43e, 0x20, 0x43f, 0x43e, 0x434, 0x43d,
+0x435, 0x70, 0x6f, 0x20, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x4d5, 0x43c, 0x431, 0x438, 0x441, 0x431, 0x43e, 0x43d, 0x44b, 0x20, 0x444,
+0x4d5, 0x441, 0x442, 0x4d5, 0xdb4, 0x2e, 0xdc0, 0x2e, 0x70, 0x6f, 0x70, 0x2e, 0x67, 0x6e, 0x2e, 0x4d, 0x63, 0x68, 0x61, 0x6e,
+0x61, 0x65, 0x6d, 0xbaa, 0xbbf, 0xbb1, 0xbcd, 0xbaa, 0xb95, 0xbb2, 0xbcd, 0xe2b, 0xe25, 0xe31, 0xe07, 0xe40, 0xe17, 0xe35, 0xe48, 0xe22,
+0xe07, 0xf55, 0xfb1, 0xf72, 0xf0b, 0xf51, 0xfb2, 0xf7c, 0xf0b, 0x12f5, 0x1215, 0x122d, 0x20, 0x1230, 0x12d3, 0x1275, 0x65, 0x66, 0x69, 0x61,
+0x66, 0x69, 0xd6, 0x53, 0x686, 0x6c8, 0x634, 0x62a, 0x649, 0x646, 0x20, 0x643, 0x6d0, 0x64a, 0x649, 0x646, 0x43f, 0x43f, 0x54, 0x4b,
+0x422, 0x41a, 0x43, 0x48, 0x79, 0x68, 0x1ecc, 0x300, 0x73, 0xe1, 0x6e, 0x186, 0x300, 0x73, 0xe1, 0x6e, 0x65, 0x74, 0x74, 0x65,
+0x72, 0x6d, 0x69, 0x64, 0x64, 0x61, 0x67, 0x70, 0x6f, 0x70, 0x6f, 0x64, 0x6e, 0x65, 0x43f, 0x43e, 0x43f, 0x43e, 0x434, 0x43d,
+0x435, 0x45, 0x57, 0x92e, 0x2e, 0x928, 0x902, 0x2e, 0x50, 0x2e, 0x4d, 0x2e, 0x128, 0x79, 0x61, 0x77, 0x129, 0x6f, 0x6f, 0x70,
+0x2e, 0x263, 0x65, 0x74, 0x72, 0x254, 0x61, 0x6d, 0x20, 0x4e, 0x61, 0x6d, 0x69, 0x74, 0x74, 0x61, 0x67, 0xa06f, 0xa2d2, 0x65,
+0x61, 0x68, 0x6b, 0x65, 0x74, 0x62, 0x65, 0x61, 0x69, 0x76, 0x65, 0x74, 0x4d, 0x6f, 0x67, 0x6c, 0x75, 0x6d, 0x61, 0x20,
+0x6c, 0x77, 0x61, 0x20, 0x70, 0x6b, 0x69, 0x6b, 0x69, 0x69, 0x257, 0x65, 0x48, 0x77, 0x61, 0x129, 0x2d, 0x69, 0x6e, 0x129,
+0x54, 0x65, 0x69, 0x70, 0x61, 0x6b, 0x69, 0x6e, 0x67, 0x6f, 0x74, 0x6f, 0x2d5c, 0x2d30, 0x2d37, 0x2d33, 0x2d33, 0x2d6f, 0x2d30, 0x2d5c,
+0x74, 0x61, 0x64, 0x67, 0x67, 0x2b7, 0x61, 0x74, 0x6e, 0x20, 0x74, 0x6d, 0x65, 0x64, 0x64, 0x69, 0x74, 0x70, 0x61, 0x6d,
+0x75, 0x6e, 0x79, 0x69, 0x6b, 0x79, 0x69, 0x75, 0x6b, 0x6f, 0x6e, 0x79, 0x69, 0x55, 0x54, 0x13d2, 0x13af, 0x13f1, 0x13a2, 0x13d7,
+0x13e2, 0x43, 0x68, 0x69, 0x6c, 0x6f, 0x4d, 0x55, 0x55, 0x61, 0x6b, 0x61, 0x73, 0x75, 0x62, 0x61, 0x168, 0x47, 0x6b, 0x6f,
+0x6f, 0x73, 0x6b, 0x6f, 0x6c, 0x69, 0x6e, 0x79, 0x1c3, 0x75, 0x69, 0x61, 0x73, 0x55, 0x68, 0x72, 0x20, 0x6e, 0x6f, 0x6d,
+0x6d, 0x65, 0x6e, 0x64, 0x61, 0x61, 0x63, 0x68, 0x73, 0x190, 0x6e, 0x64, 0xe1, 0x6d, 0xe2, 0x45, 0x69, 0x67, 0x75, 0x6c,
+0x6f, 0x69, 0x63, 0x68, 0x61, 0x6d, 0x74, 0x68, 0x69, 0x45, 0x62, 0x6f, 0x6e, 0x67, 0x69, 0x41, 0x6c, 0x75, 0x75, 0x6c,
+0x61, 0x4f, 0x54, 0x1e0c, 0x65, 0x66, 0x66, 0x69, 0x72, 0x20, 0x61, 0x7a, 0x61, 0x6e, 0x79, 0x69, 0x61, 0x67, 0x68, 0x75,
+0x6f, 0x92c, 0x947, 0x932, 0x93e, 0x938, 0x947, 0x44, 0x69, 0x6c, 0x6f, 0x6c, 0x6f, 0x6e, 0x6f, 0x6d, 0xeb, 0x74, 0x74, 0x65,
+0x73, 0x61, 0x2e, 0x6b, 0x49, 0x20, 0x253, 0x75, 0x67, 0x61, 0x6a, 0x254, 0x70, 0x5a, 0x61, 0x61, 0x72, 0x69, 0x6b, 0x61,
+0x79, 0x20, 0x62, 0x65, 0x62, 0x79, 0xe1, 0x6d, 0x75, 0x6e, 0x67, 0x259, 0x67, 0xf3, 0x67, 0x259, 0x6c, 0x65, 0x63, 0x25b,
+0x25b, 0x301, 0x6e, 0x6b, 0x6f, 0x6d, 0x63, 0x68, 0x6f, 0x63, 0x68, 0x69, 0x6c, 0x2019, 0x6c, 0x6c, 0x69, 0x6c, 0x6c, 0x69,
+0x6b, 0x75, 0x67, 0xfa, 0x54, 0x14a, 0x42d, 0x41a, 0x50, 0x61, 0x73, 0x68, 0x61, 0x6d, 0x69, 0x68, 0x65, 0x6b, 0x69, 0x73,
+0x25b, 0x301, 0x6e, 0x64, 0x25b, 0x64, 0x65, 0x20, 0x6c, 0x61, 0x20, 0x74, 0x61, 0x72, 0x64, 0x65, 0x14b, 0x6b, 0x61, 0x20,
+0x6d, 0x62, 0x254, 0x301, 0x74, 0x20, 0x6e, 0x6a, 0x69, 0x6e, 0x63, 0x77, 0xf2, 0x6e, 0x7a, 0xe9, 0x6d, 0x62f, 0x2e, 0x646,
+0x77, 0xf3, 0x74, 0x70, 0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x61, 0x70, 0x6f, 0x70, 0x6f, 0x142, 0x64, 0x6e, 0x6a, 0x75, 0x65,
+0x70, 0x2e
};
static const ushort currency_symbol_data[] = {
@@ -4886,18 +4980,18 @@ static const ushort currency_symbol_data[] = {
0x62f, 0x2e, 0x643, 0x2e, 0x200f, 0x644, 0x2e, 0x644, 0x2e, 0x200f, 0x62f, 0x2e, 0x644, 0x2e, 0x200f, 0x623, 0x2e, 0x645, 0x2e, 0x200f,
0x62f, 0x2e, 0x645, 0x2e, 0x200f, 0x631, 0x2e, 0x639, 0x2e, 0x200f, 0x631, 0x2e, 0x642, 0x2e, 0x200f, 0x631, 0x2e, 0x633, 0x2e, 0x200f,
0x53, 0x62c, 0x2e, 0x633, 0x2e, 0x644, 0x2e, 0x633, 0x2e, 0x200f, 0x62f, 0x2e, 0x62a, 0x2e, 0x200f, 0x62f, 0x2e, 0x625, 0x2e, 0x200f,
-0x631, 0x2e, 0x64a, 0x2e, 0x200f, 0xa3, 0x58f, 0x20b9, 0x20bc, 0x20bd, 0x9f3, 0x4e, 0x75, 0x2e, 0x43b, 0x432, 0x2e, 0x4b, 0x440, 0x2e,
-0x17db, 0xffe5, 0x48, 0x4b, 0x24, 0x4d, 0x4f, 0x50, 0x24, 0x48, 0x52, 0x4b, 0x4b, 0x4d, 0x4b, 0x10d, 0x6b, 0x72, 0x2e, 0x41,
-0x66, 0x6c, 0x2e, 0x4e, 0x41, 0x66, 0x2e, 0x55, 0x53, 0x24, 0x50, 0x46, 0x42, 0x75, 0x44, 0x47, 0x48, 0x20b5, 0x41, 0x72,
-0x4d, 0x4b, 0x52, 0x4d, 0x52, 0x73, 0x20a6, 0x20b1, 0x52, 0x46, 0x57, 0x53, 0x24, 0x53, 0x52, 0x4c, 0x65, 0x45, 0x6b, 0x72,
-0x54, 0x53, 0x68, 0x54, 0x24, 0x55, 0x53, 0x68, 0x56, 0x54, 0x44, 0x41, 0x43, 0x46, 0x41, 0x43, 0x46, 0x46, 0x43, 0x46,
-0x43, 0x46, 0x50, 0x46, 0x47, 0x47, 0x55, 0x4d, 0x4d, 0x41, 0x44, 0x43, 0x48, 0x46, 0x4c, 0x53, 0x44, 0x54, 0x20be, 0x20b2,
-0x46, 0x74, 0x49, 0x53, 0x4b, 0x52, 0x70, 0x43, 0x41, 0x24, 0x20b8, 0x441, 0x43e, 0x43c, 0x20a9, 0x4b, 0x50, 0x57, 0x20ba, 0x20ad,
-0x4b, 0x7a, 0x434, 0x435, 0x43d, 0x4e, 0x5a, 0x24, 0x20ae, 0x43, 0x4e, 0xa5, 0x928, 0x947, 0x930, 0x942, 0x60b, 0x631, 0x6cc, 0x627,
-0x644, 0x7a, 0x142, 0x52, 0x24, 0x200b, 0x4d, 0x54, 0x6e, 0x44, 0x62, 0x631, 0x53, 0x2f, 0x2e, 0x42, 0x73, 0x52, 0x4f, 0x4e,
-0x4c, 0x20b4, 0x52, 0x53, 0x44, 0x41a, 0x41c, 0xdbb, 0xdd4, 0x2e, 0x20a1, 0x52, 0x44, 0x24, 0x51, 0x43, 0x24, 0x42, 0x2f, 0x2e,
-0x47, 0x73, 0x2e, 0x42, 0x73, 0x2e, 0x52, 0x73, 0x2e, 0x54, 0x48, 0x42, 0xa5, 0x54, 0x4d, 0x54, 0x73, 0x6f, 0x2bb, 0x6d,
-0x441, 0x45e, 0x43c, 0x20ab, 0x4e, 0x54, 0x24, 0x41, 0x24, 0x49, 0x52, 0x52
+0x631, 0x2e, 0x64a, 0x2e, 0x200f, 0xa3, 0x58f, 0x20b9, 0x20bc, 0x20bd, 0x9f3, 0x4e, 0x75, 0x2e, 0x43b, 0x432, 0x2e, 0x4b, 0x17db, 0xffe5,
+0x48, 0x4b, 0x24, 0x4d, 0x4f, 0x50, 0x24, 0x48, 0x52, 0x4b, 0x4b, 0x4d, 0x4b, 0x10d, 0x6b, 0x72, 0x2e, 0x41, 0x66, 0x6c,
+0x2e, 0x4e, 0x41, 0x66, 0x2e, 0x55, 0x53, 0x24, 0x50, 0x46, 0x42, 0x75, 0x44, 0x47, 0x48, 0x20b5, 0x41, 0x72, 0x4d, 0x4b,
+0x52, 0x4d, 0x52, 0x73, 0x20a6, 0x20b1, 0x52, 0x46, 0x57, 0x53, 0x24, 0x53, 0x52, 0x4c, 0x65, 0x45, 0x6b, 0x72, 0x54, 0x53,
+0x68, 0x54, 0x24, 0x55, 0x53, 0x68, 0x56, 0x54, 0x44, 0x41, 0x43, 0x46, 0x41, 0x43, 0x46, 0x46, 0x43, 0x46, 0x43, 0x46,
+0x50, 0x46, 0x47, 0x47, 0x55, 0x4d, 0x4d, 0x41, 0x44, 0x43, 0x48, 0x46, 0x4c, 0x53, 0x44, 0x54, 0x20be, 0x20b2, 0x46, 0x74,
+0x49, 0x53, 0x4b, 0x52, 0x70, 0x43, 0x41, 0x24, 0x20b8, 0x441, 0x43e, 0x43c, 0x20a9, 0x4b, 0x50, 0x57, 0x20ba, 0x20ad, 0x4b, 0x7a,
+0x434, 0x435, 0x43d, 0x4e, 0x5a, 0x24, 0x20ae, 0x43, 0x4e, 0xa5, 0x928, 0x947, 0x930, 0x942, 0x60b, 0x631, 0x6cc, 0x627, 0x644, 0x7a,
+0x142, 0x52, 0x24, 0x200b, 0x4d, 0x54, 0x6e, 0x44, 0x62, 0x631, 0x53, 0x2f, 0x42, 0x73, 0x52, 0x4f, 0x4e, 0x4c, 0x20b4, 0x52,
+0x53, 0x44, 0x41a, 0x41c, 0xdbb, 0xdd4, 0x2e, 0x20a1, 0x52, 0x44, 0x24, 0x51, 0x43, 0x24, 0x42, 0x2f, 0x2e, 0x47, 0x73, 0x2e,
+0x42, 0x73, 0x2e, 0x52, 0x73, 0x2e, 0x54, 0x48, 0x42, 0xa5, 0x54, 0x4d, 0x54, 0x73, 0x6f, 0x2bb, 0x6d, 0x441, 0x45e, 0x43c,
+0x20ab, 0x4e, 0x54, 0x24, 0x41, 0x24, 0x49, 0x52, 0x52
};
static const ushort currency_display_name_data[] = {
@@ -4928,770 +5022,770 @@ static const ushort currency_display_name_data[] = {
0x627, 0x631, 0x20, 0x62c, 0x632, 0x627, 0x626, 0x631, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a,
0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627,
0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646,
-0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x629, 0x3b, 0x62f, 0x64a,
-0x646, 0x627, 0x631, 0x64b, 0x627, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x64b, 0x627, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631,
-0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631,
-0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b,
-0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643,
-0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637,
-0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631,
-0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b,
-0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20,
-0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627,
-0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b,
-0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20,
-0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627,
-0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646,
-0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a,
-0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a,
-0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646,
-0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631,
+0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631,
+0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x628, 0x62d, 0x631, 0x64a, 0x646, 0x64a,
+0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646,
+0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633,
+0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641,
+0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a,
+0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646,
+0x643, 0x20, 0x648, 0x633, 0x637, 0x20, 0x623, 0x641, 0x631, 0x64a, 0x642, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632,
+0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642,
+0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631,
+0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632,
+0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642,
+0x645, 0x631, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x632, 0x631, 0x20, 0x627, 0x644, 0x642, 0x645, 0x631, 0x3b, 0x641, 0x631,
+0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a,
+0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c,
+0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631,
+0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a, 0x64a, 0x3b, 0x641, 0x631, 0x646, 0x643, 0x20, 0x62c, 0x64a, 0x628, 0x648, 0x62a,
0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627,
0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a,
0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20,
0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x3b, 0x646, 0x627, 0x643, 0x641, 0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x3b,
-0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631,
-0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627,
-0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x639, 0x631, 0x627, 0x642,
-0x64a, 0x629, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x64b, 0x627, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x64b, 0x627, 0x3b, 0x62f,
-0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627,
-0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626,
-0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a,
-0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644,
-0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a,
-0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20,
-0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c,
-0x62f, 0x64a, 0x62f, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627,
-0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b,
-0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x62a, 0x20,
-0x623, 0x631, 0x62f, 0x646, 0x64a, 0x629, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x64b, 0x627, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a,
-0x64b, 0x627, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631,
-0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f,
-0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a,
-0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x629, 0x3b, 0x62f, 0x64a,
-0x646, 0x627, 0x631, 0x64b, 0x627, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x64b, 0x627, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20,
-0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646,
+0x646, 0x627, 0x643, 0x641, 0x627, 0x20, 0x623, 0x631, 0x64a, 0x62a, 0x631, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639,
+0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646,
+0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a,
+0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639,
+0x631, 0x627, 0x642, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x639, 0x631, 0x627, 0x642, 0x64a, 0x3b, 0x634, 0x64a, 0x643,
+0x644, 0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644,
+0x20, 0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20,
+0x625, 0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625,
+0x633, 0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633,
+0x631, 0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631,
+0x627, 0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x634, 0x64a, 0x643, 0x644, 0x20, 0x625, 0x633, 0x631, 0x627,
+0x626, 0x64a, 0x644, 0x64a, 0x20, 0x62c, 0x62f, 0x64a, 0x62f, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646,
+0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20,
+0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a,
+0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646,
+0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x623, 0x631, 0x62f, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20,
+0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a,
+0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a,
+0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20,
+0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x643, 0x648, 0x64a, 0x62a, 0x64a, 0x3b, 0x62c, 0x646,
0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646,
-0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x629, 0x20, 0x644,
+0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644,
0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646,
-0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a, 0x628, 0x64a,
-0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a,
-0x628, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x646, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x627, 0x646, 0x3b, 0x62f, 0x64a,
-0x646, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x629, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x64b, 0x627, 0x20,
-0x644, 0x64a, 0x628, 0x64a, 0x64b, 0x627, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x3b, 0x623, 0x648,
-0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20,
-0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a,
+0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x644, 0x628, 0x646, 0x627, 0x646,
+0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644,
+0x64a, 0x628, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631,
+0x627, 0x646, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x627, 0x646, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x644, 0x64a,
+0x628, 0x64a, 0x629, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x64b, 0x627, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x64b, 0x627, 0x3b, 0x62f,
+0x64a, 0x646, 0x627, 0x631, 0x20, 0x644, 0x64a, 0x628, 0x64a, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a,
0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a,
0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648,
0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20,
-0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a,
-0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631,
-0x628, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x627, 0x646, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x627, 0x646, 0x3b, 0x62f, 0x631,
-0x627, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x629, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x64b, 0x627, 0x20, 0x645, 0x63a,
-0x631, 0x628, 0x64a, 0x64b, 0x627, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x3b, 0x631, 0x64a, 0x627,
-0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631,
-0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a,
-0x3b, 0x631, 0x64a, 0x627, 0x644, 0x627, 0x62a, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x627,
-0x64b, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x64b, 0x627, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a,
-0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a,
-0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a,
-0x3b, 0x631, 0x64a, 0x627, 0x644, 0x627, 0x62a, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x629, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x627, 0x64b,
-0x20, 0x642, 0x637, 0x631, 0x64a, 0x64b, 0x627, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a,
+0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a,
+0x62a, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x623, 0x648, 0x642, 0x64a, 0x629, 0x20, 0x645, 0x648, 0x631, 0x64a, 0x62a, 0x627, 0x646, 0x64a,
+0x629, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a,
+0x631, 0x628, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x627,
+0x646, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x627, 0x646, 0x3b, 0x62f, 0x631, 0x627, 0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628,
+0x64a, 0x629, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x64b, 0x627, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x64b, 0x627, 0x3b, 0x62f, 0x631,
+0x647, 0x645, 0x20, 0x645, 0x63a, 0x631, 0x628, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b,
+0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646,
+0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645,
+0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20,
+0x639, 0x645, 0x627, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644,
+0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644,
+0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644,
+0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x642, 0x637, 0x631, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644,
+0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x3b, 0x631, 0x64a,
0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x3b,
0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f,
-0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x627, 0x62a, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x629, 0x3b, 0x631, 0x64a, 0x627, 0x644,
-0x627, 0x64b, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x64b, 0x627, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f,
-0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645,
+0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x633, 0x639, 0x648, 0x62f, 0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645,
0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635,
0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646,
-0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x62c,
-0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627,
-0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20,
-0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x627, 0x62a, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a,
-0x629, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x64b, 0x627, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x64b, 0x627, 0x3b, 0x62c, 0x646,
-0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629,
+0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634, 0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x634,
+0x644, 0x646, 0x20, 0x635, 0x648, 0x645, 0x627, 0x644, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646,
+0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633,
+0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x3b, 0x62c, 0x646,
+0x64a, 0x647, 0x627, 0x62a, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x629, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x64b, 0x627, 0x20,
+0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a, 0x64b, 0x627, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x64a,
0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631,
-0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x627, 0x62a, 0x20,
-0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631,
-0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b,
-0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648,
-0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x646, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x627, 0x646, 0x3b,
-0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x629, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631,
-0x64b, 0x627, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x64b, 0x627, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646,
-0x633, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645,
-0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a,
-0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x627, 0x647, 0x645,
-0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x629, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x64b, 0x627, 0x20, 0x625, 0x645, 0x627,
-0x631, 0x627, 0x62a, 0x64a, 0x64b, 0x627, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b,
-0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b,
-0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b,
-0x631, 0x64a, 0x627, 0x644, 0x627, 0x62a, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x629, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x627, 0x64b, 0x20,
-0x64a, 0x645, 0x646, 0x64a, 0x64b, 0x627, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a,
-0x647, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20,
-0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646,
-0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x627, 0x646, 0x20, 0x62c, 0x646,
-0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x627, 0x62a, 0x20, 0x62c, 0x646,
-0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x64b, 0x627, 0x20, 0x62c, 0x646,
-0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646, 0x648, 0x628,
-0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x540, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580,
-0x561, 0x574, 0x3b, 0x3b, 0x540, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b, 0x3b, 0x3b,
-0x3b, 0x540, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62,
-0x61, 0x79, 0x63, 0x61, 0x6e, 0x20, 0x4d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61,
-0x79, 0x63, 0x61, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62,
-0x61, 0x79, 0x63, 0x61, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x43c, 0x430, 0x43d, 0x430, 0x442, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x61, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b,
-0x3b, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b, 0x3b, 0x3b, 0x3b, 0x9ac,
-0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af,
-0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf,
-0x3b, 0x3b, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0x3b, 0xf51, 0xf44, 0xf74,
-0xf63, 0xf0b, 0xf40, 0xfb2, 0xf58, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75,
-0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x61, 0x20, 0x65, 0x75, 0x72, 0x6f, 0x69,
-0x6f, 0xf9, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x411, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435,
-0x432, 0x3b, 0x3b, 0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x3b, 0x3b, 0x3b, 0x3b,
-0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x430, 0x3b, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019,
-0x102c, 0x1000, 0x103b, 0x1015, 0x103a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x1000, 0x103b, 0x1015,
-0x103a, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c, 0x3b, 0x3b,
-0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435,
-0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x44f, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x456, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440,
-0x443, 0x441, 0x43a, 0x456, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x451, 0x45e, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441,
-0x43a, 0x430, 0x433, 0x430, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb,
-0x1787, 0x17b6, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x73, 0x3b,
-0x4eba, 0x6c11, 0x5e01, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4eba, 0x6c11, 0x5e01, 0x3b, 0x6e2f, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x6e2f, 0x5143, 0x3b, 0x6fb3, 0x95e8, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6fb3, 0x95e8, 0x5143, 0x3b, 0x65b0, 0x52a0, 0x5761,
-0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65b0, 0x52a0, 0x5761, 0x5143, 0x3b, 0x6fb3, 0x9580, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x6fb3, 0x9580, 0x5143, 0x3b, 0x65b0, 0x53f0, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65b0, 0x53f0, 0x5e63, 0x3b, 0x68, 0x72,
-0x76, 0x61, 0x74, 0x73, 0x6b, 0x61, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b,
-0x61, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x75, 0x6e,
-0x65, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x6b, 0x6f,
-0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x6b,
-0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b,
-0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b,
-0x3b, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61,
-0x6b, 0x61, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe1, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x10d, 0x65, 0x73,
-0x6b, 0xe1, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe9, 0x20, 0x6b, 0x6f, 0x72,
-0x75, 0x6e, 0x79, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe9, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x79, 0x3b, 0x10d, 0x65, 0x73,
-0x6b, 0xfd, 0x63, 0x68, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x3b, 0x44, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f,
-0x6e, 0x65, 0x3b, 0x3b, 0x44, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x44,
-0x61, 0x6e, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65,
-0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73,
-0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20,
-0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20,
-0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e,
-0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x4e,
-0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e,
-0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61,
-0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c,
-0x64, 0x65, 0x6e, 0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61,
-0x72, 0x3b, 0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61,
-0x72, 0x3b, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x3b, 0x55, 0x53, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x64, 0x6f, 0x6c,
-0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x45, 0x61,
-0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
-0x3b, 0x45, 0x61, 0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x61, 0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e,
-0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20,
-0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20,
-0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b,
-0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x73, 0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c,
-0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73,
-0x3b, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42,
-0x61, 0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42,
-0x61, 0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42, 0x65, 0x6c,
-0x69, 0x7a, 0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x73, 0x3b, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
-0x3b, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b,
-0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42, 0x6f, 0x74,
-0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e, 0x20, 0x50, 0x75, 0x6c, 0x61, 0x3b, 0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e,
-0x61, 0x6e, 0x20, 0x70, 0x75, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e,
-0x20, 0x70, 0x75, 0x6c, 0x61, 0x73, 0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x46, 0x72, 0x61,
-0x6e, 0x63, 0x3b, 0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b,
-0x3b, 0x3b, 0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x3b,
-0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20,
-0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63,
-0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x65, 0x6e, 0x74,
-0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e,
-0x63, 0x73, 0x3b, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b,
-0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x43,
-0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x43, 0x61, 0x79, 0x6d,
-0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x43,
-0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x44,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64,
-0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72, 0x6f, 0x6e,
-0x65, 0x3b, 0x3b, 0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x44,
-0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61,
-0x6e, 0x20, 0x4e, 0x61, 0x6b, 0x66, 0x61, 0x3b, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x6e, 0x61,
-0x6b, 0x66, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x6b, 0x66,
-0x61, 0x73, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20,
-0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61,
-0x6e, 0x64, 0x73, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e,
-0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x46, 0x69, 0x6a,
-0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x73, 0x3b, 0x55, 0x4b, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x55, 0x4b, 0x20, 0x70, 0x6f, 0x75,
-0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x4b, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x47, 0x61, 0x6d, 0x62,
-0x69, 0x61, 0x6e, 0x20, 0x44, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x3b, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20,
-0x64, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x61,
-0x6c, 0x61, 0x73, 0x69, 0x73, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x43, 0x65, 0x64, 0x69, 0x3b,
-0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x63, 0x65, 0x64, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x68,
-0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x63, 0x65, 0x64, 0x69, 0x73, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74,
-0x61, 0x72, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20,
-0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x70,
-0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x3b, 0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x73, 0x3b, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b,
-0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b,
-0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x49, 0x6e,
-0x64, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x72,
-0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65,
-0x73, 0x3b, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x53, 0x68, 0x65, 0x71, 0x65, 0x6c,
-0x3b, 0x3b, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x68, 0x65, 0x71, 0x65, 0x6c,
-0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x68, 0x65, 0x71,
-0x65, 0x6c, 0x73, 0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
-0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b,
-0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4b, 0x65, 0x6e,
-0x79, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e,
-0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e, 0x20,
-0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69,
-0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69,
-0x63, 0x61, 0x6e, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66,
-0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20,
-0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c,
-0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
-0x61, 0x72, 0x73, 0x3b, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x61, 0x74, 0x61, 0x63, 0x61, 0x3b,
-0x3b, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
-0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x73, 0x3b, 0x4d, 0x61, 0x6c,
-0x61, 0x67, 0x61, 0x73, 0x79, 0x20, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61,
-0x73, 0x79, 0x20, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73,
-0x79, 0x20, 0x61, 0x72, 0x69, 0x61, 0x72, 0x69, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20,
-0x4b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61,
-0x63, 0x68, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63,
-0x68, 0x61, 0x73, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x69, 0x6e, 0x67, 0x67, 0x69,
-0x74, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x67, 0x69, 0x74,
-0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x67, 0x69,
-0x74, 0x73, 0x3b, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b,
-0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d,
-0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x4e, 0x61, 0x6d, 0x69,
-0x62, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61,
-0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x6e,
-0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x4e, 0x61,
-0x69, 0x72, 0x61, 0x3b, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x69, 0x72, 0x61, 0x3b,
-0x3b, 0x3b, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x69, 0x72, 0x61, 0x73, 0x3b, 0x50,
-0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x69, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x50, 0x61, 0x6b, 0x69,
-0x73, 0x74, 0x61, 0x6e, 0x69, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x6b, 0x69, 0x73,
-0x74, 0x61, 0x6e, 0x69, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65,
-0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x4b, 0x69, 0x6e, 0x61, 0x3b, 0x3b, 0x50, 0x61, 0x70, 0x75,
-0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6b, 0x69, 0x6e, 0x61, 0x3b, 0x3b,
-0x3b, 0x3b, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20,
-0x6b, 0x69, 0x6e, 0x61, 0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x50, 0x65, 0x73, 0x6f,
-0x3b, 0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x65, 0x73, 0x6f, 0x3b, 0x3b, 0x3b,
-0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x3b, 0x52, 0x77,
-0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x6e,
-0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x66, 0x72,
-0x61, 0x6e, 0x63, 0x73, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x54, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x53, 0x61,
-0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x74, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20,
-0x74, 0x61, 0x6c, 0x61, 0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x52, 0x75, 0x70,
-0x65, 0x65, 0x3b, 0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x72, 0x75, 0x70, 0x65,
-0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x72, 0x75, 0x70,
-0x65, 0x65, 0x73, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x4c,
-0x65, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e,
-0x20, 0x6c, 0x65, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f,
-0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6c, 0x65, 0x6f, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72,
-0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20,
-0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20,
-0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61,
-0x6e, 0x64, 0x73, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20,
-0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f,
-0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
-0x73, 0x3b, 0x53, 0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b,
-0x53, 0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b,
-0x53, 0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x53, 0x75,
-0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65,
-0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65,
-0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x4c, 0x69, 0x6c, 0x61, 0x6e, 0x67,
-0x65, 0x6e, 0x69, 0x3b, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x6c, 0x69, 0x6c, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x69,
-0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x69,
-0x3b, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x53, 0x77, 0x65, 0x64,
-0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68,
-0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x6f, 0x72, 0x3b, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b,
-0x3b, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x69, 0x73,
-0x73, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e, 0x20, 0x53,
-0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e, 0x20, 0x73,
-0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e,
-0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x50, 0x61,
-0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x70, 0x61, 0x2bb, 0x61, 0x6e, 0x67,
-0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x70, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x3b,
-0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x44, 0x6f,
-0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62,
-0x61, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64,
-0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b,
-0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x55, 0x67,
-0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x67,
-0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x42, 0x72, 0x69, 0x74,
-0x69, 0x73, 0x68, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x70,
-0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x70, 0x6f, 0x75, 0x6e,
-0x64, 0x73, 0x3b, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x20, 0x56, 0x61, 0x74, 0x75, 0x3b, 0x3b, 0x56, 0x61, 0x6e,
-0x75, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x74, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75,
-0x20, 0x76, 0x61, 0x74, 0x75, 0x73, 0x3b, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61, 0x63, 0x68,
-0x61, 0x3b, 0x3b, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b, 0x3b,
-0x3b, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x73, 0x3b, 0x53, 0x6f, 0x75,
-0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53,
-0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b,
-0x3b, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f,
-0x75, 0x6e, 0x64, 0x73, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e, 0x74,
-0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x47, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x3b, 0x3b, 0x4e, 0x65, 0x74, 0x68,
-0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x67, 0x75,
-0x69, 0x6c, 0x64, 0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73,
-0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x67, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x73, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x74, 0x3b,
-0x64, 0x6f, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x64, 0x6f, 0x6e, 0x73, 0x6b, 0x20, 0x6b,
-0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x61, 0x72, 0x20, 0x6b, 0x72, 0xf3, 0x6e,
-0x75, 0x72, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72,
-0x6f, 0x61, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x64,
-0x69, 0x6e, 0x61, 0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69, 0x6e,
-0x61, 0x72, 0x73, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20,
-0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43,
-0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73,
-0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x62,
-0x75, 0x72, 0x75, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x62, 0x75, 0x72, 0x75,
-0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x62, 0x75, 0x72, 0x75,
-0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41,
-0x43, 0x29, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29,
-0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43,
-0x29, 0x3b, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x64,
-0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x6f,
-0x6c, 0x6c, 0x61, 0x72, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e,
-0x63, 0x20, 0x63, 0x6f, 0x6d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f,
-0x6d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x63, 0x6f, 0x6d,
-0x6f, 0x72, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61,
-0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x3b,
-0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x3b,
-0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72,
-0x61, 0x6e, 0x63, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72,
-0x61, 0x6e, 0x63, 0x73, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61,
-0x6e, 0x63, 0x20, 0x43, 0x46, 0x50, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x50, 0x3b, 0x3b, 0x3b,
-0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x50, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x67, 0x75,
-0x69, 0x6e, 0xe9, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e,
-0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e, 0x73, 0x3b,
-0x67, 0x6f, 0x75, 0x72, 0x64, 0x65, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x67, 0x6f,
-0x75, 0x72, 0x64, 0x65, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x6f,
-0x75, 0x72, 0x64, 0x65, 0x73, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b, 0x61, 0x72, 0x69,
-0x61, 0x72, 0x79, 0x20, 0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x3b, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79,
-0x20, 0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x73,
-0x20, 0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x73, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x20, 0x6d,
-0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x20,
-0x6d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69,
-0x79, 0x61, 0x73, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x72, 0x6f, 0x75,
-0x70, 0x69, 0x65, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x72, 0x6f, 0x75,
-0x70, 0x69, 0x65, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x72,
-0x6f, 0x75, 0x70, 0x69, 0x65, 0x73, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b,
-0x64, 0x69, 0x72, 0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x72,
-0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69, 0x72, 0x68,
-0x61, 0x6d, 0x73, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20,
-0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x72, 0x77, 0x61, 0x6e,
-0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x72, 0x77, 0x61, 0x6e, 0x64,
-0x61, 0x69, 0x73, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x64, 0x65, 0x73, 0x20, 0x53, 0x65, 0x79, 0x63, 0x68,
-0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x64, 0x65, 0x73, 0x20, 0x53, 0x65,
-0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x73, 0x20,
-0x64, 0x65, 0x73, 0x20, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
-0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73,
-0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x73, 0x3b,
-0x6c, 0x69, 0x76, 0x72, 0x65, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x6c, 0x69, 0x76, 0x72,
-0x65, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, 0x69, 0x76, 0x72, 0x65, 0x73,
-0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x74, 0x75, 0x6e,
-0x69, 0x73, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65,
-0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x73, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x6e,
-0x73, 0x3b, 0x76, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x3b, 0x3b, 0x76, 0x61,
-0x74, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x76, 0x61, 0x74, 0x75,
-0x73, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x73, 0x3b, 0x50, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53,
-0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73,
-0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e,
-0x61, 0x63, 0x68, 0x3b, 0x70, 0x75, 0x69, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63,
-0x68, 0x3b, 0x3b, 0x70, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x10e5,
-0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8,
-0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x3b, 0x3b, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0,
-0x10d8, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f,
-0x3b, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x3b,
-0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x3b, 0x3b,
-0x3b, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x395,
-0x3c5, 0x3c1, 0x3ce, 0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x64, 0x61,
-0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x3b, 0x64,
-0x61, 0x6e, 0x73, 0x6b, 0x69, 0x6e, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b,
-0x64, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b,
-0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x3b, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0,
-0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x3b, 0x3b, 0x3b, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf, 0x20, 0xab0,
-0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x75,
-0x257, 0x69, 0x6e, 0x20, 0x53, 0x65, 0x66, 0x61, 0x20, 0x6e, 0x61, 0x20, 0x41, 0x66, 0x69, 0x72, 0x6b, 0x61, 0x20, 0x54,
-0x61, 0x20, 0x59, 0x61, 0x6d, 0x6d, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5e9, 0x5f4, 0x5d7, 0x3b, 0x3b, 0x5e9,
-0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9,
-0x5d9, 0x5dd, 0x3b, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9,
-0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e,
+0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633,
+0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629,
+0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x644, 0x64a, 0x631, 0x629, 0x20, 0x633, 0x648, 0x631, 0x64a, 0x629, 0x3b, 0x62f, 0x64a,
+0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633,
+0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627,
+0x646, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x627, 0x646, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x627, 0x62a, 0x20, 0x62a, 0x648,
+0x646, 0x633, 0x64a, 0x629, 0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x64b, 0x627, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x64b, 0x627,
+0x3b, 0x62f, 0x64a, 0x646, 0x627, 0x631, 0x20, 0x62a, 0x648, 0x646, 0x633, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645,
+0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f,
+0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627,
+0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631,
+0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631, 0x627, 0x62a, 0x64a, 0x3b, 0x62f, 0x631, 0x647, 0x645, 0x20, 0x625, 0x645, 0x627, 0x631,
+0x627, 0x62a, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a,
+0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a,
+0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a,
+0x645, 0x646, 0x64a, 0x3b, 0x631, 0x64a, 0x627, 0x644, 0x20, 0x64a, 0x645, 0x646, 0x64a, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c,
+0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646, 0x648,
+0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20,
+0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x627, 0x646, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20,
+0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x627, 0x62a, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20,
+0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x64b, 0x627, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20,
+0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x62c, 0x646, 0x64a, 0x647, 0x20, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644,
+0x633, 0x648, 0x62f, 0x627, 0x646, 0x3b, 0x540, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b,
+0x3b, 0x570, 0x561, 0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b, 0x3b, 0x3b, 0x3b, 0x570, 0x561,
+0x575, 0x56f, 0x561, 0x56f, 0x561, 0x576, 0x20, 0x564, 0x580, 0x561, 0x574, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63,
+0x61, 0x6e, 0x20, 0x4d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61,
+0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63,
+0x61, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x131, 0x3b, 0x43c, 0x430, 0x43d, 0x430, 0x442, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x61, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72,
+0x6f, 0x3b, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b, 0x3b, 0x9ac, 0x9be,
+0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b, 0x3b, 0x3b, 0x3b, 0x9ac, 0x9be, 0x982, 0x9b2,
+0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9c0, 0x20, 0x99f, 0x9be, 0x995, 0x9be, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0,
+0x9c1, 0x9aa, 0x9bf, 0x3b, 0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0x3b, 0x3b, 0x3b,
+0x3b, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0x9c0, 0x9af, 0x9bc, 0x20, 0x9b0, 0x9c1, 0x9aa, 0x9bf, 0x3b, 0xf51, 0xf44, 0xf74, 0xf63, 0xf0b, 0xf40,
+0xfb2, 0xf58, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b,
+0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x61, 0x20, 0x65, 0x75, 0x72, 0x6f, 0x69, 0x6f, 0xf9, 0x3b,
+0x65, 0x75, 0x72, 0x6f, 0x3b, 0x411, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x3b, 0x3b,
+0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x3b, 0x3b, 0x3b, 0x3b, 0x431, 0x44a, 0x43b,
+0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x20, 0x43b, 0x435, 0x432, 0x430, 0x3b, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x1000, 0x103b,
+0x1015, 0x103a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x1000, 0x103b, 0x1015, 0x103a, 0x3b, 0x431,
+0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b,
+0x430, 0x440, 0x443, 0x441, 0x43a, 0x456, 0x20, 0x440, 0x443, 0x431, 0x435, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440,
+0x443, 0x441, 0x43a, 0x456, 0x44f, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x456, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a,
+0x456, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x451, 0x45e, 0x3b, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x430, 0x433,
+0x430, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x179a, 0x17c0, 0x179b, 0x200b, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x3b, 0x65, 0x75, 0x72,
+0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x73, 0x3b, 0x4eba, 0x6c11, 0x5e01,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4eba, 0x6c11, 0x5e01, 0x3b, 0x6e2f, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e2f, 0x5143,
+0x3b, 0x6fb3, 0x95e8, 0x5e01, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6fb3, 0x95e8, 0x5143, 0x3b, 0x65b0, 0x52a0, 0x5761, 0x5143, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x65b0, 0x52a0, 0x5761, 0x5143, 0x3b, 0x6fb3, 0x9580, 0x5143, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6fb3, 0x9580,
+0x5143, 0x3b, 0x65b0, 0x53f0, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65b0, 0x53f0, 0x5e63, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74,
+0x73, 0x6b, 0x61, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x61, 0x20, 0x6b,
+0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x75, 0x6e, 0x65, 0x3b, 0x3b,
+0x68, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x75, 0x6e, 0x61, 0x3b, 0x6b, 0x6f, 0x6e, 0x76, 0x65,
+0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x6b, 0x6f, 0x6e, 0x76,
+0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x6b, 0x6f, 0x6e,
+0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x6b, 0x6f,
+0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x3b,
+0x10d, 0x65, 0x73, 0x6b, 0xe1, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe1, 0x20,
+0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x61, 0x3b, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe9, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x79,
+0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xe9, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x79, 0x3b, 0x10d, 0x65, 0x73, 0x6b, 0xfd, 0x63,
+0x68, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x6e, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b,
+0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73,
+0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f,
+0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67,
+0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c,
+0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x72, 0x75, 0x62, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c,
+0x64, 0x65, 0x6e, 0x3b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c,
+0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x4e, 0x65, 0x64, 0x65,
+0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20,
+0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73,
+0x2d, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x69, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x67, 0x75, 0x6c, 0x64, 0x65, 0x6e,
+0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b,
+0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
+0x3b, 0x53, 0x75, 0x72, 0x69, 0x6e, 0x61, 0x61, 0x6d, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x41,
+0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
+0x3b, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
+0x55, 0x53, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x45, 0x61, 0x73, 0x74, 0x20,
+0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x45, 0x61,
+0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
+0x3b, 0x3b, 0x3b, 0x45, 0x61, 0x73, 0x74, 0x20, 0x43, 0x61, 0x72, 0x69, 0x62, 0x62, 0x65, 0x61, 0x6e, 0x20, 0x64, 0x6f,
+0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x73, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65,
+0x75, 0x72, 0x6f, 0x73, 0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x3b, 0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
+0x3b, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42, 0x61,
+0x72, 0x62, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x61, 0x72, 0x62,
+0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x61, 0x72, 0x62,
+0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65,
+0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73,
+0x3b, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x42, 0x65,
+0x72, 0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x65, 0x72,
+0x6d, 0x75, 0x64, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61,
+0x6e, 0x61, 0x6e, 0x20, 0x50, 0x75, 0x6c, 0x61, 0x3b, 0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e, 0x20,
+0x70, 0x75, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x6e, 0x20, 0x70, 0x75,
+0x6c, 0x61, 0x73, 0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b,
+0x3b, 0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b,
+0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x3b, 0x43, 0x65, 0x6e,
+0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20, 0x46, 0x72, 0x61,
+0x6e, 0x63, 0x3b, 0x3b, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20,
+0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x6c,
+0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x3b,
+0x43, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x43, 0x61, 0x6e,
+0x61, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x61, 0x6e, 0x61,
+0x64, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20,
+0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x43, 0x61, 0x79, 0x6d,
+0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
+0x3b, 0x43, 0x61, 0x79, 0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x73, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x44, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x3b, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x64, 0x6f,
+0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b,
+0x44, 0x61, 0x6e, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x61, 0x6e, 0x69,
+0x73, 0x68, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x4e,
+0x61, 0x6b, 0x66, 0x61, 0x3b, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x6b, 0x66, 0x61,
+0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x6b, 0x66, 0x61, 0x73, 0x3b,
+0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x50, 0x6f, 0x75,
+0x6e, 0x64, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73,
+0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49,
+0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e,
+0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x69, 0x6a, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73,
+0x3b, 0x55, 0x4b, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x55, 0x4b, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b,
+0x3b, 0x3b, 0x3b, 0x55, 0x4b, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e,
+0x20, 0x44, 0x61, 0x6c, 0x61, 0x73, 0x69, 0x3b, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x61, 0x6c,
+0x61, 0x73, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x61, 0x6c, 0x61, 0x73,
+0x69, 0x73, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x43, 0x65, 0x64, 0x69, 0x3b, 0x3b, 0x47, 0x68,
+0x61, 0x6e, 0x61, 0x69, 0x61, 0x6e, 0x20, 0x63, 0x65, 0x64, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61,
+0x69, 0x61, 0x6e, 0x20, 0x63, 0x65, 0x64, 0x69, 0x73, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20,
+0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x70, 0x6f, 0x75,
+0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x20, 0x70, 0x6f, 0x75, 0x6e,
+0x64, 0x73, 0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b,
+0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b,
+0x3b, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x65, 0x73, 0x65, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x48,
+0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x48, 0x6f, 0x6e,
+0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x48, 0x6f, 0x6e,
+0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61,
+0x6e, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65,
+0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x49,
+0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x53, 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x3b, 0x3b, 0x49,
+0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x3b, 0x3b, 0x3b,
+0x3b, 0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x69, 0x20, 0x6e, 0x65, 0x77, 0x20, 0x73, 0x68, 0x65, 0x6b, 0x65, 0x6c, 0x73,
+0x3b, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4a, 0x61,
+0x6d, 0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4a, 0x61, 0x6d,
+0x61, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e,
+0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e, 0x20, 0x73, 0x68,
+0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69,
+0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e,
+0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e,
+0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63,
+0x61, 0x6e, 0x20, 0x72, 0x61, 0x6e, 0x64, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x44, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72,
+0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73,
+0x3b, 0x4d, 0x61, 0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x61, 0x74, 0x61, 0x63, 0x61, 0x3b, 0x3b, 0x4d, 0x61,
+0x63, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x63,
+0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x61, 0x74, 0x61, 0x63, 0x61, 0x73, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61,
+0x73, 0x79, 0x20, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x20,
+0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x20, 0x61,
+0x72, 0x69, 0x61, 0x72, 0x69, 0x65, 0x73, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61,
+0x63, 0x68, 0x61, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61,
+0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x73,
+0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x3b, 0x3b,
+0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x3b, 0x3b, 0x3b,
+0x3b, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x73, 0x3b,
+0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x4d, 0x61, 0x75,
+0x72, 0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x61, 0x75, 0x72,
+0x69, 0x74, 0x69, 0x61, 0x6e, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61,
+0x6e, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64,
+0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x64, 0x6f,
+0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x4e, 0x61, 0x69, 0x72, 0x61,
+0x3b, 0x3b, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x69, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
+0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x6e, 0x20, 0x6e, 0x61, 0x69, 0x72, 0x61, 0x73, 0x3b, 0x50, 0x61, 0x6b, 0x69,
+0x73, 0x74, 0x61, 0x6e, 0x69, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61,
+0x6e, 0x69, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e,
+0x69, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73, 0x3b, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47,
+0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x4b, 0x69, 0x6e, 0x61, 0x3b, 0x3b, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e,
+0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6b, 0x69, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x50,
+0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6b, 0x69, 0x6e,
+0x61, 0x3b, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x50, 0x65, 0x73, 0x6f, 0x3b, 0x3b, 0x50,
+0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x65, 0x73, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x68,
+0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x20, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64,
+0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x66, 0x72,
+0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x6e, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63,
+0x73, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x54, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61,
+0x6e, 0x20, 0x74, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x6e, 0x20, 0x74, 0x61, 0x6c,
+0x61, 0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x52, 0x75, 0x70, 0x65, 0x65, 0x3b,
+0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x3b, 0x3b,
+0x3b, 0x3b, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x69, 0x73, 0x20, 0x72, 0x75, 0x70, 0x65, 0x65, 0x73,
+0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x4c, 0x65, 0x6f, 0x6e,
+0x65, 0x3b, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61, 0x6e, 0x20, 0x6c, 0x65,
+0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e, 0x65, 0x61,
+0x6e, 0x20, 0x6c, 0x65, 0x6f, 0x6e, 0x65, 0x73, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x44,
+0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x64, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x20, 0x64, 0x6f, 0x6c,
+0x6c, 0x61, 0x72, 0x73, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73,
+0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c,
+0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x6f, 0x6c, 0x6f, 0x6d,
+0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x53,
+0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x74, 0x2e,
+0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x74, 0x2e,
+0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b, 0x53, 0x75, 0x64, 0x61, 0x6e,
+0x65, 0x73, 0x65, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20,
+0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f,
+0x75, 0x6e, 0x64, 0x73, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x4c, 0x69, 0x6c, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x69,
+0x3b, 0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x6c, 0x69, 0x6c, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x69, 0x3b, 0x3b, 0x3b,
+0x3b, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x20, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x6e, 0x67, 0x65, 0x6e, 0x69, 0x3b, 0x53, 0x77,
+0x65, 0x64, 0x69, 0x73, 0x68, 0x20, 0x4b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68,
+0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x65, 0x64, 0x69, 0x73, 0x68, 0x20, 0x6b, 0x72,
+0x6f, 0x6e, 0x6f, 0x72, 0x3b, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x53, 0x77,
+0x69, 0x73, 0x73, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x77, 0x69, 0x73, 0x73, 0x20, 0x66,
+0x72, 0x61, 0x6e, 0x63, 0x73, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c,
+0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c,
+0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x6e, 0x20, 0x73, 0x68,
+0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x50, 0x61, 0x2bb, 0x61, 0x6e,
+0x67, 0x61, 0x3b, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x70, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x3b,
+0x3b, 0x3b, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x6e, 0x20, 0x70, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x3b, 0x54, 0x72, 0x69,
+0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x44, 0x6f, 0x6c, 0x6c, 0x61,
+0x72, 0x3b, 0x3b, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f,
+0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20,
+0x26, 0x20, 0x54, 0x6f, 0x62, 0x61, 0x67, 0x6f, 0x20, 0x64, 0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x73, 0x3b, 0x55, 0x67, 0x61,
+0x6e, 0x64, 0x61, 0x6e, 0x20, 0x53, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x55, 0x67, 0x61, 0x6e, 0x64,
+0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x67, 0x61, 0x6e, 0x64,
+0x61, 0x6e, 0x20, 0x73, 0x68, 0x69, 0x6c, 0x6c, 0x69, 0x6e, 0x67, 0x73, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68,
+0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x70, 0x6f, 0x75, 0x6e,
+0x64, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x73, 0x3b,
+0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x20, 0x56, 0x61, 0x74, 0x75, 0x3b, 0x3b, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74,
+0x75, 0x20, 0x76, 0x61, 0x74, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x20, 0x76, 0x61,
+0x74, 0x75, 0x73, 0x3b, 0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x4b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b,
+0x5a, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x5a, 0x61,
+0x6d, 0x62, 0x69, 0x61, 0x6e, 0x20, 0x6b, 0x77, 0x61, 0x63, 0x68, 0x61, 0x73, 0x3b, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20,
+0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x50, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x53, 0x6f, 0x75, 0x74,
+0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b,
+0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x65, 0x73, 0x65, 0x20, 0x70, 0x6f, 0x75, 0x6e, 0x64,
+0x73, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c,
+0x65, 0x61, 0x6e, 0x20, 0x47, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x3b, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c,
+0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e, 0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x67, 0x75, 0x69, 0x6c, 0x64,
+0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x20, 0x41, 0x6e,
+0x74, 0x69, 0x6c, 0x6c, 0x65, 0x61, 0x6e, 0x20, 0x67, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x73, 0x3b, 0x65, 0x75, 0x72,
+0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x74, 0x3b, 0x64, 0x6f, 0x6e,
+0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x64, 0x6f, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e,
+0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x61, 0x72, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x75, 0x72, 0x3b,
+0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x61, 0x3b,
+0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61,
+0x72, 0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x73,
+0x20, 0x61, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41,
+0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20,
+0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46,
+0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x62, 0x75, 0x72, 0x75,
+0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x61,
+0x69, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x61,
+0x69, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b,
+0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b,
+0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x64,
+0x6f, 0x6c, 0x6c, 0x61, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x64, 0x6f, 0x6c, 0x6c,
+0x61, 0x72, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x6f, 0x6c, 0x6c, 0x61,
+0x72, 0x73, 0x20, 0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63,
+0x6f, 0x6d, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6d, 0x6f, 0x72,
+0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x63, 0x6f, 0x6d, 0x6f, 0x72, 0x69,
+0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x3b,
+0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x3b, 0x3b,
+0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x63, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x69, 0x73, 0x3b, 0x66, 0x72, 0x61,
+0x6e, 0x63, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
+0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
+0x73, 0x20, 0x64, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20,
+0x43, 0x46, 0x50, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x50, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72,
+0x61, 0x6e, 0x63, 0x73, 0x20, 0x43, 0x46, 0x50, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9,
+0x65, 0x6e, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e, 0x3b, 0x3b, 0x3b,
+0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x67, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x6e, 0x73, 0x3b, 0x67, 0x6f, 0x75,
+0x72, 0x64, 0x65, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x67, 0x6f, 0x75, 0x72, 0x64,
+0x65, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x6f, 0x75, 0x72, 0x64,
+0x65, 0x73, 0x20, 0x68, 0x61, 0xef, 0x74, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79,
+0x20, 0x6d, 0x61, 0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x3b, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x20, 0x6d, 0x61,
+0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x61, 0x72, 0x69, 0x61, 0x72, 0x79, 0x73, 0x20, 0x6d, 0x61,
+0x6c, 0x67, 0x61, 0x63, 0x68, 0x65, 0x73, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x20, 0x6d, 0x61, 0x75, 0x72,
+0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x20, 0x6d, 0x61, 0x75,
+0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x6f, 0x75, 0x67, 0x75, 0x69, 0x79, 0x61, 0x73,
+0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65,
+0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65,
+0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70,
+0x69, 0x65, 0x73, 0x20, 0x6d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x72,
+0x68, 0x61, 0x6d, 0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x72, 0x68, 0x61, 0x6d,
+0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x69, 0x72, 0x68, 0x61, 0x6d, 0x73,
+0x20, 0x6d, 0x61, 0x72, 0x6f, 0x63, 0x61, 0x69, 0x6e, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x72, 0x77, 0x61,
+0x6e, 0x64, 0x61, 0x69, 0x73, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x69,
+0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x69, 0x73,
+0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x64, 0x65, 0x73, 0x20, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c,
+0x65, 0x73, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x20, 0x64, 0x65, 0x73, 0x20, 0x53, 0x65, 0x79, 0x63, 0x68,
+0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69, 0x65, 0x73, 0x20, 0x64, 0x65, 0x73,
+0x20, 0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x75,
+0x69, 0x73, 0x73, 0x65, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x3b, 0x3b,
+0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x73, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x73, 0x3b, 0x6c, 0x69, 0x76,
+0x72, 0x65, 0x20, 0x73, 0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x6c, 0x69, 0x76, 0x72, 0x65, 0x20, 0x73,
+0x79, 0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, 0x69, 0x76, 0x72, 0x65, 0x73, 0x20, 0x73, 0x79,
+0x72, 0x69, 0x65, 0x6e, 0x6e, 0x65, 0x73, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73, 0x69,
+0x65, 0x6e, 0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x3b, 0x3b,
+0x3b, 0x3b, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x73, 0x20, 0x74, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x73, 0x3b, 0x76,
+0x61, 0x74, 0x75, 0x20, 0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x3b, 0x3b, 0x76, 0x61, 0x74, 0x75, 0x20,
+0x76, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x76, 0x61, 0x74, 0x75, 0x73, 0x20, 0x76,
+0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x61, 0x6e, 0x73, 0x3b, 0x50, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61,
+0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e,
+0x61, 0x63, 0x68, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68,
+0x3b, 0x70, 0x75, 0x69, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x68, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x3b,
+0x70, 0x75, 0x6e, 0x6e, 0x64, 0x20, 0x53, 0x61, 0x73, 0x61, 0x6e, 0x6e, 0x61, 0x63, 0x68, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7,
+0x10e3, 0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20, 0x10da, 0x10d0,
+0x10e0, 0x10d8, 0x3b, 0x3b, 0x3b, 0x3b, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x20, 0x10da, 0x10d0, 0x10e0, 0x10d8, 0x3b, 0x45,
+0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x53, 0x63,
+0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x3b, 0x53, 0x63, 0x68,
+0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x63,
+0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x6e, 0x3b, 0x395, 0x3c5, 0x3c1, 0x3ce,
+0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b5, 0x3c5, 0x3c1, 0x3ce, 0x3b, 0x64, 0x61, 0x6e, 0x6d, 0x61,
+0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x3b, 0x64, 0x61, 0x6e, 0x73,
+0x6b, 0x69, 0x6e, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0x61, 0x6e,
+0x6d, 0x61, 0x72, 0x6b, 0x69, 0x6d, 0x75, 0x74, 0x20, 0x6b, 0x6f, 0x72, 0x75, 0x75, 0x6e, 0x69, 0x3b, 0xaad, 0xabe, 0xab0,
+0xaa4, 0xac0, 0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x3b, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf, 0x20, 0xab0,
+0xac2, 0xaaa, 0xabf, 0xaaf, 0xabe, 0x3b, 0x3b, 0x3b, 0x3b, 0xaad, 0xabe, 0xab0, 0xaa4, 0xac0, 0xaaf, 0x20, 0xab0, 0xac2, 0xaaa, 0xabf,
+0xaaf, 0xabe, 0x3b, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x75, 0x257, 0x69, 0x6e,
+0x20, 0x53, 0x65, 0x66, 0x61, 0x20, 0x6e, 0x61, 0x20, 0x41, 0x66, 0x69, 0x72, 0x6b, 0x61, 0x20, 0x54, 0x61, 0x20, 0x59,
+0x61, 0x6d, 0x6d, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x3b, 0x3b,
+0x5e9, 0x5e7, 0x5dc, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b,
+0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7, 0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x5e9, 0x5e7, 0x5dc, 0x5d9, 0x5dd, 0x20, 0x5d7,
+0x5d3, 0x5e9, 0x5d9, 0x5dd, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x92d,
+0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940,
+0x92f, 0x20, 0x930, 0x942, 0x92a, 0x90f, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74,
+0x3b, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0x3b, 0x3b, 0x3b, 0x6d,
+0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b,
+0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e,
+0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x72, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x75,
+0x72, 0x3b, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61,
+0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72,
+0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75,
+0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x76,
+0x69, 0x7a, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a,
+0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x69, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a,
+0x65, 0x72, 0x69, 0x3b, 0x65e5, 0x672c, 0x5186, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5186, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0,
+0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf, 0x3b, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa,
+0xcbe, 0xcaf, 0xcbf, 0x3b, 0x3b, 0x3b, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf,
+0xc97, 0xcb3, 0xcc1, 0x3b, 0x6c1, 0x650, 0x646, 0x62f, 0x64f, 0x633, 0x62a, 0x672, 0x646, 0x6cd, 0x20, 0x631, 0x6c4, 0x67e, 0x64e, 0x6d2,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442, 0x435, 0x4a3,
+0x433, 0x435, 0x441, 0x456, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442, 0x435, 0x4a3, 0x433,
+0x435, 0x441, 0x456, 0x3b, 0x3b, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442, 0x435, 0x4a3,
+0x433, 0x435, 0x441, 0x456, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443,
+0x3b, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443, 0x3b, 0x3b, 0x3b,
+0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443, 0x3b, 0xb300, 0xd55c, 0xbbfc,
+0xad6d, 0x20, 0xc6d0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0x20, 0xc6d0, 0x3b, 0xc870, 0xc120, 0x20, 0xbbfc,
+0xc8fc, 0xc8fc, 0xc758, 0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xc870, 0xc120,
+0x20, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x49, 0x66, 0x61, 0x72, 0x61,
+0x6e, 0x67, 0x61, 0x20, 0x72, 0x79, 0x2019, 0x55, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0xea5, 0xeb2, 0xea7, 0x20, 0xe81, 0xeb5, 0xe9a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xea5, 0xeb2, 0xea7, 0x20, 0xe81,
+0xeb5, 0xe9a, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x3b,
+0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x61, 0x6c, 0xe1, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e,
+0x67, 0xf3, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x20, 0x79, 0x61, 0x20, 0x41,
+0x6e, 0x67, 0xf3, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0xe1, 0x6e, 0x67, 0x61, 0x20,
+0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x61, 0x73,
+0x3b, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x73, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x69, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b,
+0x65, 0x75, 0x72, 0x173, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d, 0x430,
+0x440, 0x3b, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d, 0x430, 0x440, 0x3b,
+0x3b, 0x3b, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d, 0x430, 0x440, 0x438,
+0x3b, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x69, 0x6e, 0x67, 0x67, 0x69,
+0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x69, 0x6e, 0x67,
+0x67, 0x69, 0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x42,
+0x72, 0x75, 0x6e, 0x65, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x42, 0x72, 0x75,
+0x6e, 0x65, 0x69, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72, 0x61, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72, 0x61,
+0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f,
+0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a,
+0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x65, 0x77,
+0x72, 0x6f, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e,
0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d, 0x93e,
-0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x90f, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72,
-0x69, 0x6e, 0x74, 0x3b, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0x3b,
-0x3b, 0x3b, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x20, 0x66, 0x6f, 0x72, 0x69, 0x6e, 0x74, 0x3b, 0xed, 0x73, 0x6c, 0x65,
-0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b,
-0x72, 0xf3, 0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x72, 0x20, 0x6b, 0x72,
-0xf3, 0x6e, 0x75, 0x72, 0x3b, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69,
-0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x75, 0x70, 0x69, 0x61, 0x68, 0x20, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65,
-0x73, 0x69, 0x61, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b,
-0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f,
-0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x76,
-0x69, 0x7a, 0x7a, 0x65, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x69, 0x20, 0x73, 0x76,
-0x69, 0x7a, 0x7a, 0x65, 0x72, 0x69, 0x3b, 0x65e5, 0x672c, 0x5186, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x5186, 0x3b, 0xcad, 0xcbe,
-0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf, 0x3b, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20,
-0xcb0, 0xcc2, 0xcaa, 0xcbe, 0xcaf, 0xcbf, 0x3b, 0x3b, 0x3b, 0x3b, 0xcad, 0xcbe, 0xcb0, 0xca4, 0xcc0, 0xcaf, 0x20, 0xcb0, 0xcc2, 0xcaa,
-0xcbe, 0xcaf, 0xcbf, 0xc97, 0xcb3, 0xcc1, 0x3b, 0x6c1, 0x650, 0x646, 0x62f, 0x64f, 0x633, 0x62a, 0x672, 0x646, 0x6cd, 0x20, 0x631, 0x6c4,
-0x67e, 0x64e, 0x6d2, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20,
-0x442, 0x435, 0x4a3, 0x433, 0x435, 0x441, 0x456, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x442,
-0x435, 0x4a3, 0x433, 0x435, 0x441, 0x456, 0x3b, 0x3b, 0x3b, 0x3b, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x20,
-0x442, 0x435, 0x4a3, 0x433, 0x435, 0x441, 0x456, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441,
-0x43e, 0x43c, 0x443, 0x3b, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443,
-0x3b, 0x3b, 0x3b, 0x3b, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0x20, 0x441, 0x43e, 0x43c, 0x443, 0x3b,
-0xb300, 0xd55c, 0xbbfc, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0x20, 0xc6d0, 0x3b, 0xc870,
-0xc120, 0x20, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0xc870, 0xc120, 0x20, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0x20, 0xc778, 0xbbfc, 0x20, 0xacf5, 0xd654, 0xad6d, 0x20, 0xc6d0, 0x3b, 0x49, 0x66,
-0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x72, 0x79, 0x2019, 0x55, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xea5, 0xeb2, 0xea7, 0x20, 0xe81, 0xeb5, 0xe9a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xea5, 0xeb2,
-0xea7, 0x20, 0xe81, 0xeb5, 0xe9a, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x65, 0x69, 0x72, 0x6f,
-0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x46, 0x61, 0x6c, 0xe1, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20,
-0x4b, 0x6f, 0x6e, 0x67, 0xf3, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x20, 0x79,
-0x61, 0x20, 0x41, 0x6e, 0x67, 0xf3, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x6c, 0xe1, 0x6e,
-0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75,
-0x72, 0x61, 0x73, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x73, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x69, 0x3b, 0x65, 0x75,
-0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x173, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434,
-0x435, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d,
-0x430, 0x440, 0x3b, 0x3b, 0x3b, 0x3b, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x435, 0x43d,
-0x430, 0x440, 0x438, 0x3b, 0x41, 0x72, 0x69, 0x61, 0x72, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x69, 0x6e,
-0x67, 0x67, 0x69, 0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x52,
-0x69, 0x6e, 0x67, 0x67, 0x69, 0x74, 0x20, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x3b, 0x44, 0x6f, 0x6c, 0x61,
-0x72, 0x20, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20,
-0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75,
-0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x72, 0x20, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70,
-0x75, 0x72, 0x61, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d,
-0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20, 0xd30, 0xd42, 0xd2a, 0x3b, 0x3b, 0x3b, 0x3b, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0xd7b, 0x20,
-0xd30, 0xd42, 0xd2a, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x77, 0x72, 0x6f,
-0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x65, 0x77, 0x72, 0x6f, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941,
-0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b,
-0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x947, 0x3b, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433,
-0x3b, 0x3b, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x3b, 0x3b, 0x3b, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x928,
-0x947, 0x92a, 0x93e, 0x932, 0x940, 0x20, 0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x3b, 0x928, 0x947, 0x92a, 0x93e, 0x932,
-0x940, 0x20, 0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x3b, 0x3b, 0x3b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x20,
-0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901,
-0x92f, 0x93e, 0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b, 0x3b,
-0x3b, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b, 0x6e, 0x6f, 0x72,
-0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x6b, 0x72,
-0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72,
-0x3b, 0xb1f, 0xb19, 0xb15, 0xb3e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cd, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x3b, 0x631, 0x6cc, 0x627,
-0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627,
-0x646, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x3b,
-0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b,
-0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x7a, 0x142, 0x6f,
-0x74, 0x79, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x3b, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x79, 0x20, 0x70, 0x6f, 0x6c,
-0x73, 0x6b, 0x69, 0x3b, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x65, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x65, 0x3b, 0x7a,
-0x142, 0x6f, 0x74, 0x79, 0x63, 0x68, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x63, 0x68, 0x3b, 0x7a, 0x142, 0x6f, 0x74,
-0x65, 0x67, 0x6f, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x65, 0x67, 0x6f, 0x3b, 0x52, 0x65, 0x61, 0x6c, 0x20, 0x62,
-0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x52, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73,
-0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x52, 0x65, 0x61, 0x69, 0x73, 0x20, 0x62, 0x72, 0x61, 0x73,
-0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x73, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c,
-0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f,
-0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x73, 0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f,
-0x73, 0x3b, 0x45, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x20, 0x63, 0x61, 0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61,
-0x6e, 0x6f, 0x3b, 0x3b, 0x45, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x20, 0x63, 0x61, 0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64,
-0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x73, 0x20, 0x63, 0x61, 0x62, 0x6f,
-0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x44, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x73,
-0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x3b, 0x3b, 0x44, 0xf3, 0x6c,
-0x61, 0x72, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f,
-0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74,
-0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43,
-0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46,
-0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20,
-0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46,
-0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46,
-0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73,
-0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x45,
-0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x73, 0x3b, 0x50, 0x61, 0x74, 0x61, 0x63, 0x61, 0x20,
-0x64, 0x65, 0x20, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x3b, 0x50, 0x61, 0x74, 0x61, 0x63, 0x61, 0x20, 0x64, 0x65, 0x20,
-0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x74, 0x61, 0x63, 0x61, 0x73, 0x20, 0x64, 0x65, 0x20,
-0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7,
-0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x20,
-0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61,
-0x6c, 0x65, 0x73, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0x44, 0x6f,
-0x62, 0x72, 0x61, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72,
-0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x3b, 0x44, 0x6f, 0x62, 0x72, 0x61, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f,
-0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x3b, 0x3b, 0x3b,
-0x44, 0x6f, 0x62, 0x72, 0x61, 0x73, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65,
-0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x75, 0xed,
-0xe7, 0x6f, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x75, 0xed, 0xe7, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
-0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x73, 0x75, 0xed, 0xe7, 0x6f, 0x73, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40,
-0x20, 0xa30, 0xa41, 0xa2a, 0xa07, 0xa06, 0x3b, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa07, 0xa06, 0x3b,
-0x3b, 0x3b, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa0f, 0x3b, 0x631, 0x648, 0x67e, 0x626, 0x6cc, 0x6c1,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72,
-0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x66,
-0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x72, 0x6f, 0x6d,
-0xe2, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x73, 0x63, 0x3b,
-0x3b, 0x6c, 0x65, 0x69, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20,
-0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76,
-0x65, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65,
-0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x219, 0x74, 0x69,
-0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x420,
-0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x440, 0x43e, 0x441,
-0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438,
-0x439, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a,
-0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x435, 0x439, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x43e, 0x433,
-0x43e, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x411, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x20,
-0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440,
-0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443,
-0x431, 0x43b, 0x44f, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b,
-0x435, 0x439, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x440, 0x443, 0x431, 0x43b,
-0x44f, 0x3b, 0x41a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x3b, 0x43a,
-0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x3b, 0x43a, 0x430, 0x437, 0x430,
-0x445, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438,
-0x445, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x442,
-0x435, 0x43d, 0x433, 0x435, 0x3b, 0x41a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x441, 0x43e, 0x43c, 0x3b,
-0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x43a, 0x438, 0x440,
-0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x441, 0x43e, 0x43c, 0x430, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441,
-0x43a, 0x438, 0x445, 0x20, 0x441, 0x43e, 0x43c, 0x430, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x43e, 0x433, 0x43e,
-0x20, 0x441, 0x43e, 0x43c, 0x430, 0x3b, 0x41c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x43b, 0x435, 0x439,
-0x3b, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x43b, 0x435, 0x439, 0x3b, 0x3b, 0x43c, 0x43e,
-0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x43b, 0x435, 0x44f, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441,
-0x43a, 0x438, 0x445, 0x20, 0x43b, 0x435, 0x435, 0x432, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x43e, 0x433, 0x43e,
-0x20, 0x43b, 0x435, 0x44f, 0x3b, 0x423, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440, 0x438, 0x432,
-0x43d, 0x430, 0x3b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d,
-0x430, 0x3b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x438, 0x435, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44b,
-0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x433, 0x440, 0x438, 0x432, 0x435, 0x43d, 0x3b, 0x443,
-0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x43e, 0x439, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44b, 0x3b, 0x66, 0x61, 0x72,
-0xe2, 0x6e, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x421, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441,
-0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x430, 0x20, 0x434, 0x438, 0x43d,
-0x430, 0x440, 0x430, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b,
-0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b,
-0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b,
-0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76,
-0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d,
-0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65,
-0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x65, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e,
-0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65,
-0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69,
-0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x3b, 0x45, 0x76, 0x72, 0x6f, 0x3b, 0x3b,
-0x65, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x53, 0x72, 0x70,
-0x73, 0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69,
-0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x61, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x61, 0x3b, 0x3b,
-0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x61, 0x3b, 0x411, 0x43e, 0x441, 0x430, 0x43d,
-0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d,
-0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e,
-0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20,
-0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b,
-0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447,
-0x43a, 0x435, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x435, 0x20, 0x43c, 0x430, 0x440,
-0x43a, 0x65, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e,
-0x432, 0x430, 0x447, 0x43a, 0x438, 0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x438,
-0x445, 0x20, 0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430, 0x3b, 0x415, 0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x43e, 0x3b,
-0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x41b, 0x430, 0x440, 0x3b, 0x3b, 0x43b, 0x430, 0x440,
-0x3b, 0x3b, 0x3b, 0x3b, 0x43b, 0x430, 0x440, 0x44b, 0x3b, 0x421, 0x43e, 0x43c, 0x3b, 0x3b, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x3b,
-0x3b, 0x441, 0x43e, 0x43c, 0x44b, 0x3b, 0x44, 0x6f, 0x72, 0x61, 0x20, 0x72, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b,
-0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb,
-0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x3b, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4,
-0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x3b, 0x3b, 0x3b, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb,
-0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75,
-0x72, 0xe1, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x3b, 0x65, 0x75, 0x72, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76,
-0x72, 0x6f, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x65, 0x76, 0x72, 0x69, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x76, 0x3b,
-0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x20, 0x4a, 0x61, 0x62, 0x62, 0x75, 0x75, 0x74, 0x69, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x42, 0x69, 0x72, 0x74, 0x61, 0x20, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x62, 0x69, 0x79, 0x61, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x61, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x3b,
-0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x61, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70,
-0x65, 0x73, 0x6f, 0x73, 0x20, 0x61, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x73, 0x3b, 0x62, 0x6f, 0x6c, 0x69,
-0x76, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
-0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73,
-0x69, 0x6c, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0xf1,
-0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0xf1,
-0x6f, 0x73, 0x3b, 0x50, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73,
-0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x63,
-0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69,
-0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x6f,
-0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61, 0x6e, 0x6f,
-0x73, 0x3b, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x72, 0x69, 0x63, 0x65, 0x6e, 0x73,
-0x65, 0x3b, 0x3b, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x72, 0x69, 0x63, 0x65, 0x6e,
-0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x63, 0x6f, 0x6c, 0x6f, 0x6e, 0x65, 0x73, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72,
-0x72, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f,
-0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73,
-0x6f, 0x73, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x6d, 0x69,
-0x6e, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63,
-0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63,
-0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75, 0x6e, 0x69,
-0x64, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75,
-0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73, 0x20, 0x65,
-0x73, 0x74, 0x61, 0x64, 0x6f, 0x75, 0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63,
-0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43,
-0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43,
-0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x3b, 0x3b, 0x71, 0x75, 0x65,
-0x74, 0x7a, 0x61, 0x6c, 0x3b, 0x3b, 0x3b, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x65, 0x73, 0x3b, 0x6c, 0x65,
-0x6d, 0x70, 0x69, 0x72, 0x61, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x6c, 0x65, 0x6d,
-0x70, 0x69, 0x72, 0x61, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x6c, 0x65,
-0x6d, 0x70, 0x69, 0x72, 0x61, 0x73, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x70, 0x65,
-0x73, 0x6f, 0x20, 0x6d, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x6d, 0x65,
-0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x6d, 0x65, 0x78, 0x69,
-0x63, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69, 0x63, 0x61, 0x72, 0x61,
-0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69, 0x63, 0x61,
-0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x73,
-0x20, 0x6e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f,
-0x61, 0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61, 0x20, 0x70,
-0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61, 0x73, 0x20, 0x70,
-0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70, 0x61, 0x72,
-0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70, 0x61, 0x72, 0x61,
-0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x65, 0x73, 0x20, 0x70,
-0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x73, 0x3b, 0x6e, 0x75, 0x65, 0x76, 0x6f, 0x20, 0x73, 0x6f, 0x6c, 0x20,
-0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x6e, 0x75, 0x65, 0x76, 0x6f, 0x20, 0x73, 0x6f, 0x6c, 0x20, 0x70,
-0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e, 0x75, 0x65, 0x76, 0x6f, 0x73, 0x20, 0x73, 0x6f, 0x6c,
-0x65, 0x73, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x66, 0x69, 0x6c,
-0x69, 0x70, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f,
-0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x73, 0x3b,
-0x70, 0x65, 0x73, 0x6f, 0x20, 0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20,
-0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x75, 0x72,
-0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x73, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x20, 0x76, 0x65, 0x6e, 0x65,
-0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x20, 0x76, 0x65, 0x6e, 0x65,
-0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x65, 0x73, 0x20,
-0x76, 0x65, 0x6e, 0x65, 0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69,
-0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e,
-0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68,
-0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x46,
-0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x3b, 0x66, 0x61, 0x72,
-0x61, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x61, 0x72,
-0x61, 0x6e, 0x67, 0x61, 0x20, 0x7a, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e,
-0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67,
-0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e,
-0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69,
-0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69,
-0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e,
-0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x20,
-0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b,
-0x3b, 0x3b, 0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x6f, 0x72, 0x3b, 0xb87, 0xba8,
-0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20,
-0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa,
-0xbbe, 0xbaf, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf, 0xb99, 0xbcd,
-0xb95, 0xbbf, 0xb9f, 0xbcd, 0x3b, 0x3b, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf, 0xb99, 0xbcd, 0xb95,
-0xbbf, 0xb9f, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf, 0xb99, 0xbcd,
-0xb95, 0xbbf, 0xb9f, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x20,
-0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0x3b, 0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x20, 0xb9f,
-0xbbe, 0xbb2, 0xbb0, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0x20,
-0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe,
-0xbaf, 0xbcd, 0x3b, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0x3b,
-0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xc30, 0xc42,
-0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b, 0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b, 0x3b, 0x3b, 0xc30, 0xc42, 0xc2a, 0xc3e,
-0xc2f, 0xc32, 0xc41, 0x3b, 0xe1a, 0xe32, 0xe17, 0xe44, 0xe17, 0xe22, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xe1a, 0xe32, 0xe17, 0xe44,
-0xe17, 0xe22, 0x3b, 0xf61, 0xf74, 0xf0b, 0xf68, 0xf53, 0xf0b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xf62, 0xf92, 0xfb1, 0xf0b,
-0xf42, 0xf62, 0xf0b, 0xf66, 0xf92, 0xf7c, 0xf62, 0xf0b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12e8, 0x12a2, 0x1275, 0x12ee, 0x1335,
-0x12eb, 0x20, 0x1265, 0x122d, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x66,
-0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67,
-0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20, 0x4c, 0x69, 0x72,
-0x61, 0x73, 0x131, 0x3b, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20, 0x6c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x3b, 0x3b, 0x3b,
-0x54, 0xfc, 0x72, 0x6b, 0x20, 0x6c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20,
-0x6d, 0x61, 0x6e, 0x61, 0x74, 0x79, 0x3b, 0x3b, 0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61,
-0x74, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x79,
-0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x3b, 0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20,
-0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x3b, 0x3b, 0x3b, 0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649,
-0x3b, 0x443, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c, 0x43a, 0x430, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44f, 0x3b, 0x3b,
-0x433, 0x440, 0x438, 0x432, 0x43d, 0x44f, 0x3b, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x456, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x435,
-0x43d, 0x44c, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x456, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631,
-0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1,
-0x3b, 0x3b, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x628,
-0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20,
-0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6d2,
-0x3b, 0x4f, 0x2bb, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2bb, 0x6d, 0x69, 0x3b, 0x3b,
-0x4f, 0x2bb, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2bb, 0x6d, 0x69, 0x3b, 0x3b, 0x3b,
-0x3b, 0x4f, 0x2bb, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2bb, 0x6d, 0x69, 0x3b, 0x627,
-0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442,
-0x43e, 0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441,
-0x45e, 0x43c, 0x3b, 0x3b, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441, 0x45e, 0x43c,
-0x3b, 0x110, 0x1ed3, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x110, 0x1ed3, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x3b, 0x50, 0x75, 0x6e, 0x74, 0x20, 0x50,
-0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b,
-0x62, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x62, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72,
-0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70,
-0x68, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72,
-0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72, 0xed, 0x6c, 0x1eb9,
-0x301, 0xe8, 0x64, 0x65, 0x20, 0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x46, 0x61, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72, 0xed, 0x6c, 0x25b, 0x301, 0xe8, 0x64, 0x65,
-0x20, 0x42, 0x49, 0x4b, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74,
-0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x69, 0x2d, 0x53, 0x6f,
-0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x3b, 0x3b,
-0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64,
-0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20,
-0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e,
-0x65, 0x72, 0x3b, 0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x48, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76,
-0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d,
-0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65,
-0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e,
-0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65,
+0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x941, 0x92a, 0x92f, 0x947, 0x3b, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x3b, 0x442,
+0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x3b, 0x3b, 0x3b, 0x442, 0x4e9, 0x433, 0x440, 0x4e9, 0x433, 0x3b, 0x928, 0x947, 0x92a, 0x93e,
+0x932, 0x940, 0x20, 0x930, 0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x3b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x20, 0x930,
+0x942, 0x92a, 0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x3b, 0x3b, 0x3b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x20, 0x930, 0x942, 0x92a,
+0x948, 0x92f, 0x93e, 0x901, 0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b,
+0x3b, 0x92d, 0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b, 0x3b, 0x3b, 0x3b, 0x92d,
+0x93e, 0x930, 0x924, 0x940, 0x92f, 0x20, 0x930, 0x942, 0x92a, 0x93f, 0x901, 0x92f, 0x93e, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65,
+0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65,
+0x3b, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0xb1f, 0xb19,
+0xb15, 0xb3e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cd, 0x3b, 0x3b, 0x627, 0x641, 0x63a,
+0x627, 0x646, 0x6cd, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cd, 0x3b, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627,
+0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x3b, 0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b,
+0x631, 0x6cc, 0x627, 0x644, 0x20, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641,
+0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627,
+0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x20, 0x627, 0x641, 0x63a, 0x627,
+0x646, 0x633, 0x62a, 0x627, 0x646, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x79, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x3b, 0x3b,
+0x7a, 0x142, 0x6f, 0x74, 0x79, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x3b, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x65, 0x20,
+0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x65, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x79, 0x63, 0x68, 0x20, 0x70, 0x6f, 0x6c, 0x73,
+0x6b, 0x69, 0x63, 0x68, 0x3b, 0x7a, 0x142, 0x6f, 0x74, 0x65, 0x67, 0x6f, 0x20, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x65,
+0x67, 0x6f, 0x3b, 0x52, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b,
+0x52, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x52,
+0x65, 0x61, 0x69, 0x73, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x65, 0x69, 0x72, 0x6f, 0x73, 0x3b, 0x4b, 0x77, 0x61,
+0x6e, 0x7a, 0x61, 0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61,
+0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x4b, 0x77, 0x61, 0x6e, 0x7a, 0x61, 0x73,
+0x20, 0x61, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x45, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x20, 0x63, 0x61,
+0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x45, 0x73, 0x63, 0x75, 0x64, 0x6f, 0x20,
+0x63, 0x61, 0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x73, 0x63,
+0x75, 0x64, 0x6f, 0x73, 0x20, 0x63, 0x61, 0x62, 0x6f, 0x2d, 0x76, 0x65, 0x72, 0x64, 0x69, 0x61, 0x6e, 0x6f, 0x73, 0x3b,
+0x44, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e,
+0x69, 0x64, 0x6f, 0x73, 0x3b, 0x3b, 0x44, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61,
+0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0xf3, 0x6c, 0x61, 0x72, 0x65,
+0x73, 0x20, 0x64, 0x6f, 0x73, 0x20, 0x45, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73,
+0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b,
+0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b,
+0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b,
+0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b,
+0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b,
+0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f,
+0x29, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f,
+0x73, 0x3b, 0x50, 0x61, 0x74, 0x61, 0x63, 0x61, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x3b, 0x50,
+0x61, 0x74, 0x61, 0x63, 0x61, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61,
+0x74, 0x61, 0x63, 0x61, 0x73, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63,
+0x61, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0x3b, 0x4d, 0x65,
+0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b,
+0x3b, 0x3b, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x65, 0x73, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61,
+0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0x44, 0x6f, 0x62, 0x72, 0x61, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20,
+0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x3b, 0x44, 0x6f, 0x62,
+0x72, 0x61, 0x20, 0x64, 0x65, 0x20, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed,
+0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x62, 0x72, 0x61, 0x73, 0x20, 0x64, 0x65, 0x20, 0x53,
+0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x3b, 0x46,
+0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20, 0x73, 0x75, 0xed, 0xe7, 0x6f, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x20,
+0x73, 0x75, 0xed, 0xe7, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73, 0x20, 0x73, 0x75, 0xed,
+0xe7, 0x6f, 0x73, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa07, 0xa06, 0x3b, 0x3b, 0xa2d, 0xa3e, 0xa30,
+0xa24, 0xa40, 0x20, 0xa30, 0xa41, 0xa2a, 0xa07, 0xa06, 0x3b, 0x3b, 0x3b, 0x3b, 0xa2d, 0xa3e, 0xa30, 0xa24, 0xa40, 0x20, 0xa30, 0xa41,
+0xa2a, 0xa0f, 0x3b, 0x631, 0x648, 0x67e, 0x626, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e,
+0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69,
+0x7a, 0x7a, 0x65, 0x72, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x73, 0x76, 0x69, 0x7a, 0x7a, 0x65,
+0x72, 0x3b, 0x6c, 0x65, 0x75, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x75, 0x20,
+0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65,
+0x219, 0x74, 0x69, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x6c,
+0x65, 0x75, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x75, 0x20,
+0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x73, 0x63, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x6d, 0x6f, 0x6c,
+0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x3b, 0x6c, 0x65, 0x69, 0x20, 0x6d, 0x6f, 0x6c, 0x64, 0x6f,
+0x76, 0x65, 0x6e, 0x65, 0x219, 0x74, 0x69, 0x3b, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440,
+0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431,
+0x43b, 0x44c, 0x3b, 0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f,
+0x3b, 0x440, 0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x435, 0x439, 0x3b, 0x440,
+0x43e, 0x441, 0x441, 0x438, 0x439, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x411, 0x435, 0x43b,
+0x43e, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x43e,
+0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44c, 0x3b, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440,
+0x443, 0x441, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441,
+0x441, 0x43a, 0x438, 0x445, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x435, 0x439, 0x3b, 0x431, 0x435, 0x43b, 0x43e, 0x440, 0x443, 0x441, 0x441,
+0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x440, 0x443, 0x431, 0x43b, 0x44f, 0x3b, 0x41a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x439,
+0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x442, 0x435,
+0x43d, 0x433, 0x435, 0x3b, 0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435,
+0x3b, 0x43a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x43a, 0x430, 0x437,
+0x430, 0x445, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x442, 0x435, 0x43d, 0x433, 0x435, 0x3b, 0x41a, 0x438, 0x440, 0x433, 0x438, 0x437,
+0x441, 0x43a, 0x438, 0x439, 0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x439,
+0x20, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x441, 0x43e, 0x43c,
+0x430, 0x3b, 0x43a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x441, 0x43e, 0x43c, 0x43e, 0x432, 0x3b, 0x43a,
+0x438, 0x440, 0x433, 0x438, 0x437, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x441, 0x43e, 0x43c, 0x430, 0x3b, 0x41c, 0x43e, 0x43b, 0x434,
+0x430, 0x432, 0x441, 0x43a, 0x438, 0x439, 0x20, 0x43b, 0x435, 0x439, 0x3b, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a,
+0x438, 0x439, 0x20, 0x43b, 0x435, 0x439, 0x3b, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x43b,
+0x435, 0x44f, 0x3b, 0x43c, 0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x438, 0x445, 0x20, 0x43b, 0x435, 0x435, 0x432, 0x3b, 0x43c,
+0x43e, 0x43b, 0x434, 0x430, 0x432, 0x441, 0x43a, 0x43e, 0x433, 0x43e, 0x20, 0x43b, 0x435, 0x44f, 0x3b, 0x423, 0x43a, 0x440, 0x430, 0x438,
+0x43d, 0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x430, 0x3b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d,
+0x441, 0x43a, 0x430, 0x44f, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x430, 0x3b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441,
+0x43a, 0x438, 0x435, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44b, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x438,
+0x445, 0x20, 0x433, 0x440, 0x438, 0x432, 0x435, 0x43d, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x441, 0x43a, 0x43e, 0x439, 0x20,
+0x433, 0x440, 0x438, 0x432, 0x43d, 0x44b, 0x3b, 0x66, 0x61, 0x72, 0xe2, 0x6e, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x28,
+0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x421, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434,
+0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x3b, 0x3b,
+0x441, 0x440, 0x43f, 0x441, 0x43a, 0x430, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b, 0x3b, 0x441, 0x440, 0x43f, 0x441, 0x43a,
+0x438, 0x445, 0x20, 0x434, 0x438, 0x43d, 0x430, 0x440, 0x430, 0x3b, 0x411, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445,
+0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438,
+0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a,
+0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435,
+0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430,
+0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x435, 0x20, 0x43a, 0x43e,
+0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x435, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x65, 0x3b, 0x3b, 0x431,
+0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x438,
+0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x438, 0x445, 0x20, 0x43c, 0x430, 0x440,
+0x430, 0x43a, 0x430, 0x3b, 0x415, 0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x43e, 0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430,
+0x3b, 0x3b, 0x435, 0x432, 0x440, 0x430, 0x3b, 0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63,
+0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c,
+0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68,
+0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69,
+0x62, 0x69, 0x6c, 0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b,
+0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x65, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65,
+0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61,
+0x6e, 0x73, 0x6b, 0x6f, 0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b,
+0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61,
+0x3b, 0x45, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x3b, 0x65,
+0x76, 0x72, 0x61, 0x3b, 0x53, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72,
+0x70, 0x73, 0x6b, 0x69, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x61, 0x20, 0x64,
+0x69, 0x6e, 0x61, 0x72, 0x61, 0x3b, 0x3b, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x68, 0x20, 0x64, 0x69, 0x6e, 0x61, 0x72,
+0x61, 0x3b, 0x41b, 0x430, 0x440, 0x3b, 0x3b, 0x43b, 0x430, 0x440, 0x3b, 0x3b, 0x3b, 0x3b, 0x43b, 0x430, 0x440, 0x44b, 0x3b, 0x421,
+0x43e, 0x43c, 0x3b, 0x3b, 0x441, 0x43e, 0x43c, 0x3b, 0x3b, 0x3b, 0x3b, 0x441, 0x43e, 0x43c, 0x44b, 0x3b, 0x44, 0x6f, 0x72, 0x61,
+0x20, 0x72, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xdc1, 0xdca,
+0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x3b, 0xdc1, 0xdca, 0x200d,
+0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x3b, 0x3b, 0x3b, 0xdc1, 0xdca,
+0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0x20, 0xdbb, 0xdd4, 0xdb4, 0xdd2, 0xdba, 0xdbd, 0x3b, 0x65, 0x75, 0x72, 0x6f,
+0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0xe1, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x3b, 0x65, 0x75,
+0x72, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x3b, 0x65, 0x76, 0x72, 0x61, 0x3b, 0x65, 0x76,
+0x72, 0x69, 0x3b, 0x3b, 0x65, 0x76, 0x72, 0x6f, 0x76, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x20, 0x73, 0x6f, 0x6f,
+0x6d, 0x61, 0x61, 0x6c, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x20, 0x4a, 0x61,
+0x62, 0x62, 0x75, 0x75, 0x74, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x42, 0x69, 0x72, 0x74, 0x61, 0x20, 0x49,
+0x74, 0x6f, 0x6f, 0x62, 0x62, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20,
+0x61, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x61, 0x72, 0x67, 0x65,
+0x6e, 0x74, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x61, 0x72, 0x67, 0x65, 0x6e,
+0x74, 0x69, 0x6e, 0x6f, 0x73, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f,
+0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
+0x64, 0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73, 0x20, 0x62, 0x65, 0x6c, 0x69, 0x63, 0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x62, 0x6f,
+0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b,
+0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72,
+0x61, 0x73, 0x69, 0x6c, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c,
+0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x72, 0x65, 0x61, 0x6c, 0x65, 0x73, 0x20, 0x62, 0x72, 0x61, 0x73, 0x69, 0x6c,
+0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x50, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x3b, 0x3b, 0x70,
+0x65, 0x73, 0x6f, 0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73,
+0x20, 0x63, 0x68, 0x69, 0x6c, 0x65, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d,
+0x62, 0x69, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61,
+0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x63, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61,
+0x6e, 0x6f, 0x73, 0x3b, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x72, 0x69, 0x63, 0x65,
+0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x63, 0x6f, 0x6c, 0xf3, 0x6e, 0x20, 0x63, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x72, 0x69, 0x63,
+0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x63, 0x6f, 0x6c, 0x6f, 0x6e, 0x65, 0x73, 0x20, 0x63, 0x6f, 0x73, 0x74,
+0x61, 0x72, 0x72, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x75, 0x62, 0x61,
+0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70,
+0x65, 0x73, 0x6f, 0x73, 0x20, 0x63, 0x75, 0x62, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x64, 0x6f,
+0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e,
+0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x64, 0x6f, 0x6d, 0x69, 0x6e,
+0x69, 0x63, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75,
+0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x20, 0x65, 0x73, 0x74, 0x61, 0x64,
+0x6f, 0x75, 0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x64, 0xf3, 0x6c, 0x61, 0x72, 0x65, 0x73,
+0x20, 0x65, 0x73, 0x74, 0x61, 0x64, 0x6f, 0x75, 0x6e, 0x69, 0x64, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x66, 0x72, 0x61,
+0x6e, 0x63, 0x6f, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f,
+0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x6f, 0x73,
+0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x3b, 0x3b, 0x71,
+0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x3b, 0x3b, 0x3b, 0x3b, 0x71, 0x75, 0x65, 0x74, 0x7a, 0x61, 0x6c, 0x65, 0x73, 0x3b,
+0x6c, 0x65, 0x6d, 0x70, 0x69, 0x72, 0x61, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x6c,
+0x65, 0x6d, 0x70, 0x69, 0x72, 0x61, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
+0x6c, 0x65, 0x6d, 0x70, 0x69, 0x72, 0x61, 0x73, 0x20, 0x68, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x65, 0xf1, 0x6f, 0x73, 0x3b,
+0x70, 0x65, 0x73, 0x6f, 0x20, 0x6d, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20,
+0x6d, 0x65, 0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x6d, 0x65,
+0x78, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69, 0x63, 0x61,
+0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62, 0x61, 0x20, 0x6e, 0x69,
+0x63, 0x61, 0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x63, 0xf3, 0x72, 0x64, 0x6f, 0x62,
+0x61, 0x73, 0x20, 0x6e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67, 0xfc, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x3b, 0x62, 0x61, 0x6c,
+0x62, 0x6f, 0x61, 0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61,
+0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x61, 0x6c, 0x62, 0x6f, 0x61, 0x73,
+0x20, 0x70, 0x61, 0x6e, 0x61, 0x6d, 0x65, 0xf1, 0x6f, 0x73, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70,
+0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x20, 0x70, 0x61,
+0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x75, 0x61, 0x72, 0x61, 0x6e, 0xed, 0x65, 0x73,
+0x20, 0x70, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x73, 0x3b, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x75,
+0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x73, 0x6f, 0x6c, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
+0x73, 0x6f, 0x6c, 0x65, 0x73, 0x20, 0x70, 0x65, 0x72, 0x75, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20,
+0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70,
+0x69, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73, 0x20, 0x66, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e,
+0x6f, 0x73, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x20, 0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x70, 0x65,
+0x73, 0x6f, 0x20, 0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x70, 0x65, 0x73, 0x6f, 0x73,
+0x20, 0x75, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x6f, 0x73, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x20, 0x76,
+0x65, 0x6e, 0x65, 0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72, 0x20, 0x76,
+0x65, 0x6e, 0x65, 0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x62, 0x6f, 0x6c, 0xed, 0x76, 0x61, 0x72,
+0x65, 0x73, 0x20, 0x76, 0x65, 0x6e, 0x65, 0x7a, 0x6f, 0x6c, 0x61, 0x6e, 0x6f, 0x73, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69,
+0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69,
+0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b,
+0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69,
+0x61, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x3b,
+0x66, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b,
+0x66, 0x61, 0x72, 0x61, 0x6e, 0x67, 0x61, 0x20, 0x7a, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x3b, 0x53, 0x68, 0x69,
+0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c,
+0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69,
+0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69,
+0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x6c, 0x69,
+0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69,
+0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x7a, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x73, 0x76, 0x65, 0x6e,
+0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x61, 0x3b, 0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f,
+0x6e, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x6f, 0x72,
+0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4,
+0xbbf, 0xbaf, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0x20,
+0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0,
+0xbbf, 0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0x3b, 0x3b, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0, 0xbbf,
+0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xbae, 0xbb2, 0xbc7, 0xbb7, 0xbbf, 0xbaf, 0xba9, 0xbcd, 0x20, 0xbb0,
+0xbbf, 0xb99, 0xbcd, 0xb95, 0xbbf, 0xb9f, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2,
+0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0x3b, 0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0,
+0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0x3b, 0x3b, 0x3b, 0x3b, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2,
+0xbb0, 0xbcd, 0x20, 0xb9f, 0xbbe, 0xbb2, 0xbb0, 0xbcd, 0xb95, 0xbb3, 0xbcd, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0,
+0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0x3b, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd,
+0x3b, 0x3b, 0x3b, 0x3b, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0x20, 0xbb0, 0xbc2, 0xbaa, 0xbbe, 0xbaf, 0xbcd, 0xb95, 0xbb3, 0xbcd,
+0x3b, 0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b, 0xc30, 0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc3f, 0x3b, 0x3b, 0x3b, 0x3b, 0xc30,
+0xc42, 0xc2a, 0xc3e, 0xc2f, 0xc32, 0xc41, 0x3b, 0xe1a, 0xe32, 0xe17, 0xe44, 0xe17, 0xe22, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xe1a,
+0xe32, 0xe17, 0xe44, 0xe17, 0xe22, 0x3b, 0xf61, 0xf74, 0xf0b, 0xf68, 0xf53, 0xf0b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xf62,
+0xf92, 0xfb1, 0xf0b, 0xf42, 0xf62, 0xf0b, 0xf66, 0xf92, 0xf7c, 0xf62, 0xf0b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x12e8, 0x12a2,
+0x1275, 0x12ee, 0x1335, 0x12eb, 0x20, 0x1265, 0x122d, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x2bb, 0x61, 0x6e, 0x67,
+0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x50, 0x61, 0x2bb,
+0x61, 0x6e, 0x67, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20,
+0x4c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20, 0x6c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b,
+0x3b, 0x3b, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x20, 0x6c, 0x69, 0x72, 0x61, 0x73, 0x131, 0x3b, 0x54, 0xfc, 0x72, 0x6b, 0x6d,
+0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e, 0x61, 0x74, 0x79, 0x3b, 0x3b, 0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d,
+0x61, 0x6e, 0x61, 0x74, 0x79, 0x3b, 0x3b, 0x3b, 0x3b, 0x74, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x20, 0x6d, 0x61, 0x6e,
+0x61, 0x74, 0x79, 0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x3b, 0x3b, 0x62c, 0x6c7, 0x6ad,
+0x6af, 0x648, 0x20, 0x64a, 0x6c8, 0x6d5, 0x646, 0x649, 0x3b, 0x3b, 0x3b, 0x3b, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x20, 0x64a, 0x6c8,
+0x6d5, 0x646, 0x649, 0x3b, 0x443, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c, 0x43a, 0x430, 0x20, 0x433, 0x440, 0x438, 0x432, 0x43d,
+0x44f, 0x3b, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x44f, 0x3b, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x456, 0x3b, 0x433, 0x440,
+0x438, 0x432, 0x435, 0x43d, 0x44c, 0x3b, 0x433, 0x440, 0x438, 0x432, 0x43d, 0x456, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646,
+0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648,
+0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc,
+0x6c1, 0x3b, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x628, 0x6be, 0x627, 0x631,
+0x62a, 0x6cc, 0x20, 0x631, 0x648, 0x67e, 0x6cc, 0x6c1, 0x3b, 0x3b, 0x3b, 0x3b, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6cc, 0x20, 0x631,
+0x648, 0x67e, 0x6d2, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d,
+0x69, 0x3b, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d, 0x69,
+0x3b, 0x3b, 0x3b, 0x3b, 0x4f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x20, 0x73, 0x6f, 0x2018, 0x6d,
+0x69, 0x3b, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x6cc, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a,
+0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e,
+0x43d, 0x20, 0x441, 0x45e, 0x43c, 0x3b, 0x3b, 0x3b, 0x3b, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x20,
+0x441, 0x45e, 0x43c, 0x3b, 0x110, 0x1ed3, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x110, 0x1ed3, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x3b, 0x50, 0x75, 0x6e,
+0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61,
+0x69, 0x6e, 0x3b, 0x62, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x62, 0x75, 0x6e, 0x74,
+0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69,
+0x6e, 0x3b, 0x70, 0x68, 0x75, 0x6e, 0x74, 0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x70, 0x75, 0x6e, 0x74,
+0x20, 0x50, 0x72, 0x79, 0x64, 0x61, 0x69, 0x6e, 0x3b, 0x4e, 0x61, 0x69, 0x72, 0x61, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72,
+0xed, 0x6c, 0x1eb9, 0x301, 0xe8, 0x64, 0x65, 0x20, 0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x46, 0x61, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x20, 0x74, 0x69, 0x20, 0x4f, 0x72, 0xed, 0x6c, 0x25b, 0x301,
+0xe8, 0x64, 0x65, 0x20, 0x42, 0x49, 0x4b, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x69, 0x2d, 0x53,
+0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b, 0x3b, 0x69,
+0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52, 0x61, 0x6e, 0x64, 0x3b,
+0x3b, 0x3b, 0x3b, 0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x52,
+0x61, 0x6e, 0x64, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x6e, 0x6f, 0x72,
+0x73, 0x6b, 0x20, 0x6b, 0x72, 0x6f, 0x6e, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x65, 0x20, 0x6b,
+0x72, 0x6f, 0x6e, 0x65, 0x72, 0x3b, 0x42, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67,
+0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x61,
+0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65, 0x72, 0x63,
+0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x61, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62, 0x69, 0x6c,
+0x6e, 0x61, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x61, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f, 0x68, 0x65,
0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x65, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72, 0x74, 0x69, 0x62,
0x69, 0x6c, 0x6e, 0x65, 0x20, 0x6d, 0x61, 0x72, 0x6b, 0x65, 0x3b, 0x3b, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x6f,
-0x2d, 0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65,
-0x72, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x3b, 0x41a, 0x43e, 0x43d,
-0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e,
-0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20,
-0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b,
-0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447,
-0x43a, 0x435, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x435, 0x20, 0x43c, 0x430, 0x440,
-0x43a, 0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432,
-0x430, 0x447, 0x43a, 0x438, 0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x438, 0x445,
-0x20, 0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x53, 0x69, 0x64, 0x69, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x1ecb, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c,
-0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69,
-0x256, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x3b, 0x263, 0x65, 0x74,
-0x6f, 0x256, 0x6f, 0x66, 0x65, 0x20, 0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66,
-0x72, 0x61, 0x6e, 0x63, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x263, 0x65, 0x74, 0x6f, 0x256, 0x6f, 0x66, 0x65,
-0x20, 0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20,
-0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x263, 0x65, 0x74, 0x6f, 0x256, 0x6f, 0x66, 0x65, 0x20, 0x61, 0x66,
-0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x42, 0x43, 0x45,
-0x41, 0x4f, 0x3b, 0x50, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73,
+0x68, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x61, 0x10d, 0x6b, 0x69, 0x68, 0x20, 0x6b, 0x6f, 0x6e, 0x76, 0x65, 0x72,
+0x74, 0x69, 0x62, 0x69, 0x6c, 0x6e, 0x69, 0x68, 0x20, 0x6d, 0x61, 0x72, 0x61, 0x6b, 0x61, 0x3b, 0x41a, 0x43e, 0x43d, 0x432,
+0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b, 0x431, 0x43e, 0x441,
+0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a, 0x430, 0x20, 0x43a,
+0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x430, 0x20, 0x43c, 0x430, 0x440, 0x43a, 0x430, 0x3b, 0x3b,
+0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430, 0x447, 0x43a,
+0x435, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x435, 0x20, 0x43c, 0x430, 0x440, 0x43a,
+0x3b, 0x3b, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x43e, 0x2d, 0x445, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x430,
+0x447, 0x43a, 0x438, 0x445, 0x20, 0x43a, 0x43e, 0x43d, 0x432, 0x435, 0x440, 0x442, 0x438, 0x431, 0x438, 0x43b, 0x43d, 0x438, 0x445, 0x20,
+0x43c, 0x430, 0x440, 0x430, 0x43a, 0x430, 0x3b, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x53, 0x69, 0x64, 0x69, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x61, 0x1ecb, 0x72, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c, 0x69,
+0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x67,
+0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256,
+0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x67, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x73, 0x69, 0x256, 0x69, 0x3b, 0x263, 0x65, 0x74, 0x6f,
+0x256, 0x6f, 0x66, 0x65, 0x20, 0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72,
+0x61, 0x6e, 0x63, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x263, 0x65, 0x74, 0x6f, 0x256, 0x6f, 0x66, 0x65, 0x20,
+0x61, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x42,
+0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x263, 0x65, 0x74, 0x6f, 0x256, 0x6f, 0x66, 0x65, 0x20, 0x61, 0x66, 0x72,
+0x69, 0x6b, 0x61, 0x67, 0x61, 0x20, 0x43, 0x46, 0x41, 0x20, 0x66, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x42, 0x43, 0x45, 0x41,
+0x4f, 0x3b, 0x50, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x3b,
+0x3b, 0x70, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x3b, 0x3b,
0x3b, 0x3b, 0x70, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x3b,
-0x3b, 0x3b, 0x3b, 0x70, 0x69, 0x73, 0x6f, 0x20, 0x6e, 0x67, 0x20, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73,
-0x3b, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x3b, 0x53,
-0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53,
-0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x6e, 0x6f, 0x72, 0x67,
-0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b,
-0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e,
-0x6f, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x65,
-0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72,
-0x6f, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x72, 0x75,
-0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20,
-0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75,
-0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e,
-0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x75, 0x20, 0x53, 0x65, 0x65, 0x66,
-0x61, 0x61, 0x20, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x62, 0x75, 0x75, 0x257,
-0x69, 0x20, 0x53, 0x65, 0x65, 0x66, 0x61, 0x61, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x55, 0x67, 0x69, 0x79, 0x79, 0x61, 0x20, 0x4d, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x43, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e, 0x6a, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x65, 0x65, 0x6c, 0x20, 0x4b, 0x65,
-0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65,
-0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f,
-0x6c, 0x61, 0x20, 0x79, 0x61, 0x73, 0x65, 0x20, 0x41, 0x6d, 0x65, 0x6c, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x68, 0x65, 0x6c, 0x65, 0x72, 0x69, 0x20, 0x73, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x2d30, 0x2d37, 0x2d54, 0x2d49, 0x2d4e, 0x20, 0x2d4f, 0x20, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54, 0x2d49,
-0x2d31, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x61, 0x64, 0x72, 0x69, 0x6d, 0x20, 0x6e, 0x20, 0x6c, 0x6d, 0x263, 0x72,
-0x69, 0x62, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x41, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x41, 0x7a, 0x7a, 0x61,
-0x79, 0x72, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x73, 0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20,
-0x79, 0x61, 0x20, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c,
-0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e,
-0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x65, 0x66, 0x61, 0x20, 0x46, 0x72, 0x61,
-0x14b, 0x20, 0x28, 0x42, 0x43, 0x45, 0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x13a4, 0x13c3, 0x13cd, 0x13d7,
-0x3b, 0x3b, 0x13a4, 0x13c3, 0x13cd, 0x13d7, 0x3b, 0x3b, 0x3b, 0x3b, 0x13e7, 0x13c3, 0x13cd, 0x13d7, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69,
+0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x3b, 0x53, 0x63,
+0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x63,
+0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x65, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x75, 0x72, 0x6f, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75,
+0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f,
+0x3b, 0x6e, 0x6f, 0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x3b, 0x6e, 0x6f,
+0x72, 0x67, 0x67, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65,
+0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x72, 0x75, 0x6f, 0x167,
+0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b,
+0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e,
+0x6f, 0x3b, 0x3b, 0x3b, 0x72, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x20, 0x6b, 0x72, 0x75, 0x76, 0x64, 0x6e, 0x6f, 0x3b, 0x53,
+0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x75, 0x20, 0x53, 0x65, 0x65, 0x66, 0x61, 0x61, 0x20, 0x42, 0x43, 0x45,
+0x41, 0x4f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x62, 0x75, 0x75, 0x257, 0x69, 0x20, 0x53, 0x65, 0x65, 0x66,
+0x61, 0x61, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x67, 0x69, 0x79, 0x79, 0x61,
+0x20, 0x4d, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x43, 0x69, 0x72, 0x69,
+0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4e,
+0x6a, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x65, 0x65, 0x6c, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x4d, 0x65, 0x74, 0x69, 0x63, 0x61, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0x6f, 0xe7, 0x61, 0x6d,
+0x62, 0x69, 0x71, 0x75, 0x65, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x44, 0x6f, 0x6c, 0x61, 0x20, 0x79, 0x61, 0x73,
+0x65, 0x20, 0x41, 0x6d, 0x65, 0x6c, 0x69, 0x6b, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x68, 0x65, 0x6c, 0x65,
+0x72, 0x69, 0x20, 0x73, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x2d30, 0x2d37, 0x2d54, 0x2d49, 0x2d4e, 0x20, 0x2d4f, 0x20, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x61, 0x64, 0x72, 0x69, 0x6d, 0x20, 0x6e, 0x20, 0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62, 0x3b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x41, 0x64, 0x69, 0x6e, 0x61, 0x72, 0x20, 0x41, 0x7a, 0x7a, 0x61, 0x79, 0x72, 0x69, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x45, 0x73, 0x68, 0x69, 0x72, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x55, 0x67, 0x61,
+0x6e, 0x64, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79,
+0x61, 0x20, 0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53,
+0x68, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x65, 0x66, 0x61, 0x20, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x28, 0x42, 0x43, 0x45,
+0x41, 0x4f, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x13a0, 0x13d5, 0x13b3, 0x3b, 0x3b, 0x55, 0x53,
+0x20, 0x13a0, 0x13d5, 0x13b3, 0x3b, 0x3b, 0x3b, 0x3b, 0x55, 0x53, 0x20, 0x13a0, 0x13d5, 0x13b3, 0x3b, 0x72, 0x6f, 0x75, 0x70, 0x69,
0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x68, 0x69, 0x6c,
0xed, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0xed, 0x61, 0x3b, 0x3b,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x53, 0x69, 0x6c, 0x69, 0x6e, 0x67, 0x69, 0x20, 0x65, 0x79, 0x61, 0x20, 0x59, 0x75, 0x67,
@@ -5726,28 +5820,32 @@ static const ushort currency_display_name_data[] = {
0x43, 0x46, 0x41, 0x20, 0x28, 0x42, 0x45, 0x41, 0x43, 0x29, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x72, 0xe1,
0x14b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x6f, 0x6c, 0x61, 0x69, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x20, 0x42, 0x45, 0x41, 0x43, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x49, 0x68, 0x65, 0x6c, 0x61, 0x20, 0x79, 0x61, 0x20, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e,
-0x69, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xa55e, 0xa524, 0xa52b, 0xa569, 0x20, 0xa55c, 0xa55e, 0xa54c, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x61, 0x69, 0x62, 0x68, 0x69, 0x79, 0x61, 0x20, 0x44, 0x61, 0x6c, 0x61, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x25b, 0x6c, 0xe2, 0x14b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61,
-0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x73, 0x68, 0x69, 0x72, 0xe8, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x65, 0x6c, 0xe1, 0x14b, 0x20, 0x43, 0x46, 0x41, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x62f, 0x6cc, 0x646, 0x627, 0x631, 0x6cc, 0x20, 0x639, 0x6ce, 0x631, 0x627, 0x642, 0x6cc, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x695, 0x6cc, 0x627, 0x6b5, 0x6cc, 0x20, 0x626, 0x6ce, 0x631, 0x627, 0x646, 0x6cc, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
-0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f,
-0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75,
-0x72, 0x61, 0x6a, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x77, 0x3b, 0x65, 0x75, 0x72, 0x6f,
-0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x20, 0x631, 0x6cc, 0x627, 0x644, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x3b, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x20, 0x631, 0x6cc, 0x627, 0x644, 0x3b, 0x6e2f, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b,
-0x3b, 0x3b, 0x6e2f, 0x5e63, 0x3b
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430, 0x20, 0x441, 0x43e, 0x43b, 0x43a, 0x443,
+0x43e, 0x431, 0x430, 0x439, 0x430, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430,
+0x20, 0x441, 0x43e, 0x43b, 0x43a, 0x443, 0x43e, 0x431, 0x430, 0x439, 0x430, 0x3b, 0x49, 0x68, 0x65, 0x6c, 0x61, 0x20, 0x79, 0x61,
+0x20, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0xa55e, 0xa524, 0xa52b,
+0xa569, 0x20, 0xa55c, 0xa55e, 0xa54c, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x4c, 0x61, 0x69, 0x62, 0x68, 0x69, 0x79, 0x61,
+0x20, 0x44, 0x61, 0x6c, 0x61, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x25b, 0x6c, 0xe2, 0x14b, 0x3b, 0x3b, 0x3b,
+0x3b, 0x3b, 0x3b, 0x3b, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x20, 0x43, 0x46, 0x41, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
+0x73, 0x68, 0x69, 0x72, 0xe8, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x66, 0x65, 0x6c, 0xe1, 0x14b, 0x20, 0x43, 0x46,
+0x41, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x62f, 0x6cc, 0x646, 0x627, 0x631, 0x6cc, 0x20, 0x639, 0x6ce, 0x631, 0x627, 0x642,
+0x6cc, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x695, 0x6cc, 0x627, 0x6b5, 0x6cc, 0x20, 0x626, 0x6ce, 0x631, 0x627, 0x646, 0x6cc,
+0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75,
+0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b,
+0x65, 0x75, 0x72, 0x6f, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x6a, 0x3b, 0x65, 0x75, 0x72, 0x61, 0x3b, 0x3b, 0x65, 0x75, 0x72,
+0x6f, 0x77, 0x3b, 0x65, 0x75, 0x72, 0x6f, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x20,
+0x631, 0x6cc, 0x627, 0x644, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x20, 0x631, 0x6cc, 0x627, 0x644,
+0x3b, 0x6e2f, 0x5e63, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x6e2f, 0x5e63, 0x3b
};
static const ushort currency_format_data[] = {
0x25, 0x31, 0x25, 0x32, 0x25, 0x32, 0x25, 0x31, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x25, 0x32,
0x25, 0x31, 0x4b, 0x25, 0x32, 0xa0, 0x2d, 0x25, 0x31, 0x28, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x29, 0x25, 0x32, 0x2d, 0x25,
-0x31, 0x25, 0x31, 0xa0, 0x6d, 0x6e, 0xa0, 0x25, 0x32, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x2d, 0x25, 0x32, 0xa0, 0x25, 0x31,
-0x4b, 0x200e, 0x25, 0x32, 0x25, 0x31, 0x28, 0x25, 0x32, 0x25, 0x31, 0x29, 0x25, 0x32, 0x2d, 0xa0, 0x25, 0x31
+0x31, 0x25, 0x31, 0xa0, 0x6d, 0x6e, 0xa0, 0x25, 0x32, 0x25, 0x32, 0xa0, 0x25, 0x31, 0x2d, 0x25, 0x32, 0x2212, 0x25, 0x31,
+0x200f, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x200f, 0x200e, 0x2d, 0x25, 0x31, 0xa0, 0x25, 0x32, 0x200e, 0x25, 0x32, 0x25, 0x31, 0x25,
+0x32, 0xa0, 0x25, 0x31, 0x4b, 0x28, 0x25, 0x32, 0x25, 0x31, 0x29, 0x25, 0x32, 0x2d, 0xa0, 0x25, 0x31
};
+
static const ushort endonyms_data[] = {
0x4f, 0x72, 0x6f, 0x6d, 0x6f, 0x6f, 0x49, 0x74, 0x6f, 0x6f, 0x70, 0x68, 0x69, 0x79, 0x61, 0x61, 0x4b, 0x65, 0x65, 0x6e,
0x69, 0x79, 0x61, 0x61, 0x41, 0x66, 0x72, 0x69, 0x6b, 0x61, 0x61, 0x6e, 0x73, 0x53, 0x75, 0x69, 0x64, 0x2d, 0x41, 0x66,
@@ -5766,271 +5864,271 @@ static const ushort endonyms_data[] = {
0x62a, 0x62d, 0x62f, 0x629, 0x627, 0x644, 0x635, 0x62d, 0x631, 0x627, 0x621, 0x20, 0x627, 0x644, 0x63a, 0x631, 0x628, 0x64a, 0x629, 0x627,
0x644, 0x64a, 0x645, 0x646, 0x62c, 0x646, 0x648, 0x628, 0x20, 0x627, 0x644, 0x633, 0x648, 0x62f, 0x627, 0x646, 0x570, 0x561, 0x575, 0x565,
0x580, 0x565, 0x576, 0x540, 0x561, 0x575, 0x561, 0x57d, 0x57f, 0x561, 0x576, 0x985, 0x9b8, 0x9ae, 0x9c0, 0x9af, 0x9bc, 0x9be, 0x9ad, 0x9be,
-0x9f0, 0x9a4, 0x61, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x20, 0x64, 0x69, 0x6c, 0x69, 0x41, 0x7a, 0x259,
-0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x430, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9, 0x430, 0x43d, 0x20, 0x434, 0x438,
-0x43b, 0x438, 0x410, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9, 0x430, 0x43d, 0x65, 0x75, 0x73, 0x6b, 0x61, 0x72, 0x61, 0x45,
-0x73, 0x70, 0x61, 0x69, 0x6e, 0x69, 0x61, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6,
-0x9ad, 0x9be, 0x9b0, 0x9a4, 0xf62, 0xfab, 0xf7c, 0xf44, 0xf0b, 0xf41, 0xf60, 0xf56, 0xfb2, 0xf74, 0xf42, 0x62, 0x72, 0x65, 0x7a, 0x68,
-0x6f, 0x6e, 0x65, 0x67, 0x46, 0x72, 0x61, 0xf1, 0x73, 0x431, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x411, 0x44a,
-0x43b, 0x433, 0x430, 0x440, 0x438, 0x44f, 0x1017, 0x1019, 0x102c, 0x1019, 0x103c, 0x1014, 0x103a, 0x1019, 0x102c, 0x431, 0x435, 0x43b, 0x430, 0x440,
-0x443, 0x441, 0x43a, 0x430, 0x44f, 0x411, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x44c, 0x1781, 0x17d2, 0x1798, 0x17c2, 0x179a, 0x1780, 0x1798,
-0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x63, 0x61, 0x74, 0x61, 0x6c, 0xe0, 0x45, 0x73, 0x70, 0x61, 0x6e, 0x79, 0x61, 0x41, 0x6e,
-0x64, 0x6f, 0x72, 0x72, 0x61, 0x46, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x49, 0x74, 0xe0, 0x6c, 0x69, 0x61, 0x7b80, 0x4f53, 0x4e2d,
-0x6587, 0x4e2d, 0x56fd, 0x4e2d, 0x56fd, 0x9999, 0x6e2f, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x4e2d, 0x56fd, 0x6fb3, 0x95e8, 0x7279, 0x522b, 0x884c, 0x653f,
-0x533a, 0x65b0, 0x52a0, 0x5761, 0x7e41, 0x9ad4, 0x4e2d, 0x6587, 0x4e2d, 0x83ef, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x570b, 0x9999, 0x6e2f, 0x7279, 0x5225, 0x884c,
-0x653f, 0x5340, 0x4e2d, 0x83ef, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x570b, 0x6fb3, 0x9580, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x53f0, 0x7063, 0x68, 0x72,
-0x76, 0x61, 0x74, 0x73, 0x6b, 0x69, 0x48, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x61, 0x42, 0x6f, 0x73, 0x6e, 0x61, 0x20,
-0x69, 0x20, 0x48, 0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x69, 0x6e, 0x61, 0x10d, 0x65, 0x161, 0x74, 0x69, 0x6e, 0x61,
-0x10c, 0x65, 0x73, 0x6b, 0xe1, 0x20, 0x72, 0x65, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x6b, 0x61, 0x64, 0x61, 0x6e, 0x73, 0x6b,
-0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x47, 0x72, 0xf8, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x65, 0x64, 0x65, 0x72,
-0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x41, 0x72, 0x75, 0x62, 0x61, 0x56,
-0x6c, 0x61, 0x61, 0x6d, 0x73, 0x42, 0x65, 0x6c, 0x67, 0x69, 0xeb, 0x43, 0x75, 0x72, 0x61, 0xe7, 0x61, 0x6f, 0x53, 0x75,
-0x72, 0x69, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x61, 0x72, 0x69, 0x62, 0x69, 0x73, 0x63, 0x68, 0x20, 0x4e, 0x65, 0x64, 0x65,
-0x72, 0x6c, 0x61, 0x6e, 0x64, 0x53, 0x69, 0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x65, 0x6e, 0x41, 0x6d, 0x65,
-0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20,
-0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61,
-0x6e, 0x20, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x41, 0x6e, 0x74, 0x69, 0x67,
-0x75, 0x61, 0x20, 0x26, 0x20, 0x42, 0x61, 0x72, 0x62, 0x75, 0x64, 0x61, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69,
-0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61, 0x41,
-0x75, 0x73, 0x74, 0x72, 0x69, 0x61, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x61, 0x73, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64, 0x6f,
-0x73, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x75, 0x6d, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x42, 0x65, 0x72, 0x6d, 0x75, 0x64,
-0x61, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x49, 0x6e, 0x64,
-0x69, 0x61, 0x6e, 0x20, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x20, 0x54, 0x65, 0x72, 0x72, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42,
-0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x43, 0x61, 0x6d, 0x65, 0x72, 0x6f, 0x6f, 0x6e, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x69,
-0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x43, 0x61, 0x79, 0x6d,
-0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73, 0x20,
-0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x20, 0x28, 0x4b, 0x65, 0x65, 0x6c, 0x69, 0x6e, 0x67,
-0x29, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x43, 0x6f, 0x6f, 0x6b, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64,
-0x73, 0x43, 0x79, 0x70, 0x72, 0x75, 0x73, 0x44, 0x65, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69,
-0x63, 0x61, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49, 0x73,
-0x6c, 0x61, 0x6e, 0x64, 0x73, 0x46, 0x69, 0x6a, 0x69, 0x46, 0x69, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x47, 0x75, 0x65, 0x72,
-0x6e, 0x73, 0x65, 0x79, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x47, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x79, 0x47, 0x68, 0x61,
-0x6e, 0x61, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x47, 0x75,
-0x61, 0x6d, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x53, 0x41,
-0x52, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x49, 0x72, 0x65, 0x6c, 0x61, 0x6e, 0x64, 0x49,
-0x73, 0x72, 0x61, 0x65, 0x6c, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x4b, 0x69, 0x72,
-0x69, 0x62, 0x61, 0x74, 0x69, 0x4c, 0x65, 0x73, 0x6f, 0x74, 0x68, 0x6f, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61, 0x4d,
-0x61, 0x63, 0x61, 0x75, 0x20, 0x53, 0x41, 0x52, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x4d, 0x61, 0x64, 0x61, 0x67, 0x61,
-0x73, 0x63, 0x61, 0x72, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x4d, 0x61,
-0x6c, 0x74, 0x61, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4d,
-0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x4d, 0x6f,
-0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x4e, 0x61, 0x75, 0x72, 0x75,
-0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c, 0x61,
-0x6e, 0x64, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x4e, 0x69, 0x75, 0x65, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c, 0x6b,
-0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x20, 0x4d, 0x61, 0x72, 0x69,
-0x61, 0x6e, 0x61, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x50,
-0x61, 0x6c, 0x61, 0x75, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61,
-0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x73, 0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e, 0x20,
-0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x20, 0x52, 0x69, 0x63, 0x6f, 0x52, 0x77,
-0x61, 0x6e, 0x64, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x20, 0x26, 0x20, 0x4e, 0x65, 0x76, 0x69,
-0x73, 0x53, 0x74, 0x2e, 0x20, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x56, 0x69, 0x6e, 0x63, 0x65, 0x6e,
-0x74, 0x20, 0x26, 0x20, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x53,
-0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f, 0x6e,
-0x65, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x69, 0x61, 0x53, 0x6f,
-0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41,
-0x66, 0x72, 0x69, 0x63, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x53, 0x75, 0x64, 0x61, 0x6e,
-0x53, 0x77, 0x61, 0x7a, 0x69, 0x6c, 0x61, 0x6e, 0x64, 0x53, 0x77, 0x65, 0x64, 0x65, 0x6e, 0x53, 0x77, 0x69, 0x74, 0x7a,
-0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x54, 0x6f, 0x6b, 0x65, 0x6c, 0x61,
-0x75, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f, 0x62,
-0x61, 0x67, 0x6f, 0x54, 0x75, 0x72, 0x6b, 0x73, 0x20, 0x26, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x49, 0x73,
-0x6c, 0x61, 0x6e, 0x64, 0x73, 0x54, 0x75, 0x76, 0x61, 0x6c, 0x75, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x42, 0x72, 0x69,
-0x74, 0x69, 0x73, 0x68, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20, 0x4b,
-0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x55, 0x2e, 0x53, 0x2e, 0x20, 0x4f, 0x75, 0x74, 0x6c, 0x79, 0x69, 0x6e, 0x67, 0x20,
-0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73,
-0x68, 0x20, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x55, 0x2e, 0x53, 0x2e,
-0x20, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x5a, 0x61, 0x6d, 0x62, 0x69,
-0x61, 0x5a, 0x69, 0x6d, 0x62, 0x61, 0x62, 0x77, 0x65, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x20, 0x47, 0x61, 0x72, 0x63, 0x69,
-0x61, 0x49, 0x73, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61, 0x6e, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x53, 0x6f,
-0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x53, 0x69, 0x6e, 0x74, 0x20, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x65,
-0x6e, 0x65, 0x65, 0x73, 0x74, 0x69, 0x45, 0x65, 0x73, 0x74, 0x69, 0x66, 0xf8, 0x72, 0x6f, 0x79, 0x73, 0x6b, 0x74, 0x46,
-0xf8, 0x72, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x75, 0x6f, 0x6d, 0x69, 0x53, 0x75, 0x6f, 0x6d, 0x69, 0x66, 0x72, 0x61, 0x6e,
-0xe7, 0x61, 0x69, 0x73, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x42, 0x65, 0x6c,
-0x67, 0x69, 0x71, 0x75, 0x65, 0x42, 0xe9, 0x6e, 0x69, 0x6e, 0x42, 0x75, 0x72, 0x6b, 0x69, 0x6e, 0x61, 0x20, 0x46, 0x61,
-0x73, 0x6f, 0x43, 0x61, 0x6d, 0x65, 0x72, 0x6f, 0x75, 0x6e, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x20, 0x63,
-0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x52, 0xe9, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x71, 0x75, 0x65, 0x20, 0x63, 0x65,
-0x6e, 0x74, 0x72, 0x61, 0x66, 0x72, 0x69, 0x63, 0x61, 0x69, 0x6e, 0x65, 0x54, 0x63, 0x68, 0x61, 0x64, 0x43, 0x6f, 0x6d,
-0x6f, 0x72, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x67, 0x6f, 0x2d, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x43, 0x6f,
-0x6e, 0x67, 0x6f, 0x2d, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x43, 0xf4, 0x74, 0x65, 0x20,
-0x64, 0x2019, 0x49, 0x76, 0x6f, 0x69, 0x72, 0x65, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x47, 0x75, 0x69, 0x6e,
-0xe9, 0x65, 0x20, 0xe9, 0x71, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x65, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x65,
-0x20, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x79, 0x6e, 0xe9, 0x73, 0x69, 0x65, 0x20,
-0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65, 0x47, 0x61, 0x62, 0x6f, 0x6e, 0x47, 0x75, 0x61, 0x64, 0x65, 0x6c,
-0x6f, 0x75, 0x70, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x48, 0x61, 0xef, 0x74, 0x69, 0x4c, 0x75, 0x78, 0x65, 0x6d,
-0x62, 0x6f, 0x75, 0x72, 0x67, 0x4d, 0x61, 0x6c, 0x69, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x4d,
-0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x79, 0x6f,
-0x74, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x4d, 0x61, 0x72, 0x6f, 0x63, 0x4e, 0x6f, 0x75, 0x76, 0x65, 0x6c,
-0x6c, 0x65, 0x2d, 0x43, 0x61, 0x6c, 0xe9, 0x64, 0x6f, 0x6e, 0x69, 0x65, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x4c, 0x61, 0x20,
-0x52, 0xe9, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x53, 0xe9, 0x6e, 0xe9, 0x67, 0x61, 0x6c, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d,
-0x50, 0x69, 0x65, 0x72, 0x72, 0x65, 0x2d, 0x65, 0x74, 0x2d, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x66, 0x72,
-0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x53, 0x75, 0x69, 0x73, 0x73, 0x65, 0x53,
-0x79, 0x72, 0x69, 0x65, 0x54, 0x6f, 0x67, 0x6f, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x57, 0x61, 0x6c, 0x6c, 0x69,
-0x73, 0x2d, 0x65, 0x74, 0x2d, 0x46, 0x75, 0x74, 0x75, 0x6e, 0x61, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x42, 0x61, 0x72,
-0x74, 0x68, 0xe9, 0x6c, 0x65, 0x6d, 0x79, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x57,
-0x65, 0x73, 0x74, 0x2d, 0x46, 0x72, 0x79, 0x73, 0x6b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0xe2, 0x6e, 0x47, 0xe0, 0x69,
-0x64, 0x68, 0x6c, 0x69, 0x67, 0x41, 0x6e, 0x20, 0x52, 0xec, 0x6f, 0x67, 0x68, 0x61, 0x63, 0x68, 0x64, 0x20, 0x41, 0x6f,
-0x6e, 0x61, 0x69, 0x63, 0x68, 0x74, 0x65, 0x67, 0x61, 0x6c, 0x65, 0x67, 0x6f, 0x45, 0x73, 0x70, 0x61, 0xf1, 0x61, 0x10e5,
-0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x10e1, 0x10d0, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10d5, 0x10d4, 0x10da, 0x10dd, 0x44, 0x65, 0x75, 0x74,
-0x73, 0x63, 0x68, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0xd6, 0x73, 0x74, 0x65, 0x72, 0x72,
-0x65, 0x69, 0x63, 0x68, 0x69, 0x73, 0x63, 0x68, 0x65, 0x73, 0x20, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0xd6, 0x73,
-0x74, 0x65, 0x72, 0x72, 0x65, 0x69, 0x63, 0x68, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x65, 0x6e, 0x4c, 0x69, 0x65, 0x63, 0x68,
-0x74, 0x65, 0x6e, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x75, 0x72, 0x67, 0x53, 0x63, 0x68,
-0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x48, 0x6f, 0x63, 0x68, 0x64, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x53, 0x63,
-0x68, 0x77, 0x65, 0x69, 0x7a, 0x395, 0x3bb, 0x3bb, 0x3b7, 0x3bd, 0x3b9, 0x3ba, 0x3ac, 0x395, 0x3bb, 0x3bb, 0x3ac, 0x3b4, 0x3b1, 0x39a,
-0x3cd, 0x3c0, 0x3c1, 0x3bf, 0x3c2, 0x6b, 0x61, 0x6c, 0x61, 0x61, 0x6c, 0x6c, 0x69, 0x73, 0x75, 0x74, 0x4b, 0x61, 0x6c, 0x61,
-0x61, 0x6c, 0x6c, 0x69, 0x74, 0x20, 0x4e, 0x75, 0x6e, 0x61, 0x61, 0x74, 0xa97, 0xac1, 0xa9c, 0xab0, 0xabe, 0xaa4, 0xac0, 0xaad,
-0xabe, 0xab0, 0xaa4, 0x48, 0x61, 0x75, 0x73, 0x61, 0x4e, 0x61, 0x6a, 0x65, 0x72, 0x69, 0x79, 0x61, 0x47, 0x61, 0x6e, 0x61,
-0x4e, 0x69, 0x6a, 0x61, 0x72, 0x5e2, 0x5d1, 0x5e8, 0x5d9, 0x5ea, 0x5d9, 0x5e9, 0x5e8, 0x5d0, 0x5dc, 0x939, 0x93f, 0x928, 0x94d, 0x926,
-0x940, 0x92d, 0x93e, 0x930, 0x924, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x4d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x6f, 0x72, 0x73,
-0x7a, 0xe1, 0x67, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0xcd, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x49, 0x6e, 0x64,
-0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x47, 0x61, 0x65, 0x69, 0x6c, 0x67, 0x65, 0xc9, 0x69, 0x72, 0x65, 0x69, 0x74, 0x61,
-0x6c, 0x69, 0x61, 0x6e, 0x6f, 0x49, 0x74, 0x61, 0x6c, 0x69, 0x61, 0x53, 0x61, 0x6e, 0x20, 0x4d, 0x61, 0x72, 0x69, 0x6e,
-0x6f, 0x53, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x61, 0x65e5, 0x672c, 0x8a9e, 0x65e5, 0x672c, 0xc95, 0xca8, 0xccd, 0xca8, 0xca1, 0xcad,
-0xcbe, 0xcb0, 0xca4, 0x6a9, 0x672, 0x634, 0x64f, 0x631, 0x6c1, 0x650, 0x646, 0x65b, 0x62f, 0x648, 0x633, 0x62a, 0x627, 0x646, 0x49b, 0x430,
-0x437, 0x430, 0x49b, 0x20, 0x442, 0x456, 0x43b, 0x456, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441, 0x442, 0x430, 0x43d, 0x4b, 0x69, 0x6e,
-0x79, 0x61, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x43a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x447, 0x430, 0x41a, 0x44b, 0x440, 0x433,
-0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0xd55c, 0xad6d, 0xc5b4, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0xc870, 0xc120, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0xc778,
-0xbbfc, 0xacf5, 0xd654, 0xad6d, 0x49, 0x6b, 0x69, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x55, 0x62, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69,
-0xea5, 0xeb2, 0xea7, 0x6c, 0x61, 0x74, 0x76, 0x69, 0x65, 0x161, 0x75, 0x4c, 0x61, 0x74, 0x76, 0x69, 0x6a, 0x61, 0x6c, 0x69,
-0x6e, 0x67, 0xe1, 0x6c, 0x61, 0x52, 0x65, 0x70, 0x69, 0x62, 0x69, 0x6b, 0x69, 0x20, 0x64, 0x65, 0x6d, 0x6f, 0x6b, 0x72,
-0x61, 0x74, 0x69, 0x6b, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0xf3, 0x41, 0x6e, 0x67, 0xf3, 0x6c, 0x61,
-0x52, 0x65, 0x70, 0x69, 0x62, 0x69, 0x6b, 0x69, 0x20, 0x79, 0x61, 0x20, 0x41, 0x66, 0x72, 0xed, 0x6b, 0x61, 0x20, 0x79,
-0x61, 0x20, 0x4b, 0xe1, 0x74, 0x69, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69, 0x65, 0x74, 0x75, 0x76, 0x69, 0x173, 0x4c,
-0x69, 0x65, 0x74, 0x75, 0x76, 0x61, 0x43c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x441, 0x43a, 0x438, 0x41c, 0x430, 0x43a, 0x435,
-0x434, 0x43e, 0x43d, 0x438, 0x458, 0x430, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73, 0x79, 0x4d, 0x61, 0x64, 0x61, 0x67, 0x61,
-0x73, 0x69, 0x6b, 0x61, 0x72, 0x61, 0x42, 0x61, 0x68, 0x61, 0x73, 0x61, 0x20, 0x4d, 0x65, 0x6c, 0x61, 0x79, 0x75, 0x42,
-0x72, 0x75, 0x6e, 0x65, 0x69, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72, 0x61, 0xd2e, 0xd32, 0xd2f, 0xd3e, 0xd33, 0xd02,
-0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0x4d, 0x61, 0x6c, 0x74, 0x69, 0x92e, 0x930, 0x93e, 0x920, 0x940, 0x43c, 0x43e, 0x43d, 0x433,
-0x43e, 0x43b, 0x41c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x940, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x6e,
-0x6f, 0x72, 0x73, 0x6b, 0x20, 0x62, 0x6f, 0x6b, 0x6d, 0xe5, 0x6c, 0x4e, 0x6f, 0x72, 0x67, 0x65, 0x53, 0x76, 0x61, 0x6c,
-0x62, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x67, 0x20, 0x4a, 0x61, 0x6e, 0x20, 0x4d, 0x61, 0x79, 0x65, 0x6e, 0xb13, 0xb21, 0xb3c,
-0xb3f, 0xb06, 0xb2d, 0xb3e, 0xb30, 0xb24, 0x67e, 0x69a, 0x62a, 0x648, 0x627, 0x641, 0x63a, 0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x641,
-0x627, 0x631, 0x633, 0x6cc, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x62f, 0x631, 0x6cc, 0x70, 0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x50, 0x6f,
-0x6c, 0x73, 0x6b, 0x61, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea, 0x73, 0x20, 0x64, 0x6f, 0x20, 0x42, 0x72, 0x61,
-0x73, 0x69, 0x6c, 0x42, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea, 0x73, 0x41, 0x6e,
-0x67, 0x6f, 0x6c, 0x61, 0x43, 0x61, 0x62, 0x6f, 0x20, 0x56, 0x65, 0x72, 0x64, 0x65, 0x54, 0x69, 0x6d, 0x6f, 0x72, 0x2d,
-0x4c, 0x65, 0x73, 0x74, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x20, 0x45, 0x71, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61,
-0x6c, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x2d, 0x42, 0x69, 0x73, 0x73, 0x61, 0x75, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x75,
-0x72, 0x67, 0x6f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x2c, 0x20, 0x52, 0x41, 0x45, 0x20, 0x64, 0x61, 0x20, 0x43, 0x68, 0x69,
-0x6e, 0x61, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea,
-0x73, 0x20, 0x65, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x75, 0x50, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x61, 0x6c, 0x53, 0xe3, 0x6f,
-0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e, 0x63, 0x69, 0x70, 0x65, 0x53, 0x75, 0xed, 0xe7,
-0x61, 0xa2a, 0xa70, 0xa1c, 0xa3e, 0xa2c, 0xa40, 0xa2d, 0xa3e, 0xa30, 0xa24, 0x67e, 0x646, 0x62c, 0x627, 0x628, 0x6cc, 0x67e, 0x6a9, 0x633,
-0x62a, 0x627, 0x646, 0x52, 0x75, 0x6e, 0x61, 0x73, 0x69, 0x6d, 0x69, 0x50, 0x65, 0x72, 0xfa, 0x42, 0x6f, 0x6c, 0x69, 0x76,
-0x69, 0x61, 0x45, 0x63, 0x75, 0x61, 0x64, 0x6f, 0x72, 0x72, 0x75, 0x6d, 0x61, 0x6e, 0x74, 0x73, 0x63, 0x68, 0x53, 0x76,
-0x69, 0x7a, 0x72, 0x61, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x103, 0x52, 0x6f, 0x6d, 0xe2, 0x6e, 0x69, 0x61, 0x6d, 0x6f, 0x6c,
-0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x61, 0x73, 0x63, 0x103, 0x52, 0x65, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20,
-0x4d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x61, 0x440, 0x443, 0x441, 0x441, 0x43a, 0x438, 0x439, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x44f,
-0x41a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x442, 0x430, 0x43d, 0x41a, 0x438, 0x440, 0x433, 0x438, 0x437, 0x438, 0x44f, 0x41c, 0x43e, 0x43b,
-0x434, 0x43e, 0x432, 0x430, 0x423, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x430, 0x53, 0xe4, 0x6e, 0x67, 0xf6, 0x4b, 0xf6, 0x64, 0xf6,
-0x72, 0xf6, 0x73, 0xea, 0x73, 0x65, 0x20, 0x74, 0xee, 0x20, 0x42, 0xea, 0x61, 0x66, 0x72, 0xee, 0x6b, 0x61, 0x441, 0x440,
-0x43f, 0x441, 0x43a, 0x438, 0x421, 0x440, 0x431, 0x438, 0x458, 0x430, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x43, 0x72, 0x6e, 0x61,
-0x20, 0x47, 0x6f, 0x72, 0x61, 0x53, 0x72, 0x62, 0x69, 0x6a, 0x61, 0x411, 0x43e, 0x441, 0x43d, 0x430, 0x20, 0x438, 0x20, 0x425,
-0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x438, 0x43d, 0x430, 0x426, 0x440, 0x43d, 0x430, 0x20, 0x413, 0x43e, 0x440, 0x430, 0x41a,
-0x43e, 0x441, 0x43e, 0x432, 0x43e, 0x4b, 0x6f, 0x73, 0x6f, 0x76, 0x6f, 0x438, 0x440, 0x43e, 0x43d, 0x413, 0x443, 0x44b, 0x440, 0x434,
-0x437, 0x44b, 0x441, 0x442, 0x43e, 0x43d, 0x423, 0x4d5, 0x440, 0x4d5, 0x441, 0x435, 0x63, 0x68, 0x69, 0x53, 0x68, 0x6f, 0x6e, 0x61,
-0xdc3, 0xdd2, 0xd82, 0xdc4, 0xdbd, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20, 0xdbd, 0xd82, 0xd9a, 0xdcf, 0xdc0, 0x73, 0x6c, 0x6f, 0x76,
-0x65, 0x6e, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x6f, 0x73, 0x6c, 0x6f, 0x76, 0x65,
-0x6e, 0x161, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x69, 0x6a, 0x61, 0x53, 0x6f, 0x6f, 0x6d, 0x61,
-0x61, 0x6c, 0x69, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x79, 0x61, 0x4a, 0x61, 0x62, 0x75, 0x75, 0x74, 0x69,
-0x49, 0x74, 0x6f, 0x6f, 0x62, 0x69, 0x79, 0x61, 0x4b, 0x69, 0x69, 0x6e, 0x69, 0x79, 0x61, 0x65, 0x73, 0x70, 0x61, 0xf1,
-0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x45, 0x73, 0x70, 0x61, 0xf1, 0x61, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x41,
-0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69,
-0x61, 0x43, 0x6f, 0x73, 0x74, 0x61, 0x20, 0x52, 0x69, 0x63, 0x61, 0x43, 0x75, 0x62, 0x61, 0x52, 0x65, 0x70, 0xfa, 0x62,
-0x6c, 0x69, 0x63, 0x61, 0x20, 0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x6e, 0x61, 0x45, 0x6c, 0x20, 0x53, 0x61,
-0x6c, 0x76, 0x61, 0x64, 0x6f, 0x72, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x20, 0x45, 0x63, 0x75, 0x61, 0x74, 0x6f, 0x72,
-0x69, 0x61, 0x6c, 0x47, 0x75, 0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x48, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x61, 0x73,
-0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0xe9, 0x78, 0x69, 0x63, 0x6f, 0x4d, 0xe9, 0x78,
-0x69, 0x63, 0x6f, 0x4e, 0x69, 0x63, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0xe1, 0x50, 0x61,
-0x72, 0x61, 0x67, 0x75, 0x61, 0x79, 0x46, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x45, 0x73, 0x74, 0x61, 0x64,
-0x6f, 0x73, 0x20, 0x55, 0x6e, 0x69, 0x64, 0x6f, 0x73, 0x55, 0x72, 0x75, 0x67, 0x75, 0x61, 0x79, 0x56, 0x65, 0x6e, 0x65,
-0x7a, 0x75, 0x65, 0x6c, 0x61, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x61, 0x73, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c,
-0x20, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x6f, 0x61, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x4c, 0x61, 0x74, 0x69,
-0x6e, 0x6f, 0x61, 0x6d, 0xe9, 0x72, 0x69, 0x63, 0x61, 0x43, 0x65, 0x75, 0x74, 0x61, 0x20, 0x79, 0x20, 0x4d, 0x65, 0x6c,
-0x69, 0x6c, 0x6c, 0x61, 0x4b, 0x69, 0x73, 0x77, 0x61, 0x68, 0x69, 0x6c, 0x69, 0x4b, 0x69, 0x73, 0x77, 0x61, 0x68, 0x69,
-0x6c, 0x69, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x4a, 0x61, 0x6d, 0x68, 0x75, 0x72, 0x69, 0x20, 0x79,
-0x61, 0x20, 0x4b, 0x69, 0x64, 0x65, 0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x73, 0x69, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f,
-0x6e, 0x67, 0x6f, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x53, 0x76, 0x65, 0x72, 0x69, 0x67, 0x65, 0xc5, 0x6c, 0x61,
-0x6e, 0x64, 0xba4, 0xbae, 0xbbf, 0xbb4, 0xbcd, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0xbbe, 0xbae, 0xbb2, 0xbc7, 0xb9a, 0xbbf, 0xbaf,
-0xbbe, 0xb9a, 0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0xc24, 0xc46,
-0xc32, 0xc41, 0xc17, 0xc41, 0xc2d, 0xc3e, 0xc30, 0xc24, 0x20, 0xc26, 0xc47, 0xc36, 0xc02, 0xe44, 0xe17, 0xe22, 0xf56, 0xf7c, 0xf51, 0xf0b,
-0xf66, 0xf90, 0xf51, 0xf0b, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf53, 0xf42, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf42, 0xf62, 0xf0b, 0x1275, 0x130d, 0x122d,
-0x129b, 0x12a4, 0x122d, 0x1275, 0x122b, 0x6c, 0x65, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0xfc,
-0x72, 0x6b, 0xe7, 0x65, 0x54, 0xfc, 0x72, 0x6b, 0x69, 0x79, 0x65, 0x4b, 0x131, 0x62, 0x72, 0x131, 0x73, 0x74, 0xfc, 0x72,
-0x6b, 0x6d, 0x65, 0x6e, 0xe7, 0x65, 0x54, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x626, 0x6c7,
-0x64a, 0x63a, 0x6c7, 0x631, 0x686, 0x6d5, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x443, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c, 0x43a,
-0x430, 0x423, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x430, 0x627, 0x631, 0x62f, 0x648, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x628,
-0x6be, 0x627, 0x631, 0x62a, 0x6f, 0x2018, 0x7a, 0x62, 0x65, 0x6b, 0x4f, 0x2bb, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f,
-0x6e, 0x627, 0x648, 0x632, 0x628, 0x6cc, 0x6a9, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442,
-0x43e, 0x43d, 0x54, 0x69, 0x1ebf, 0x6e, 0x67, 0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d,
-0x43, 0x79, 0x6d, 0x72, 0x61, 0x65, 0x67, 0x59, 0x20, 0x44, 0x65, 0x79, 0x72, 0x6e, 0x61, 0x73, 0x20, 0x55, 0x6e, 0x65,
-0x64, 0x69, 0x67, 0xc8, 0x64, 0xe8, 0x20, 0x59, 0x6f, 0x72, 0xf9, 0x62, 0xe1, 0x4f, 0x72, 0xed, 0x6c, 0x1eb9, 0x301, 0xe8,
-0x64, 0x65, 0x20, 0x4e, 0xe0, 0xec, 0x6a, 0xed, 0x72, 0xed, 0xe0, 0x4f, 0x72, 0xed, 0x6c, 0x25b, 0x301, 0xe8, 0x64, 0x65,
-0x20, 0x42, 0x25b, 0x300, 0x6e, 0x25b, 0x300, 0x69, 0x73, 0x69, 0x5a, 0x75, 0x6c, 0x75, 0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74,
-0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x79, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x4e, 0x6f, 0x72, 0x65, 0x67,
-0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b, 0x69, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x438, 0x47, 0x61, 0x65, 0x6c,
-0x67, 0x45, 0x6c, 0x6c, 0x61, 0x6e, 0x20, 0x56, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x77, 0x65,
-0x6b, 0x52, 0x79, 0x77, 0x76, 0x61, 0x6e, 0x65, 0x74, 0x68, 0x20, 0x55, 0x6e, 0x79, 0x73, 0x41, 0x6b, 0x61, 0x6e, 0x47,
-0x61, 0x61, 0x6e, 0x61, 0x915, 0x94b, 0x902, 0x915, 0x923, 0x940, 0x49, 0x67, 0x62, 0x6f, 0x4b, 0x69, 0x6b, 0x61, 0x6d, 0x62,
-0x61, 0x66, 0x75, 0x72, 0x6c, 0x61, 0x6e, 0x49, 0x74, 0x61, 0x6c, 0x69, 0x65, 0x45, 0x28b, 0x65, 0x67, 0x62, 0x65, 0x47,
-0x68, 0x61, 0x6e, 0x61, 0x20, 0x6e, 0x75, 0x74, 0x6f, 0x6d, 0x65, 0x54, 0x6f, 0x67, 0x6f, 0x20, 0x6e, 0x75, 0x74, 0x6f,
-0x6d, 0x65, 0x2bb, 0x14c, 0x6c, 0x65, 0x6c, 0x6f, 0x20, 0x48, 0x61, 0x77, 0x61, 0x69, 0x2bb, 0x69, 0x2bb, 0x41, 0x6d, 0x65,
-0x6c, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x75, 0x69, 0x20, 0x50, 0x16b, 0x20, 0x2bb, 0x49, 0x61, 0x46, 0x69, 0x6c, 0x69, 0x70,
-0x69, 0x6e, 0x6f, 0x50, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65,
-0x72, 0x74, 0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x46, 0x72, 0x61, 0x6e, 0x6b,
-0x72, 0x69, 0x69, 0x63, 0x68, 0x4c, 0x69, 0xe4, 0x63, 0x68, 0x74, 0x65, 0x73, 0x63, 0x68, 0x74, 0xe4, 0x69, 0xa188, 0xa320,
-0xa259, 0xa34f, 0xa1e9, 0x64, 0x61, 0x76, 0x76, 0x69, 0x73, 0xe1, 0x6d, 0x65, 0x67, 0x69, 0x65, 0x6c, 0x6c, 0x61, 0x4e, 0x6f,
-0x72, 0x67, 0x61, 0x53, 0x75, 0x6f, 0x70, 0x6d, 0x61, 0x52, 0x75, 0x6f, 0x167, 0x167, 0x61, 0x45, 0x6b, 0x65, 0x67, 0x75,
-0x73, 0x69, 0x69, 0x4b, 0x69, 0x74, 0x61, 0x69, 0x74, 0x61, 0x50, 0x75, 0x6c, 0x61, 0x61, 0x72, 0x53, 0x65, 0x6e, 0x65,
-0x67, 0x61, 0x61, 0x6c, 0x4b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x75, 0x6e, 0x47, 0x69, 0x6e, 0x65, 0x4d, 0x75, 0x72, 0x69,
-0x74, 0x61, 0x6e, 0x69, 0x47, 0x69, 0x6b, 0x75, 0x79, 0x75, 0x4b, 0x69, 0x73, 0x61, 0x6d, 0x70, 0x75, 0x72, 0x73, 0x65,
-0x6e, 0x61, 0x69, 0x73, 0x69, 0x4e, 0x64, 0x65, 0x62, 0x65, 0x6c, 0x65, 0x4b, 0x69, 0x68, 0x6f, 0x72, 0x6f, 0x6d, 0x62,
-0x6f, 0x2d5c, 0x2d30, 0x2d5b, 0x2d4d, 0x2d43, 0x2d49, 0x2d5c, 0x2d4d, 0x2d4e, 0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x54, 0x61, 0x73, 0x68, 0x65, 0x6c,
-0x1e25, 0x69, 0x79, 0x74, 0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62, 0x54, 0x61, 0x71, 0x62, 0x61, 0x79, 0x6c, 0x69, 0x74, 0x4c,
-0x65, 0x7a, 0x7a, 0x61, 0x79, 0x65, 0x72, 0x52, 0x75, 0x6e, 0x79, 0x61, 0x6e, 0x6b, 0x6f, 0x72, 0x65, 0x48, 0x69, 0x62,
-0x65, 0x6e, 0x61, 0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x4b, 0x79, 0x69, 0x76, 0x75, 0x6e, 0x6a,
-0x6f, 0x62, 0x61, 0x6d, 0x61, 0x6e, 0x61, 0x6b, 0x61, 0x6e, 0x4b, 0x129, 0x65, 0x6d, 0x62, 0x75, 0x13e3, 0x13b3, 0x13a9, 0x13a0,
-0x13b9, 0x13f0, 0x13df, 0x6b, 0x72, 0x65, 0x6f, 0x6c, 0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x4d, 0x6f, 0x72,
-0x69, 0x73, 0x43, 0x68, 0x69, 0x6d, 0x61, 0x6b, 0x6f, 0x6e, 0x64, 0x65, 0x4b, 0x268, 0x6c, 0x61, 0x61, 0x6e, 0x67, 0x69,
-0x54, 0x61, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0xed, 0x61, 0x4c, 0x75, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x59, 0x75, 0x67, 0x61,
-0x6e, 0x64, 0x61, 0x49, 0x63, 0x68, 0x69, 0x62, 0x65, 0x6d, 0x62, 0x61, 0x6b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72, 0x64,
-0x69, 0x61, 0x6e, 0x75, 0x4b, 0x61, 0x62, 0x75, 0x20, 0x56, 0x65, 0x72, 0x64, 0x69, 0x4b, 0x129, 0x6d, 0x129, 0x72, 0x169,
-0x4b, 0x61, 0x6c, 0x65, 0x6e, 0x6a, 0x69, 0x6e, 0x45, 0x6d, 0x65, 0x74, 0x61, 0x62, 0x20, 0x4b, 0x65, 0x6e, 0x79, 0x61,
-0x4b, 0x68, 0x6f, 0x65, 0x6b, 0x68, 0x6f, 0x65, 0x67, 0x6f, 0x77, 0x61, 0x62, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61,
-0x62, 0x4b, 0x69, 0x6d, 0x61, 0x63, 0x68, 0x61, 0x6d, 0x65, 0x4b, 0xf6, 0x6c, 0x73, 0x63, 0x68, 0x44, 0x6f, 0xfc, 0x74,
-0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x61, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x61, 0x4f, 0x6c,
-0x75, 0x73, 0x6f, 0x67, 0x61, 0x4c, 0x75, 0x6c, 0x75, 0x68, 0x69, 0x61, 0x4b, 0x69, 0x70, 0x61, 0x72, 0x65, 0x54, 0x61,
-0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x4b, 0x69, 0x74, 0x65, 0x73, 0x6f, 0x4b, 0x65, 0x6e, 0x69, 0x61, 0x4b, 0x6f, 0x79,
-0x72, 0x61, 0x20, 0x63, 0x69, 0x69, 0x6e, 0x69, 0x4d, 0x61, 0x61, 0x6c, 0x69, 0x4b, 0x69, 0x72, 0x75, 0x77, 0x61, 0x44,
-0x68, 0x6f, 0x6c, 0x75, 0x6f, 0x52, 0x75, 0x6b, 0x69, 0x67, 0x61, 0x54, 0x61, 0x6d, 0x61, 0x7a, 0x69, 0x263, 0x74, 0x20,
-0x6e, 0x20, 0x6c, 0x61, 0x1e6d, 0x6c, 0x61, 0x1e63, 0x4d, 0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x4b, 0x6f, 0x79, 0x72, 0x61, 0x62,
-0x6f, 0x72, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69, 0x4b, 0x69, 0x73, 0x68, 0x61, 0x6d, 0x62, 0x61, 0x61, 0x92c, 0x921,
-0x93c, 0x94b, 0x43d, 0x43e, 0x445, 0x447, 0x438, 0x439, 0x43d, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x446, 0x435, 0x440, 0x43a, 0x43e, 0x432,
-0x43d, 0x43e, 0x441, 0x43b, 0x43e, 0x432, 0x435, 0x301, 0x43d, 0x441, 0x43a, 0x457, 0x439, 0x440, 0x461, 0x441, 0x441, 0x456, 0x301, 0x430,
-0x54, 0x73, 0x68, 0x69, 0x6c, 0x75, 0x62, 0x61, 0x44, 0x69, 0x74, 0x75, 0x6e, 0x67, 0x61, 0x20, 0x77, 0x61, 0x20, 0x4b,
-0x6f, 0x6e, 0x67, 0x75, 0x4c, 0xeb, 0x74, 0x7a, 0x65, 0x62, 0x75, 0x65, 0x72, 0x67, 0x65, 0x73, 0x63, 0x68, 0x4c, 0xeb,
-0x74, 0x7a, 0x65, 0x62, 0x75, 0x65, 0x72, 0x67, 0x41, 0x67, 0x68, 0x65, 0x6d, 0x4b, 0xe0, 0x6d, 0xe0, 0x6c, 0xfb, 0x14b,
-0x181, 0xe0, 0x73, 0xe0, 0x61, 0x4b, 0xe0, 0x6d, 0x25b, 0x300, 0x72, 0xfb, 0x6e, 0x5a, 0x61, 0x72, 0x6d, 0x61, 0x63, 0x69,
-0x69, 0x6e, 0x65, 0x4e, 0x69, 0x17e, 0x65, 0x72, 0x64, 0x75, 0xe1, 0x6c, 0xe1, 0x6a, 0x6f, 0x6f, 0x6c, 0x61, 0x53, 0x65,
-0x6e, 0x65, 0x67, 0x61, 0x6c, 0x65, 0x77, 0x6f, 0x6e, 0x64, 0x6f, 0x4b, 0x61, 0x6d, 0x259, 0x72, 0xfa, 0x6e, 0x72, 0x69,
-0x6b, 0x70, 0x61, 0x6b, 0x61, 0x6d, 0x25b, 0x72, 0xfa, 0x6e, 0x4d, 0x61, 0x6b, 0x75, 0x61, 0x55, 0x6d, 0x6f, 0x7a, 0x61,
-0x6d, 0x62, 0x69, 0x6b, 0x69, 0x4d, 0x55, 0x4e, 0x44, 0x41, 0x14a, 0x6b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x14b, 0x4b, 0x77,
-0x61, 0x73, 0x69, 0x6f, 0x4b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x6e, 0x54, 0x68, 0x6f, 0x6b, 0x20, 0x4e, 0x61, 0x74, 0x68,
-0x441, 0x430, 0x445, 0x430, 0x20, 0x442, 0x44b, 0x43b, 0x430, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430, 0x49, 0x73,
-0x68, 0x69, 0x73, 0x61, 0x6e, 0x67, 0x75, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0x54, 0x61, 0x73, 0x61,
-0x77, 0x61, 0x71, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69, 0xa559, 0xa524, 0xa55e, 0xa524, 0xa52b, 0xa569, 0x56, 0x61, 0x69, 0x4c, 0x61,
-0x69, 0x62, 0x68, 0x69, 0x79, 0x61, 0x57, 0x61, 0x6c, 0x73, 0x65, 0x72, 0x53, 0x63, 0x68, 0x77, 0x69, 0x7a, 0x6e, 0x75,
-0x61, 0x73, 0x75, 0x65, 0x4b, 0x65, 0x6d, 0x65, 0x6c, 0xfa, 0x6e, 0x61, 0x73, 0x74, 0x75, 0x72, 0x69, 0x61, 0x6e, 0x75,
-0x4e, 0x64, 0x61, 0xa78c, 0x61, 0x4b, 0x61, 0x6d, 0x25b, 0x6c, 0xfb, 0x6e, 0x6b, 0x61, 0x6b, 0x254, 0x4b, 0x61, 0x6d, 0x25b,
-0x72, 0x75, 0x6e, 0x6d, 0x65, 0x74, 0x61, 0x2bc, 0x4b, 0x61, 0x6d, 0x61, 0x6c, 0x75, 0x6e, 0x53, 0x68, 0x77, 0xf3, 0x14b,
-0xf2, 0x20, 0x6e, 0x67, 0x69, 0x65, 0x6d, 0x62, 0x254, 0x254, 0x6e, 0x4b, 0xe0, 0x6d, 0x61, 0x6c, 0xfb, 0x6d, 0x4c, 0x61,
-0x6b, 0x21f, 0xf3, 0x6c, 0x2bc, 0x69, 0x79, 0x61, 0x70, 0x69, 0x4d, 0xed, 0x6c, 0x61, 0x68, 0x61, 0x14b, 0x73, 0x6b, 0x61,
-0x20, 0x54, 0x21f, 0x61, 0x6d, 0xe1, 0x6b, 0x21f, 0x6f, 0x10d, 0x68, 0x65, 0x2d5c, 0x2d30, 0x2d4e, 0x2d30, 0x2d63, 0x2d49, 0x2d56, 0x2d5c,
-0x6a9, 0x648, 0x631, 0x62f, 0x6cc, 0x6cc, 0x20, 0x646, 0x627, 0x648, 0x6d5, 0x646, 0x62f, 0x6cc, 0x639, 0x6ce, 0x631, 0x627, 0x642, 0x626,
-0x6ce, 0x631, 0x627, 0x646, 0x64, 0x6f, 0x6c, 0x6e, 0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107, 0x69, 0x6e, 0x61, 0x4e, 0x69,
-0x6d, 0x73, 0x6b, 0x61, 0x68, 0x6f, 0x72, 0x6e, 0x6a, 0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107, 0x69, 0x6e, 0x61, 0x4e,
-0x11b, 0x6d, 0x73, 0x6b, 0x61, 0x61, 0x6e, 0x61, 0x72, 0xe2, 0x161, 0x6b, 0x69, 0x65, 0x6c, 0xe2, 0x53, 0x75, 0x6f, 0x6d,
-0xe2, 0x645, 0x627, 0x632, 0x631, 0x648, 0x646, 0x6cc, 0x644, 0x6ca, 0x631, 0x6cc, 0x20, 0x634, 0x648, 0x645, 0x627, 0x644, 0x6cc, 0x7cb5,
-0x8a9e
+0x9f0, 0x9a4, 0x61, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63, 0x61, 0x6e, 0x41, 0x7a, 0x259, 0x72, 0x62, 0x61, 0x79, 0x63,
+0x61, 0x6e, 0x430, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9, 0x430, 0x43d, 0x410, 0x437, 0x4d9, 0x440, 0x431, 0x430, 0x458, 0x4b9,
+0x430, 0x43d, 0x65, 0x75, 0x73, 0x6b, 0x61, 0x72, 0x61, 0x45, 0x73, 0x70, 0x61, 0x69, 0x6e, 0x69, 0x61, 0x9ac, 0x9be, 0x982,
+0x9b2, 0x9be, 0x9ac, 0x9be, 0x982, 0x9b2, 0x9be, 0x9a6, 0x9c7, 0x9b6, 0x9ad, 0x9be, 0x9b0, 0x9a4, 0xf62, 0xfab, 0xf7c, 0xf44, 0xf0b, 0xf41,
+0xf60, 0xf56, 0xfb2, 0xf74, 0xf42, 0x62, 0x72, 0x65, 0x7a, 0x68, 0x6f, 0x6e, 0x65, 0x67, 0x46, 0x72, 0x61, 0xf1, 0x73, 0x431,
+0x44a, 0x43b, 0x433, 0x430, 0x440, 0x441, 0x43a, 0x438, 0x411, 0x44a, 0x43b, 0x433, 0x430, 0x440, 0x438, 0x44f, 0x1019, 0x103c, 0x1014, 0x103a,
+0x1019, 0x102c, 0x431, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x43a, 0x430, 0x44f, 0x411, 0x435, 0x43b, 0x430, 0x440, 0x443, 0x441, 0x44c,
+0x1781, 0x17d2, 0x1798, 0x17c2, 0x179a, 0x1780, 0x1798, 0x17d2, 0x1796, 0x17bb, 0x1787, 0x17b6, 0x63, 0x61, 0x74, 0x61, 0x6c, 0xe0, 0x45, 0x73,
+0x70, 0x61, 0x6e, 0x79, 0x61, 0x41, 0x6e, 0x64, 0x6f, 0x72, 0x72, 0x61, 0x46, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x49, 0x74,
+0xe0, 0x6c, 0x69, 0x61, 0x7b80, 0x4f53, 0x4e2d, 0x6587, 0x4e2d, 0x56fd, 0x4e2d, 0x56fd, 0x9999, 0x6e2f, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x4e2d,
+0x56fd, 0x6fb3, 0x95e8, 0x7279, 0x522b, 0x884c, 0x653f, 0x533a, 0x65b0, 0x52a0, 0x5761, 0x7e41, 0x9ad4, 0x4e2d, 0x6587, 0x4e2d, 0x570b, 0x9999, 0x6e2f, 0x7279,
+0x5225, 0x884c, 0x653f, 0x5340, 0x4e2d, 0x570b, 0x6fb3, 0x9580, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340, 0x53f0, 0x7063, 0x68, 0x72, 0x76, 0x61, 0x74,
+0x73, 0x6b, 0x69, 0x48, 0x72, 0x76, 0x61, 0x74, 0x73, 0x6b, 0x61, 0x42, 0x6f, 0x73, 0x6e, 0x61, 0x20, 0x69, 0x20, 0x48,
+0x65, 0x72, 0x63, 0x65, 0x67, 0x6f, 0x76, 0x69, 0x6e, 0x61, 0x10d, 0x65, 0x161, 0x74, 0x69, 0x6e, 0x61, 0x10c, 0x65, 0x73,
+0x6b, 0x6f, 0x64, 0x61, 0x6e, 0x73, 0x6b, 0x44, 0x61, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x47, 0x72, 0xf8, 0x6e, 0x6c, 0x61,
+0x6e, 0x64, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e,
+0x64, 0x41, 0x72, 0x75, 0x62, 0x61, 0x42, 0x65, 0x6c, 0x67, 0x69, 0xeb, 0x43, 0x75, 0x72, 0x61, 0xe7, 0x61, 0x6f, 0x53,
+0x75, 0x72, 0x69, 0x6e, 0x61, 0x6d, 0x65, 0x43, 0x61, 0x72, 0x69, 0x62, 0x69, 0x73, 0x63, 0x68, 0x20, 0x4e, 0x65, 0x64,
+0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x53, 0x69, 0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x61, 0x72, 0x74, 0x65, 0x6e, 0x41, 0x6d,
+0x65, 0x72, 0x69, 0x63, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64,
+0x20, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x41, 0x6d, 0x65, 0x72, 0x69, 0x63,
+0x61, 0x6e, 0x20, 0x53, 0x61, 0x6d, 0x6f, 0x61, 0x41, 0x6e, 0x67, 0x75, 0x69, 0x6c, 0x6c, 0x61, 0x41, 0x6e, 0x74, 0x69,
+0x67, 0x75, 0x61, 0x20, 0x26, 0x20, 0x42, 0x61, 0x72, 0x62, 0x75, 0x64, 0x61, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c,
+0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x41, 0x75, 0x73, 0x74, 0x72, 0x61, 0x6c, 0x69, 0x61,
+0x41, 0x75, 0x73, 0x74, 0x72, 0x69, 0x61, 0x42, 0x61, 0x68, 0x61, 0x6d, 0x61, 0x73, 0x42, 0x61, 0x72, 0x62, 0x61, 0x64,
+0x6f, 0x73, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x75, 0x6d, 0x42, 0x65, 0x6c, 0x69, 0x7a, 0x65, 0x42, 0x65, 0x72, 0x6d, 0x75,
+0x64, 0x61, 0x42, 0x6f, 0x74, 0x73, 0x77, 0x61, 0x6e, 0x61, 0x42, 0x72, 0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x49, 0x6e,
+0x64, 0x69, 0x61, 0x6e, 0x20, 0x4f, 0x63, 0x65, 0x61, 0x6e, 0x20, 0x54, 0x65, 0x72, 0x72, 0x69, 0x74, 0x6f, 0x72, 0x79,
+0x42, 0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x43, 0x61, 0x6d, 0x65, 0x72, 0x6f, 0x6f, 0x6e, 0x43, 0x61, 0x6e, 0x61, 0x64,
+0x69, 0x61, 0x6e, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x43, 0x61, 0x6e, 0x61, 0x64, 0x61, 0x43, 0x61, 0x79,
+0x6d, 0x61, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x43, 0x68, 0x72, 0x69, 0x73, 0x74, 0x6d, 0x61, 0x73,
+0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x43, 0x6f, 0x63, 0x6f, 0x73, 0x20, 0x28, 0x4b, 0x65, 0x65, 0x6c, 0x69, 0x6e,
+0x67, 0x29, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x43, 0x6f, 0x6f, 0x6b, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e,
+0x64, 0x73, 0x43, 0x79, 0x70, 0x72, 0x75, 0x73, 0x44, 0x65, 0x6e, 0x6d, 0x61, 0x72, 0x6b, 0x44, 0x6f, 0x6d, 0x69, 0x6e,
+0x69, 0x63, 0x61, 0x45, 0x72, 0x69, 0x74, 0x72, 0x65, 0x61, 0x46, 0x61, 0x6c, 0x6b, 0x6c, 0x61, 0x6e, 0x64, 0x20, 0x49,
+0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x46, 0x69, 0x6a, 0x69, 0x46, 0x69, 0x6e, 0x6c, 0x61, 0x6e, 0x64, 0x47, 0x75, 0x65,
+0x72, 0x6e, 0x73, 0x65, 0x79, 0x47, 0x61, 0x6d, 0x62, 0x69, 0x61, 0x47, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x79, 0x47, 0x68,
+0x61, 0x6e, 0x61, 0x47, 0x69, 0x62, 0x72, 0x61, 0x6c, 0x74, 0x61, 0x72, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x61, 0x47,
+0x75, 0x61, 0x6d, 0x47, 0x75, 0x79, 0x61, 0x6e, 0x61, 0x48, 0x6f, 0x6e, 0x67, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0x20, 0x53,
+0x41, 0x52, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x49, 0x6e, 0x64, 0x69, 0x61, 0x49, 0x72, 0x65, 0x6c, 0x61, 0x6e, 0x64,
+0x49, 0x73, 0x72, 0x61, 0x65, 0x6c, 0x4a, 0x61, 0x6d, 0x61, 0x69, 0x63, 0x61, 0x4b, 0x65, 0x6e, 0x79, 0x61, 0x4b, 0x69,
+0x72, 0x69, 0x62, 0x61, 0x74, 0x69, 0x4c, 0x65, 0x73, 0x6f, 0x74, 0x68, 0x6f, 0x4c, 0x69, 0x62, 0x65, 0x72, 0x69, 0x61,
+0x4d, 0x61, 0x63, 0x61, 0x75, 0x20, 0x53, 0x41, 0x52, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x4d, 0x61, 0x64, 0x61, 0x67,
+0x61, 0x73, 0x63, 0x61, 0x72, 0x4d, 0x61, 0x6c, 0x61, 0x77, 0x69, 0x4d, 0x61, 0x6c, 0x61, 0x79, 0x73, 0x69, 0x61, 0x4d,
+0x61, 0x6c, 0x74, 0x61, 0x4d, 0x61, 0x72, 0x73, 0x68, 0x61, 0x6c, 0x6c, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73,
+0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x69, 0x75, 0x73, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x4d,
+0x6f, 0x6e, 0x74, 0x73, 0x65, 0x72, 0x72, 0x61, 0x74, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69, 0x61, 0x4e, 0x61, 0x75, 0x72,
+0x75, 0x4e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x4e, 0x65, 0x77, 0x20, 0x5a, 0x65, 0x61, 0x6c,
+0x61, 0x6e, 0x64, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x69, 0x61, 0x4e, 0x69, 0x75, 0x65, 0x4e, 0x6f, 0x72, 0x66, 0x6f, 0x6c,
+0x6b, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x4e, 0x6f, 0x72, 0x74, 0x68, 0x65, 0x72, 0x6e, 0x20, 0x4d, 0x61, 0x72,
+0x69, 0x61, 0x6e, 0x61, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x50, 0x61, 0x6b, 0x69, 0x73, 0x74, 0x61, 0x6e,
+0x50, 0x61, 0x6c, 0x61, 0x75, 0x50, 0x61, 0x70, 0x75, 0x61, 0x20, 0x4e, 0x65, 0x77, 0x20, 0x47, 0x75, 0x69, 0x6e, 0x65,
+0x61, 0x50, 0x68, 0x69, 0x6c, 0x69, 0x70, 0x70, 0x69, 0x6e, 0x65, 0x73, 0x50, 0x69, 0x74, 0x63, 0x61, 0x69, 0x72, 0x6e,
+0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6f, 0x20, 0x52, 0x69, 0x63, 0x6f, 0x52,
+0x77, 0x61, 0x6e, 0x64, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x4b, 0x69, 0x74, 0x74, 0x73, 0x20, 0x26, 0x20, 0x4e, 0x65, 0x76,
+0x69, 0x73, 0x53, 0x74, 0x2e, 0x20, 0x4c, 0x75, 0x63, 0x69, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x56, 0x69, 0x6e, 0x63, 0x65,
+0x6e, 0x74, 0x20, 0x26, 0x20, 0x47, 0x72, 0x65, 0x6e, 0x61, 0x64, 0x69, 0x6e, 0x65, 0x73, 0x53, 0x61, 0x6d, 0x6f, 0x61,
+0x53, 0x65, 0x79, 0x63, 0x68, 0x65, 0x6c, 0x6c, 0x65, 0x73, 0x53, 0x69, 0x65, 0x72, 0x72, 0x61, 0x20, 0x4c, 0x65, 0x6f,
+0x6e, 0x65, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x6f, 0x72, 0x65, 0x53, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x69, 0x61, 0x53,
+0x6f, 0x6c, 0x6f, 0x6d, 0x6f, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20,
+0x41, 0x66, 0x72, 0x69, 0x63, 0x61, 0x53, 0x74, 0x2e, 0x20, 0x48, 0x65, 0x6c, 0x65, 0x6e, 0x61, 0x53, 0x75, 0x64, 0x61,
+0x6e, 0x53, 0x77, 0x61, 0x7a, 0x69, 0x6c, 0x61, 0x6e, 0x64, 0x53, 0x77, 0x65, 0x64, 0x65, 0x6e, 0x53, 0x77, 0x69, 0x74,
+0x7a, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x64, 0x54, 0x61, 0x6e, 0x7a, 0x61, 0x6e, 0x69, 0x61, 0x54, 0x6f, 0x6b, 0x65, 0x6c,
+0x61, 0x75, 0x54, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0x72, 0x69, 0x6e, 0x69, 0x64, 0x61, 0x64, 0x20, 0x26, 0x20, 0x54, 0x6f,
+0x62, 0x61, 0x67, 0x6f, 0x54, 0x75, 0x72, 0x6b, 0x73, 0x20, 0x26, 0x20, 0x43, 0x61, 0x69, 0x63, 0x6f, 0x73, 0x20, 0x49,
+0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x54, 0x75, 0x76, 0x61, 0x6c, 0x75, 0x55, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x42, 0x72,
+0x69, 0x74, 0x69, 0x73, 0x68, 0x20, 0x45, 0x6e, 0x67, 0x6c, 0x69, 0x73, 0x68, 0x55, 0x6e, 0x69, 0x74, 0x65, 0x64, 0x20,
+0x4b, 0x69, 0x6e, 0x67, 0x64, 0x6f, 0x6d, 0x55, 0x2e, 0x53, 0x2e, 0x20, 0x4f, 0x75, 0x74, 0x6c, 0x79, 0x69, 0x6e, 0x67,
+0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x56, 0x61, 0x6e, 0x75, 0x61, 0x74, 0x75, 0x42, 0x72, 0x69, 0x74, 0x69,
+0x73, 0x68, 0x20, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x55, 0x2e, 0x53,
+0x2e, 0x20, 0x56, 0x69, 0x72, 0x67, 0x69, 0x6e, 0x20, 0x49, 0x73, 0x6c, 0x61, 0x6e, 0x64, 0x73, 0x5a, 0x61, 0x6d, 0x62,
+0x69, 0x61, 0x5a, 0x69, 0x6d, 0x62, 0x61, 0x62, 0x77, 0x65, 0x44, 0x69, 0x65, 0x67, 0x6f, 0x20, 0x47, 0x61, 0x72, 0x63,
+0x69, 0x61, 0x49, 0x73, 0x6c, 0x65, 0x20, 0x6f, 0x66, 0x20, 0x4d, 0x61, 0x6e, 0x4a, 0x65, 0x72, 0x73, 0x65, 0x79, 0x53,
+0x6f, 0x75, 0x74, 0x68, 0x20, 0x53, 0x75, 0x64, 0x61, 0x6e, 0x53, 0x69, 0x6e, 0x74, 0x20, 0x4d, 0x61, 0x61, 0x72, 0x74,
+0x65, 0x6e, 0x65, 0x65, 0x73, 0x74, 0x69, 0x45, 0x65, 0x73, 0x74, 0x69, 0x66, 0xf8, 0x72, 0x6f, 0x79, 0x73, 0x6b, 0x74,
+0x46, 0xf8, 0x72, 0x6f, 0x79, 0x61, 0x72, 0x73, 0x75, 0x6f, 0x6d, 0x69, 0x53, 0x75, 0x6f, 0x6d, 0x69, 0x66, 0x72, 0x61,
+0x6e, 0xe7, 0x61, 0x69, 0x73, 0x46, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x41, 0x6c, 0x67, 0xe9, 0x72, 0x69, 0x65, 0x42, 0x65,
+0x6c, 0x67, 0x69, 0x71, 0x75, 0x65, 0x42, 0xe9, 0x6e, 0x69, 0x6e, 0x42, 0x75, 0x72, 0x6b, 0x69, 0x6e, 0x61, 0x20, 0x46,
+0x61, 0x73, 0x6f, 0x43, 0x61, 0x6d, 0x65, 0x72, 0x6f, 0x75, 0x6e, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x20,
+0x63, 0x61, 0x6e, 0x61, 0x64, 0x69, 0x65, 0x6e, 0x52, 0xe9, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x71, 0x75, 0x65, 0x20, 0x63,
+0x65, 0x6e, 0x74, 0x72, 0x61, 0x66, 0x72, 0x69, 0x63, 0x61, 0x69, 0x6e, 0x65, 0x54, 0x63, 0x68, 0x61, 0x64, 0x43, 0x6f,
+0x6d, 0x6f, 0x72, 0x65, 0x73, 0x43, 0x6f, 0x6e, 0x67, 0x6f, 0x2d, 0x4b, 0x69, 0x6e, 0x73, 0x68, 0x61, 0x73, 0x61, 0x43,
+0x6f, 0x6e, 0x67, 0x6f, 0x2d, 0x42, 0x72, 0x61, 0x7a, 0x7a, 0x61, 0x76, 0x69, 0x6c, 0x6c, 0x65, 0x43, 0xf4, 0x74, 0x65,
+0x20, 0x64, 0x2019, 0x49, 0x76, 0x6f, 0x69, 0x72, 0x65, 0x44, 0x6a, 0x69, 0x62, 0x6f, 0x75, 0x74, 0x69, 0x47, 0x75, 0x69,
+0x6e, 0xe9, 0x65, 0x20, 0xe9, 0x71, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x65, 0x47, 0x75, 0x79, 0x61, 0x6e,
+0x65, 0x20, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65, 0x50, 0x6f, 0x6c, 0x79, 0x6e, 0xe9, 0x73, 0x69, 0x65,
+0x20, 0x66, 0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x65, 0x47, 0x61, 0x62, 0x6f, 0x6e, 0x47, 0x75, 0x61, 0x64, 0x65,
+0x6c, 0x6f, 0x75, 0x70, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x65, 0x48, 0x61, 0xef, 0x74, 0x69, 0x4c, 0x75, 0x78, 0x65,
+0x6d, 0x62, 0x6f, 0x75, 0x72, 0x67, 0x4d, 0x61, 0x6c, 0x69, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e, 0x69, 0x71, 0x75, 0x65,
+0x4d, 0x61, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x65, 0x4d, 0x61, 0x75, 0x72, 0x69, 0x63, 0x65, 0x4d, 0x61, 0x79,
+0x6f, 0x74, 0x74, 0x65, 0x4d, 0x6f, 0x6e, 0x61, 0x63, 0x6f, 0x4d, 0x61, 0x72, 0x6f, 0x63, 0x4e, 0x6f, 0x75, 0x76, 0x65,
+0x6c, 0x6c, 0x65, 0x2d, 0x43, 0x61, 0x6c, 0xe9, 0x64, 0x6f, 0x6e, 0x69, 0x65, 0x4e, 0x69, 0x67, 0x65, 0x72, 0x4c, 0x61,
+0x20, 0x52, 0xe9, 0x75, 0x6e, 0x69, 0x6f, 0x6e, 0x53, 0xe9, 0x6e, 0xe9, 0x67, 0x61, 0x6c, 0x53, 0x61, 0x69, 0x6e, 0x74,
+0x2d, 0x50, 0x69, 0x65, 0x72, 0x72, 0x65, 0x2d, 0x65, 0x74, 0x2d, 0x4d, 0x69, 0x71, 0x75, 0x65, 0x6c, 0x6f, 0x6e, 0x66,
+0x72, 0x61, 0x6e, 0xe7, 0x61, 0x69, 0x73, 0x20, 0x73, 0x75, 0x69, 0x73, 0x73, 0x65, 0x53, 0x75, 0x69, 0x73, 0x73, 0x65,
+0x53, 0x79, 0x72, 0x69, 0x65, 0x54, 0x6f, 0x67, 0x6f, 0x54, 0x75, 0x6e, 0x69, 0x73, 0x69, 0x65, 0x57, 0x61, 0x6c, 0x6c,
+0x69, 0x73, 0x2d, 0x65, 0x74, 0x2d, 0x46, 0x75, 0x74, 0x75, 0x6e, 0x61, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x42, 0x61,
+0x72, 0x74, 0x68, 0xe9, 0x6c, 0x65, 0x6d, 0x79, 0x53, 0x61, 0x69, 0x6e, 0x74, 0x2d, 0x4d, 0x61, 0x72, 0x74, 0x69, 0x6e,
+0x57, 0x65, 0x73, 0x74, 0x2d, 0x46, 0x72, 0x79, 0x73, 0x6b, 0x4e, 0x65, 0x64, 0x65, 0x72, 0x6c, 0xe2, 0x6e, 0x47, 0xe0,
+0x69, 0x64, 0x68, 0x6c, 0x69, 0x67, 0x41, 0x6e, 0x20, 0x52, 0xec, 0x6f, 0x67, 0x68, 0x61, 0x63, 0x68, 0x64, 0x20, 0x41,
+0x6f, 0x6e, 0x61, 0x69, 0x63, 0x68, 0x74, 0x65, 0x67, 0x61, 0x6c, 0x65, 0x67, 0x6f, 0x45, 0x73, 0x70, 0x61, 0xf1, 0x61,
+0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10e3, 0x10da, 0x10d8, 0x10e1, 0x10d0, 0x10e5, 0x10d0, 0x10e0, 0x10d7, 0x10d5, 0x10d4, 0x10da, 0x10dd, 0x44, 0x65, 0x75,
+0x74, 0x73, 0x63, 0x68, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0xd6, 0x73, 0x74, 0x65, 0x72,
+0x72, 0x65, 0x69, 0x63, 0x68, 0x69, 0x73, 0x63, 0x68, 0x65, 0x73, 0x20, 0x44, 0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0xd6,
+0x73, 0x74, 0x65, 0x72, 0x72, 0x65, 0x69, 0x63, 0x68, 0x42, 0x65, 0x6c, 0x67, 0x69, 0x65, 0x6e, 0x49, 0x74, 0x61, 0x6c,
+0x69, 0x65, 0x6e, 0x4c, 0x69, 0x65, 0x63, 0x68, 0x74, 0x65, 0x6e, 0x73, 0x74, 0x65, 0x69, 0x6e, 0x4c, 0x75, 0x78, 0x65,
+0x6d, 0x62, 0x75, 0x72, 0x67, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x65, 0x72, 0x20, 0x48, 0x6f, 0x63, 0x68, 0x64,
+0x65, 0x75, 0x74, 0x73, 0x63, 0x68, 0x53, 0x63, 0x68, 0x77, 0x65, 0x69, 0x7a, 0x395, 0x3bb, 0x3bb, 0x3b7, 0x3bd, 0x3b9, 0x3ba,
+0x3ac, 0x395, 0x3bb, 0x3bb, 0x3ac, 0x3b4, 0x3b1, 0x39a, 0x3cd, 0x3c0, 0x3c1, 0x3bf, 0x3c2, 0x6b, 0x61, 0x6c, 0x61, 0x61, 0x6c, 0x6c,
+0x69, 0x73, 0x75, 0x74, 0x4b, 0x61, 0x6c, 0x61, 0x61, 0x6c, 0x6c, 0x69, 0x74, 0x20, 0x4e, 0x75, 0x6e, 0x61, 0x61, 0x74,
+0xa97, 0xac1, 0xa9c, 0xab0, 0xabe, 0xaa4, 0xac0, 0xaad, 0xabe, 0xab0, 0xaa4, 0x48, 0x61, 0x75, 0x73, 0x61, 0x4e, 0x61, 0x6a, 0x65,
+0x72, 0x69, 0x79, 0x61, 0x47, 0x61, 0x6e, 0x61, 0x4e, 0x69, 0x6a, 0x61, 0x72, 0x5e2, 0x5d1, 0x5e8, 0x5d9, 0x5ea, 0x5d9, 0x5e9,
+0x5e8, 0x5d0, 0x5dc, 0x939, 0x93f, 0x928, 0x94d, 0x926, 0x940, 0x92d, 0x93e, 0x930, 0x924, 0x6d, 0x61, 0x67, 0x79, 0x61, 0x72, 0x4d,
+0x61, 0x67, 0x79, 0x61, 0x72, 0x6f, 0x72, 0x73, 0x7a, 0xe1, 0x67, 0xed, 0x73, 0x6c, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0xcd,
+0x73, 0x6c, 0x61, 0x6e, 0x64, 0x49, 0x6e, 0x64, 0x6f, 0x6e, 0x65, 0x73, 0x69, 0x61, 0x47, 0x61, 0x65, 0x69, 0x6c, 0x67,
+0x65, 0xc9, 0x69, 0x72, 0x65, 0x69, 0x74, 0x61, 0x6c, 0x69, 0x61, 0x6e, 0x6f, 0x49, 0x74, 0x61, 0x6c, 0x69, 0x61, 0x53,
+0x61, 0x6e, 0x20, 0x4d, 0x61, 0x72, 0x69, 0x6e, 0x6f, 0x53, 0x76, 0x69, 0x7a, 0x7a, 0x65, 0x72, 0x61, 0x43, 0x69, 0x74,
+0x74, 0xe0, 0x20, 0x64, 0x65, 0x6c, 0x20, 0x56, 0x61, 0x74, 0x69, 0x63, 0x61, 0x6e, 0x6f, 0x65e5, 0x672c, 0x8a9e, 0x65e5, 0x672c,
+0xc95, 0xca8, 0xccd, 0xca8, 0xca1, 0xcad, 0xcbe, 0xcb0, 0xca4, 0x6a9, 0x672, 0x634, 0x64f, 0x631, 0x6c1, 0x650, 0x646, 0x65b, 0x62f, 0x648,
+0x633, 0x62a, 0x627, 0x646, 0x49b, 0x430, 0x437, 0x430, 0x49b, 0x20, 0x442, 0x456, 0x43b, 0x456, 0x49a, 0x430, 0x437, 0x430, 0x49b, 0x441,
+0x442, 0x430, 0x43d, 0x4b, 0x69, 0x6e, 0x79, 0x61, 0x72, 0x77, 0x61, 0x6e, 0x64, 0x61, 0x43a, 0x44b, 0x440, 0x433, 0x44b, 0x437,
+0x447, 0x430, 0x41a, 0x44b, 0x440, 0x433, 0x44b, 0x437, 0x441, 0x442, 0x430, 0x43d, 0xd55c, 0xad6d, 0xc5b4, 0xb300, 0xd55c, 0xbbfc, 0xad6d, 0xc870,
+0xc120, 0xbbfc, 0xc8fc, 0xc8fc, 0xc758, 0xc778, 0xbbfc, 0xacf5, 0xd654, 0xad6d, 0x49, 0x6b, 0x69, 0x72, 0x75, 0x6e, 0x64, 0x69, 0x55, 0x62,
+0x75, 0x72, 0x75, 0x6e, 0x64, 0x69, 0xea5, 0xeb2, 0xea7, 0x6c, 0x61, 0x74, 0x76, 0x69, 0x65, 0x161, 0x75, 0x4c, 0x61, 0x74,
+0x76, 0x69, 0x6a, 0x61, 0x6c, 0x69, 0x6e, 0x67, 0xe1, 0x6c, 0x61, 0x52, 0x65, 0x70, 0x75, 0x62, 0x6c, 0xed, 0x6b, 0x69,
+0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67, 0xf3, 0x20, 0x44, 0x65, 0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x74, 0xed, 0x6b,
+0x69, 0x41, 0x6e, 0x67, 0xf3, 0x6c, 0x61, 0x52, 0x65, 0x70, 0x69, 0x62, 0x69, 0x6b, 0x69, 0x20, 0x79, 0x61, 0x20, 0x41,
+0x66, 0x72, 0xed, 0x6b, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0xe1, 0x74, 0x69, 0x4b, 0x6f, 0x6e, 0x67, 0x6f, 0x6c, 0x69,
+0x65, 0x74, 0x75, 0x76, 0x69, 0x173, 0x4c, 0x69, 0x65, 0x74, 0x75, 0x76, 0x61, 0x43c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d,
+0x441, 0x43a, 0x438, 0x41c, 0x430, 0x43a, 0x435, 0x434, 0x43e, 0x43d, 0x438, 0x458, 0x430, 0x4d, 0x61, 0x6c, 0x61, 0x67, 0x61, 0x73,
+0x79, 0x4d, 0x61, 0x64, 0x61, 0x67, 0x61, 0x73, 0x69, 0x6b, 0x61, 0x72, 0x61, 0x42, 0x61, 0x68, 0x61, 0x73, 0x61, 0x20,
+0x4d, 0x65, 0x6c, 0x61, 0x79, 0x75, 0x42, 0x72, 0x75, 0x6e, 0x65, 0x69, 0x53, 0x69, 0x6e, 0x67, 0x61, 0x70, 0x75, 0x72,
+0x61, 0xd2e, 0xd32, 0xd2f, 0xd3e, 0xd33, 0xd02, 0xd07, 0xd28, 0xd4d, 0xd24, 0xd4d, 0xd2f, 0x4d, 0x61, 0x6c, 0x74, 0x69, 0x92e, 0x930,
+0x93e, 0x920, 0x940, 0x43c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x41c, 0x43e, 0x43d, 0x433, 0x43e, 0x43b, 0x928, 0x947, 0x92a, 0x93e, 0x932,
+0x940, 0x928, 0x947, 0x92a, 0x93e, 0x932, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x20, 0x62, 0x6f, 0x6b, 0x6d, 0xe5, 0x6c, 0x4e, 0x6f,
+0x72, 0x67, 0x65, 0x53, 0x76, 0x61, 0x6c, 0x62, 0x61, 0x72, 0x64, 0x20, 0x6f, 0x67, 0x20, 0x4a, 0x61, 0x6e, 0x20, 0x4d,
+0x61, 0x79, 0x65, 0x6e, 0xb13, 0xb21, 0xb3c, 0xb3f, 0xb06, 0xb2d, 0xb3e, 0xb30, 0xb24, 0x67e, 0x69a, 0x62a, 0x648, 0x627, 0x641, 0x63a,
+0x627, 0x646, 0x633, 0x62a, 0x627, 0x646, 0x641, 0x627, 0x631, 0x633, 0x6cc, 0x627, 0x6cc, 0x631, 0x627, 0x646, 0x62f, 0x631, 0x6cc, 0x70,
+0x6f, 0x6c, 0x73, 0x6b, 0x69, 0x50, 0x6f, 0x6c, 0x73, 0x6b, 0x61, 0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea, 0x73,
+0x42, 0x72, 0x61, 0x73, 0x69, 0x6c, 0x41, 0x6e, 0x67, 0x6f, 0x6c, 0x61, 0x43, 0x61, 0x62, 0x6f, 0x20, 0x56, 0x65, 0x72,
+0x64, 0x65, 0x54, 0x69, 0x6d, 0x6f, 0x72, 0x2d, 0x4c, 0x65, 0x73, 0x74, 0x65, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x20, 0x45,
+0x71, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x47, 0x75, 0x69, 0x6e, 0xe9, 0x2d, 0x42, 0x69, 0x73, 0x73, 0x61,
+0x75, 0x4c, 0x75, 0x78, 0x65, 0x6d, 0x62, 0x75, 0x72, 0x67, 0x6f, 0x4d, 0x61, 0x63, 0x61, 0x75, 0x2c, 0x20, 0x52, 0x41,
+0x45, 0x20, 0x64, 0x61, 0x20, 0x43, 0x68, 0x69, 0x6e, 0x61, 0x4d, 0x6f, 0xe7, 0x61, 0x6d, 0x62, 0x69, 0x71, 0x75, 0x65,
+0x70, 0x6f, 0x72, 0x74, 0x75, 0x67, 0x75, 0xea, 0x73, 0x20, 0x65, 0x75, 0x72, 0x6f, 0x70, 0x65, 0x75, 0x50, 0x6f, 0x72,
+0x74, 0x75, 0x67, 0x61, 0x6c, 0x53, 0xe3, 0x6f, 0x20, 0x54, 0x6f, 0x6d, 0xe9, 0x20, 0x65, 0x20, 0x50, 0x72, 0xed, 0x6e,
+0x63, 0x69, 0x70, 0x65, 0x53, 0x75, 0xed, 0xe7, 0x61, 0xa2a, 0xa70, 0xa1c, 0xa3e, 0xa2c, 0xa40, 0xa2d, 0xa3e, 0xa30, 0xa24, 0x67e,
+0x646, 0x62c, 0x627, 0x628, 0x6cc, 0x67e, 0x627, 0x6a9, 0x633, 0x62a, 0x627, 0x646, 0x52, 0x75, 0x6e, 0x61, 0x73, 0x69, 0x6d, 0x69,
+0x50, 0x65, 0x72, 0xfa, 0x42, 0x6f, 0x6c, 0x69, 0x76, 0x69, 0x61, 0x45, 0x63, 0x75, 0x61, 0x64, 0x6f, 0x72, 0x72, 0x75,
+0x6d, 0x61, 0x6e, 0x74, 0x73, 0x63, 0x68, 0x53, 0x76, 0x69, 0x7a, 0x72, 0x61, 0x72, 0x6f, 0x6d, 0xe2, 0x6e, 0x103, 0x52,
+0x6f, 0x6d, 0xe2, 0x6e, 0x69, 0x61, 0x6d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x65, 0x6e, 0x65, 0x61, 0x73, 0x63, 0x103, 0x52,
+0x65, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20, 0x4d, 0x6f, 0x6c, 0x64, 0x6f, 0x76, 0x61, 0x440, 0x443, 0x441, 0x441,
+0x43a, 0x438, 0x439, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x44f, 0x41a, 0x430, 0x437, 0x430, 0x445, 0x441, 0x442, 0x430, 0x43d, 0x41a, 0x438,
+0x440, 0x433, 0x438, 0x437, 0x438, 0x44f, 0x41c, 0x43e, 0x43b, 0x434, 0x43e, 0x432, 0x430, 0x423, 0x43a, 0x440, 0x430, 0x438, 0x43d, 0x430,
+0x53, 0xe4, 0x6e, 0x67, 0xf6, 0x4b, 0xf6, 0x64, 0xf6, 0x72, 0xf6, 0x73, 0xea, 0x73, 0x65, 0x20, 0x74, 0xee, 0x20, 0x42,
+0xea, 0x61, 0x66, 0x72, 0xee, 0x6b, 0x61, 0x441, 0x440, 0x43f, 0x441, 0x43a, 0x438, 0x421, 0x440, 0x431, 0x438, 0x458, 0x430, 0x411,
+0x43e, 0x441, 0x43d, 0x430, 0x20, 0x438, 0x20, 0x425, 0x435, 0x440, 0x446, 0x435, 0x433, 0x43e, 0x432, 0x438, 0x43d, 0x430, 0x426, 0x440,
+0x43d, 0x430, 0x20, 0x413, 0x43e, 0x440, 0x430, 0x41a, 0x43e, 0x441, 0x43e, 0x432, 0x43e, 0x73, 0x72, 0x70, 0x73, 0x6b, 0x69, 0x43,
+0x72, 0x6e, 0x61, 0x20, 0x47, 0x6f, 0x72, 0x61, 0x53, 0x72, 0x62, 0x69, 0x6a, 0x61, 0x4b, 0x6f, 0x73, 0x6f, 0x76, 0x6f,
+0x438, 0x440, 0x43e, 0x43d, 0x413, 0x443, 0x44b, 0x440, 0x434, 0x437, 0x44b, 0x441, 0x442, 0x43e, 0x43d, 0x423, 0x4d5, 0x440, 0x4d5, 0x441,
+0x435, 0x63, 0x68, 0x69, 0x53, 0x68, 0x6f, 0x6e, 0x61, 0xdc3, 0xdd2, 0xd82, 0xdc4, 0xdbd, 0xdc1, 0xdca, 0x200d, 0xdbb, 0xdd3, 0x20,
+0xdbd, 0xd82, 0xd9a, 0xdcf, 0xdc0, 0x73, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f, 0x76, 0x65,
+0x6e, 0x73, 0x6b, 0x6f, 0x73, 0x6c, 0x6f, 0x76, 0x65, 0x6e, 0x161, 0x10d, 0x69, 0x6e, 0x61, 0x53, 0x6c, 0x6f, 0x76, 0x65,
+0x6e, 0x69, 0x6a, 0x61, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69, 0x53, 0x6f, 0x6f, 0x6d, 0x61, 0x61, 0x6c, 0x69,
+0x79, 0x61, 0x4a, 0x61, 0x62, 0x75, 0x75, 0x74, 0x69, 0x49, 0x74, 0x6f, 0x6f, 0x62, 0x69, 0x79, 0x61, 0x4b, 0x69, 0x69,
+0x6e, 0x69, 0x79, 0x61, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x45, 0x73, 0x70, 0x61, 0xf1,
+0x61, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x41, 0x72, 0x67, 0x65, 0x6e, 0x74, 0x69, 0x6e, 0x61, 0x42, 0x65, 0x6c,
+0x69, 0x63, 0x65, 0x43, 0x68, 0x69, 0x6c, 0x65, 0x43, 0x6f, 0x6c, 0x6f, 0x6d, 0x62, 0x69, 0x61, 0x43, 0x6f, 0x73, 0x74,
+0x61, 0x20, 0x52, 0x69, 0x63, 0x61, 0x43, 0x75, 0x62, 0x61, 0x52, 0x65, 0x70, 0xfa, 0x62, 0x6c, 0x69, 0x63, 0x61, 0x20,
+0x44, 0x6f, 0x6d, 0x69, 0x6e, 0x69, 0x63, 0x61, 0x6e, 0x61, 0x45, 0x6c, 0x20, 0x53, 0x61, 0x6c, 0x76, 0x61, 0x64, 0x6f,
+0x72, 0x47, 0x75, 0x69, 0x6e, 0x65, 0x61, 0x20, 0x45, 0x63, 0x75, 0x61, 0x74, 0x6f, 0x72, 0x69, 0x61, 0x6c, 0x47, 0x75,
+0x61, 0x74, 0x65, 0x6d, 0x61, 0x6c, 0x61, 0x48, 0x6f, 0x6e, 0x64, 0x75, 0x72, 0x61, 0x73, 0x65, 0x73, 0x70, 0x61, 0xf1,
+0x6f, 0x6c, 0x20, 0x64, 0x65, 0x20, 0x4d, 0xe9, 0x78, 0x69, 0x63, 0x6f, 0x4d, 0xe9, 0x78, 0x69, 0x63, 0x6f, 0x4e, 0x69,
+0x63, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61, 0x50, 0x61, 0x6e, 0x61, 0x6d, 0xe1, 0x50, 0x61, 0x72, 0x61, 0x67, 0x75, 0x61,
+0x79, 0x46, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x61, 0x73, 0x45, 0x45, 0x2e, 0x20, 0x55, 0x55, 0x2e, 0x55, 0x72, 0x75,
+0x67, 0x75, 0x61, 0x79, 0x56, 0x65, 0x6e, 0x65, 0x7a, 0x75, 0x65, 0x6c, 0x61, 0x43, 0x61, 0x6e, 0x61, 0x72, 0x69, 0x61,
+0x73, 0x65, 0x73, 0x70, 0x61, 0xf1, 0x6f, 0x6c, 0x20, 0x6c, 0x61, 0x74, 0x69, 0x6e, 0x6f, 0x61, 0x6d, 0x65, 0x72, 0x69,
+0x63, 0x61, 0x6e, 0x6f, 0x4c, 0x61, 0x74, 0x69, 0x6e, 0x6f, 0x61, 0x6d, 0xe9, 0x72, 0x69, 0x63, 0x61, 0x43, 0x65, 0x75,
+0x74, 0x61, 0x20, 0x79, 0x20, 0x4d, 0x65, 0x6c, 0x69, 0x6c, 0x6c, 0x61, 0x4b, 0x69, 0x73, 0x77, 0x61, 0x68, 0x69, 0x6c,
+0x69, 0x4b, 0x69, 0x6e, 0x67, 0x77, 0x61, 0x6e, 0x61, 0x4a, 0x61, 0x6d, 0x68, 0x75, 0x72, 0x69, 0x20, 0x79, 0x61, 0x20,
+0x4b, 0x69, 0x64, 0x65, 0x6d, 0x6f, 0x6b, 0x72, 0x61, 0x73, 0x69, 0x61, 0x20, 0x79, 0x61, 0x20, 0x4b, 0x6f, 0x6e, 0x67,
+0x6f, 0x73, 0x76, 0x65, 0x6e, 0x73, 0x6b, 0x61, 0x53, 0x76, 0x65, 0x72, 0x69, 0x67, 0x65, 0xc5, 0x6c, 0x61, 0x6e, 0x64,
+0xba4, 0xbae, 0xbbf, 0xbb4, 0xbcd, 0xb87, 0xba8, 0xbcd, 0xba4, 0xbbf, 0xbaf, 0xbbe, 0xbae, 0xbb2, 0xbc7, 0xb9a, 0xbbf, 0xbaf, 0xbbe, 0xb9a,
+0xbbf, 0xb99, 0xbcd, 0xb95, 0xbaa, 0xbcd, 0xbaa, 0xbc2, 0xbb0, 0xbcd, 0xb87, 0xbb2, 0xb99, 0xbcd, 0xb95, 0xbc8, 0xc24, 0xc46, 0xc32, 0xc41,
+0xc17, 0xc41, 0xc2d, 0xc3e, 0xc30, 0xc24, 0x20, 0xc26, 0xc47, 0xc36, 0xc02, 0xe44, 0xe17, 0xe22, 0xf56, 0xf7c, 0xf51, 0xf0b, 0xf66, 0xf90,
+0xf51, 0xf0b, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf53, 0xf42, 0xf62, 0xf92, 0xfb1, 0xf0b, 0xf42, 0xf62, 0xf0b, 0x1275, 0x130d, 0x122d, 0x129b, 0x12a4,
+0x122d, 0x1275, 0x122b, 0x6c, 0x65, 0x61, 0x20, 0x66, 0x61, 0x6b, 0x61, 0x74, 0x6f, 0x6e, 0x67, 0x61, 0x54, 0xfc, 0x72, 0x6b,
+0xe7, 0x65, 0x54, 0xfc, 0x72, 0x6b, 0x69, 0x79, 0x65, 0x4b, 0x131, 0x62, 0x72, 0x131, 0x73, 0x74, 0xfc, 0x72, 0x6b, 0x6d,
+0x65, 0x6e, 0xe7, 0x65, 0x54, 0xfc, 0x72, 0x6b, 0x6d, 0x65, 0x6e, 0x69, 0x73, 0x74, 0x61, 0x6e, 0x626, 0x6c7, 0x64a, 0x63a,
+0x6c7, 0x631, 0x686, 0x6d5, 0x62c, 0x6c7, 0x6ad, 0x6af, 0x648, 0x443, 0x43a, 0x440, 0x430, 0x457, 0x43d, 0x441, 0x44c, 0x43a, 0x430, 0x423,
+0x43a, 0x440, 0x430, 0x457, 0x43d, 0x430, 0x627, 0x631, 0x62f, 0x648, 0x628, 0x6be, 0x627, 0x631, 0x62a, 0x6f, 0x2018, 0x7a, 0x62, 0x65,
+0x6b, 0x4f, 0x2bb, 0x7a, 0x62, 0x65, 0x6b, 0x69, 0x73, 0x74, 0x6f, 0x6e, 0x627, 0x648, 0x632, 0x628, 0x6cc, 0x6a9, 0x45e, 0x437,
+0x431, 0x435, 0x43a, 0x447, 0x430, 0x40e, 0x437, 0x431, 0x435, 0x43a, 0x438, 0x441, 0x442, 0x43e, 0x43d, 0x54, 0x69, 0x1ebf, 0x6e, 0x67,
+0x20, 0x56, 0x69, 0x1ec7, 0x74, 0x56, 0x69, 0x1ec7, 0x74, 0x20, 0x4e, 0x61, 0x6d, 0x43, 0x79, 0x6d, 0x72, 0x61, 0x65, 0x67,
+0x59, 0x20, 0x44, 0x65, 0x79, 0x72, 0x6e, 0x61, 0x73, 0x20, 0x55, 0x6e, 0x65, 0x64, 0x69, 0x67, 0xc8, 0x64, 0xe8, 0x20,
+0x59, 0x6f, 0x72, 0xf9, 0x62, 0xe1, 0x4f, 0x72, 0xed, 0x6c, 0x1eb9, 0x301, 0xe8, 0x64, 0x65, 0x20, 0x4e, 0xe0, 0xec, 0x6a,
+0xed, 0x72, 0xed, 0xe0, 0x4f, 0x72, 0xed, 0x6c, 0x25b, 0x301, 0xe8, 0x64, 0x65, 0x20, 0x42, 0x25b, 0x300, 0x6e, 0x25b, 0x300,
+0x69, 0x73, 0x69, 0x5a, 0x75, 0x6c, 0x75, 0x69, 0x2d, 0x53, 0x6f, 0x75, 0x74, 0x68, 0x20, 0x41, 0x66, 0x72, 0x69, 0x63,
+0x61, 0x6e, 0x79, 0x6e, 0x6f, 0x72, 0x73, 0x6b, 0x4e, 0x6f, 0x72, 0x65, 0x67, 0x62, 0x6f, 0x73, 0x61, 0x6e, 0x73, 0x6b,
+0x69, 0x431, 0x43e, 0x441, 0x430, 0x43d, 0x441, 0x43a, 0x438, 0x47, 0x61, 0x65, 0x6c, 0x67, 0x45, 0x6c, 0x6c, 0x61, 0x6e, 0x20,
+0x56, 0x61, 0x6e, 0x6e, 0x69, 0x6e, 0x6b, 0x65, 0x72, 0x6e, 0x65, 0x77, 0x65, 0x6b, 0x52, 0x79, 0x77, 0x76, 0x61, 0x6e,
+0x65, 0x74, 0x68, 0x20, 0x55, 0x6e, 0x79, 0x73, 0x41, 0x6b, 0x61, 0x6e, 0x47, 0x61, 0x61, 0x6e, 0x61, 0x915, 0x94b, 0x902,
+0x915, 0x923, 0x940, 0x49, 0x67, 0x62, 0x6f, 0x4b, 0x69, 0x6b, 0x61, 0x6d, 0x62, 0x61, 0x66, 0x75, 0x72, 0x6c, 0x61, 0x6e,
+0x49, 0x74, 0x61, 0x6c, 0x69, 0x65, 0x45, 0x28b, 0x65, 0x67, 0x62, 0x65, 0x47, 0x68, 0x61, 0x6e, 0x61, 0x20, 0x6e, 0x75,
+0x74, 0x6f, 0x6d, 0x65, 0x54, 0x6f, 0x67, 0x6f, 0x20, 0x6e, 0x75, 0x74, 0x6f, 0x6d, 0x65, 0x2bb, 0x14c, 0x6c, 0x65, 0x6c,
+0x6f, 0x20, 0x48, 0x61, 0x77, 0x61, 0x69, 0x2bb, 0x69, 0x2bb, 0x41, 0x6d, 0x65, 0x6c, 0x69, 0x6b, 0x61, 0x20, 0x48, 0x75,
+0x69, 0x20, 0x50, 0x16b, 0x20, 0x2bb, 0x49, 0x61, 0x46, 0x69, 0x6c, 0x69, 0x70, 0x69, 0x6e, 0x6f, 0x50, 0x69, 0x6c, 0x69,
+0x70, 0x69, 0x6e, 0x61, 0x73, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x65, 0x72, 0x74, 0xfc, 0xfc, 0x74, 0x73, 0x63,
+0x68, 0x53, 0x63, 0x68, 0x77, 0x69, 0x69, 0x7a, 0x46, 0x72, 0x61, 0x6e, 0x6b, 0x72, 0x69, 0x69, 0x63, 0x68, 0x4c, 0x69,
+0xe4, 0x63, 0x68, 0x74, 0x65, 0x73, 0x63, 0x68, 0x74, 0xe4, 0x69, 0xa188, 0xa320, 0xa259, 0xa34f, 0xa1e9, 0x4e, 0x65, 0x64, 0x64,
+0x65, 0x72, 0x73, 0x61, 0x73, 0x73, 0x2019, 0x73, 0x63, 0x68, 0x44, 0xfc, 0xfc, 0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e,
+0x64, 0x4e, 0x65, 0x64, 0x64, 0x65, 0x72, 0x6c, 0x61, 0x6e, 0x6e, 0x65, 0x6e, 0x64, 0x61, 0x76, 0x76, 0x69, 0x73, 0xe1,
+0x6d, 0x65, 0x67, 0x69, 0x65, 0x6c, 0x6c, 0x61, 0x4e, 0x6f, 0x72, 0x67, 0x61, 0x53, 0x75, 0x6f, 0x70, 0x6d, 0x61, 0x52,
+0x75, 0x6f, 0x167, 0x167, 0x61, 0x45, 0x6b, 0x65, 0x67, 0x75, 0x73, 0x69, 0x69, 0x4b, 0x69, 0x74, 0x61, 0x69, 0x74, 0x61,
+0x50, 0x75, 0x6c, 0x61, 0x61, 0x72, 0x53, 0x65, 0x6e, 0x65, 0x67, 0x61, 0x61, 0x6c, 0x4b, 0x61, 0x6d, 0x65, 0x72, 0x75,
+0x75, 0x6e, 0x47, 0x69, 0x6e, 0x65, 0x4d, 0x75, 0x72, 0x69, 0x74, 0x61, 0x6e, 0x69, 0x47, 0x69, 0x6b, 0x75, 0x79, 0x75,
+0x4b, 0x69, 0x73, 0x61, 0x6d, 0x70, 0x75, 0x72, 0x73, 0x65, 0x6e, 0x61, 0x69, 0x73, 0x69, 0x4e, 0x64, 0x65, 0x62, 0x65,
+0x6c, 0x65, 0x4b, 0x69, 0x68, 0x6f, 0x72, 0x6f, 0x6d, 0x62, 0x6f, 0x2d5c, 0x2d30, 0x2d5b, 0x2d4d, 0x2d43, 0x2d49, 0x2d5c, 0x2d4d, 0x2d4e,
+0x2d56, 0x2d54, 0x2d49, 0x2d31, 0x54, 0x61, 0x73, 0x68, 0x65, 0x6c, 0x1e25, 0x69, 0x79, 0x74, 0x6c, 0x6d, 0x263, 0x72, 0x69, 0x62,
+0x54, 0x61, 0x71, 0x62, 0x61, 0x79, 0x6c, 0x69, 0x74, 0x4c, 0x65, 0x7a, 0x7a, 0x61, 0x79, 0x65, 0x72, 0x52, 0x75, 0x6e,
+0x79, 0x61, 0x6e, 0x6b, 0x6f, 0x72, 0x65, 0x48, 0x69, 0x62, 0x65, 0x6e, 0x61, 0x48, 0x75, 0x74, 0x61, 0x6e, 0x7a, 0x61,
+0x6e, 0x69, 0x61, 0x4b, 0x79, 0x69, 0x76, 0x75, 0x6e, 0x6a, 0x6f, 0x62, 0x61, 0x6d, 0x61, 0x6e, 0x61, 0x6b, 0x61, 0x6e,
+0x4b, 0x129, 0x65, 0x6d, 0x62, 0x75, 0x13e3, 0x13b3, 0x13a9, 0x13cc, 0x13ca, 0x20, 0x13a2, 0x13f3, 0x13be, 0x13b5, 0x13cd, 0x13d4, 0x13c5, 0x20,
+0x13cd, 0x13a6, 0x13da, 0x13a9, 0x6b, 0x72, 0x65, 0x6f, 0x6c, 0x20, 0x6d, 0x6f, 0x72, 0x69, 0x73, 0x69, 0x65, 0x6e, 0x4d, 0x6f,
+0x72, 0x69, 0x73, 0x43, 0x68, 0x69, 0x6d, 0x61, 0x6b, 0x6f, 0x6e, 0x64, 0x65, 0x4b, 0x268, 0x6c, 0x61, 0x61, 0x6e, 0x67,
+0x69, 0x54, 0x61, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0xed, 0x61, 0x4c, 0x75, 0x67, 0x61, 0x6e, 0x64, 0x61, 0x59, 0x75, 0x67,
+0x61, 0x6e, 0x64, 0x61, 0x49, 0x63, 0x68, 0x69, 0x62, 0x65, 0x6d, 0x62, 0x61, 0x6b, 0x61, 0x62, 0x75, 0x76, 0x65, 0x72,
+0x64, 0x69, 0x61, 0x6e, 0x75, 0x4b, 0x61, 0x62, 0x75, 0x20, 0x56, 0x65, 0x72, 0x64, 0x69, 0x4b, 0x129, 0x6d, 0x129, 0x72,
+0x169, 0x4b, 0x61, 0x6c, 0x65, 0x6e, 0x6a, 0x69, 0x6e, 0x45, 0x6d, 0x65, 0x74, 0x61, 0x62, 0x20, 0x4b, 0x65, 0x6e, 0x79,
+0x61, 0x4b, 0x68, 0x6f, 0x65, 0x6b, 0x68, 0x6f, 0x65, 0x67, 0x6f, 0x77, 0x61, 0x62, 0x4e, 0x61, 0x6d, 0x69, 0x62, 0x69,
+0x61, 0x62, 0x4b, 0x69, 0x6d, 0x61, 0x63, 0x68, 0x61, 0x6d, 0x65, 0x4b, 0xf6, 0x6c, 0x73, 0x63, 0x68, 0x44, 0x6f, 0xfc,
+0x74, 0x73, 0x63, 0x68, 0x6c, 0x61, 0x6e, 0x64, 0x4d, 0x61, 0x61, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x61, 0x4f,
+0x6c, 0x75, 0x73, 0x6f, 0x67, 0x61, 0x4c, 0x75, 0x6c, 0x75, 0x68, 0x69, 0x61, 0x4b, 0x69, 0x70, 0x61, 0x72, 0x65, 0x54,
+0x61, 0x64, 0x68, 0x61, 0x6e, 0x69, 0x61, 0x4b, 0x69, 0x74, 0x65, 0x73, 0x6f, 0x4b, 0x65, 0x6e, 0x69, 0x61, 0x4b, 0x6f,
+0x79, 0x72, 0x61, 0x20, 0x63, 0x69, 0x69, 0x6e, 0x69, 0x4d, 0x61, 0x61, 0x6c, 0x69, 0x4b, 0x69, 0x72, 0x75, 0x77, 0x61,
+0x44, 0x68, 0x6f, 0x6c, 0x75, 0x6f, 0x52, 0x75, 0x6b, 0x69, 0x67, 0x61, 0x54, 0x61, 0x6d, 0x61, 0x7a, 0x69, 0x263, 0x74,
+0x20, 0x6e, 0x20, 0x6c, 0x61, 0x1e6d, 0x6c, 0x61, 0x1e63, 0x4d, 0x65, 0x1e5b, 0x1e5b, 0x75, 0x6b, 0x4b, 0x6f, 0x79, 0x72, 0x61,
+0x62, 0x6f, 0x72, 0x6f, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69, 0x4b, 0x69, 0x73, 0x68, 0x61, 0x6d, 0x62, 0x61, 0x61, 0x92c,
+0x921, 0x93c, 0x94b, 0x43d, 0x43e, 0x445, 0x447, 0x438, 0x439, 0x43d, 0x420, 0x43e, 0x441, 0x441, 0x438, 0x446, 0x435, 0x440, 0x43a, 0x43e,
+0x432, 0x43d, 0x43e, 0x441, 0x43b, 0x43e, 0x432, 0x435, 0x301, 0x43d, 0x441, 0x43a, 0x457, 0x439, 0x440, 0x461, 0x441, 0x441, 0x456, 0x301,
+0x430, 0x54, 0x73, 0x68, 0x69, 0x6c, 0x75, 0x62, 0x61, 0x44, 0x69, 0x74, 0x75, 0x6e, 0x67, 0x61, 0x20, 0x77, 0x61, 0x20,
+0x4b, 0x6f, 0x6e, 0x67, 0x75, 0x4c, 0xeb, 0x74, 0x7a, 0x65, 0x62, 0x75, 0x65, 0x72, 0x67, 0x65, 0x73, 0x63, 0x68, 0x4c,
+0xeb, 0x74, 0x7a, 0x65, 0x62, 0x75, 0x65, 0x72, 0x67, 0x41, 0x67, 0x68, 0x65, 0x6d, 0x4b, 0xe0, 0x6d, 0xe0, 0x6c, 0xfb,
+0x14b, 0x181, 0xe0, 0x73, 0xe0, 0x61, 0x4b, 0xe0, 0x6d, 0x25b, 0x300, 0x72, 0xfb, 0x6e, 0x5a, 0x61, 0x72, 0x6d, 0x61, 0x63,
+0x69, 0x69, 0x6e, 0x65, 0x4e, 0x69, 0x17e, 0x65, 0x72, 0x64, 0x75, 0xe1, 0x6c, 0xe1, 0x6a, 0x6f, 0x6f, 0x6c, 0x61, 0x53,
+0x65, 0x6e, 0x65, 0x67, 0x61, 0x6c, 0x65, 0x77, 0x6f, 0x6e, 0x64, 0x6f, 0x4b, 0x61, 0x6d, 0x259, 0x72, 0xfa, 0x6e, 0x72,
+0x69, 0x6b, 0x70, 0x61, 0x6b, 0x61, 0x6d, 0x25b, 0x72, 0xfa, 0x6e, 0x4d, 0x61, 0x6b, 0x75, 0x61, 0x55, 0x6d, 0x6f, 0x7a,
+0x61, 0x6d, 0x62, 0x69, 0x6b, 0x69, 0x4d, 0x55, 0x4e, 0x44, 0x41, 0x14a, 0x6b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x14b, 0x4b,
+0x77, 0x61, 0x73, 0x69, 0x6f, 0x4b, 0x61, 0x6d, 0x65, 0x72, 0x75, 0x6e, 0x54, 0x68, 0x6f, 0x6b, 0x20, 0x4e, 0x61, 0x74,
+0x68, 0x441, 0x430, 0x445, 0x430, 0x20, 0x442, 0x44b, 0x43b, 0x430, 0x410, 0x440, 0x430, 0x441, 0x441, 0x44b, 0x44b, 0x439, 0x430, 0x49,
+0x73, 0x68, 0x69, 0x73, 0x61, 0x6e, 0x67, 0x75, 0x54, 0x61, 0x6e, 0x73, 0x61, 0x6e, 0x69, 0x79, 0x61, 0x54, 0x61, 0x73,
+0x61, 0x77, 0x61, 0x71, 0x20, 0x73, 0x65, 0x6e, 0x6e, 0x69, 0xa559, 0xa524, 0xa55e, 0xa524, 0xa52b, 0xa569, 0x56, 0x61, 0x69, 0x4c,
+0x61, 0x69, 0x62, 0x68, 0x69, 0x79, 0x61, 0x57, 0x61, 0x6c, 0x73, 0x65, 0x72, 0x53, 0x63, 0x68, 0x77, 0x69, 0x7a, 0x6e,
+0x75, 0x61, 0x73, 0x75, 0x65, 0x4b, 0x65, 0x6d, 0x65, 0x6c, 0xfa, 0x6e, 0x61, 0x73, 0x74, 0x75, 0x72, 0x69, 0x61, 0x6e,
+0x75, 0x4e, 0x64, 0x61, 0xa78c, 0x61, 0x4b, 0x61, 0x6d, 0x25b, 0x6c, 0xfb, 0x6e, 0x6b, 0x61, 0x6b, 0x254, 0x4b, 0x61, 0x6d,
+0x25b, 0x72, 0x75, 0x6e, 0x6d, 0x65, 0x74, 0x61, 0x2bc, 0x4b, 0x61, 0x6d, 0x61, 0x6c, 0x75, 0x6e, 0x53, 0x68, 0x77, 0xf3,
+0x14b, 0xf2, 0x20, 0x6e, 0x67, 0x69, 0x65, 0x6d, 0x62, 0x254, 0x254, 0x6e, 0x4b, 0xe0, 0x6d, 0x61, 0x6c, 0xfb, 0x6d, 0x4c,
+0x61, 0x6b, 0x21f, 0xf3, 0x6c, 0x2bc, 0x69, 0x79, 0x61, 0x70, 0x69, 0x4d, 0xed, 0x6c, 0x61, 0x68, 0x61, 0x14b, 0x73, 0x6b,
+0x61, 0x20, 0x54, 0x21f, 0x61, 0x6d, 0xe1, 0x6b, 0x21f, 0x6f, 0x10d, 0x68, 0x65, 0x2d5c, 0x2d30, 0x2d4e, 0x2d30, 0x2d63, 0x2d49, 0x2d56,
+0x2d5c, 0x6a9, 0x648, 0x631, 0x62f, 0x6cc, 0x6cc, 0x20, 0x646, 0x627, 0x648, 0x6d5, 0x646, 0x62f, 0x6cc, 0x639, 0x6ce, 0x631, 0x627, 0x642,
+0x626, 0x6ce, 0x631, 0x627, 0x646, 0x64, 0x6f, 0x6c, 0x6e, 0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107, 0x69, 0x6e, 0x61, 0x4e,
+0x69, 0x6d, 0x73, 0x6b, 0x61, 0x68, 0x6f, 0x72, 0x6e, 0x6a, 0x6f, 0x73, 0x65, 0x72, 0x62, 0x161, 0x107, 0x69, 0x6e, 0x61,
+0x4e, 0x11b, 0x6d, 0x73, 0x6b, 0x61, 0x61, 0x6e, 0x61, 0x72, 0xe2, 0x161, 0x6b, 0x69, 0x65, 0x6c, 0xe2, 0x53, 0x75, 0x6f,
+0x6d, 0xe2, 0x645, 0x627, 0x632, 0x631, 0x648, 0x646, 0x6cc, 0x644, 0x6ca, 0x631, 0x6cc, 0x20, 0x634, 0x648, 0x645, 0x627, 0x644, 0x6cc,
+0x7cb5, 0x8a9e, 0x4e2d, 0x83ef, 0x4eba, 0x6c11, 0x5171, 0x548c, 0x570b, 0x9999, 0x6e2f, 0x7279, 0x5225, 0x884c, 0x653f, 0x5340
};
static const char language_name_list[] =
diff --git a/src/corelib/tools/qlocale_mac.mm b/src/corelib/tools/qlocale_mac.mm
index c5519bfabf..edbaaf5d18 100644
--- a/src/corelib/tools/qlocale_mac.mm
+++ b/src/corelib/tools/qlocale_mac.mm
@@ -150,7 +150,7 @@ static QString macTimeToString(const QTime &time, bool short_format)
// See also qtbase/util/local_database/dateconverter.py
// Makes the assumption that input formats are always well formed and consecutive letters
// never exceed the maximum for the format code.
-static QString macToQtFormat(const QString &sys_fmt)
+static QString macToQtFormat(QStringView sys_fmt)
{
QString result;
int i = 0;
@@ -166,7 +166,7 @@ static QString macToQtFormat(const QString &sys_fmt)
}
QChar c = sys_fmt.at(i);
- int repeat = qt_repeatCount(sys_fmt, i);
+ int repeat = qt_repeatCount(sys_fmt.mid(i));
switch (c.unicode()) {
// Qt does not support the following options
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index f7adb021b6..7eb8b7372c 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -254,25 +254,21 @@ public:
return float(d);
}
- double stringToDouble(const QChar *begin, int len, bool *ok,
- QLocale::NumberOptions number_options) const;
- qint64 stringToLongLong(const QChar *begin, int len, int base, bool *ok,
- QLocale::NumberOptions number_options) const;
- quint64 stringToUnsLongLong(const QChar *begin, int len, int base, bool *ok,
- QLocale::NumberOptions number_options) const;
-
- // these functions are used in QIntValidator (QtGui)
- Q_CORE_EXPORT static double bytearrayToDouble(const char *num, bool *ok, bool *overflow = 0);
- Q_CORE_EXPORT static qint64 bytearrayToLongLong(const char *num, int base, bool *ok, bool *overflow = 0);
- Q_CORE_EXPORT static quint64 bytearrayToUnsLongLong(const char *num, int base, bool *ok);
-
- bool numberToCLocale(const QChar *str, int len, QLocale::NumberOptions number_options,
+ double stringToDouble(QStringView str, bool *ok, QLocale::NumberOptions options) const;
+ qint64 stringToLongLong(QStringView str, int base, bool *ok, QLocale::NumberOptions options) const;
+ quint64 stringToUnsLongLong(QStringView str, int base, bool *ok, QLocale::NumberOptions options) const;
+
+ static double bytearrayToDouble(const char *num, bool *ok);
+ // this function is used in QIntValidator (QtGui)
+ Q_CORE_EXPORT static qint64 bytearrayToLongLong(const char *num, int base, bool *ok);
+ static quint64 bytearrayToUnsLongLong(const char *num, int base, bool *ok);
+
+ bool numberToCLocale(QStringView s, QLocale::NumberOptions number_options,
CharBuff *result) const;
inline char digitToCLocale(QChar c) const;
// this function is used in QIntValidator (QtGui)
- Q_CORE_EXPORT bool validateChars(
- const QString &str, NumberMode numMode, QByteArray *buff, int decDigits = -1,
+ Q_CORE_EXPORT bool validateChars(QStringView str, NumberMode numMode, QByteArray *buff, int decDigits = -1,
QLocale::NumberOptions number_options = QLocale::DefaultNumberOptions) const;
public:
@@ -304,6 +300,9 @@ public:
quint16 m_narrow_day_names_idx, m_narrow_day_names_size;
quint16 m_am_idx, m_am_size;
quint16 m_pm_idx, m_pm_size;
+ quint16 m_byte_idx, m_byte_size;
+ quint16 m_byte_si_quantified_idx, m_byte_si_quantified_size;
+ quint16 m_byte_iec_quantified_idx, m_byte_iec_quantified_size;
char m_currency_iso_code[3];
quint16 m_currency_symbol_idx, m_currency_symbol_size;
quint16 m_currency_display_name_idx, m_currency_display_name_size;
@@ -349,23 +348,16 @@ public:
QByteArray bcp47Name(char separator = '-') const;
- // ### QByteArray::fromRawData would be more optimal
- inline QString languageCode() const { return QLocalePrivate::languageToCode(QLocale::Language(m_data->m_language_id)); }
- inline QString scriptCode() const { return QLocalePrivate::scriptToCode(QLocale::Script(m_data->m_script_id)); }
- inline QString countryCode() const { return QLocalePrivate::countryToCode(QLocale::Country(m_data->m_country_id)); }
-
- static QString languageToCode(QLocale::Language language);
- static QString scriptToCode(QLocale::Script script);
- static QString countryToCode(QLocale::Country country);
- static QLocale::Language codeToLanguage(const QChar *code, int len) Q_DECL_NOTHROW;
- static QLocale::Language codeToLanguage(const QString &code) Q_DECL_NOTHROW { return codeToLanguage(code.data(), code.size()); }
- static QLocale::Language codeToLanguage(const QStringRef &code) Q_DECL_NOTHROW { return codeToLanguage(code.data(), code.size()); }
- static QLocale::Script codeToScript(const QChar *code, int len) Q_DECL_NOTHROW;
- static QLocale::Script codeToScript(const QString &code) Q_DECL_NOTHROW { return codeToScript(code.data(), code.size()); }
- static QLocale::Script codeToScript(const QStringRef &code) Q_DECL_NOTHROW { return codeToScript(code.data(), code.size()); }
- static QLocale::Country codeToCountry(const QChar *code, int len) Q_DECL_NOTHROW;
- static QLocale::Country codeToCountry(const QString &code) Q_DECL_NOTHROW { return codeToCountry(code.data(), code.size()); }
- static QLocale::Country codeToCountry(const QStringRef &code) Q_DECL_NOTHROW { return codeToCountry(code.data(), code.size()); }
+ inline QLatin1String languageCode() const { return QLocalePrivate::languageToCode(QLocale::Language(m_data->m_language_id)); }
+ inline QLatin1String scriptCode() const { return QLocalePrivate::scriptToCode(QLocale::Script(m_data->m_script_id)); }
+ inline QLatin1String countryCode() const { return QLocalePrivate::countryToCode(QLocale::Country(m_data->m_country_id)); }
+
+ static QLatin1String languageToCode(QLocale::Language language);
+ static QLatin1String scriptToCode(QLocale::Script script);
+ static QLatin1String countryToCode(QLocale::Country country);
+ static QLocale::Language codeToLanguage(QStringView code) Q_DECL_NOTHROW;
+ static QLocale::Script codeToScript(QStringView code) Q_DECL_NOTHROW;
+ static QLocale::Country codeToCountry(QStringView code) Q_DECL_NOTHROW;
static void getLangAndCountry(const QString &name, QLocale::Language &lang,
QLocale::Script &script, QLocale::Country &cntry);
@@ -373,7 +365,7 @@ public:
static void updateSystemPrivate();
- QString dateTimeToString(const QString &format, const QDateTime &datetime,
+ QString dateTimeToString(QStringView format, const QDateTime &datetime,
const QDate &dateOnly, const QTime &timeOnly,
const QLocale *q) const;
@@ -423,9 +415,9 @@ inline char QLocaleData::digitToCLocale(QChar in) const
return 0;
}
-QString qt_readEscapedFormatString(const QString &format, int *idx);
+QString qt_readEscapedFormatString(QStringView format, int *idx);
bool qt_splitLocaleName(const QString &name, QString &lang, QString &script, QString &cntry);
-int qt_repeatCount(const QString &s, int i);
+int qt_repeatCount(QStringView s);
enum { AsciiSpaceMask = (1 << (' ' - 1)) |
(1 << ('\t' - 1)) | // 9: HT - horizontal tab
diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp
index 2475859abd..1d80320d8e 100644
--- a/src/corelib/tools/qlocale_win.cpp
+++ b/src/corelib/tools/qlocale_win.cpp
@@ -160,7 +160,7 @@ private:
SubstitutionType substitution();
QString &substituteDigits(QString &string);
- static QString winToQtFormat(const QString &sys_fmt);
+ static QString winToQtFormat(QStringView sys_fmt);
};
Q_GLOBAL_STATIC(QSystemLocalePrivate, systemLocalePrivate)
@@ -680,7 +680,7 @@ void QSystemLocalePrivate::update()
zero = QChar();
}
-QString QSystemLocalePrivate::winToQtFormat(const QString &sys_fmt)
+QString QSystemLocalePrivate::winToQtFormat(QStringView sys_fmt)
{
QString result;
int i = 0;
@@ -696,7 +696,7 @@ QString QSystemLocalePrivate::winToQtFormat(const QString &sys_fmt)
}
QChar c = sys_fmt.at(i);
- int repeat = qt_repeatCount(sys_fmt, i);
+ int repeat = qt_repeatCount(sys_fmt.mid(i));
switch (c.unicode()) {
// Date
diff --git a/src/corelib/tools/qmap.cpp b/src/corelib/tools/qmap.cpp
index 29534bdeee..afdd30e5c8 100644
--- a/src/corelib/tools/qmap.cpp
+++ b/src/corelib/tools/qmap.cpp
@@ -908,6 +908,61 @@ void QMapDataBase::freeData(QMapDataBase *d)
\sa keyBegin(), lastKey()
*/
+
+/*! \fn QMap::key_value_iterator QMap::keyValueBegin()
+ \since 5.10
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the map.
+
+ \sa keyValueEnd()
+*/
+
+/*! \fn QMap::key_value_iterator QMap::keyValueEnd()
+ \since 5.10
+
+ Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the map.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn QMap::const_key_value_iterator QMap::keyValueBegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the map.
+
+ \sa keyValueEnd()
+*/
+
+/*! \fn QMap::const_key_value_iterator QMap::constKeyValueBegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first entry
+ in the map.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn QMap::const_key_value_iterator QMap::keyValueEnd() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the map.
+
+ \sa keyValueBegin()
+*/
+
+/*! \fn QMap::const_key_value_iterator QMap::constKeyValueEnd() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ entry after the last entry in the map.
+
+ \sa constKeyValueBegin()
+*/
+
/*! \fn const Key &QMap::firstKey() const
\since 5.2
@@ -1782,6 +1837,18 @@ void QMapDataBase::freeData(QMapDataBase *d)
Returns the underlying const_iterator this key_iterator is based on.
*/
+/*! \typedef QMap::key_value_iterator
+ \inmodule QtCore
+ \since 5.10
+ \brief The QMap::key_value_iterator typedef provides an STL-style iterator for QMap and QMultiMap.
+
+ QMap::key_value_iterator is essentially the same as QMap::iterator
+ with the difference that operator*() returns a key/value pair instead of a
+ value.
+
+ \sa QKeyValueIterator
+*/
+
/*! \fn QDataStream &operator<<(QDataStream &out, const QMap<Key, T> &map)
\relates QMap
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index 37ed24000d..16442014ff 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -548,6 +548,8 @@ public:
const_iterator base() const { return i; }
};
+ typedef QKeyValueIterator<const Key&, const T&, const_iterator> const_key_value_iterator;
+ typedef QKeyValueIterator<const Key&, T&, iterator> key_value_iterator;
// STL style
inline iterator begin() { detach(); return iterator(d->begin()); }
@@ -560,6 +562,12 @@ public:
inline const_iterator cend() const { return const_iterator(d->end()); }
inline key_iterator keyBegin() const { return key_iterator(begin()); }
inline key_iterator keyEnd() const { return key_iterator(end()); }
+ inline key_value_iterator keyValueBegin() { return key_value_iterator(begin()); }
+ inline key_value_iterator keyValueEnd() { return key_value_iterator(end()); }
+ inline const_key_value_iterator keyValueBegin() const { return const_key_value_iterator(begin()); }
+ inline const_key_value_iterator constKeyValueBegin() const { return const_key_value_iterator(begin()); }
+ inline const_key_value_iterator keyValueEnd() const { return const_key_value_iterator(end()); }
+ inline const_key_value_iterator constKeyValueEnd() const { return const_key_value_iterator(end()); }
iterator erase(iterator it);
// more Qt
@@ -948,7 +956,7 @@ Q_OUTOFLINE_TEMPLATE T QMap<Key, T>::take(const Key &akey)
Node *node = d->findNode(akey);
if (node) {
- T t = node->value;
+ T t = std::move(node->value);
d->deleteNode(node);
return t;
}
diff --git a/src/corelib/tools/qrect.h b/src/corelib/tools/qrect.h
index 19ff87b420..3b40055b5a 100644
--- a/src/corelib/tools/qrect.h
+++ b/src/corelib/tools/qrect.h
@@ -870,7 +870,7 @@ Q_DECL_CONSTEXPR inline bool operator!=(const QRectF &r1, const QRectF &r2) Q_DE
Q_DECL_CONSTEXPR inline QRect QRectF::toRect() const Q_DECL_NOTHROW
{
- return QRect(qRound(xp), qRound(yp), qRound(w), qRound(h));
+ return QRect(QPoint(qRound(xp), qRound(yp)), QPoint(qRound(xp + w) - 1, qRound(yp + h) - 1));
}
Q_DECL_CONSTEXPR inline QRectF operator+(const QRectF &lhs, const QMarginsF &rhs) Q_DECL_NOTHROW
diff --git a/src/corelib/tools/qregularexpression.cpp b/src/corelib/tools/qregularexpression.cpp
index 88b696f53a..86bc99716d 100644
--- a/src/corelib/tools/qregularexpression.cpp
+++ b/src/corelib/tools/qregularexpression.cpp
@@ -871,7 +871,7 @@ struct QRegularExpressionPrivate : QSharedData
CheckSubjectStringOption checkSubjectStringOption = CheckSubjectString,
const QRegularExpressionMatchPrivate *previous = 0) const;
- int captureIndexForName(const QString &name) const;
+ int captureIndexForName(QStringView name) const;
// sizeof(QSharedData) == 4, so start our members with an enum
QRegularExpression::PatternOptions patternOptions;
@@ -1173,14 +1173,14 @@ void QRegularExpressionPrivate::optimizePattern(OptimizePatternOption option)
Returns the capturing group number for the given name. Duplicated names for
capturing groups are not supported.
*/
-int QRegularExpressionPrivate::captureIndexForName(const QString &name) const
+int QRegularExpressionPrivate::captureIndexForName(QStringView name) const
{
Q_ASSERT(!name.isEmpty());
if (!compiledPattern)
return -1;
- int index = pcre2_substring_number_from_name_16(compiledPattern, name.utf16());
+ int index = pcre2_substring_number_from_name_16(compiledPattern, reinterpret_cast<PCRE2_SPTR16>(name.utf16()));
if (index >= 0)
return index;
@@ -2054,11 +2054,12 @@ int QRegularExpressionMatch::lastCapturedIndex() const
}
/*!
- Returns the substring captured by the \a nth capturing group. If the \a nth
- capturing group did not capture a string or doesn't exist, returns a null
- QString.
+ Returns the substring captured by the \a nth capturing group.
- \sa capturedRef(), lastCapturedIndex(), capturedStart(), capturedEnd(),
+ If the \a nth capturing group did not capture a string, or if there is no
+ such capturing group, returns a null QString.
+
+ \sa capturedRef(), capturedView(), lastCapturedIndex(), capturedStart(), capturedEnd(),
capturedLength(), QString::isNull()
*/
QString QRegularExpressionMatch::captured(int nth) const
@@ -2076,10 +2077,11 @@ QString QRegularExpressionMatch::captured(int nth) const
/*!
Returns a reference to the substring captured by the \a nth capturing group.
- If the \a nth capturing group did not capture a string or doesn't exist,
- returns a null QStringRef.
- \sa captured(), lastCapturedIndex(), capturedStart(), capturedEnd(),
+ If the \a nth capturing group did not capture a string, or if there is no
+ such capturing group, returns a null QStringRef.
+
+ \sa captured(), capturedView(), lastCapturedIndex(), capturedStart(), capturedEnd(),
capturedLength(), QStringRef::isNull()
*/
QStringRef QRegularExpressionMatch::capturedRef(int nth) const
@@ -2096,15 +2098,65 @@ QStringRef QRegularExpressionMatch::capturedRef(int nth) const
}
/*!
- Returns the substring captured by the capturing group named \a name. If the
- capturing group named \a name did not capture a string or doesn't exist,
- returns a null QString.
+ \since 5.10
+
+ Returns a view of the substring captured by the \a nth capturing group.
+
+ If the \a nth capturing group did not capture a string, or if there is no
+ such capturing group, returns a null QStringView.
+
+ \sa captured(), capturedRef(), lastCapturedIndex(), capturedStart(), capturedEnd(),
+ capturedLength(), QStringView::isNull()
+*/
+QStringView QRegularExpressionMatch::capturedView(int nth) const
+{
+ return capturedRef(nth);
+}
+
+#if QT_STRINGVIEW_LEVEL < 2
+/*!
+ Returns the substring captured by the capturing group named \a name.
- \sa capturedRef(), capturedStart(), capturedEnd(), capturedLength(),
+ If the named capturing group \a name did not capture a string, or if
+ there is no capturing group named \a name, returns a null QString.
+
+ \sa capturedRef(), capturedView(), capturedStart(), capturedEnd(), capturedLength(),
QString::isNull()
*/
QString QRegularExpressionMatch::captured(const QString &name) const
{
+ return captured(qToStringViewIgnoringNull(name));
+}
+
+/*!
+ Returns a reference to the string captured by the capturing group named \a
+ name.
+
+ If the named capturing group \a name did not capture a string, or if
+ there is no capturing group named \a name, returns a null QStringRef.
+
+ \sa captured(), capturedView(), capturedStart(), capturedEnd(), capturedLength(),
+ QStringRef::isNull()
+*/
+QStringRef QRegularExpressionMatch::capturedRef(const QString &name) const
+{
+ return capturedRef(qToStringViewIgnoringNull(name));
+}
+#endif // QT_STRINGVIEW_LEVEL < 2
+
+/*!
+ \since 5.10
+
+ Returns the substring captured by the capturing group named \a name.
+
+ If the named capturing group \a name did not capture a string, or if
+ there is no capturing group named \a name, returns a null QString.
+
+ \sa capturedRef(), capturedView(), capturedStart(), capturedEnd(), capturedLength(),
+ QString::isNull()
+*/
+QString QRegularExpressionMatch::captured(QStringView name) const
+{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::captured: empty capturing group name passed");
return QString();
@@ -2116,14 +2168,18 @@ QString QRegularExpressionMatch::captured(const QString &name) const
}
/*!
+ \since 5.10
+
Returns a reference to the string captured by the capturing group named \a
- name. If the capturing group named \a name did not capture a string or
- doesn't exist, returns a null QStringRef.
+ name.
+
+ If the named capturing group \a name did not capture a string, or if
+ there is no capturing group named \a name, returns a null QStringRef.
- \sa captured(), capturedStart(), capturedEnd(), capturedLength(),
+ \sa captured(), capturedView(), capturedStart(), capturedEnd(), capturedLength(),
QStringRef::isNull()
*/
-QStringRef QRegularExpressionMatch::capturedRef(const QString &name) const
+QStringRef QRegularExpressionMatch::capturedRef(QStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedRef: empty capturing group name passed");
@@ -2136,6 +2192,30 @@ QStringRef QRegularExpressionMatch::capturedRef(const QString &name) const
}
/*!
+ \since 5.10
+
+ Returns a view of the string captured by the capturing group named \a
+ name.
+
+ If the named capturing group \a name did not capture a string, or if
+ there is no capturing group named \a name, returns a null QStringView.
+
+ \sa captured(), capturedRef(), capturedStart(), capturedEnd(), capturedLength(),
+ QStringRef::isNull()
+*/
+QStringView QRegularExpressionMatch::capturedView(QStringView name) const
+{
+ if (name.isEmpty()) {
+ qWarning("QRegularExpressionMatch::capturedView: empty capturing group name passed");
+ return QStringView();
+ }
+ int nth = d->regularExpression.d->captureIndexForName(name);
+ if (nth == -1)
+ return QStringView();
+ return capturedView(nth);
+}
+
+/*!
Returns a list of all strings captured by capturing groups, in the order
the groups themselves appear in the pattern string.
*/
@@ -2193,6 +2273,7 @@ int QRegularExpressionMatch::capturedEnd(int nth) const
return d->capturedOffsets.at(nth * 2 + 1);
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns the offset inside the subject string corresponding to the starting
position of the substring captured by the capturing group named \a name.
@@ -2203,6 +2284,49 @@ int QRegularExpressionMatch::capturedEnd(int nth) const
*/
int QRegularExpressionMatch::capturedStart(const QString &name) const
{
+ return capturedStart(qToStringViewIgnoringNull(name));
+}
+
+/*!
+ Returns the length of the substring captured by the capturing group named
+ \a name.
+
+ \note This function returns 0 if the capturing group named \a name did not
+ capture a string or doesn't exist.
+
+ \sa capturedStart(), capturedEnd(), captured()
+*/
+int QRegularExpressionMatch::capturedLength(const QString &name) const
+{
+ return capturedLength(qToStringViewIgnoringNull(name));
+}
+
+/*!
+ Returns the offset inside the subject string immediately after the ending
+ position of the substring captured by the capturing group named \a name. If
+ the capturing group named \a name did not capture a string or doesn't
+ exist, returns -1.
+
+ \sa capturedStart(), capturedLength(), captured()
+*/
+int QRegularExpressionMatch::capturedEnd(const QString &name) const
+{
+ return capturedEnd(qToStringViewIgnoringNull(name));
+}
+#endif // QT_STRINGVIEW_LEVEL < 2
+
+/*!
+ \since 5.10
+
+ Returns the offset inside the subject string corresponding to the starting
+ position of the substring captured by the capturing group named \a name.
+ If the capturing group named \a name did not capture a string or doesn't
+ exist, returns -1.
+
+ \sa capturedEnd(), capturedLength(), captured()
+*/
+int QRegularExpressionMatch::capturedStart(QStringView name) const
+{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedStart: empty capturing group name passed");
return -1;
@@ -2214,15 +2338,17 @@ int QRegularExpressionMatch::capturedStart(const QString &name) const
}
/*!
- Returns the offset inside the subject string corresponding to the starting
- position of the substring captured by the capturing group named \a name.
+ \since 5.10
+
+ Returns the length of the substring captured by the capturing group named
+ \a name.
\note This function returns 0 if the capturing group named \a name did not
capture a string or doesn't exist.
\sa capturedStart(), capturedEnd(), captured()
*/
-int QRegularExpressionMatch::capturedLength(const QString &name) const
+int QRegularExpressionMatch::capturedLength(QStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedLength: empty capturing group name passed");
@@ -2235,6 +2361,8 @@ int QRegularExpressionMatch::capturedLength(const QString &name) const
}
/*!
+ \since 5.10
+
Returns the offset inside the subject string immediately after the ending
position of the substring captured by the capturing group named \a name. If
the capturing group named \a name did not capture a string or doesn't
@@ -2242,7 +2370,7 @@ int QRegularExpressionMatch::capturedLength(const QString &name) const
\sa capturedStart(), capturedLength(), captured()
*/
-int QRegularExpressionMatch::capturedEnd(const QString &name) const
+int QRegularExpressionMatch::capturedEnd(QStringView name) const
{
if (name.isEmpty()) {
qWarning("QRegularExpressionMatch::capturedEnd: empty capturing group name passed");
diff --git a/src/corelib/tools/qregularexpression.h b/src/corelib/tools/qregularexpression.h
index fa1cc5660a..050841e70e 100644
--- a/src/corelib/tools/qregularexpression.h
+++ b/src/corelib/tools/qregularexpression.h
@@ -52,6 +52,8 @@
QT_BEGIN_NAMESPACE
+class QStringView;
+
class QRegularExpressionMatch;
class QRegularExpressionMatchIterator;
struct QRegularExpressionPrivate;
@@ -197,9 +199,16 @@ public:
QString captured(int nth = 0) const;
QStringRef capturedRef(int nth = 0) const;
+ QStringView capturedView(int nth = 0) const;
+#if QT_STRINGVIEW_LEVEL < 2
QString captured(const QString &name) const;
QStringRef capturedRef(const QString &name) const;
+#endif
+
+ QString captured(QStringView name) const;
+ QStringRef capturedRef(QStringView name) const;
+ QStringView capturedView(QStringView name) const;
QStringList capturedTexts() const;
@@ -207,9 +216,15 @@ public:
int capturedLength(int nth = 0) const;
int capturedEnd(int nth = 0) const;
+#if QT_STRINGVIEW_LEVEL < 2
int capturedStart(const QString &name) const;
int capturedLength(const QString &name) const;
int capturedEnd(const QString &name) const;
+#endif
+
+ int capturedStart(QStringView name) const;
+ int capturedLength(QStringView name) const;
+ int capturedEnd(QStringView name) const;
private:
friend class QRegularExpression;
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index 325b71f267..558a456515 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -159,6 +159,8 @@ private:
qint64 bufferSize;
};
+Q_DECLARE_TYPEINFO(QRingBuffer, Q_MOVABLE_TYPE);
+
QT_END_NAMESPACE
#endif // QRINGBUFFER_P_H
diff --git a/src/corelib/tools/qscopedpointer.cpp b/src/corelib/tools/qscopedpointer.cpp
index 0e8eba2a0f..8d84b3beca 100644
--- a/src/corelib/tools/qscopedpointer.cpp
+++ b/src/corelib/tools/qscopedpointer.cpp
@@ -303,10 +303,10 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QScopedArrayPointer::QScopedArrayPointer(D * p, QtPrivate::QScopedArrayEnsureSameType<T, D>::Type = 0)
- \internal
+ \fn QScopedArrayPointer::QScopedArrayPointer(D * p)
- Constructs a QScopedArrayPointer and stores the array of objects.
+ Constructs a QScopedArrayPointer and stores the array of objects
+ pointed to by \a p.
*/
/*!
diff --git a/src/corelib/tools/qscopedpointer.h b/src/corelib/tools/qscopedpointer.h
index 92d7df6e5d..141a3f8c70 100644
--- a/src/corelib/tools/qscopedpointer.h
+++ b/src/corelib/tools/qscopedpointer.h
@@ -215,21 +215,16 @@ template <class T, class Cleanup>
inline void swap(QScopedPointer<T, Cleanup> &p1, QScopedPointer<T, Cleanup> &p2) Q_DECL_NOTHROW
{ p1.swap(p2); }
-
-namespace QtPrivate {
- template <typename X, typename Y> struct QScopedArrayEnsureSameType;
- template <typename X> struct QScopedArrayEnsureSameType<X,X> { typedef X* Type; };
- template <typename X> struct QScopedArrayEnsureSameType<const X, X> { typedef X* Type; };
-}
-
template <typename T, typename Cleanup = QScopedPointerArrayDeleter<T> >
class QScopedArrayPointer : public QScopedPointer<T, Cleanup>
{
+ template <typename Ptr>
+ using if_same_type = typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, Ptr>::value, bool>::type;
public:
inline QScopedArrayPointer() : QScopedPointer<T, Cleanup>(Q_NULLPTR) {}
- template <typename D>
- explicit inline QScopedArrayPointer(D *p, typename QtPrivate::QScopedArrayEnsureSameType<T,D>::Type = Q_NULLPTR)
+ template <typename D, if_same_type<D> = true>
+ explicit QScopedArrayPointer(D *p)
: QScopedPointer<T, Cleanup>(p)
{
}
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
index 023a4b08d2..3ef29f4823 100644
--- a/src/corelib/tools/qsimd_p.h
+++ b/src/corelib/tools/qsimd_p.h
@@ -262,7 +262,7 @@
# endif
#endif
-#if defined(__AES__) || defined(__PCLMUL__)
+#if defined(__AES__) || defined(__PCLMUL__) || (defined(QT_COMPILER_SUPPORTS_AES) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS))
# include <wmmintrin.h>
#endif
@@ -287,7 +287,7 @@
#define QT_FUNCTION_TARGET_STRING_PCLMUL "pclmul,sse4.2"
#define QT_FUNCTION_TARGET_STRING_POPCNT "popcnt"
#define QT_FUNCTION_TARGET_STRING_F16C "f16c,avx"
-#define QT_FUNCTION_TARGET_STRING_RDRAND "rdrnd"
+#define QT_FUNCTION_TARGET_STRING_RDRND "rdrnd"
#define QT_FUNCTION_TARGET_STRING_BMI "bmi"
#define QT_FUNCTION_TARGET_STRING_BMI2 "bmi2"
#define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed"
@@ -330,8 +330,6 @@
# include <arm_acle.h>
#endif
-#undef QT_COMPILER_SUPPORTS_SIMD_ALWAYS
-
QT_BEGIN_NAMESPACE
@@ -357,7 +355,7 @@ enum CPUFeatures {
CpuFeatureAES = (0 + 25),
CpuFeatureAVX = (0 + 28),
CpuFeatureF16C = (0 + 29),
- CpuFeatureRDRAND = (0 + 30),
+ CpuFeatureRDRND = (0 + 30),
// 31 is always zero and we've used it for the QSimdInitialized
// in level 7, leaf 0, EBX
@@ -396,7 +394,7 @@ static const quint64 qCompilerCpuFeatures = 0
| (Q_UINT64_C(1) << CpuFeatureRTM)
#endif
#ifdef __RDRND__
- | (Q_UINT64_C(1) << CpuFeatureRDRAND)
+ | (Q_UINT64_C(1) << CpuFeatureRDRND)
#endif
#ifdef __RDSEED__
| (Q_UINT64_C(1) << CpuFeatureRDSEED)
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 941532658b..3826d7531a 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -152,21 +152,19 @@ static inline int qt_string_count(const QChar *haystack, int haystackLen,
QChar needle, Qt::CaseSensitivity cs);
static inline int qt_find_latin1_string(const QChar *hay, int size, QLatin1String needle,
int from, Qt::CaseSensitivity cs);
-static inline bool qt_starts_with(const QChar *haystack, int haystackLen,
- const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
-static inline bool qt_starts_with(const QChar *haystack, int haystackLen,
- QLatin1String needle, Qt::CaseSensitivity cs);
-static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
- const QChar *needle, int needleLen, Qt::CaseSensitivity cs);
-static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
- QLatin1String needle, Qt::CaseSensitivity cs);
+static inline bool qt_starts_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs);
+static inline bool qt_starts_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
+static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
+static inline bool qt_ends_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs);
+static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs);
+static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs);
#if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
namespace {
template <uint MaxCount> struct UnrollTailLoop
{
- template <typename RetType, typename Functor1, typename Functor2>
- static inline RetType exec(int count, RetType returnIfExited, Functor1 loopCheck, Functor2 returnIfFailed, int i = 0)
+ template <typename RetType, typename Functor1, typename Functor2, typename Number>
+ static inline RetType exec(Number count, RetType returnIfExited, Functor1 loopCheck, Functor2 returnIfFailed, Number i = 0)
{
/* equivalent to:
* while (count--) {
@@ -188,18 +186,18 @@ template <uint MaxCount> struct UnrollTailLoop
return UnrollTailLoop<MaxCount - 1>::exec(count - 1, returnIfExited, loopCheck, returnIfFailed, i + 1);
}
- template <typename Functor>
- static inline void exec(int count, Functor code)
+ template <typename Functor, typename Number>
+ static inline void exec(Number count, Functor code)
{
/* equivalent to:
- * for (int i = 0; i < count; ++i)
+ * for (Number i = 0; i < count; ++i)
* code(i);
*/
- exec(count, 0, [=](int i) -> bool { code(i); return false; }, [](int) { return 0; });
+ exec(count, 0, [=](Number i) -> bool { code(i); return false; }, [](Number) { return 0; });
}
};
-template <> template <typename RetType, typename Functor1, typename Functor2>
-inline RetType UnrollTailLoop<0>::exec(int, RetType returnIfExited, Functor1, Functor2, int)
+template <> template <typename RetType, typename Functor1, typename Functor2, typename Number>
+inline RetType UnrollTailLoop<0>::exec(Number, RetType returnIfExited, Functor1, Functor2, Number)
{
return returnIfExited;
}
@@ -374,16 +372,16 @@ static void qt_to_latin1(uchar *dst, const ushort *src, int length)
}
// Unicode case-insensitive comparison
-static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const ushort *be)
+static int ucstricmp(const QChar *a, const QChar *ae, const QChar *b, const QChar *be)
{
if (a == b)
return (ae - be);
if (a == 0)
- return 1;
+ return be - b;
if (b == 0)
- return -1;
+ return a - ae;
- const ushort *e = ae;
+ const QChar *e = ae;
if (be - b < ae - a)
e = a + (be - b);
@@ -393,7 +391,7 @@ static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const u
// qDebug() << hex << alast << blast;
// qDebug() << hex << "*a=" << *a << "alast=" << alast << "folded=" << foldCase (*a, alast);
// qDebug() << hex << "*b=" << *b << "blast=" << blast << "folded=" << foldCase (*b, blast);
- int diff = foldCase(*a, alast) - foldCase(*b, blast);
+ int diff = foldCase(a->unicode(), alast) - foldCase(b->unicode(), blast);
if ((diff))
return diff;
++a;
@@ -408,22 +406,19 @@ static int ucstricmp(const ushort *a, const ushort *ae, const ushort *b, const u
}
// Case-insensitive comparison between a Unicode string and a QLatin1String
-static int ucstricmp(const ushort *a, const ushort *ae, const uchar *b, const uchar *be)
+static int ucstricmp(const QChar *a, const QChar *ae, const char *b, const char *be)
{
- if (a == 0) {
- if (b == 0)
- return 0;
- return 1;
- }
- if (b == 0)
- return -1;
+ if (!a)
+ return be - b;
+ if (!b)
+ return a - ae;
- const ushort *e = ae;
+ auto e = ae;
if (be - b < ae - a)
e = a + (be - b);
while (a < e) {
- int diff = foldCase(*a) - foldCase(*b);
+ int diff = foldCase(a->unicode()) - foldCase(uchar(*b));
if ((diff))
return diff;
++a;
@@ -445,7 +440,7 @@ extern "C" int qt_ucstrncmp_mips_dsp_asm(const ushort *a,
#endif
// Unicode case-sensitive compare two same-sized strings
-static int ucstrncmp(const QChar *a, const QChar *b, int l)
+static int ucstrncmp(const QChar *a, const QChar *b, size_t l)
{
#ifdef __OPTIMIZE_SIZE__
const QChar *end = a + l;
@@ -458,6 +453,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l)
return 0;
#else
#if defined(__mips_dsp)
+ Q_STATIC_ASSERT(sizeof(uint) == sizeof(size_t));
if (l >= 8) {
return qt_ucstrncmp_mips_dsp_asm(reinterpret_cast<const ushort*>(a),
reinterpret_cast<const ushort*>(b),
@@ -484,13 +480,11 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l)
- reinterpret_cast<const QChar *>(ptr + distance + idx)->unicode();
}
}
-# if defined(Q_COMPILER_LAMBDA)
- const auto &lambda = [=](int i) -> int {
+ const auto lambda = [=](size_t i) -> int {
return reinterpret_cast<const QChar *>(ptr)[i].unicode()
- reinterpret_cast<const QChar *>(ptr + distance)[i].unicode();
};
return UnrollTailLoop<7>::exec(l, 0, lambda, lambda);
-# endif
#endif
#if defined(__ARM_NEON__) && defined(Q_PROCESSOR_ARM_64) // vaddv is only available on Aarch64
if (l >= 8) {
@@ -511,7 +505,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l)
}
l &= 7;
}
- const auto &lambda = [=](int i) -> int {
+ const auto lambda = [=](size_t i) -> int {
return a[i].unicode() - b[i].unicode();
};
return UnrollTailLoop<7>::exec(l, 0, lambda, lambda);
@@ -565,7 +559,7 @@ static int ucstrncmp(const QChar *a, const QChar *b, int l)
#endif
}
-static int ucstrncmp(const QChar *a, const uchar *c, int l)
+static int ucstrncmp(const QChar *a, const uchar *c, size_t l)
{
const ushort *uc = reinterpret_cast<const ushort *>(a);
const ushort *e = uc + l;
@@ -640,8 +634,8 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
uc += offset;
c += offset;
-# if defined(Q_COMPILER_LAMBDA) && !defined(__OPTIMIZE_SIZE__)
- const auto &lambda = [=](int i) { return uc[i] - ushort(c[i]); };
+# if !defined(__OPTIMIZE_SIZE__)
+ const auto lambda = [=](size_t i) { return uc[i] - ushort(c[i]); };
return UnrollTailLoop<MaxTailLength>::exec(e - uc, 0, lambda, lambda);
# endif
#endif
@@ -656,35 +650,140 @@ static int ucstrncmp(const QChar *a, const uchar *c, int l)
return 0;
}
+template <typename Number>
+Q_DECL_CONSTEXPR int lencmp(Number lhs, Number rhs) Q_DECL_NOTHROW
+{
+ return lhs == rhs ? 0 :
+ lhs > rhs ? 1 :
+ /* else */ -1 ;
+}
+
// Unicode case-sensitive comparison
-static int ucstrcmp(const QChar *a, int alen, const QChar *b, int blen)
+static int ucstrcmp(const QChar *a, size_t alen, const QChar *b, size_t blen)
{
if (a == b && alen == blen)
return 0;
- int l = qMin(alen, blen);
+ const size_t l = qMin(alen, blen);
int cmp = ucstrncmp(a, b, l);
- return cmp ? cmp : (alen-blen);
+ return cmp ? cmp : lencmp(alen, blen);
}
-// Unicode case-insensitive compare two same-sized strings
-static int ucstrnicmp(const ushort *a, const ushort *b, int l)
+static int ucstrcmp(const QChar *a, size_t alen, const char *b, size_t blen)
{
- return ucstricmp(a, a + l, b, b + l);
+ const size_t l = qMin(alen, blen);
+ const int cmp = ucstrncmp(a, reinterpret_cast<const uchar*>(b), l);
+ return cmp ? cmp : lencmp(alen, blen);
}
-static bool qMemEquals(const quint16 *a, const quint16 *b, int length)
+static int qt_compare_strings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
- if (a == b || !length)
- return true;
+ if (cs == Qt::CaseSensitive)
+ return ucstrcmp(lhs.begin(), lhs.size(), rhs.begin(), rhs.size());
+ else
+ return ucstricmp(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+}
+
+static int qt_compare_strings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ if (cs == Qt::CaseSensitive)
+ return ucstrcmp(lhs.begin(), lhs.size(), rhs.begin(), rhs.size());
+ else
+ return ucstricmp(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
+}
- return ucstrncmp(reinterpret_cast<const QChar *>(a), reinterpret_cast<const QChar *>(b), length) == 0;
+static int qt_compare_strings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return -qt_compare_strings(rhs, lhs, cs);
}
-static int ucstrcmp(const QChar *a, int alen, const uchar *b, int blen)
+static int qt_compare_strings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
- int l = qMin(alen, blen);
- int cmp = ucstrncmp(a, b, l);
- return cmp ? cmp : (alen-blen);
+ if (lhs.isEmpty())
+ return lencmp(0, rhs.size());
+ const auto l = std::min(lhs.size(), rhs.size());
+ int r;
+ if (cs == Qt::CaseSensitive)
+ r = qstrncmp(lhs.data(), rhs.data(), l);
+ else
+ r = qstrnicmp(lhs.data(), rhs.data(), l);
+ return r ? r : lencmp(lhs.size(), rhs.size());
+}
+
+/*!
+ \relates QStringView
+ \since 5.10
+
+ Returns an integer that compares to 0 as \a lhs compares to \a rhs.
+
+ If \a cs is Qt::CaseSensitive (the default), the comparison is case-sensitive;
+ otherwise the comparison is case-insensitive.
+
+ Case-sensitive comparison is based exclusively on the numeric Unicode values
+ of the characters and is very fast, but is not what a human would expect.
+ Consider sorting user-visible strings with QString::localeAwareCompare().
+
+ \snippet qstring/main.cpp qCompareStrings-QSV-QSV
+*/
+int qCompareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_compare_strings(lhs, rhs, cs);
+}
+
+/*!
+ \relates QStringView
+ \since 5.10
+ \overload
+
+ Returns an integer that compares to 0 as \a lhs compares to \a rhs.
+
+ If \a cs is Qt::CaseSensitive (the default), the comparison is case-sensitive;
+ otherwise the comparison is case-insensitive.
+
+ Case-sensitive comparison is based exclusively on the numeric Unicode values
+ of the characters and is very fast, but is not what a human would expect.
+ Consider sorting user-visible strings with QString::localeAwareCompare().
+*/
+int qCompareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_compare_strings(lhs, rhs, cs);
+}
+
+/*!
+ \relates QStringView
+ \since 5.10
+ \overload
+
+ Returns an integer that compares to 0 as \a lhs compares to \a rhs.
+
+ If \a cs is Qt::CaseSensitive (the default), the comparison is case-sensitive;
+ otherwise the comparison is case-insensitive.
+
+ Case-sensitive comparison is based exclusively on the numeric Unicode values
+ of the characters and is very fast, but is not what a human would expect.
+ Consider sorting user-visible strings with QString::localeAwareCompare().
+*/
+int qCompareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_compare_strings(lhs, rhs, cs);
+}
+
+/*!
+ \relates QStringView
+ \since 5.10
+ \overload
+
+ Returns an integer that compares to 0 as \a lhs compares to \a rhs.
+
+ If \a cs is Qt::CaseSensitive (the default), the comparison is case-sensitive;
+ otherwise the comparison is case-insensitive.
+
+ Case-sensitive comparison is based exclusively on the numeric Latin-1 values
+ of the characters and is very fast, but is not what a human would expect.
+ Consider sorting user-visible strings with QString::localeAwareCompare().
+*/
+int qCompareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_compare_strings(lhs, rhs, cs);
}
/*!
@@ -1502,7 +1601,7 @@ int QString::toUcs4_helper(const ushort *uc, int length, uint *out)
{
int count = 0;
- QStringIterator i(reinterpret_cast<const QChar *>(uc), reinterpret_cast<const QChar *>(uc + length));
+ QStringIterator i(QStringView(uc, length));
while (i.hasNext())
out[count++] = i.next();
@@ -2789,7 +2888,7 @@ bool operator==(const QString &s1, const QString &s2) Q_DECL_NOTHROW
if (s1.d->size != s2.d->size)
return false;
- return qMemEquals(s1.d->data(), s2.d->data(), s1.d->size);
+ return qt_compare_strings(s1, s2, Qt::CaseSensitive) == 0;
}
/*!
@@ -2802,10 +2901,7 @@ bool QString::operator==(QLatin1String other) const Q_DECL_NOTHROW
if (d->size != other.size())
return false;
- if (!other.size())
- return isEmpty();
-
- return compare_helper(data(), size(), other, Qt::CaseSensitive) == 0;
+ return qt_compare_strings(*this, other, Qt::CaseSensitive) == 0;
}
/*! \fn bool QString::operator==(const QByteArray &other) const
@@ -2850,8 +2946,9 @@ bool QString::operator==(QLatin1String other) const Q_DECL_NOTHROW
*/
bool operator<(const QString &s1, const QString &s2) Q_DECL_NOTHROW
{
- return ucstrcmp(s1.constData(), s1.length(), s2.constData(), s2.length()) < 0;
+ return qt_compare_strings(s1, s2, Qt::CaseSensitive) < 0;
}
+
/*!
\overload operator<()
@@ -2860,11 +2957,7 @@ bool operator<(const QString &s1, const QString &s2) Q_DECL_NOTHROW
*/
bool QString::operator<(QLatin1String other) const Q_DECL_NOTHROW
{
- const uchar *c = (const uchar *) other.latin1();
- if (!c || *c == 0)
- return false;
-
- return compare_helper(data(), size(), other, Qt::CaseSensitive) < 0;
+ return qt_compare_strings(*this, other, Qt::CaseSensitive) < 0;
}
/*! \fn bool QString::operator<(const QByteArray &other) const
@@ -2965,11 +3058,7 @@ bool QString::operator<(QLatin1String other) const Q_DECL_NOTHROW
*/
bool QString::operator>(QLatin1String other) const Q_DECL_NOTHROW
{
- const uchar *c = (const uchar *) other.latin1();
- if (!c || *c == '\0')
- return !isEmpty();
-
- return compare_helper(data(), size(), other, Qt::CaseSensitive) > 0;
+ return qt_compare_strings(*this, other, Qt::CaseSensitive) > 0;
}
/*! \fn bool QString::operator>(const QByteArray &other) const
@@ -3166,11 +3255,12 @@ int qFindString(
return qFindStringBoyerMoore(haystack0, haystackLen, from,
needle0, needleLen, cs);
+ auto sv = [sl](const ushort *v) { return QStringView(v, sl); };
/*
We use some hashing for efficiency's sake. Instead of
comparing strings, we compare the hash value of str with that
of a part of this QString. Only if that matches, we call
- ucstrncmp() or ucstrnicmp().
+ qt_string_compare().
*/
const ushort *needle = (const ushort *)needle0;
const ushort *haystack = (const ushort *)haystack0 + from;
@@ -3189,7 +3279,7 @@ int qFindString(
while (haystack <= end) {
hashHaystack += haystack[sl_minus_1];
if (hashHaystack == hashNeedle
- && ucstrncmp((const QChar *)needle, (const QChar *)haystack, sl) == 0)
+ && qt_compare_strings(sv(needle), sv(haystack), Qt::CaseSensitive) == 0)
return haystack - (const ushort *)haystack0;
REHASH(*haystack);
@@ -3205,7 +3295,8 @@ int qFindString(
while (haystack <= end) {
hashHaystack += foldCase(haystack + sl_minus_1, haystack_start);
- if (hashHaystack == hashNeedle && ucstrnicmp(needle, haystack, sl) == 0)
+ if (hashHaystack == hashNeedle
+ && qt_compare_strings(sv(needle), sv(haystack), Qt::CaseInsensitive) == 0)
return haystack - (const ushort *)haystack0;
REHASH(foldCase(haystack, haystack_start));
@@ -3250,6 +3341,8 @@ static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *nee
See indexOf() for explanations.
*/
+ auto sv = [sl](const ushort *v) { return QStringView(v, sl); };
+
const ushort *end = haystack;
haystack += from;
const uint sl_minus_1 = sl - 1;
@@ -3268,7 +3361,7 @@ static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *nee
while (haystack >= end) {
hashHaystack += *haystack;
if (hashHaystack == hashNeedle
- && ucstrncmp((const QChar *)needle, (const QChar *)haystack, sl) == 0)
+ && qt_compare_strings(sv(needle), sv(haystack), Qt::CaseSensitive) == 0)
return haystack - end;
--haystack;
REHASH(haystack[sl]);
@@ -3282,7 +3375,8 @@ static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *nee
while (haystack >= end) {
hashHaystack += foldCase(haystack, end);
- if (hashHaystack == hashNeedle && ucstrnicmp(needle, haystack, sl) == 0)
+ if (hashHaystack == hashNeedle
+ && qt_compare_strings(sv(haystack), sv(needle), Qt::CaseInsensitive) == 0)
return haystack - end;
--haystack;
REHASH(foldCase(haystack + sl, end));
@@ -4366,7 +4460,7 @@ QString QString::section(const QRegularExpression &re, int start, int end, Secti
\snippet qstring/main.cpp 31
- \sa right(), mid(), startsWith()
+ \sa right(), mid(), startsWith(), chopped(), chop(), truncate()
*/
QString QString::left(int n) const
{
@@ -4384,7 +4478,7 @@ QString QString::left(int n) const
\snippet qstring/main.cpp 48
- \sa left(), mid(), endsWith()
+ \sa left(), mid(), endsWith(), chopped(), chop(), truncate()
*/
QString QString::right(int n) const
{
@@ -4407,7 +4501,7 @@ QString QString::right(int n) const
\snippet qstring/main.cpp 34
- \sa left(), right()
+ \sa left(), right(), chopped(), chop(), truncate()
*/
QString QString::mid(int position, int n) const
@@ -4431,6 +4525,19 @@ QString QString::mid(int position, int n) const
}
/*!
+ \fn QString::chopped(int len) const
+ \since 5.10
+
+ Returns a substring that contains the size() - \a len leftmost characters
+ of this string.
+
+ \note The behavior is undefined if \a len is negative or greater than size().
+
+ \sa endsWith(), left(), right(), mid(), chop(), truncate()
+*/
+
+#if QT_STRINGVIEW_LEVEL < 2
+/*!
Returns \c true if the string starts with \a s; otherwise returns
\c false.
@@ -4443,16 +4550,16 @@ QString QString::mid(int position, int n) const
*/
bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const
{
- return qt_starts_with(isNull() ? 0 : unicode(), size(),
- s.isNull() ? 0 : s.unicode(), s.size(), cs);
+ return qt_starts_with(*this, s, cs);
}
+#endif
/*!
\overload startsWith()
*/
bool QString::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const
{
- return qt_starts_with(isNull() ? 0 : unicode(), size(), s, cs);
+ return qt_starts_with(*this, s, cs);
}
/*!
@@ -4463,12 +4570,10 @@ bool QString::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const
*/
bool QString::startsWith(QChar c, Qt::CaseSensitivity cs) const
{
- return d->size
- && (cs == Qt::CaseSensitive
- ? d->data()[0] == c
- : foldCase(d->data()[0]) == foldCase(c.unicode()));
+ return qt_starts_with(*this, c, cs);
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\since 4.8
\overload
@@ -4482,10 +4587,25 @@ bool QString::startsWith(QChar c, Qt::CaseSensitivity cs) const
*/
bool QString::startsWith(const QStringRef &s, Qt::CaseSensitivity cs) const
{
- return qt_starts_with(isNull() ? 0 : unicode(), size(),
- s.isNull() ? 0 : s.unicode(), s.size(), cs);
+ return qt_starts_with(*this, s, cs);
}
+#endif
+
+/*!
+ \fn bool QString::startsWith(QStringView str, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \overload
+
+ Returns \c true if the string starts with the string-view \a str;
+ otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case-sensitive;
+ otherwise the search is case insensitive.
+
+ \sa endsWith()
+*/
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns \c true if the string ends with \a s; otherwise returns
\c false.
@@ -4499,8 +4619,7 @@ bool QString::startsWith(const QStringRef &s, Qt::CaseSensitivity cs) const
*/
bool QString::endsWith(const QString &s, Qt::CaseSensitivity cs) const
{
- return qt_ends_with(isNull() ? 0 : unicode(), size(),
- s.isNull() ? 0 : s.unicode(), s.size(), cs);
+ return qt_ends_with(*this, s, cs);
}
/*!
@@ -4516,17 +4635,29 @@ bool QString::endsWith(const QString &s, Qt::CaseSensitivity cs) const
*/
bool QString::endsWith(const QStringRef &s, Qt::CaseSensitivity cs) const
{
- return qt_ends_with(isNull() ? 0 : unicode(), size(),
- s.isNull() ? 0 : s.unicode(), s.size(), cs);
+ return qt_ends_with(*this, s, cs);
}
+#endif // QT_STRINGVIEW_LEVEL < 2
+/*!
+ \fn bool QString::endsWith(QStringView str, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \overload endsWith()
+ Returns \c true if the string ends with the string view \a str;
+ otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (default), the search is case
+ sensitive; otherwise the search is case insensitive.
+
+ \sa startsWith()
+*/
/*!
\overload endsWith()
*/
bool QString::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const
{
- return qt_ends_with(isNull() ? 0 : unicode(), size(), s, cs);
+ return qt_ends_with(*this, s, cs);
}
/*!
@@ -4537,35 +4668,54 @@ bool QString::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const
*/
bool QString::endsWith(QChar c, Qt::CaseSensitivity cs) const
{
- return d->size
- && (cs == Qt::CaseSensitive
- ? d->data()[d->size - 1] == c
- : foldCase(d->data()[d->size - 1]) == foldCase(c.unicode()));
+ return qt_ends_with(*this, c, cs);
}
+static QByteArray qt_convert_to_latin1(QStringView string);
+
QByteArray QString::toLatin1_helper(const QString &string)
{
- if (Q_UNLIKELY(string.isNull()))
- return QByteArray();
-
- return toLatin1_helper(string.constData(), string.length());
+ return qt_convert_to_latin1(string);
}
QByteArray QString::toLatin1_helper(const QChar *data, int length)
{
- QByteArray ba(length, Qt::Uninitialized);
+ return qt_convert_to_latin1(QStringView(data, length));
+}
+
+/*!
+ \since 5.10
+ \relates QStringView
+
+ Returns a Latin-1 representation of \a string as a QByteArray.
+
+ The behavior is undefined if \a string contains non-Latin1 characters.
+
+ \sa QString::toLatin1(), QStringView::toLatin1(), qConvertToUtf8(), qConvertToLocal8Bit(), qConvertToUcs4()
+*/
+QByteArray qConvertToLatin1(QStringView string)
+{
+ return qt_convert_to_latin1(string);
+}
+
+static QByteArray qt_convert_to_latin1(QStringView string)
+{
+ if (Q_UNLIKELY(string.isNull()))
+ return QByteArray();
+
+ QByteArray ba(string.length(), Qt::Uninitialized);
// since we own the only copy, we're going to const_cast the constData;
// that avoids an unnecessary call to detach() and expansion code that will never get used
qt_to_latin1(reinterpret_cast<uchar *>(const_cast<char *>(ba.constData())),
- reinterpret_cast<const ushort *>(data), length);
+ reinterpret_cast<const ushort *>(string.data()), string.length());
return ba;
}
QByteArray QString::toLatin1_helper_inplace(QString &s)
{
if (!s.isDetached())
- return s.toLatin1();
+ return qt_convert_to_latin1(s);
// We can return our own buffer to the caller.
// Conversion to Latin-1 always shrinks the buffer by half.
@@ -4601,7 +4751,7 @@ QByteArray QString::toLatin1_helper_inplace(QString &s)
characters. Those characters may be suppressed or replaced with a
question mark.
- \sa fromLatin1(), toUtf8(), toLocal8Bit(), QTextCodec
+ \sa fromLatin1(), toUtf8(), toLocal8Bit(), QTextCodec, qConvertToLatin1()
*/
/*!
@@ -4617,6 +4767,8 @@ QByteArray QString::toLatin1_helper_inplace(QString &s)
\sa fromAscii(), toLatin1(), toUtf8(), toLocal8Bit(), QTextCodec
*/
+static QByteArray qt_convert_to_local_8bit(QStringView string);
+
/*!
\fn QByteArray QString::toLocal8Bit() const
@@ -4632,21 +4784,47 @@ QByteArray QString::toLatin1_helper_inplace(QString &s)
locale, the returned byte array is undefined. Those characters may be
suppressed or replaced by another.
- \sa fromLocal8Bit(), toLatin1(), toUtf8(), QTextCodec
+ \sa fromLocal8Bit(), toLatin1(), toUtf8(), QTextCodec, qConvertToLocal8Bit()
*/
QByteArray QString::toLocal8Bit_helper(const QChar *data, int size)
{
- if (!data)
+ return qt_convert_to_local_8bit(QStringView(data, size));
+}
+
+static QByteArray qt_convert_to_local_8bit(QStringView string)
+{
+ if (string.isNull())
return QByteArray();
#ifndef QT_NO_TEXTCODEC
QTextCodec *localeCodec = QTextCodec::codecForLocale();
if (localeCodec)
- return localeCodec->fromUnicode(data, size);
+ return localeCodec->fromUnicode(string);
#endif // QT_NO_TEXTCODEC
- return toLatin1_helper(data, size);
+ return qt_convert_to_latin1(string);
}
+/*!
+ \since 5.10
+ \relates QStringView
+
+ Returns a local 8-bit representation of \a string as a QByteArray.
+
+ QTextCodec::codecForLocale() is used to perform the conversion from
+ Unicode. If the locale's encoding could not be determined, this function
+ does the same as qConvertToLatin1().
+
+ The behavior is undefined if \a string contains characters not
+ supported by the locale's 8-bit encoding.
+
+ \sa QString::toLocal8Bit(), QStringView::toLocal8Bit(), qConvertToLatin1(), qConvertToUtf8(), qConvertToUcs4()
+*/
+QByteArray qConvertToLocal8Bit(QStringView string)
+{
+ return qt_convert_to_local_8bit(string);
+}
+
+static QByteArray qt_convert_to_utf8(QStringView str);
/*!
\fn QByteArray QString::toUtf8() const
@@ -4656,18 +4834,41 @@ QByteArray QString::toLocal8Bit_helper(const QChar *data, int size)
UTF-8 is a Unicode codec and can represent all characters in a Unicode
string like QString.
- \sa fromUtf8(), toLatin1(), toLocal8Bit(), QTextCodec
+ \sa fromUtf8(), toLatin1(), toLocal8Bit(), QTextCodec, qConvertToUtf8()
*/
QByteArray QString::toUtf8_helper(const QString &str)
{
+ return qt_convert_to_utf8(str);
+}
+
+static QByteArray qt_convert_to_utf8(QStringView str)
+{
if (str.isNull())
return QByteArray();
- return QUtf8::convertFromUnicode(str.constData(), str.length());
+ return QUtf8::convertFromUnicode(str.data(), str.length());
}
/*!
+ \since 5.10
+ \relates QStringView
+
+ Returns a UTF-8 representation of \a string as a QByteArray.
+
+ UTF-8 is a Unicode codec and can represent all characters in a Unicode
+ string like QStringView.
+
+ \sa QString::toUtf8(), QStringView::toUtf8(), qConvertToLatin1(), qConvertToLocal8Bit(), qConvertToUcs4()
+*/
+QByteArray qConvertToUtf8(QStringView string)
+{
+ return qt_convert_to_utf8(string);
+}
+
+static QVector<uint> qt_convert_to_ucs4(QStringView string);
+
+/*!
\since 4.2
Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>.
@@ -4679,17 +4880,44 @@ QByteArray QString::toUtf8_helper(const QString &str)
The returned vector is not NUL terminated.
- \sa fromUtf8(), toUtf8(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray()
+ \sa fromUtf8(), toUtf8(), toLatin1(), toLocal8Bit(), QTextCodec, fromUcs4(), toWCharArray(), qConvertToUcs4()
*/
QVector<uint> QString::toUcs4() const
{
- QVector<uint> v(length());
- uint *a = v.data();
- int len = toUcs4_helper(d->data(), length(), a);
- v.resize(len);
+ return qt_convert_to_ucs4(*this);
+}
+
+static QVector<uint> qt_convert_to_ucs4(QStringView string)
+{
+ QVector<uint> v(string.length());
+ uint *a = const_cast<uint*>(v.constData());
+ QStringIterator it(string);
+ while (it.hasNext())
+ *a++ = it.next();
+ v.resize(a - v.constData());
return v;
}
+/*!
+ \since 5.10
+ \relates QStringView
+
+ Returns a UCS-4/UTF-32 representation of \a string as a QVector<uint>.
+
+ UCS-4 is a Unicode codec and therefore it is lossless. All characters from
+ this string will be encoded in UCS-4. Any invalid sequence of code units in
+ this string is replaced by the Unicode's replacement character
+ (QChar::ReplacementCharacter, which corresponds to \c{U+FFFD}).
+
+ The returned vector is not NUL terminated.
+
+ \sa QString::toUcs4(), QStringView::toUcs4(), qConvertToLatin1(), qConvertToLocal8Bit(), qConvertToUtf8()
+*/
+QVector<uint> qConvertToUcs4(QStringView string)
+{
+ return qt_convert_to_ucs4(string);
+}
+
QString::Data *QString::fromLatin1_helper(const char *str, int size)
{
Data *d;
@@ -4980,6 +5208,41 @@ QString QString::simplified_helper(QString &str)
return QStringAlgorithms<QString>::simplified_helper(str);
}
+namespace {
+ template <typename StringView>
+ StringView qt_trimmed(StringView s) Q_DECL_NOTHROW
+ {
+ auto begin = s.begin();
+ auto end = s.end();
+ QStringAlgorithms<const StringView>::trimmed_helper_positions(begin, end);
+ return StringView{begin, end};
+ }
+}
+
+/*!
+ \fn QStringView qTrimmed(QStringView s)
+ \fn QLatin1String qTrimmed(QLatin1String s)
+ \relates QStringView
+ \since 5.10
+
+ Returns \a s with whitespace removed from the start and the end.
+
+ Whitespace means any character for which QChar::isSpace() returns
+ \c true. This includes the ASCII characters '\\t', '\\n', '\\v',
+ '\\f', '\\r', and ' '.
+
+ \sa QString::trimmed(), QStringView::trimmed(), QLatin1String::trimmed()
+*/
+QStringView qTrimmed(QStringView s) Q_DECL_NOTHROW
+{
+ return qt_trimmed(s);
+}
+
+QLatin1String qTrimmed(QLatin1String s) Q_DECL_NOTHROW
+{
+ return qt_trimmed(s);
+}
+
/*!
\fn QString QString::trimmed() const
@@ -5057,6 +5320,66 @@ modifiable reference.
*/
/*!
+ \fn QChar QString::front() const
+ \since 5.10
+
+ Returns the first character in the string.
+ Same as \c{at(0)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa back(), at(), operator[]()
+*/
+
+/*!
+ \fn QChar QString::back() const
+ \since 5.10
+
+ Returns the last character in the string.
+ Same as \c{at(size() - 1)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa front(), at(), operator[]()
+*/
+
+/*!
+ \fn QCharRef QString::front()
+ \since 5.10
+
+ Returns a reference to the first character in the string.
+ Same as \c{operator[](0)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa back(), at(), operator[]()
+*/
+
+/*!
+ \fn QCharRef QString::back()
+ \since 5.10
+
+ Returns a reference to the last character in the string.
+ Same as \c{operator[](size() - 1)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa front(), at(), operator[]()
+*/
+
+/*!
\fn void QString::truncate(int position)
Truncates the string at the given \a position index.
@@ -5277,7 +5600,7 @@ QString& QString::fill(QChar ch, int size)
Equivalent to \c {s1 != 0 && compare(s1, s2) == 0}.
- \sa QString::compare()
+ \sa qCompareStrings()
*/
/*!
@@ -5290,7 +5613,7 @@ QString& QString::fill(QChar ch, int size)
For \a s1 != 0, this is equivalent to \c {compare(} \a s1, \a s2
\c {) != 0}. Note that no string is equal to \a s1 being 0.
- \sa QString::compare()
+ \sa qCompareStrings()
*/
/*!
@@ -5306,7 +5629,7 @@ QString& QString::fill(QChar ch, int size)
expect. Consider sorting user-interface strings using the
QString::localeAwareCompare() function.
- \sa QString::compare()
+ \sa qCompareStrings()
*/
/*!
@@ -5322,7 +5645,7 @@ QString& QString::fill(QChar ch, int size)
expect. Consider sorting user-interface strings with
QString::localeAwareCompare().
- \sa QString::compare()
+ \sa qCompareStrings()
*/
/*!
@@ -5337,7 +5660,7 @@ QString& QString::fill(QChar ch, int size)
expect. Consider sorting user-interface strings using the
QString::localeAwareCompare() function.
- \sa QString::compare()
+ \sa qCompareStrings()
*/
/*!
@@ -5418,7 +5741,7 @@ QString& QString::fill(QChar ch, int size)
\snippet qstring/main.cpp 16
- \sa operator==(), operator<(), operator>()
+ \sa qCompareStrings(), operator==(), operator<(), operator>()
*/
/*!
@@ -5428,6 +5751,8 @@ QString& QString::fill(QChar ch, int size)
Performs a comparison of \a s1 and \a s2, using the case
sensitivity setting \a cs.
+
+ \sa qCompareStrings()
*/
/*!
@@ -5438,6 +5763,8 @@ QString& QString::fill(QChar ch, int size)
Performs a comparison of \a s1 and \a s2, using the case
sensitivity setting \a cs.
+
+ \sa qCompareStrings()
*/
@@ -5451,12 +5778,12 @@ QString& QString::fill(QChar ch, int size)
string.
Same as compare(*this, \a other, \a cs).
+
+ \sa qCompareStrings()
*/
int QString::compare(const QString &other, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{
- if (cs == Qt::CaseSensitive)
- return ucstrcmp(constData(), length(), other.constData(), other.length());
- return ucstricmp(d->data(), d->data() + d->size, other.d->data(), other.d->data() + other.d->size);
+ return qt_compare_strings(*this, other, cs);
}
/*!
@@ -5466,11 +5793,11 @@ int QString::compare(const QString &other, Qt::CaseSensitivity cs) const Q_DECL_
int QString::compare_helper(const QChar *data1, int length1, const QChar *data2, int length2,
Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
- if (cs == Qt::CaseSensitive)
- return ucstrcmp(data1, length1, data2, length2);
- const ushort *s1 = reinterpret_cast<const ushort *>(data1);
- const ushort *s2 = reinterpret_cast<const ushort *>(data2);
- return ucstricmp(s1, s1 + length1, s2, s2 + length2);
+ Q_ASSERT(length1 >= 0);
+ Q_ASSERT(length2 >= 0);
+ Q_ASSERT(data1 || length1 == 0);
+ Q_ASSERT(data2 || length2 == 0);
+ return qt_compare_strings(QStringView(data1, length1), QStringView(data2, length2), cs);
}
/*!
@@ -5478,10 +5805,12 @@ int QString::compare_helper(const QChar *data1, int length1, const QChar *data2,
\since 4.2
Same as compare(*this, \a other, \a cs).
+
+ \sa qCompareStrings()
*/
int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
{
- return compare_helper(unicode(), length(), other, cs);
+ return qt_compare_strings(*this, other, cs);
}
/*!
@@ -5491,6 +5820,8 @@ int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const Q_DECL_N
Compares the string reference, \a ref, with the string and returns
an integer less than, equal to, or greater than zero if the string
is less than, equal to, or greater than \a ref.
+
+ \sa qCompareStrings()
*/
/*!
@@ -5500,6 +5831,8 @@ int QString::compare(QLatin1String other, Qt::CaseSensitivity cs) const Q_DECL_N
int QString::compare_helper(const QChar *data1, int length1, const char *data2, int length2,
Qt::CaseSensitivity cs)
{
+ Q_ASSERT(length1 >= 0);
+ Q_ASSERT(data1 || length1 == 0);
if (!data2)
return length1;
if (Q_UNLIKELY(length2 < 0))
@@ -5508,12 +5841,14 @@ int QString::compare_helper(const QChar *data1, int length1, const char *data2,
QVarLengthArray<ushort> s2(length2);
const auto beg = reinterpret_cast<QChar *>(s2.data());
const auto end = QUtf8::convertToUnicode(beg, data2, length2);
- return compare_helper(data1, length1, beg, end - beg, cs);
+ return qt_compare_strings(QStringView(data1, length1), QStringView(beg, end - beg), cs);
}
/*!
\fn int QString::compare(const QString &s1, const QStringRef &s2, Qt::CaseSensitivity cs = Qt::CaseSensitive)
\overload compare()
+
+ \sa qCompareStrings()
*/
/*!
@@ -5523,18 +5858,9 @@ int QString::compare_helper(const QChar *data1, int length1, const char *data2,
int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2,
Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
- const ushort *uc = reinterpret_cast<const ushort *>(data1);
- const ushort *uce = uc + length1;
- const uchar *c = (const uchar *)s2.latin1();
-
- if (!c)
- return length1;
-
- if (cs == Qt::CaseSensitive) {
- return ucstrcmp(data1, length1, c, s2.size());
- } else {
- return ucstricmp(uc, uce, c, c + s2.size());
- }
+ Q_ASSERT(length1 >= 0);
+ Q_ASSERT(data1 || length1 == 0);
+ return qt_compare_strings(QStringView(data1, length1), s2, cs);
}
/*!
@@ -5620,9 +5946,15 @@ Q_GLOBAL_STATIC(QThreadStorage<QCollator>, defaultCollator)
int QString::localeAwareCompare_helper(const QChar *data1, int length1,
const QChar *data2, int length2)
{
+ Q_ASSERT(length1 >= 0);
+ Q_ASSERT(data1 || length1 == 0);
+ Q_ASSERT(length2 >= 0);
+ Q_ASSERT(data2 || length2 == 0);
+
// do the right thing for null and empty
if (length1 == 0 || length2 == 0)
- return ucstrcmp(data1, length1, data2, length2);
+ return qt_compare_strings(QStringView(data1, length1), QStringView(data2, length2),
+ Qt::CaseSensitive);
#if defined(Q_OS_WIN)
# ifndef Q_OS_WINRT
@@ -5663,10 +5995,12 @@ int QString::localeAwareCompare_helper(const QChar *data1, int length1,
// declared in <string.h>
int delta = strcoll(toLocal8Bit_helper(data1, length1).constData(), toLocal8Bit_helper(data2, length2).constData());
if (delta == 0)
- delta = ucstrcmp(data1, length1, data2, length2);
+ delta = qt_compare_strings(QStringView(data1, length1), QStringView(data2, length2),
+ Qt::CaseSensitive);
return delta;
#else
- return ucstrcmp(data1, length1, data2, length2);
+ return qt_compare_strings(QStringView(data1, length1), QStringView(data2, length2),
+ Qt::CaseSensitive);
#endif
}
@@ -6363,7 +6697,7 @@ qlonglong QString::toIntegral_helper(const QChar *data, int len, bool *ok, int b
}
#endif
- return QLocaleData::c()->stringToLongLong(data, len, base, ok, QLocale::RejectGroupSeparator);
+ return QLocaleData::c()->stringToLongLong(QStringView(data, len), base, ok, QLocale::RejectGroupSeparator);
}
@@ -6403,7 +6737,7 @@ qulonglong QString::toIntegral_helper(const QChar *data, uint len, bool *ok, int
}
#endif
- return QLocaleData::c()->stringToUnsLongLong(data, len, base, ok,
+ return QLocaleData::c()->stringToUnsLongLong(QStringView(data, len), base, ok,
QLocale::RejectGroupSeparator);
}
@@ -6605,7 +6939,7 @@ ushort QString::toUShort(bool *ok, int base) const
double QString::toDouble(bool *ok) const
{
- return QLocaleData::c()->stringToDouble(constData(), size(), ok, QLocale::RejectGroupSeparator);
+ return QLocaleData::c()->stringToDouble(*this, ok, QLocale::RejectGroupSeparator);
}
/*!
@@ -7263,10 +7597,10 @@ struct ArgEscapeData
int escape_len; // total length of escape sequences which will be replaced
};
-static ArgEscapeData findArgEscapes(const QString &s)
+static ArgEscapeData findArgEscapes(QStringView s)
{
- const QChar *uc_begin = s.unicode();
- const QChar *uc_end = uc_begin + s.length();
+ const QChar *uc_begin = s.begin();
+ const QChar *uc_end = s.end();
ArgEscapeData d;
@@ -7325,11 +7659,11 @@ static ArgEscapeData findArgEscapes(const QString &s)
return d;
}
-static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int field_width,
- const QString &arg, const QString &larg, QChar fillChar = QLatin1Char(' '))
+static QString replaceArgEscapes(QStringView s, const ArgEscapeData &d, int field_width,
+ QStringView arg, QStringView larg, QChar fillChar)
{
- const QChar *uc_begin = s.unicode();
- const QChar *uc_end = uc_begin + s.length();
+ const QChar *uc_begin = s.begin();
+ const QChar *uc_end = s.end();
int abs_field_width = qAbs(field_width);
int result_len = s.length()
@@ -7393,11 +7727,11 @@ static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int f
}
if (locale_arg) {
- memcpy(rc, larg.unicode(), larg.length()*sizeof(QChar));
+ memcpy(rc, larg.data(), larg.length()*sizeof(QChar));
rc += larg.length();
}
else {
- memcpy(rc, arg.unicode(), arg.length()*sizeof(QChar));
+ memcpy(rc, arg.data(), arg.length()*sizeof(QChar));
rc += arg.length();
}
@@ -7419,6 +7753,7 @@ static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int f
return result;
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Returns a copy of this string with the lowest numbered place marker
replaced by string \a a, i.e., \c %1, \c %2, ..., \c %99.
@@ -7450,17 +7785,86 @@ static QString replaceArgEscapes(const QString &s, const ArgEscapeData &d, int f
*/
QString QString::arg(const QString &a, int fieldWidth, QChar fillChar) const
{
+ return arg(qToStringViewIgnoringNull(a), fieldWidth, fillChar);
+}
+#endif // QT_STRINGVIEW_LEVEL < 2
+
+/*!
+ \overload
+ \since 5.10
+
+ Returns a copy of this string with the lowest-numbered place-marker
+ replaced by string \a a, i.e., \c %1, \c %2, ..., \c %99.
+
+ \a fieldWidth specifies the minimum amount of space that \a a
+ shall occupy. If \a a requires less space than \a fieldWidth, it
+ is padded to \a fieldWidth with character \a fillChar. A positive
+ \a fieldWidth produces right-aligned text. A negative \a fieldWidth
+ produces left-aligned text.
+
+ This example shows how we might create a \c status string for
+ reporting progress while processing a list of files:
+
+ \snippet qstring/main.cpp 11-qstringview
+
+ First, \c arg(i) replaces \c %1. Then \c arg(total) replaces \c
+ %2. Finally, \c arg(fileName) replaces \c %3.
+
+ One advantage of using arg() over asprintf() is that the order of the
+ numbered place markers can change, if the application's strings are
+ translated into other languages, but each arg() will still replace
+ the lowest-numbered unreplaced place-marker, no matter where it
+ appears. Also, if place-marker \c %i appears more than once in the
+ string, arg() replaces all of them.
+
+ If there is no unreplaced place-marker remaining, a warning message
+ is printed and the result is undefined. Place-marker numbers must be
+ in the range 1 to 99.
+*/
+QString QString::arg(QStringView a, int fieldWidth, QChar fillChar) const
+{
ArgEscapeData d = findArgEscapes(*this);
- if (d.occurrences == 0) {
- qWarning("QString::arg: Argument missing: %s, %s", toLocal8Bit().data(),
- a.toLocal8Bit().data());
+ if (Q_UNLIKELY(d.occurrences == 0)) {
+ qWarning("QString::arg: Argument missing: %ls, %ls", qUtf16Printable(*this),
+ qUtf16Printable(a.toString()));
return *this;
}
return replaceArgEscapes(*this, d, fieldWidth, a, a, fillChar);
}
/*!
+ \overload
+ \since 5.10
+
+ Returns a copy of this string with the lowest-numbered place-marker
+ replaced by string \a a, i.e., \c %1, \c %2, ..., \c %99.
+
+ \a fieldWidth specifies the minimum amount of space that \a a
+ shall occupy. If \a a requires less space than \a fieldWidth, it
+ is padded to \a fieldWidth with character \a fillChar. A positive
+ \a fieldWidth produces right-aligned text. A negative \a fieldWidth
+ produces left-aligned text.
+
+ One advantage of using arg() over asprintf() is that the order of the
+ numbered place markers can change, if the application's strings are
+ translated into other languages, but each arg() will still replace
+ the lowest-numbered unreplaced place-marker, no matter where it
+ appears. Also, if place-marker \c %i appears more than once in the
+ string, arg() replaces all of them.
+
+ If there is no unreplaced place-marker remaining, a warning message
+ is printed and the result is undefined. Place-marker numbers must be
+ in the range 1 to 99.
+*/
+QString QString::arg(QLatin1String a, int fieldWidth, QChar fillChar) const
+{
+ QVarLengthArray<ushort> utf16(a.size());
+ qt_from_latin1(utf16.data(), a.data(), a.size());
+ return arg(QStringView(utf16.data(), utf16.size()), fieldWidth, fillChar);
+}
+
+/*!
\fn QString QString::arg(const QString& a1, const QString& a2) const
\overload arg()
@@ -8139,6 +8543,15 @@ bool QString::isRightToLeft() const
Appends the given \a ch character onto the end of this string.
*/
+/*! \fn void QString::shrink_to_fit()
+ \since 5.10
+
+ This function is provided for STL compatibility. It is
+ equivalent to squeeze().
+
+ \sa squeeze()
+*/
+
/*!
\fn std::string QString::toStdString() const
@@ -8316,6 +8729,76 @@ QString &QString::setRawData(const QChar *unicode, int size)
\sa QString, QLatin1Char, {QStringLiteral()}{QStringLiteral}
*/
+/*!
+ \typedef QLatin1String::value_type
+ \since 5.10
+
+ Alias for \c{const char}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1String::difference_type
+ \since 5.10
+
+ Alias for \c{int}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1String::size_type
+ \since 5.10
+
+ Alias for \c{int}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1String::reference
+ \since 5.10
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QLatin1String::iterator
+ \since 5.10
+
+ This typedef provides an STL-style const iterator for QLatin1String.
+
+ QLatin1String does not support mutable iterators, so this is the same
+ as const_iterator.
+
+ \sa const_iterator, reverse_iterator
+*/
+
+/*!
+ \typedef QLatin1String::const_iterator
+ \since 5.10
+
+ This typedef provides an STL-style const iterator for QLatin1String.
+
+ \sa iterator, const_reverse_iterator
+*/
+
+/*!
+ \typedef QLatin1String::reverse_iterator
+ \since 5.10
+
+ This typedef provides an STL-style const reverse iterator for QLatin1String.
+
+ QLatin1String does not support mutable reverse iterators, so this is the
+ same as const_reverse_iterator.
+
+ \sa const_reverse_iterator, iterator
+*/
+
+/*!
+ \typedef QLatin1String::const_reverse_iterator
+ \since 5.10
+
+ This typedef provides an STL-style const reverse iterator for QLatin1String.
+
+ \sa reverse_iterator, const_iterator
+*/
+
/*! \fn QLatin1String::QLatin1String()
\since 5.6
@@ -8344,6 +8827,24 @@ QString &QString::setRawData(const QChar *unicode, int size)
\sa latin1()
*/
+/*!
+ \fn QLatin1String::QLatin1String(const char *first, const char *last)
+ \since 5.10
+
+ Constructs a QLatin1String object that stores \a first with length
+ (\a last - \a first).
+
+ The range \c{[first,last)} must remain valid for the lifetime of
+ this Latin-1 string object.
+
+ Passing \c nullptr as \a first is safe if \a last is \c nullptr,
+ too, and results in a null Latin-1 string.
+
+ The behavior is undefined if \a last precedes \a first, \a first
+ is \c nullptr and \a last is not, or if \c{last - first >
+ INT_MAX}.
+*/
+
/*! \fn QLatin1String::QLatin1String(const QByteArray &str)
Constructs a QLatin1String object that stores \a str.
@@ -8370,6 +8871,24 @@ QString &QString::setRawData(const QChar *unicode, int size)
Returns the size of the Latin-1 string stored in this object.
*/
+/*! \fn bool QLatin1String::isNull() const
+ \since 5.10
+
+ Returns whether the Latin-1 string stored in this object is null
+ (\c{data() == nullptr}) or not.
+
+ \sa isEmpty(), data()
+*/
+
+/*! \fn bool QLatin1String::isEmpty() const
+ \since 5.10
+
+ Returns whether the Latin-1 string stored in this object is empty
+ (\c{size() == 0}) or not.
+
+ \sa isNull(), size()
+*/
+
/*! \fn QLatin1Char QLatin1String::at(int pos) const
\since 5.8
@@ -8392,6 +8911,167 @@ QString &QString::setRawData(const QChar *unicode, int size)
\sa at()
*/
+/*!
+ \fn QLatin1Char QLatin1String::front() const
+ \since 5.10
+
+ Returns the first character in the string.
+ Same as \c{at(0)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa back(), at(), operator[]()
+*/
+
+/*!
+ \fn QLatin1Char QLatin1String::back() const
+ \since 5.10
+
+ Returns the last character in the string.
+ Same as \c{at(size() - 1)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa front(), at(), operator[]()
+*/
+
+/*!
+ \fn bool QLatin1String::startsWith(QStringView str, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \fn bool QLatin1String::startsWith(QLatin1String l1, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \fn bool QLatin1String::startsWith(QChar ch) const
+ \since 5.10
+ \fn bool QLatin1String::startsWith(QChar ch, Qt::CaseSensitivity cs) const
+ \since 5.10
+
+ Returns \c true if this Latin-1 string starts with string-view \a str,
+ Latin-1 string \a l1, or character \a ch, respectively;
+ otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
+ otherwise the search is case-insensitive.
+
+ \sa endsWith(), qStartsWith()
+*/
+
+/*!
+ \fn bool QLatin1String::endsWith(QStringView str, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \fn bool QLatin1String::endsWith(QLatin1String l1, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \fn bool QLatin1String::endsWith(QChar ch) const
+ \since 5.10
+ \fn bool QLatin1String::endsWith(QChar ch, Qt::CaseSensitivity cs) const
+ \since 5.10
+
+ Returns \c true if this Latin-1 string ends with string-view \a str,
+ Latin-1 string \a l1, or character \a ch, respectively;
+ otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
+ otherwise the search is case-insensitive.
+
+ \sa startsWith(), qEndsWith()
+*/
+
+/*!
+ \fn QLatin1String::const_iterator QLatin1String::begin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character in
+ the string.
+
+ This function is provided for STL compatibility.
+
+ \sa end(), cbegin(), rbegin(), data()
+*/
+
+/*!
+ \fn QLatin1String::const_iterator QLatin1String::cbegin() const
+ \since 5.10
+
+ Same as begin().
+
+ This function is provided for STL compatibility.
+
+ \sa cend(), begin(), crbegin(), data()
+*/
+
+/*!
+ \fn QLatin1String::const_iterator QLatin1String::end() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ character after the last character in the list.
+
+ This function is provided for STL compatibility.
+
+ \sa begin(), cend(), rend()
+*/
+
+/*! \fn QLatin1String::const_iterator QLatin1String::cend() const
+ \since 5.10
+
+ Same as end().
+
+ This function is provided for STL compatibility.
+
+ \sa cbegin(), end(), crend()
+*/
+
+/*!
+ \fn QLatin1String::const_reverse_iterator QLatin1String::rbegin() const
+ \since 5.10
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
+ character in the string, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rend(), crbegin(), begin()
+*/
+
+/*!
+ \fn QLatin1String::const_reverse_iterator QLatin1String::crbegin() const
+ \since 5.10
+
+ Same as rbegin().
+
+ This function is provided for STL compatibility.
+
+ \sa crend(), rbegin(), cbegin()
+*/
+
+/*!
+ \fn QLatin1String::const_reverse_iterator QLatin1String::rend() const
+ \since 5.10
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
+ the last character in the string, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rbegin(), crend(), end()
+*/
+
+/*!
+ \fn QLatin1String::const_reverse_iterator QLatin1String::crend() const
+ \since 5.10
+
+ Same as rend().
+
+ This function is provided for STL compatibility.
+
+ \sa crbegin(), rend(), cend()
+*/
+
/*! \fn QLatin1String QLatin1String::mid(int start) const
\since 5.8
@@ -8401,7 +9081,7 @@ QString &QString::setRawData(const QChar *unicode, int size)
\note This function performs no error checking.
The behavior is undefined when \a start < 0 or \a start > size().
- \sa left(), right()
+ \sa left(), right(), chopped(), chop(), truncate()
*/
/*! \fn QLatin1String QLatin1String::mid(int start, int length) const
@@ -8415,7 +9095,7 @@ QString &QString::setRawData(const QChar *unicode, int size)
The behavior is undefined when \a start < 0, \a length < 0,
or \a start + \a length > size().
- \sa left(), right()
+ \sa left(), right(), chopped(), chop(), truncate()
*/
/*! \fn QLatin1String QLatin1String::left(int length) const
@@ -8427,7 +9107,7 @@ QString &QString::setRawData(const QChar *unicode, int size)
\note This function performs no error checking.
The behavior is undefined when \a length < 0 or \a length > size().
- \sa mid(), right()
+ \sa mid(), right(), chopped(), chop(), truncate()
*/
/*! \fn QLatin1String QLatin1String::right(int length) const
@@ -8439,7 +9119,60 @@ QString &QString::setRawData(const QChar *unicode, int size)
\note This function performs no error checking.
The behavior is undefined when \a length < 0 or \a length > size().
- \sa mid(), left()
+ \sa mid(), left(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QLatin1String QLatin1String::chopped(int length) const
+ \since 5.10
+
+ Returns the substring of length size() - \a length starting at the
+ beginning of this object.
+
+ Same as \c{left(size() - length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa mid(), left(), right(), chop(), truncate()
+*/
+
+/*!
+ \fn void QLatin1String::truncate(int length)
+ \since 5.10
+
+ Truncates this string to length \a length.
+
+ Same as \c{*this = left(length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa mid(), left(), right(), chopped(), chop()
+*/
+
+/*!
+ \fn void QLatin1String::chop(int length)
+ \since 5.10
+
+ Truncates this string by \a length characters.
+
+ Same as \c{*this = left(size() - length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa mid(), left(), right(), chopped(), truncate()
+*/
+
+/*!
+ \fn QLatin1String QLatin1String::trimmed() const
+ \since 5.10
+
+ Strips leading and trailing whitespace and returns the result.
+
+ Whitespace means any character for which QChar::isSpace() returns
+ \c true. This includes the ASCII characters '\\t', '\\n', '\\v',
+ '\\f', '\\r', and ' '.
+
+ \sa qTrimmed()
*/
/*! \fn bool QLatin1String::operator==(const QString &other) const
@@ -9137,8 +9870,8 @@ QString QStringRef::toString() const {
returns \c false.
*/
bool operator==(const QStringRef &s1,const QStringRef &s2) Q_DECL_NOTHROW
-{ return (s1.size() == s2.size() &&
- qMemEquals((const ushort *)s1.unicode(), (const ushort *)s2.unicode(), s1.size()));
+{
+ return s1.size() == s2.size() && qt_compare_strings(s1, s2, Qt::CaseSensitive) == 0;
}
/*! \relates QStringRef
@@ -9147,8 +9880,8 @@ bool operator==(const QStringRef &s1,const QStringRef &s2) Q_DECL_NOTHROW
returns \c false.
*/
bool operator==(const QString &s1,const QStringRef &s2) Q_DECL_NOTHROW
-{ return (s1.size() == s2.size() &&
- qMemEquals((const ushort *)s1.unicode(), (const ushort *)s2.unicode(), s1.size()));
+{
+ return s1.size() == s2.size() && qt_compare_strings(s1, s2, Qt::CaseSensitive) == 0;
}
/*! \relates QStringRef
@@ -9161,10 +9894,7 @@ bool operator==(QLatin1String s1, const QStringRef &s2) Q_DECL_NOTHROW
if (s1.size() != s2.size())
return false;
- const uchar *c = reinterpret_cast<const uchar *>(s1.latin1());
- if (!c)
- return s2.isEmpty();
- return ucstrncmp(s2.unicode(), c, s2.size()) == 0;
+ return qt_compare_strings(s2, s1, Qt::CaseSensitive) == 0;
}
/*!
@@ -9180,7 +9910,7 @@ bool operator==(QLatin1String s1, const QStringRef &s2) Q_DECL_NOTHROW
*/
bool operator<(const QStringRef &s1,const QStringRef &s2) Q_DECL_NOTHROW
{
- return ucstrcmp(s1.constData(), s1.length(), s2.constData(), s2.length()) < 0;
+ return qt_compare_strings(s1, s2, Qt::CaseSensitive) < 0;
}
/*!\fn bool operator<=(const QStringRef &s1,const QStringRef &s2)
@@ -9247,6 +9977,36 @@ bool operator<(const QStringRef &s1,const QStringRef &s2) Q_DECL_NOTHROW
*/
/*!
+ \fn QChar QStringRef::front() const
+ \since 5.10
+
+ Returns the first character in the string.
+ Same as \c{at(0)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa back(), at(), operator[]()
+*/
+
+/*!
+ \fn QChar QStringRef::back() const
+ \since 5.10
+
+ Returns the last character in the string.
+ Same as \c{at(size() - 1)}.
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string constitutes
+ undefined behavior.
+
+ \sa front(), at(), operator[]()
+*/
+
+/*!
\fn void QStringRef::clear()
Clears the contents of the string reference by making it null and empty.
@@ -9411,6 +10171,8 @@ QStringRef QStringRef::appendTo(QString *string) const
If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
otherwise the comparison is case insensitive.
+
+ \sa qCompareStrings()
*/
/*!
@@ -9424,6 +10186,8 @@ QStringRef QStringRef::appendTo(QString *string) const
If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
otherwise the comparison is case insensitive.
+
+ \sa qCompareStrings()
*/
/*!
@@ -9437,6 +10201,8 @@ QStringRef QStringRef::appendTo(QString *string) const
If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
otherwise the comparison is case insensitive.
+
+ \sa qCompareStrings()
*/
/*!
@@ -9453,7 +10219,7 @@ QStringRef QStringRef::appendTo(QString *string) const
Equivalent to \c {compare(*this, other, cs)}.
- \sa QString::compare()
+ \sa qCompareStrings()
*/
/*!
@@ -9470,7 +10236,7 @@ QStringRef QStringRef::appendTo(QString *string) const
Equivalent to \c {compare(*this, other, cs)}.
- \sa QString::compare()
+ \sa qCompareStrings()
*/
/*!
@@ -9487,7 +10253,7 @@ QStringRef QStringRef::appendTo(QString *string) const
Equivalent to \c {compare(*this, other, cs)}.
- \sa QString::compare()
+ \sa qCompareStrings()
*/
/*!
@@ -9505,7 +10271,7 @@ QStringRef QStringRef::appendTo(QString *string) const
Equivalent to \c {compare(*this, other, cs)}.
- \sa QString::compare()
+ \sa qCompareStrings()
*/
/*!
@@ -9597,7 +10363,7 @@ QString &QString::append(const QStringRef &str)
If \a n is greater than or equal to size(), or less than zero,
a reference to the entire string is returned.
- \sa right(), mid(), startsWith()
+ \sa right(), mid(), startsWith(), chopped(), chop(), truncate()
*/
QStringRef QStringRef::left(int n) const
{
@@ -9634,7 +10400,7 @@ QStringRef QString::leftRef(int n) const
If \a n is greater than or equal to size(), or less than zero,
a reference to the entire string is returned.
- \sa left(), mid(), endsWith()
+ \sa left(), mid(), endsWith(), chopped(), chop(), truncate()
*/
QStringRef QStringRef::right(int n) const
{
@@ -9676,7 +10442,7 @@ QStringRef QString::rightRef(int n) const
function returns all characters from the specified \a position
onwards.
- \sa left(), right()
+ \sa left(), right(), chopped(), chop(), truncate()
*/
QStringRef QStringRef::mid(int pos, int n) const
{
@@ -9696,6 +10462,18 @@ QStringRef QStringRef::mid(int pos, int n) const
}
/*!
+ \fn QStringRef::chopped(int len) const
+ \since 5.10
+
+ Returns a substring reference to the size() - \a len leftmost characters
+ of this string.
+
+ \note The behavior is undefined if \a len is negative or greater than size().
+
+ \sa endsWith(), left(), right(), mid(), chop(), truncate()
+*/
+
+/*!
\since 4.4
Returns a substring reference to \a n characters of this string,
@@ -10011,8 +10789,7 @@ bool QStringRef::isRightToLeft() const
*/
bool QStringRef::startsWith(const QString &str, Qt::CaseSensitivity cs) const
{
- return qt_starts_with(isNull() ? 0 : unicode(), size(),
- str.isNull() ? 0 : str.unicode(), str.size(), cs);
+ return qt_starts_with(*this, str, cs);
}
/*!
@@ -10022,18 +10799,24 @@ bool QStringRef::startsWith(const QString &str, Qt::CaseSensitivity cs) const
*/
bool QStringRef::startsWith(QLatin1String str, Qt::CaseSensitivity cs) const
{
- return qt_starts_with(isNull() ? 0 : unicode(), size(), str, cs);
+ return qt_starts_with(*this, str, cs);
}
/*!
+ \fn bool QStringRef::startsWith(QStringView str, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \overload startsWith()
+ \sa QString::startsWith(), endsWith()
+*/
+
+/*!
\since 4.8
\overload startsWith()
\sa QString::startsWith(), endsWith()
*/
bool QStringRef::startsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
{
- return qt_starts_with(isNull() ? 0 : unicode(), size(),
- str.isNull() ? 0 : str.unicode(), str.size(), cs);
+ return qt_starts_with(*this, str, cs);
}
/*!
@@ -10050,14 +10833,7 @@ bool QStringRef::startsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
*/
bool QStringRef::startsWith(QChar ch, Qt::CaseSensitivity cs) const
{
- if (!isEmpty()) {
- const ushort *data = reinterpret_cast<const ushort*>(unicode());
- return (cs == Qt::CaseSensitive
- ? data[0] == ch
- : foldCase(data[0]) == foldCase(ch.unicode()));
- } else {
- return false;
- }
+ return qt_starts_with(*this, ch, cs);
}
/*!
@@ -10072,8 +10848,7 @@ bool QStringRef::startsWith(QChar ch, Qt::CaseSensitivity cs) const
*/
bool QStringRef::endsWith(const QString &str, Qt::CaseSensitivity cs) const
{
- return qt_ends_with(isNull() ? 0 : unicode(), size(),
- str.isNull() ? 0 : str.unicode(), str.size(), cs);
+ return qt_ends_with(*this, str, cs);
}
/*!
@@ -10090,15 +10865,7 @@ bool QStringRef::endsWith(const QString &str, Qt::CaseSensitivity cs) const
*/
bool QStringRef::endsWith(QChar ch, Qt::CaseSensitivity cs) const
{
- if (!isEmpty()) {
- const ushort *data = reinterpret_cast<const ushort*>(unicode());
- const int size = length();
- return (cs == Qt::CaseSensitive
- ? data[size - 1] == ch
- : foldCase(data[size - 1]) == foldCase(ch.unicode()));
- } else {
- return false;
- }
+ return qt_ends_with(*this, ch, cs);
}
/*!
@@ -10108,18 +10875,24 @@ bool QStringRef::endsWith(QChar ch, Qt::CaseSensitivity cs) const
*/
bool QStringRef::endsWith(QLatin1String str, Qt::CaseSensitivity cs) const
{
- return qt_ends_with(isNull() ? 0 : unicode(), size(), str, cs);
+ return qt_ends_with(*this, str, cs);
}
/*!
+ \fn bool QStringRef::endsWith(QStringView str, Qt::CaseSensitivity cs) const
+ \since 5.10
+ \overload endsWith()
+ \sa QString::endsWith(), startsWith()
+*/
+
+/*!
\since 4.8
\overload endsWith()
\sa QString::endsWith(), endsWith()
*/
bool QStringRef::endsWith(const QStringRef &str, Qt::CaseSensitivity cs) const
{
- return qt_ends_with(isNull() ? 0 : unicode(), size(),
- str.isNull() ? 0 : str.unicode(), str.size(), cs);
+ return qt_ends_with(*this, str, cs);
}
@@ -10254,101 +11027,148 @@ static inline int qt_find_latin1_string(const QChar *haystack, int size,
reinterpret_cast<const QChar*>(s.constData()), len, cs);
}
-static inline bool qt_starts_with(const QChar *haystack, int haystackLen,
- const QChar *needle, int needleLen, Qt::CaseSensitivity cs)
+template <typename Haystack, typename Needle>
+bool qt_starts_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
- if (!haystack)
- return !needle;
+ if (haystack.isNull())
+ return needle.isNull(); // historical behavior, consider changing in ### Qt 6.
+ const auto haystackLen = haystack.size();
+ const auto needleLen = needle.size();
if (haystackLen == 0)
return needleLen == 0;
if (needleLen > haystackLen)
return false;
- const ushort *h = reinterpret_cast<const ushort*>(haystack);
- const ushort *n = reinterpret_cast<const ushort*>(needle);
+ return qt_compare_strings(haystack.left(needleLen), needle, cs) == 0;
+}
- if (cs == Qt::CaseSensitive) {
- return qMemEquals(h, n, needleLen);
- } else {
- uint last = 0;
- uint olast = 0;
- for (int i = 0; i < needleLen; ++i)
- if (foldCase(h[i], last) != foldCase(n[i], olast))
- return false;
- }
- return true;
+static inline bool qt_starts_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
+{
+ return qt_starts_with_impl(haystack, needle, cs);
}
-static inline bool qt_starts_with(const QChar *haystack, int haystackLen,
- QLatin1String needle, Qt::CaseSensitivity cs)
+static inline bool qt_starts_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
{
- if (!haystack)
- return !needle.latin1();
- if (haystackLen == 0)
- return !needle.latin1() || *needle.latin1() == 0;
- const int slen = needle.size();
- if (slen > haystackLen)
- return false;
- const ushort *data = reinterpret_cast<const ushort*>(haystack);
- const uchar *latin = reinterpret_cast<const uchar*>(needle.latin1());
- if (cs == Qt::CaseSensitive) {
- return ucstrncmp(haystack, latin, slen) == 0;
- } else {
- for (int i = 0; i < slen; ++i)
- if (foldCase(data[i]) != foldCase((ushort)latin[i]))
- return false;
- }
- return true;
+ return qt_starts_with_impl(haystack, needle, cs);
}
-static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
- const QChar *needle, int needleLen, Qt::CaseSensitivity cs)
+static inline bool qt_starts_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs)
{
- if (!haystack)
- return !needle;
+ return haystack.size()
+ && (cs == Qt::CaseSensitive ? haystack.front() == needle
+ : foldCase(haystack.front()) == foldCase(needle));
+}
+
+/*!
+ \fn bool qStartsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
+ \since 5.10
+ \fn bool qStartsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
+ \since 5.10
+ \fn bool qStartsWith(QLatin1String haystack, QStringview needle, Qt::CaseSensitivity cs)
+ \since 5.10
+ \fn bool qStartsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs)
+ \since 5.10
+ \relates QStringView
+
+ Returns \c true if \a haystack starts with \a needle,
+ otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
+ otherwise the search is case-insensitive.
+
+ \sa qEndsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1String::endsWith()
+*/
+
+bool qStartsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_starts_with_impl(haystack, needle, cs);
+}
+
+bool qStartsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_starts_with_impl(haystack, needle, cs);
+}
+
+bool qStartsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_starts_with_impl(haystack, needle, cs);
+}
+
+bool qStartsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_starts_with_impl(haystack, needle, cs);
+}
+
+template <typename Haystack, typename Needle>
+bool qt_ends_with_impl(Haystack haystack, Needle needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ if (haystack.isNull())
+ return needle.isNull(); // historical behavior, consider changing in ### Qt 6.
+ const auto haystackLen = haystack.size();
+ const auto needleLen = needle.size();
if (haystackLen == 0)
return needleLen == 0;
- const int pos = haystackLen - needleLen;
- if (pos < 0)
+ if (haystackLen < needleLen)
return false;
- const ushort *h = reinterpret_cast<const ushort*>(haystack);
- const ushort *n = reinterpret_cast<const ushort*>(needle);
+ return qt_compare_strings(haystack.right(needleLen), needle, cs) == 0;
+}
- if (cs == Qt::CaseSensitive) {
- return qMemEquals(h + pos, n, needleLen);
- } else {
- uint last = 0;
- uint olast = 0;
- for (int i = 0; i < needleLen; i++)
- if (foldCase(h[pos+i], last) != foldCase(n[i], olast))
- return false;
- }
- return true;
+static inline bool qt_ends_with(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
+{
+ return qt_ends_with_impl(haystack, needle, cs);
+}
+
+static inline bool qt_ends_with(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
+{
+ return qt_ends_with_impl(haystack, needle, cs);
}
+static inline bool qt_ends_with(QStringView haystack, QChar needle, Qt::CaseSensitivity cs)
+{
+ return haystack.size()
+ && (cs == Qt::CaseSensitive ? haystack.back() == needle
+ : foldCase(haystack.back()) == foldCase(needle));
+}
+
+/*!
+ \fn bool qEndsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs)
+ \since 5.10
+ \fn bool qEndsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs)
+ \since 5.10
+ \fn bool qEndsWith(QLatin1String haystack, QStringview needle, Qt::CaseSensitivity cs)
+ \since 5.10
+ \fn bool qEndsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs)
+ \since 5.10
+ \relates QStringView
-static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
- QLatin1String needle, Qt::CaseSensitivity cs)
+ Returns \c true if \a haystack ends with \a needle,
+ otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
+ otherwise the search is case-insensitive.
+
+ \sa qEndsWith(), QString::endsWith(), QStringView::endsWith(), QLatin1String::endsWith()
+*/
+
+bool qEndsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
{
- if (!haystack)
- return !needle.latin1();
- if (haystackLen == 0)
- return !needle.latin1() || *needle.latin1() == 0;
- const int slen = needle.size();
- int pos = haystackLen - slen;
- if (pos < 0)
- return false;
- const uchar *latin = reinterpret_cast<const uchar*>(needle.latin1());
- const ushort *data = reinterpret_cast<const ushort*>(haystack);
- if (cs == Qt::CaseSensitive) {
- return ucstrncmp(haystack + pos, latin, slen) == 0;
- } else {
- for (int i = 0; i < slen; i++)
- if (foldCase(data[pos+i]) != foldCase((ushort)latin[i]))
- return false;
- }
- return true;
+ return qt_ends_with_impl(haystack, needle, cs);
+}
+
+bool qEndsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_ends_with_impl(haystack, needle, cs);
+}
+
+bool qEndsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_ends_with_impl(haystack, needle, cs);
+}
+
+bool qEndsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs) Q_DECL_NOTHROW
+{
+ return qt_ends_with_impl(haystack, needle, cs);
}
/*!
@@ -10364,9 +11184,7 @@ static inline bool qt_ends_with(const QChar *haystack, int haystackLen,
*/
QByteArray QStringRef::toLatin1() const
{
- if (isNull())
- return QByteArray();
- return QString::toLatin1_helper(unicode(), length());
+ return qt_convert_to_latin1(*this);
}
/*!
@@ -10403,14 +11221,7 @@ QByteArray QStringRef::toLatin1() const
*/
QByteArray QStringRef::toLocal8Bit() const
{
-#ifndef QT_NO_TEXTCODEC
- if (!isNull()) {
- QTextCodec *localeCodec = QTextCodec::codecForLocale();
- if (localeCodec)
- return localeCodec->fromUnicode(unicode(), length());
- }
-#endif // QT_NO_TEXTCODEC
- return toLatin1();
+ return qt_convert_to_local_8bit(*this);
}
/*!
@@ -10425,10 +11236,7 @@ QByteArray QStringRef::toLocal8Bit() const
*/
QByteArray QStringRef::toUtf8() const
{
- if (isNull())
- return QByteArray();
-
- return QUtf8::convertFromUnicode(constData(), length());
+ return qt_convert_to_utf8(*this);
}
/*!
@@ -10447,11 +11255,7 @@ QByteArray QStringRef::toUtf8() const
*/
QVector<uint> QStringRef::toUcs4() const
{
- QVector<uint> v(length());
- uint *a = v.data();
- int len = QString::toUcs4_helper(reinterpret_cast<const ushort *>(unicode()), length(), a);
- v.resize(len);
- return v;
+ return qt_convert_to_ucs4(*this);
}
/*!
@@ -10475,8 +11279,6 @@ QStringRef QStringRef::trimmed() const
QStringAlgorithms<const QStringRef>::trimmed_helper_positions(begin, end);
if (begin == cbegin() && end == cend())
return *this;
- if (begin == end)
- return QStringRef();
int position = m_position + (begin - cbegin());
return QStringRef(m_string, position, end - begin);
}
@@ -10709,7 +11511,7 @@ ushort QStringRef::toUShort(bool *ok, int base) const
double QStringRef::toDouble(bool *ok) const
{
- return QLocaleData::c()->stringToDouble(constData(), size(), ok, QLocale::RejectGroupSeparator);
+ return QLocaleData::c()->stringToDouble(*this, ok, QLocale::RejectGroupSeparator);
}
/*!
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 88ba4a3fb5..a3e100c568 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -49,6 +49,9 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qrefcount.h>
#include <QtCore/qnamespace.h>
+#include <QtCore/qstringliteral.h>
+#include <QtCore/qstringalgorithms.h>
+#include <QtCore/qstringview.h>
#include <string>
#include <iterator>
@@ -90,6 +93,8 @@ class QLatin1String
public:
Q_DECL_CONSTEXPR inline QLatin1String() Q_DECL_NOTHROW : m_size(0), m_data(Q_NULLPTR) {}
Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) Q_DECL_NOTHROW : m_size(s ? int(strlen(s)) : 0), m_data(s) {}
+ Q_DECL_CONSTEXPR explicit QLatin1String(const char *f, const char *l)
+ : QLatin1String(f, int(l - f)) {}
Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) Q_DECL_NOTHROW : m_size(sz), m_data(s) {}
inline explicit QLatin1String(const QByteArray &s) Q_DECL_NOTHROW : m_size(int(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {}
@@ -97,17 +102,72 @@ public:
Q_DECL_CONSTEXPR int size() const Q_DECL_NOTHROW { return m_size; }
Q_DECL_CONSTEXPR const char *data() const Q_DECL_NOTHROW { return m_data; }
- Q_DECL_CONSTEXPR QLatin1Char at(int i) const { return QLatin1Char(m_data[i]); }
+ Q_DECL_CONSTEXPR bool isNull() const Q_DECL_NOTHROW { return !data(); }
+ Q_DECL_CONSTEXPR bool isEmpty() const Q_DECL_NOTHROW { return !size(); }
+
+ Q_DECL_CONSTEXPR QLatin1Char at(int i) const
+ { return Q_ASSERT(i >= 0), Q_ASSERT(i < size()), QLatin1Char(m_data[i]); }
Q_DECL_CONSTEXPR QLatin1Char operator[](int i) const { return at(i); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char front() const { return at(0); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char back() const { return at(size() - 1); }
+
+ Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return qStartsWith(*this, s, cs); }
+ Q_REQUIRED_RESULT bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return qStartsWith(*this, s, cs); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool startsWith(QChar c) const Q_DECL_NOTHROW
+ { return !isEmpty() && front() == c; }
+ Q_REQUIRED_RESULT inline bool startsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+ { return qStartsWith(*this, QStringView(&c, 1), cs); }
+
+ Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return qEndsWith(*this, s, cs); }
+ Q_REQUIRED_RESULT bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return qEndsWith(*this, s, cs); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool endsWith(QChar c) const Q_DECL_NOTHROW
+ { return !isEmpty() && back() == c; }
+ Q_REQUIRED_RESULT inline bool endsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+ { return qEndsWith(*this, QStringView(&c, 1), cs); }
+
+ using value_type = const char;
+ using reference = value_type&;
+ using const_reference = reference;
+ using iterator = value_type*;
+ using const_iterator = iterator;
+ using difference_type = int; // violates Container concept requirements
+ using size_type = int; // violates Container concept requirements
+
+ Q_DECL_CONSTEXPR const_iterator begin() const Q_DECL_NOTHROW { return data(); }
+ Q_DECL_CONSTEXPR const_iterator cbegin() const Q_DECL_NOTHROW { return data(); }
+ Q_DECL_CONSTEXPR const_iterator end() const Q_DECL_NOTHROW { return data() + size(); }
+ Q_DECL_CONSTEXPR const_iterator cend() const Q_DECL_NOTHROW { return data() + size(); }
+
+ using reverse_iterator = std::reverse_iterator<iterator>;
+ using const_reverse_iterator = reverse_iterator;
+
+ const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
+ const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
+ const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ const_reverse_iterator crend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+
Q_DECL_CONSTEXPR QLatin1String mid(int pos) const
- { return QLatin1String(m_data + pos, m_size - pos); }
+ { return Q_ASSERT(pos >= 0), Q_ASSERT(pos <= size()), QLatin1String(m_data + pos, m_size - pos); }
Q_DECL_CONSTEXPR QLatin1String mid(int pos, int n) const
- { return QLatin1String(m_data + pos, n); }
+ { return Q_ASSERT(pos >= 0), Q_ASSERT(n >= 0), Q_ASSERT(pos + n <= size()), QLatin1String(m_data + pos, n); }
Q_DECL_CONSTEXPR QLatin1String left(int n) const
- { return QLatin1String(m_data, n); }
+ { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data, n); }
Q_DECL_CONSTEXPR QLatin1String right(int n) const
- { return QLatin1String(m_data + m_size - n, n); }
+ { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data + m_size - n, n); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1String chopped(int n) const
+ { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QLatin1String(m_data, m_size - n); }
+
+ Q_DECL_RELAXED_CONSTEXPR void chop(int n)
+ { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size -= n; }
+ Q_DECL_RELAXED_CONSTEXPR void truncate(int n)
+ { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size = n; }
+
+ Q_REQUIRED_RESULT QLatin1String trimmed() const Q_DECL_NOTHROW { return qTrimmed(*this); }
inline bool operator==(const QString &s) const Q_DECL_NOTHROW;
inline bool operator!=(const QString &s) const Q_DECL_NOTHROW;
@@ -141,73 +201,13 @@ Q_DECLARE_TYPEINFO(QLatin1String, Q_MOVABLE_TYPE);
// Qt 4.x compatibility
typedef QLatin1String QLatin1Literal;
-
-typedef QTypedArrayData<ushort> QStringData;
-
-#if defined(Q_OS_WIN) && !defined(Q_COMPILER_UNICODE_STRINGS)
-// fall back to wchar_t if the a Windows compiler does not
-// support Unicode string literals, assuming wchar_t is 2 bytes
-// on that platform (sanity-checked by static_assert further below)
-
-#if defined(Q_CC_MSVC)
-# define QT_UNICODE_LITERAL_II(str) L##str
-#else
-# define QT_UNICODE_LITERAL_II(str) L"" str
-#endif
-typedef wchar_t qunicodechar;
-
-#else
-// all our supported compilers support Unicode string literals,
-// even if their Q_COMPILER_UNICODE_STRING has been revoked due
-// to lacking stdlib support. But QStringLiteral only needs the
-// core language feature, so just use u"" here unconditionally:
-
-#define QT_UNICODE_LITERAL_II(str) u"" str
-typedef char16_t qunicodechar;
-
-#endif
-
-Q_STATIC_ASSERT_X(sizeof(qunicodechar) == 2,
- "qunicodechar must typedef an integral type of size 2");
-
-#define QT_UNICODE_LITERAL(str) QT_UNICODE_LITERAL_II(str)
-#define QStringLiteral(str) \
- ([]() Q_DECL_NOEXCEPT -> QString { \
- enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
- static const QStaticStringData<Size> qstring_literal = { \
- Q_STATIC_STRING_DATA_HEADER_INITIALIZER(Size), \
- QT_UNICODE_LITERAL(str) }; \
- QStringDataPtr holder = { qstring_literal.data_ptr() }; \
- const QString qstring_literal_temp(holder); \
- return qstring_literal_temp; \
- }()) \
- /**/
-
-#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
- { Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, offset } \
- /**/
-
-#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER(size) \
- Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, sizeof(QStringData)) \
- /**/
-
-template <int N>
-struct QStaticStringData
-{
- QArrayData str;
- qunicodechar data[N + 1];
-
- QStringData *data_ptr() const
- {
- Q_ASSERT(str.ref.isStatic());
- return const_cast<QStringData *>(static_cast<const QStringData*>(&str));
- }
-};
-
-struct QStringDataPtr
-{
- QStringData *ptr;
-};
+//
+// QStringView members that require QLatin1String:
+//
+bool QStringView::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+{ return qStartsWith(*this, s, cs); }
+bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+{ return qEndsWith(*this, s, cs); }
class Q_CORE_EXPORT QString
{
@@ -261,6 +261,11 @@ public:
const QChar operator[](uint i) const;
QCharRef operator[](uint i);
+ Q_REQUIRED_RESULT inline QChar front() const { return at(0); }
+ Q_REQUIRED_RESULT inline QCharRef front();
+ Q_REQUIRED_RESULT inline QChar back() const { return at(size() - 1); }
+ Q_REQUIRED_RESULT inline QCharRef back();
+
Q_REQUIRED_RESULT QString arg(qlonglong a, int fieldwidth=0, int base=10,
QChar fillChar = QLatin1Char(' ')) const;
Q_REQUIRED_RESULT QString arg(qulonglong a, int fieldwidth=0, int base=10,
@@ -283,8 +288,14 @@ public:
QChar fillChar = QLatin1Char(' ')) const;
Q_REQUIRED_RESULT QString arg(QChar a, int fieldWidth = 0,
QChar fillChar = QLatin1Char(' ')) const;
+#if QT_STRINGVIEW_LEVEL < 2
Q_REQUIRED_RESULT QString arg(const QString &a, int fieldWidth = 0,
QChar fillChar = QLatin1Char(' ')) const;
+#endif
+ Q_REQUIRED_RESULT QString arg(QStringView a, int fieldWidth = 0,
+ QChar fillChar = QLatin1Char(' ')) const;
+ Q_REQUIRED_RESULT QString arg(QLatin1String a, int fieldWidth = 0,
+ QChar fillChar = QLatin1Char(' ')) const;
Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2) const;
Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2, const QString &a3) const;
Q_REQUIRED_RESULT QString arg(const QString &a1, const QString &a2, const QString &a3,
@@ -366,16 +377,29 @@ public:
Q_REQUIRED_RESULT QString left(int n) const;
Q_REQUIRED_RESULT QString right(int n) const;
Q_REQUIRED_RESULT QString mid(int position, int n = -1) const;
+ Q_REQUIRED_RESULT QString chopped(int n) const
+ { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return left(size() - n); }
+
+
Q_REQUIRED_RESULT QStringRef leftRef(int n) const;
Q_REQUIRED_RESULT QStringRef rightRef(int n) const;
Q_REQUIRED_RESULT QStringRef midRef(int position, int n = -1) const;
+#if QT_STRINGVIEW_LEVEL < 2
bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
+ Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return qStartsWith(*this, s, cs); }
bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+
+#if QT_STRINGVIEW_LEVEL < 2
bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
+ Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return qEndsWith(*this, s, cs); }
bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
@@ -652,7 +676,7 @@ public:
{}
template <int N>
inline QString &operator=(const char (&ch)[N])
- { return (*this = fromLatin1(ch, N - 1)); }
+ { return (*this = fromUtf8(ch, N - 1)); }
#endif
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
inline QT_ASCII_CAST_WARN QString(const char *ch)
@@ -750,6 +774,7 @@ public:
inline void push_back(const QString &s) { append(s); }
inline void push_front(QChar c) { prepend(c); }
inline void push_front(const QString &s) { prepend(s); }
+ void shrink_to_fit() { squeeze(); }
static inline QString fromStdString(const std::string &s);
inline std::string toStdString() const;
@@ -850,6 +875,7 @@ private:
friend class QCharRef;
friend class QTextCodec;
friend class QStringRef;
+ friend class QStringView;
friend class QByteArray;
friend class QCollator;
friend struct QAbstractConcatenable;
@@ -877,6 +903,15 @@ public:
inline DataPtr &data_ptr() { return d; }
};
+//
+// QStringView inline members that require QString:
+//
+QString QStringView::toString() const
+{ return Q_ASSERT(size() == length()), QString(data(), length()); }
+
+//
+// QString inline members
+//
inline QString::QString(QLatin1String aLatin1) : d(fromLatin1_helper(aLatin1.latin1(), aLatin1.size()))
{ }
inline int QString::length() const
@@ -1112,6 +1147,8 @@ inline QCharRef QString::operator[](int i)
{ Q_ASSERT(i >= 0); return QCharRef(*this, i); }
inline QCharRef QString::operator[](uint i)
{ return QCharRef(*this, i); }
+inline QCharRef QString::front() { return operator[](0); }
+inline QCharRef QString::back() { return operator[](size() - 1); }
inline QString::iterator QString::begin()
{ detach(); return reinterpret_cast<QChar*>(d->data()); }
inline QString::const_iterator QString::begin() const
@@ -1433,6 +1470,8 @@ public:
Q_REQUIRED_RESULT QStringRef left(int n) const;
Q_REQUIRED_RESULT QStringRef right(int n) const;
Q_REQUIRED_RESULT QStringRef mid(int pos, int n = -1) const;
+ Q_REQUIRED_RESULT QStringRef chopped(int n) const
+ { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); return left(size() - n); }
void truncate(int pos) Q_DECL_NOTHROW { m_size = qBound(0, pos, m_size); }
void chop(int n) Q_DECL_NOTHROW
@@ -1445,15 +1484,23 @@ public:
bool isRightToLeft() const;
- bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return qStartsWith(*this, s, cs); }
bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#if QT_STRINGVIEW_LEVEL < 2
+ bool startsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool startsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
- bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return qEndsWith(*this, s, cs); }
bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#if QT_STRINGVIEW_LEVEL < 2
+ bool endsWith(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
bool endsWith(const QStringRef &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+#endif
inline QStringRef &operator=(const QString *string);
@@ -1496,6 +1543,8 @@ public:
inline const QChar at(int i) const
{ Q_ASSERT(uint(i) < uint(size())); return m_string->at(i + m_position); }
QChar operator[](int i) const { return at(i); }
+ Q_REQUIRED_RESULT QChar front() const { return at(0); }
+ Q_REQUIRED_RESULT QChar back() const { return at(size() - 1); }
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
// ASCII compatibility
@@ -1610,7 +1659,7 @@ inline bool operator>=(const QStringRef &lhs, QLatin1String rhs) Q_DECL_NOTHROW
// QChar <> QString
inline bool operator==(QChar lhs, const QString &rhs) Q_DECL_NOTHROW
-{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) == 0; }
+{ return rhs.size() == 1 && lhs == rhs.front(); }
inline bool operator< (QChar lhs, const QString &rhs) Q_DECL_NOTHROW
{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) < 0; }
inline bool operator> (QChar lhs, const QString &rhs) Q_DECL_NOTHROW
@@ -1629,7 +1678,7 @@ inline bool operator>=(const QString &lhs, QChar rhs) Q_DECL_NOTHROW { return !(
// QChar <> QStringRef
inline bool operator==(QChar lhs, const QStringRef &rhs) Q_DECL_NOTHROW
-{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) == 0; }
+{ return rhs.size() == 1 && lhs == rhs.front(); }
inline bool operator< (QChar lhs, const QStringRef &rhs) Q_DECL_NOTHROW
{ return QString::compare_helper(&lhs, 1, rhs.data(), rhs.size()) < 0; }
inline bool operator> (QChar lhs, const QStringRef &rhs) Q_DECL_NOTHROW
@@ -1648,7 +1697,7 @@ inline bool operator>=(const QStringRef &lhs, QChar rhs) Q_DECL_NOTHROW { return
// QChar <> QLatin1String
inline bool operator==(QChar lhs, QLatin1String rhs) Q_DECL_NOTHROW
-{ return QString::compare_helper(&lhs, 1, rhs) == 0; }
+{ return rhs.size() == 1 && lhs == rhs.front(); }
inline bool operator< (QChar lhs, QLatin1String rhs) Q_DECL_NOTHROW
{ return QString::compare_helper(&lhs, 1, rhs) < 0; }
inline bool operator> (QChar lhs, QLatin1String rhs) Q_DECL_NOTHROW
@@ -1665,6 +1714,44 @@ inline bool operator> (QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return r
inline bool operator<=(QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs < lhs); }
inline bool operator>=(QLatin1String lhs, QChar rhs) Q_DECL_NOTHROW { return !(rhs > lhs); }
+// QStringView <> QStringView
+inline bool operator==(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && qCompareStrings(lhs, rhs) == 0; }
+inline bool operator!=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
+inline bool operator< (QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) < 0; }
+inline bool operator<=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) <= 0; }
+inline bool operator> (QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) > 0; }
+inline bool operator>=(QStringView lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) >= 0; }
+
+// QStringView <> QChar
+inline bool operator==(QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs == QStringView(&rhs, 1); }
+inline bool operator!=(QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs != QStringView(&rhs, 1); }
+inline bool operator< (QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs < QStringView(&rhs, 1); }
+inline bool operator<=(QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs <= QStringView(&rhs, 1); }
+inline bool operator> (QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs > QStringView(&rhs, 1); }
+inline bool operator>=(QStringView lhs, QChar rhs) Q_DECL_NOTHROW { return lhs >= QStringView(&rhs, 1); }
+
+inline bool operator==(QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) == rhs; }
+inline bool operator!=(QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) != rhs; }
+inline bool operator< (QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) < rhs; }
+inline bool operator<=(QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) <= rhs; }
+inline bool operator> (QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) > rhs; }
+inline bool operator>=(QChar lhs, QStringView rhs) Q_DECL_NOTHROW { return QStringView(&lhs, 1) >= rhs; }
+
+// QStringView <> QLatin1String
+inline bool operator==(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && qCompareStrings(lhs, rhs) == 0; }
+inline bool operator!=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
+inline bool operator< (QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) < 0; }
+inline bool operator<=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) <= 0; }
+inline bool operator> (QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) > 0; }
+inline bool operator>=(QStringView lhs, QLatin1String rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) >= 0; }
+
+inline bool operator==(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return lhs.size() == rhs.size() && qCompareStrings(lhs, rhs) == 0; }
+inline bool operator!=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
+inline bool operator< (QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) < 0; }
+inline bool operator<=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) <= 0; }
+inline bool operator> (QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) > 0; }
+inline bool operator>=(QLatin1String lhs, QStringView rhs) Q_DECL_NOTHROW { return qCompareStrings(lhs, rhs) >= 0; }
+
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
// QStringRef <> QByteArray
inline QT_ASCII_CAST_WARN bool operator==(const QStringRef &lhs, const QByteArray &rhs) { return lhs.compare(rhs) == 0; }
diff --git a/src/corelib/tools/qstringalgorithms.h b/src/corelib/tools/qstringalgorithms.h
new file mode 100644
index 0000000000..e1b8b90428
--- /dev/null
+++ b/src/corelib/tools/qstringalgorithms.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRINGALGORITHMS_H
+#define QSTRINGALGORITHMS_H
+
+#include <QtCore/qnamespace.h>
+
+#if 0
+#pragma qt_class(QStringAlgorithms)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class QByteArray;
+class QLatin1String;
+class QStringView;
+template <typename T> class QVector;
+
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QStringView lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QLatin1String lhs, QStringView rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION int qCompareStrings(QLatin1String lhs, QLatin1String rhs, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+
+
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qStartsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qStartsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qStartsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qStartsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qEndsWith(QStringView haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qEndsWith(QStringView haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qEndsWith(QLatin1String haystack, QStringView needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION bool qEndsWith(QLatin1String haystack, QLatin1String needle, Qt::CaseSensitivity cs = Qt::CaseSensitive) Q_DECL_NOTHROW;
+
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QStringView qTrimmed(QStringView s) Q_DECL_NOTHROW;
+Q_REQUIRED_RESULT Q_CORE_EXPORT Q_DECL_PURE_FUNCTION QLatin1String qTrimmed(QLatin1String s) Q_DECL_NOTHROW;
+
+Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray qConvertToLatin1(QStringView str);
+Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray qConvertToUtf8(QStringView str);
+Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray qConvertToLocal8Bit(QStringView str);
+Q_REQUIRED_RESULT Q_CORE_EXPORT QVector<uint> qConvertToUcs4(QStringView str);
+
+QT_END_NAMESPACE
+
+#endif // QSTRINGALGORTIHMS_H
diff --git a/src/corelib/tools/qstringalgorithms_p.h b/src/corelib/tools/qstringalgorithms_p.h
index c5470bc7ad..4bcf697f78 100644
--- a/src/corelib/tools/qstringalgorithms_p.h
+++ b/src/corelib/tools/qstringalgorithms_p.h
@@ -89,14 +89,12 @@ template <typename StringType> struct QStringAlgorithms
static inline void trimmed_helper_positions(const Char *&begin, const Char *&end)
{
+ // skip white space from end
+ while (begin < end && isSpace(end[-1]))
+ --end;
// skip white space from start
while (begin < end && isSpace(*begin))
begin++;
- // skip white space from end
- if (begin < end) {
- while (begin < end && isSpace(end[-1]))
- end--;
- }
}
static inline StringType trimmed_helper(StringType &str)
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
index 9a40abcfed..5c6d990314 100644
--- a/src/corelib/tools/qstringbuilder.h
+++ b/src/corelib/tools/qstringbuilder.h
@@ -303,7 +303,7 @@ template <int N> struct QConcatenable<char[N]> : QConcatenable<const char[N]>
template <> struct QConcatenable<const char *> : private QAbstractConcatenable
{
- typedef char const *type;
+ typedef const char *type;
typedef QByteArray ConvertTo;
enum { ExactSize = false };
static int size(const char *a) { return qstrlen(a); }
@@ -320,6 +320,11 @@ template <> struct QConcatenable<const char *> : private QAbstractConcatenable
}
};
+template <> struct QConcatenable<char *> : QConcatenable<const char*>
+{
+ typedef char *type;
+};
+
template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
{
typedef QByteArray type;
diff --git a/src/corelib/tools/qstringiterator.qdoc b/src/corelib/tools/qstringiterator.qdoc
index ff759b6f0e..95c2247bc1 100644
--- a/src/corelib/tools/qstringiterator.qdoc
+++ b/src/corelib/tools/qstringiterator.qdoc
@@ -55,7 +55,7 @@
that may be present in a QString, and return the individual Unicode code points.
You can create a QStringIterator that iterates over a given
- QString by passing the string to the QStringIterator's constructor:
+ QStringView by passing the string to the QStringIterator's constructor:
\snippet code/src_corelib_tools_qstringiterator.cpp 0
@@ -120,12 +120,12 @@
*/
/*!
- \fn QStringIterator::QStringIterator(const QString &string)
+ \fn QStringIterator::QStringIterator(QStringView string, qssize_t idx)
Constructs an iterator over the contents of \a string. The iterator will point
- before the first position in the string.
+ before position \a idx in the string.
- The string \a string must remain valid while the iterator is being used.
+ The string view \a string must remain valid while the iterator is being used.
*/
/*!
diff --git a/src/corelib/tools/qstringiterator_p.h b/src/corelib/tools/qstringiterator_p.h
index 7cf59ae42f..8b1a6a1cd3 100644
--- a/src/corelib/tools/qstringiterator_p.h
+++ b/src/corelib/tools/qstringiterator_p.h
@@ -60,12 +60,12 @@ QT_BEGIN_NAMESPACE
class QStringIterator
{
QString::const_iterator i, pos, e;
-
+ Q_STATIC_ASSERT((std::is_same<QString::const_iterator, const QChar *>::value));
public:
- inline explicit QStringIterator(const QString &string)
- : i(string.constBegin()),
- pos(string.constBegin()),
- e(string.constEnd())
+ explicit QStringIterator(QStringView string, qssize_t idx = 0)
+ : i(string.begin()),
+ pos(i + idx),
+ e(string.end())
{
}
diff --git a/src/corelib/tools/qstringlist.cpp b/src/corelib/tools/qstringlist.cpp
index 75ff934f15..d65563f76d 100644
--- a/src/corelib/tools/qstringlist.cpp
+++ b/src/corelib/tools/qstringlist.cpp
@@ -299,6 +299,16 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QString
return res;
}
+template<typename T>
+static bool stringList_contains(const QStringList &stringList, const T &str, Qt::CaseSensitivity cs)
+{
+ for (const auto &string : stringList) {
+ if (string.size() == str.size() && string.compare(str, cs) == 0)
+ return true;
+ }
+ return false;
+}
+
/*!
\fn bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) const
@@ -312,12 +322,24 @@ QStringList QtPrivate::QStringList_filter(const QStringList *that, const QString
bool QtPrivate::QStringList_contains(const QStringList *that, const QString &str,
Qt::CaseSensitivity cs)
{
- for (int i = 0; i < that->size(); ++i) {
- const QString & string = that->at(i);
- if (string.length() == str.length() && str.compare(string, cs) == 0)
- return true;
- }
- return false;
+ return stringList_contains(*that, str, cs);
+}
+
+/*!
+ \fn bool QStringList::contains(QLatin1String str, Qt::CaseSensitivity cs) const
+ \overload
+ \since 5.10
+
+ Returns \c true if the list contains the string \a str; otherwise
+ returns \c false. The search is case insensitive if \a cs is
+ Qt::CaseInsensitive; the search is case sensitive by default.
+
+ \sa indexOf(), lastIndexOf(), QString::contains()
+ */
+bool QtPrivate::QStringList_contains(const QStringList *that, QLatin1String str,
+ Qt::CaseSensitivity cs)
+{
+ return stringList_contains(*that, str, cs);
}
#ifndef QT_NO_REGEXP
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index 720d7d7419..b11856d9be 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -120,6 +120,7 @@ public:
#endif
inline bool contains(const QString &str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
+ inline bool contains(QLatin1String str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
inline QStringList operator+(const QStringList &other) const
{ QStringList n = *this; n += other; return n; }
@@ -165,6 +166,7 @@ namespace QtPrivate {
Qt::CaseSensitivity cs);
bool Q_CORE_EXPORT QStringList_contains(const QStringList *that, const QString &str, Qt::CaseSensitivity cs);
+ bool Q_CORE_EXPORT QStringList_contains(const QStringList *that, QLatin1String str, Qt::CaseSensitivity cs);
void Q_CORE_EXPORT QStringList_replaceInStrings(QStringList *that, const QString &before, const QString &after,
Qt::CaseSensitivity cs);
@@ -222,6 +224,11 @@ inline bool QStringList::contains(const QString &str, Qt::CaseSensitivity cs) co
return QtPrivate::QStringList_contains(this, str, cs);
}
+inline bool QStringList::contains(QLatin1String str, Qt::CaseSensitivity cs) const
+{
+ return QtPrivate::QStringList_contains(this, str, cs);
+}
+
inline QStringList &QListSpecialMethods<QString>::replaceInStrings(const QString &before, const QString &after, Qt::CaseSensitivity cs)
{
QtPrivate::QStringList_replaceInStrings(self(), before, after, cs);
diff --git a/src/corelib/tools/qstringliteral.h b/src/corelib/tools/qstringliteral.h
new file mode 100644
index 0000000000..6a1a74a80e
--- /dev/null
+++ b/src/corelib/tools/qstringliteral.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRINGLITERAL_H
+#define QSTRINGLITERAL_H
+
+#include <QtCore/qarraydata.h>
+
+#if 0
+#pragma qt_class(QStringLiteral)
+#endif
+
+QT_BEGIN_NAMESPACE
+
+typedef QTypedArrayData<ushort> QStringData;
+
+#if defined(Q_OS_WIN) && !defined(Q_COMPILER_UNICODE_STRINGS)
+// fall back to wchar_t if the a Windows compiler does not
+// support Unicode string literals, assuming wchar_t is 2 bytes
+// on that platform (sanity-checked by static_assert further below)
+
+#if defined(Q_CC_MSVC)
+# define QT_UNICODE_LITERAL_II(str) L##str
+#else
+# define QT_UNICODE_LITERAL_II(str) L"" str
+#endif
+typedef wchar_t qunicodechar;
+
+#else
+// all our supported compilers support Unicode string literals,
+// even if their Q_COMPILER_UNICODE_STRING has been revoked due
+// to lacking stdlib support. But QStringLiteral only needs the
+// core language feature, so just use u"" here unconditionally:
+
+#define QT_UNICODE_LITERAL_II(str) u"" str
+typedef char16_t qunicodechar;
+
+#endif
+
+Q_STATIC_ASSERT_X(sizeof(qunicodechar) == 2,
+ "qunicodechar must typedef an integral type of size 2");
+
+#define QT_UNICODE_LITERAL(str) QT_UNICODE_LITERAL_II(str)
+#define QStringLiteral(str) \
+ ([]() Q_DECL_NOEXCEPT -> QString { \
+ enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
+ static const QStaticStringData<Size> qstring_literal = { \
+ Q_STATIC_STRING_DATA_HEADER_INITIALIZER(Size), \
+ QT_UNICODE_LITERAL(str) }; \
+ QStringDataPtr holder = { qstring_literal.data_ptr() }; \
+ const QString qstring_literal_temp(holder); \
+ return qstring_literal_temp; \
+ }()) \
+ /**/
+
+#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, offset) \
+ { Q_REFCOUNT_INITIALIZE_STATIC, size, 0, 0, offset } \
+ /**/
+
+#define Q_STATIC_STRING_DATA_HEADER_INITIALIZER(size) \
+ Q_STATIC_STRING_DATA_HEADER_INITIALIZER_WITH_OFFSET(size, sizeof(QStringData)) \
+ /**/
+
+#ifndef QT_NO_UNICODE_LITERAL
+# ifndef QT_UNICODE_LITERAL
+# error "If you change QStringLiteral, please change QStringViewLiteral, too"
+# endif
+# define QStringViewLiteral(str) QStringView(QT_UNICODE_LITERAL(str))
+#endif
+
+template <int N>
+struct QStaticStringData
+{
+ QArrayData str;
+ qunicodechar data[N + 1];
+
+ QStringData *data_ptr() const
+ {
+ Q_ASSERT(str.ref.isStatic());
+ return const_cast<QStringData *>(static_cast<const QStringData*>(&str));
+ }
+};
+
+struct QStringDataPtr
+{
+ QStringData *ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QSTRINGLITERAL_H
diff --git a/src/corelib/tools/qstringview.cpp b/src/corelib/tools/qstringview.cpp
new file mode 100644
index 0000000000..8eefc6d814
--- /dev/null
+++ b/src/corelib/tools/qstringview.cpp
@@ -0,0 +1,777 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstringview.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QStringView
+ \inmodule QtCore
+ \since 5.10
+ \brief The QStringView class provides a unified view on UTF-16 strings with a read-only subset of the QString API.
+ \reentrant
+ \ingroup tools
+ \ingroup string-processing
+
+ A QStringView references a contiguous portion of a UTF-16 string it does
+ not own. It acts as an interface type to all kinds of UTF-16 string,
+ without the need to construct a QString first.
+
+ The UTF-16 string may be represented as an array (or an array-compatible
+ data-structure such as QString,
+ std::basic_string, etc.) of QChar, \c ushort, \c char16_t (on compilers that
+ support C++11 Unicode strings) or (on platforms, such as Windows,
+ where it is a 16-bit type) \c wchar_t.
+
+ QStringView is designed as an interface type; its main use-case is
+ as a function parameter type. When QStringViews are used as automatic
+ variables or data members, care must be taken to ensure that the referenced
+ string data (for example, owned by a QString) outlives the QStringView on all code paths,
+ lest the string view ends up referencing deleted data.
+
+ When used as an interface type, QStringView allows a single function to accept
+ a wide variety of UTF-16 string data sources. One function accepting QStringView
+ thus replaces three function overloads (taking QString, QStringRef, and
+ \c{(const QChar*, int)}), while at the same time enabling even more string data
+ sources to be passed to the function, such as \c{u"Hello World"}, a \c char16_t
+ string literal.
+
+ QStringViews should be passed by value, not by reference-to-const:
+ \code
+ void myfun1(QStringView sv); // preferred
+ void myfun2(const QStringView &sv); // compiles and works, but slower
+ \endcode
+
+ If you want to give your users maximum freedom in what strings they can pass
+ to your function, accompany the QStringView overload with overloads for
+
+ \list
+ \li \e QChar: this overload can delegate to the QStringView version:
+ \code
+ void fun(QChar ch) { fun(QStringView(&ch, 1)); }
+ \endcode
+ even though, for technical reasons, QStringView cannot provide a
+ QChar constructor by itself.
+ \li \e QString: if you store an unmodified copy of the string and thus would
+ like to take advantage of QString's implicit sharing.
+ \li QLatin1String: if you can implement the function without converting the
+ QLatin1String to UTF-16 first; users expect a function overloaded on
+ QLatin1String to perform strictly less memory allocations than the
+ semantically equivalent call of the QStringView version, involving
+ construction of a QString from the QLatin1String.
+ \endlist
+
+ QStringView can also be used as the return value of a function. If you call a
+ function returning QStringView, take extra care to not keep the QStringView
+ around longer than the function promises to keep the referenced string data alive.
+ If in doubt, obtain a strong reference to the data by calling toString() to convert
+ the QStringView into a QString.
+
+ QStringView is a \e{Literal Type}, but since it stores data as \c{char16_t}, iteration
+ is not \c constexpr (casts from \c{const char16_t*} to \c{const QChar*}, which is not
+ allowed in \c constexpr functions). You can use an indexed loop and/or utf16() in
+ \c constexpr contexts instead.
+
+ \note We strongly discourage the use of QList<QStringView>,
+ because QList is a very inefficient container for QStringViews (it would heap-allocate
+ every element). Use QVector (or std::vector) to hold QStringViews instead.
+
+ \sa QString, QStringRef
+*/
+
+/*!
+ \typedef QStringView::value_type
+
+ Alias for \c{const QChar}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QStringView::difference_type
+
+ Alias for \c{std::ptrdiff_t}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QStringView::size_type
+
+ Alias for qssize_t. Provided for compatibility with the STL.
+
+ Unlike other Qt classes, QStringView uses qssize_t as its \c size_type, to allow
+ accepting data from \c{std::basic_string} without truncation. The Qt API functions,
+ for example length(), return \c int, while the STL-compatible functions, for example
+ size(), return \c size_type.
+*/
+
+/*!
+ \typedef QStringView::reference
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+
+ QStringView does not support mutable references, so this is the same
+ as const_reference.
+*/
+
+/*!
+ \typedef QStringView::const_reference
+
+ Alias for \c{value_type &}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QStringView::pointer
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+
+ QStringView does not support mutable pointers, so this is the same
+ as const_pointer.
+*/
+
+/*!
+ \typedef QStringView::const_pointer
+
+ Alias for \c{value_type *}. Provided for compatibility with the STL.
+*/
+
+/*!
+ \typedef QStringView::iterator
+
+ This typedef provides an STL-style const iterator for QStringView.
+
+ QStringView does not support mutable iterators, so this is the same
+ as const_iterator.
+
+ \sa const_iterator, reverse_iterator
+*/
+
+/*!
+ \typedef QStringView::const_iterator
+
+ This typedef provides an STL-style const iterator for QStringView.
+
+ \sa iterator, const_reverse_iterator
+*/
+
+/*!
+ \typedef QStringView::reverse_iterator
+
+ This typedef provides an STL-style const reverse iterator for QStringView.
+
+ QStringView does not support mutable reverse iterators, so this is the
+ same as const_reverse_iterator.
+
+ \sa const_reverse_iterator, iterator
+*/
+
+/*!
+ \typedef QStringView::const_reverse_iterator
+
+ This typedef provides an STL-style const reverse iterator for QStringView.
+
+ \sa reverse_iterator, const_iterator
+*/
+
+/*!
+ \fn QStringView::QStringView()
+
+ Constructs a null string view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QStringView::QStringView(std::nullptr_t)
+
+ Constructs a null string view.
+
+ \sa isNull()
+*/
+
+/*!
+ \fn QStringView::QStringView(const Char *str, qssize_t len)
+
+ Constructs a string view on \a str with length \a len.
+
+ The range \c{[str,len)} must remain valid for the lifetime of this string view object.
+
+ Passing \c nullptr as \a str is safe if \a len is 0, too, and results in a null string view.
+
+ The behavior is undefined if \a len is negative or, when positive, if \a str is \c nullptr.
+
+ This constructor only participates in overload resolution if \c Char is a compatible
+ character type. The compatible character types are: \c QChar, \c ushort, \c char16_t and
+ (on platforms, such as Windows, where it is a 16-bit type) \c wchar_t.
+*/
+
+/*!
+ \fn QStringView::QStringView(const Char *first, const Char *last)
+
+ Constructs a string view on \a first with length (\a last - \a first).
+
+ The range \c{[first,last)} must remain valid for the lifetime of
+ this string view object.
+
+ Passing \c nullptr as \a first is safe if \a last is nullptr, too,
+ and results in a null string view.
+
+ The behavior is undefined if \a last precedes \a first, or \a first
+ is \c nullptr and \a last is not.
+
+ This constructor only participates in overload resolution if \c Char
+ is a compatible character type. The compatible character types
+ are: \c QChar, \c ushort, \c char16_t and (on platforms, such as
+ Windows, where it is a 16-bit type) \c wchar_t.
+*/
+
+/*!
+ \fn QStringView::QStringView(const Char *str)
+
+ Constructs a string view on \a str. The length is determined
+ by scanning for the first \c{Char(0)}.
+
+ \a str must remain valid for the lifetime of this string view object.
+
+ Passing \c nullptr as \a str is safe and results in a null string view.
+
+ This constructor only participates in overload resolution if \a
+ str is not an array and if \c Char is a compatible character
+ type. The compatible character types are: \c QChar, \c ushort, \c
+ char16_t and (on platforms, such as Windows, where it is a 16-bit
+ type) \c wchar_t.
+*/
+
+/*!
+ \fn QStringView::QStringView(const Char (&string)[N])
+
+ Constructs a string view on the character string literal \a string.
+ The length is set to \c{N-1}, excluding the trailing \{Char(0)}.
+ If you need the full array, use the constructor from pointer and
+ size instead:
+
+ \code
+ auto sv = QStringView(array, std::size(array)); // using C++17 std::size()
+ \endcode
+
+ \a string must remain valid for the lifetime of this string view
+ object.
+
+ This constructor only participates in overload resolution if \a
+ string is an actual array and \c Char is a compatible character
+ type. The compatible character types are: \c QChar, \c ushort, \c
+ char16_t and (on platforms, such as Windows, where it is a 16-bit
+ type) \c wchar_t.
+*/
+
+/*!
+ \fn QStringView::QStringView(const QString &str)
+
+ Constructs a string view on \a str.
+
+ \c{str.data()} must remain valid for the lifetime of this string view object.
+
+ The string view will be null if and only if \c{str.isNull()}.
+*/
+
+/*!
+ \fn QStringView::QStringView(const QStringRef &str)
+
+ Constructs a string view on \a str.
+
+ \c{str.data()} must remain valid for the lifetime of this string view object.
+
+ The string view will be null if and only if \c{str.isNull()}.
+*/
+
+/*!
+ \fn QStringView::QStringView(const StdBasicString &str)
+
+ Constructs a string view on \a str. The length is taken from \c{str.size()}.
+
+ \c{str.data()} must remain valid for the lifetime of this string view object.
+
+ This constructor only participates in overload resolution if \c StdBasicString is an
+ instantiation of \c std::basic_string with a compatible character type. The
+ compatible character types are: \c QChar, \c ushort, \c char16_t and
+ (on platforms, such as Windows, where it is a 16-bit type) \c wchar_t.
+
+ The string view will be empty if and only if \c{str.empty()}. It is unspecified
+ whether this constructor can result in a null string view (\c{str.data()} would
+ have to return \c nullptr for this).
+
+ \sa isNull(), isEmpty()
+*/
+
+/*!
+ \fn QString QStringView::toString() const
+
+ Returns a deep copy of this string view's data as a QString.
+
+ The return value will be the null QString if and only if this string view is null.
+
+ \warning QStringView can store strings with more than 2\sup{30} characters
+ while QString cannot. Calling this function on a string view for which size()
+ returns a value greater than \c{INT_MAX / 2} constitutes undefined behavior.
+*/
+
+/*!
+ \fn const QChar *QStringView::data() const
+
+ Returns a const pointer to the first character in the string.
+
+ \note The character array represented by the return value is \e not null-terminated.
+
+ \sa begin(), end(), utf16()
+*/
+
+/*!
+ \fn const storage_type *QStringView::utf16() const
+
+ Returns a const pointer to the first character in the string.
+
+ \c{storage_type} is \c{char16_t}, except on MSVC 2013 (which lacks \c char16_t support),
+ where it is \c{wchar_t} instead.
+
+ \note The character array represented by the return value is \e not null-terminated.
+
+ \sa begin(), end(), data()
+*/
+
+/*!
+ \fn QStringView::const_iterator QStringView::begin() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character in
+ the string.
+
+ This function is provided for STL compatibility.
+
+ \sa end(), cbegin(), rbegin(), data()
+*/
+
+/*!
+ \fn QStringView::const_iterator QStringView::cbegin() const
+
+ Same as begin().
+
+ This function is provided for STL compatibility.
+
+ \sa cend(), begin(), crbegin(), data()
+*/
+
+/*!
+ \fn QStringView::const_iterator QStringView::end() const
+
+ Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
+ character after the last character in the list.
+
+ This function is provided for STL compatibility.
+
+ \sa begin(), cend(), rend()
+*/
+
+/*! \fn QStringView::const_iterator QStringView::cend() const
+
+ Same as end().
+
+ This function is provided for STL compatibility.
+
+ \sa cbegin(), end(), crend()
+*/
+
+/*!
+ \fn QStringView::const_reverse_iterator QStringView::rbegin() const
+
+ Returns a const \l{STL-style iterators}{STL-style} reverse iterator pointing to the first
+ character in the string, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rend(), crbegin(), begin()
+*/
+
+/*!
+ \fn QStringView::const_reverse_iterator QStringView::crbegin() const
+
+ Same as rbegin().
+
+ This function is provided for STL compatibility.
+
+ \sa crend(), rbegin(), cbegin()
+*/
+
+/*!
+ \fn QStringView::const_reverse_iterator QStringView::rend() const
+
+ Returns a \l{STL-style iterators}{STL-style} reverse iterator pointing to one past
+ the last character in the string, in reverse order.
+
+ This function is provided for STL compatibility.
+
+ \sa rbegin(), crend(), end()
+*/
+
+/*!
+ \fn QStringView::const_reverse_iterator QStringView::crend() const
+
+ Same as rend().
+
+ This function is provided for STL compatibility.
+
+ \sa crbegin(), rend(), cend()
+*/
+
+/*!
+ \fn bool QStringView::empty() const
+
+ Returns whether this string view is empty - that is, whether \c{size() == 0}.
+
+ This function is provided for STL compatibility.
+
+ \sa isEmpty(), isNull(), size(), length()
+*/
+
+/*!
+ \fn bool QStringView::isEmpty() const
+
+ Returns whether this string view is empty - that is, whether \c{size() == 0}.
+
+ This function is provided for compatibility with other Qt containers.
+
+ \sa empty(), isNull(), size(), length()
+*/
+
+/*!
+ \fn bool QStringView::isNull() const
+
+ Returns whether this string view is null - that is, whether \c{data() == nullptr}.
+
+ This functions is provided for compatibility with other Qt containers.
+
+ \sa empty(), isEmpty(), size(), length()
+*/
+
+/*!
+ \fn qssize_t QStringView::size() const
+
+ Returns the size of this string view, in UTF-16 code points (that is,
+ surrogate pairs count as two for the purposes of this function, the same
+ as in QString and QStringRef).
+
+ \sa empty(), isEmpty(), isNull(), length()
+*/
+
+/*!
+ \fn int QStringView::length() const
+
+ Same as size(), except returns the result as an \c int.
+
+ This function is provided for compatibility with other Qt containers.
+
+ \warning QStringView can represent strings with more than 2\sup{31} characters.
+ Calling this function on a string view for which size() returns a value greater
+ than \c{INT_MAX} constitutes undefined behavior.
+
+ \sa empty(), isEmpty(), isNull(), size()
+*/
+
+/*!
+ \fn QChar QStringView::operator[](qssize_t n) const
+
+ Returns the character at position \a n in this string view.
+
+ The behavior is undefined if \a n is negative or not less than size().
+
+ \sa at(), front(), back()
+*/
+
+/*!
+ \fn QChar QStringView::at(qssize_t n) const
+
+ Returns the character at position \a n in this string view.
+
+ The behavior is undefined if \a n is negative or not less than size().
+
+ \sa operator[](), front(), back()
+*/
+
+/*!
+ \fn QChar QStringView::front() const
+
+ Returns the first character in the string. Same as first().
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa back(), first(), last()
+*/
+
+/*!
+ \fn QChar QStringView::back() const
+
+ Returns the last character in the string. Same as last().
+
+ This function is provided for STL compatibility.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa front(), first(), last()
+*/
+
+/*!
+ \fn QChar QStringView::first() const
+
+ Returns the first character in the string. Same as front().
+
+ This function is provided for compatibility with other Qt containers.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa front(), back(), last()
+*/
+
+/*!
+ \fn QChar QStringView::last() const
+
+ Returns the last character in the string. Same as back().
+
+ This function is provided for compatibility with other Qt containers.
+
+ \warning Calling this function on an empty string view constitutes
+ undefined behavior.
+
+ \sa back(), front(), first()
+*/
+
+/*!
+ \fn QStringView QStringView::mid(qssize_t start) const
+
+ Returns the substring starting at position \a start in this object,
+ and extending to the end of the string.
+
+ \note The behavior is undefined when \a start < 0 or \a start > size().
+
+ \sa left(), right(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QStringView QStringView::mid(qssize_t start, qssize_t length) const
+ \overload
+
+ Returns the substring of length \a length starting at position
+ \a start in this object.
+
+ \note The behavior is undefined when \a start < 0, \a length < 0,
+ or \a start + \a length > size().
+
+ \sa left(), right(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QStringView QStringView::left(qssize_t length) const
+
+ Returns the substring of length \a length starting at position
+ 0 in this object.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa mid(), right(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QStringView QStringView::right(qssize_t length) const
+
+ Returns the substring of length \a length starting at position
+ size() - \a length in this object.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa mid(), left(), chopped(), chop(), truncate()
+*/
+
+/*!
+ \fn QStringView QStringView::chopped(qssize_t length) const
+
+ Returns the substring of length size() - \a length starting at the
+ beginning of this object.
+
+ Same as \c{left(size() - length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa mid(), left(), right(), chop(), truncate()
+*/
+
+/*!
+ \fn void QStringView::truncate(qssize_t length)
+
+ Truncates this string view to length \a length.
+
+ Same as \c{*this = left(length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa mid(), left(), right(), chopped(), chop()
+*/
+
+/*!
+ \fn void QStringView::chop(qssize_t length)
+
+ Truncates this string view by \a length characters.
+
+ Same as \c{*this = left(size() - length)}.
+
+ \note The behavior is undefined when \a length < 0 or \a length > size().
+
+ \sa mid(), left(), right(), chopped(), truncate()
+*/
+
+/*!
+ \fn QStringView QStringView::trimmed() const
+
+ Strips leading and trailing whitespace and returns the result.
+
+ Whitespace means any character for which QChar::isSpace() returns
+ \c true. This includes the ASCII characters '\\t', '\\n', '\\v',
+ '\\f', '\\r', and ' '.
+
+ \sa qTrimmed()
+*/
+
+/*!
+ \fn bool QStringView::startsWith(QStringView str, Qt::CaseSensitivity cs) const
+ \fn bool QStringView::startsWith(QLatin1String l1, Qt::CaseSensitivity cs) const
+ \fn bool QStringView::startsWith(QChar ch) const
+ \fn bool QStringView::startsWith(QChar ch, Qt::CaseSensitivity cs) const
+
+ Returns \c true if this string-view starts with string-view \a str,
+ Latin-1 string \a l1, or character \a ch, respectively;
+ otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
+ otherwise the search is case-insensitive.
+
+ \sa endsWith(), qStartsWith()
+*/
+
+/*!
+ \fn bool QStringView::endsWith(QStringView str, Qt::CaseSensitivity cs) const
+ \fn bool QStringView::endsWith(QLatin1String l1, Qt::CaseSensitivity cs) const
+ \fn bool QStringView::endsWith(QChar ch) const
+ \fn bool QStringView::endsWith(QChar ch, Qt::CaseSensitivity cs) const
+
+ Returns \c true if this string-view ends with string-view \a str,
+ Latin-1 string \a l1, or character \a ch, respectively;
+ otherwise returns \c false.
+
+ If \a cs is Qt::CaseSensitive (the default), the search is case-sensitive;
+ otherwise the search is case-insensitive.
+
+ \sa startsWith(), qEndsWith()
+*/
+
+/*!
+ \fn QByteArray QStringView::toLatin1() const
+
+ Returns a Latin-1 representation of the string as a QByteArray.
+
+ The behavior is undefined if the string contains non-Latin1 characters.
+
+ \sa toUtf8(), toLocal8Bit(), QTextCodec, qConvertToLatin1()
+*/
+
+/*!
+ \fn QByteArray QStringView::toLocal8Bit() const
+
+ Returns a local 8-bit representation of the string as a QByteArray.
+
+ QTextCodec::codecForLocale() is used to perform the conversion from
+ Unicode. If the locale's encoding could not be determined, this function
+ does the same as toLatin1().
+
+ The behavior is undefined if the string contains characters not
+ supported by the locale's 8-bit encoding.
+
+ \sa toLatin1(), toUtf8(), QTextCodec, qConvertToLocal8Bit()
+*/
+
+/*!
+ \fn QByteArray QStringView::toUtf8() const
+
+ Returns a UTF-8 representation of the string as a QByteArray.
+
+ UTF-8 is a Unicode codec and can represent all characters in a Unicode
+ string like QString.
+
+ \sa toLatin1(), toLocal8Bit(), QTextCodec, qConvertToUtf8()
+*/
+
+/*!
+ \fn QVector<uint> QStringView::toUcs4() const
+
+ Returns a UCS-4/UTF-32 representation of the string as a QVector<uint>.
+
+ UCS-4 is a Unicode codec and therefore it is lossless. All characters from
+ this string will be encoded in UCS-4. Any invalid sequence of code units in
+ this string is replaced by the Unicode replacement character
+ (QChar::ReplacementCharacter, which corresponds to \c{U+FFFD}).
+
+ The returned vector is not 0-terminated.
+
+ \sa toUtf8(), toLatin1(), toLocal8Bit(), QTextCodec
+*/
+
+/*!
+ \fn qToStringViewIgnoringNull(const QStringLike &s);
+ \since 5.10
+ \internal
+
+ Convert \a s to a QStringView ignoring \c{s.isNull()}.
+
+ Returns a string-view that references \a{s}' data, but is never null.
+
+ This is a faster way to convert a QString or QStringRef to a QStringView,
+ if null QStrings can legitimately be treated as empty ones.
+
+ \sa QString::isNull(), QStringRef::isNull(), QStringView
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qstringview.h b/src/corelib/tools/qstringview.h
new file mode 100644
index 0000000000..24be441b00
--- /dev/null
+++ b/src/corelib/tools/qstringview.h
@@ -0,0 +1,305 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef QSTRINGVIEW_H
+#define QSTRINGVIEW_H
+
+#ifndef QT_STRINGVIEW_LEVEL
+# define QT_STRINGVIEW_LEVEL 1
+#endif
+
+#include <QtCore/qchar.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qstringliteral.h>
+#include <QtCore/qstringalgorithms.h>
+
+#include <string>
+
+QT_BEGIN_NAMESPACE
+
+class QString;
+class QStringRef;
+
+namespace QtPrivate {
+template <typename Char>
+struct IsCompatibleCharTypeHelper
+ : std::integral_constant<bool,
+ std::is_same<Char, QChar>::value ||
+ std::is_same<Char, ushort>::value ||
+#if defined(Q_COMPILER_UNICODE_STRINGS)
+ std::is_same<Char, char16_t>::value ||
+#endif
+ (std::is_same<Char, wchar_t>::value && sizeof(wchar_t) == sizeof(QChar))> {};
+template <typename Char>
+struct IsCompatibleCharType
+ : IsCompatibleCharTypeHelper<typename std::remove_cv<typename std::remove_reference<Char>::type>::type> {};
+
+template <typename Array>
+struct IsCompatibleArrayHelper : std::false_type {};
+template <typename Char, size_t N>
+struct IsCompatibleArrayHelper<Char[N]>
+ : IsCompatibleCharType<Char> {};
+template <typename Array>
+struct IsCompatibleArray
+ : IsCompatibleArrayHelper<typename std::remove_cv<typename std::remove_reference<Array>::type>::type> {};
+
+template <typename Pointer>
+struct IsCompatiblePointerHelper : std::false_type {};
+template <typename Char>
+struct IsCompatiblePointerHelper<Char*>
+ : IsCompatibleCharType<Char> {};
+template <typename Pointer>
+struct IsCompatiblePointer
+ : IsCompatiblePointerHelper<typename std::remove_cv<typename std::remove_reference<Pointer>::type>::type> {};
+
+template <typename T>
+struct IsCompatibleStdBasicStringHelper : std::false_type {};
+template <typename Char, typename...Args>
+struct IsCompatibleStdBasicStringHelper<std::basic_string<Char, Args...> >
+ : IsCompatibleCharType<Char> {};
+
+template <typename T>
+struct IsCompatibleStdBasicString
+ : IsCompatibleStdBasicStringHelper<
+ typename std::remove_cv<typename std::remove_reference<T>::type>::type
+ > {};
+
+} // namespace QtPrivate
+
+class QStringView
+{
+public:
+#if defined(Q_OS_WIN) && !defined(Q_COMPILER_UNICODE_STRINGS)
+ typedef wchar_t storage_type;
+#else
+ typedef char16_t storage_type;
+#endif
+ typedef const QChar value_type;
+ typedef std::ptrdiff_t difference_type;
+ typedef qssize_t size_type;
+ typedef value_type &reference;
+ typedef value_type &const_reference;
+ typedef value_type *pointer;
+ typedef value_type *const_pointer;
+
+ typedef pointer iterator;
+ typedef const_pointer const_iterator;
+ typedef std::reverse_iterator<iterator> reverse_iterator;
+ typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
+
+private:
+ template <typename Char>
+ using if_compatible_char = typename std::enable_if<QtPrivate::IsCompatibleCharType<Char>::value, bool>::type;
+
+ template <typename Array>
+ using if_compatible_array = typename std::enable_if<QtPrivate::IsCompatibleArray<Array>::value, bool>::type;
+
+ template <typename Pointer>
+ using if_compatible_pointer = typename std::enable_if<QtPrivate::IsCompatiblePointer<Pointer>::value, bool>::type;
+
+ template <typename T>
+ using if_compatible_string = typename std::enable_if<QtPrivate::IsCompatibleStdBasicString<T>::value, bool>::type;
+
+ template <typename T>
+ using if_compatible_qstring_like = typename std::enable_if<std::is_same<T, QString>::value || std::is_same<T, QStringRef>::value, bool>::type;
+
+ template <typename Char, size_t N>
+ static Q_DECL_CONSTEXPR qssize_t lengthHelperArray(const Char (&)[N]) Q_DECL_NOTHROW
+ {
+ return qssize_t(N - 1);
+ }
+ template <typename Char>
+ static Q_DECL_RELAXED_CONSTEXPR qssize_t lengthHelperPointer(const Char *str) Q_DECL_NOTHROW
+ {
+ qssize_t result = 0;
+ while (*str++)
+ ++result;
+ return result;
+ }
+ static Q_DECL_RELAXED_CONSTEXPR qssize_t lengthHelperPointer(const QChar *str) Q_DECL_NOTHROW
+ {
+ qssize_t result = 0;
+ while (!str++->isNull())
+ ++result;
+ return result;
+ }
+
+ template <typename Char>
+ static const storage_type *castHelper(const Char *str) Q_DECL_NOTHROW
+ { return reinterpret_cast<const storage_type*>(str); }
+ static Q_DECL_CONSTEXPR const storage_type *castHelper(const storage_type *str) Q_DECL_NOTHROW
+ { return str; }
+
+public:
+ Q_DECL_CONSTEXPR QStringView() Q_DECL_NOTHROW
+ : m_size(0), m_data(nullptr) {}
+ Q_DECL_CONSTEXPR QStringView(std::nullptr_t) Q_DECL_NOTHROW
+ : QStringView() {}
+
+ template <typename Char, if_compatible_char<Char> = true>
+ Q_DECL_CONSTEXPR QStringView(const Char *str, qssize_t len)
+ : m_size((Q_ASSERT(len >= 0), Q_ASSERT(str || !len), len)),
+ m_data(castHelper(str)) {}
+
+ template <typename Char, if_compatible_char<Char> = true>
+ Q_DECL_CONSTEXPR QStringView(const Char *f, const Char *l)
+ : QStringView(f, l - f) {}
+
+#ifdef Q_QDOC
+ template <typename Char, size_t N>
+ Q_DECL_CONSTEXPR QStringView(const Char (&array)[N]) Q_DECL_NOTHROW;
+
+ template <typename Char>
+ Q_DECL_CONSTEXPR QStringView(const Char *str) Q_DECL_NOTHROW;
+#else
+ template <typename Array, if_compatible_array<Array> = true>
+ Q_DECL_CONSTEXPR QStringView(const Array &str) Q_DECL_NOTHROW
+ : QStringView(str, lengthHelperArray(str)) {}
+
+ template <typename Pointer, if_compatible_pointer<Pointer> = true>
+ Q_DECL_CONSTEXPR QStringView(const Pointer &str) Q_DECL_NOTHROW
+ : QStringView(str, str ? lengthHelperPointer(str) : 0) {}
+#endif
+
+#ifdef Q_QDOC
+ QStringView(const QString &str) Q_DECL_NOTHROW;
+ QStringView(const QStringRef &str) Q_DECL_NOTHROW;
+#else
+ template <typename String, if_compatible_qstring_like<String> = true>
+ QStringView(const String &str) Q_DECL_NOTHROW
+ : QStringView(str.isNull() ? nullptr : str.data(), qssize_t(str.size())) {}
+#endif
+
+ template <typename StdBasicString, if_compatible_string<StdBasicString> = true>
+ QStringView(const StdBasicString &str) Q_DECL_NOTHROW
+ : QStringView(str.data(), qssize_t(str.size())) {}
+
+ Q_REQUIRED_RESULT inline QString toString() const; // defined in qstring.h
+
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR qssize_t size() const Q_DECL_NOTHROW { return m_size; }
+ Q_REQUIRED_RESULT const_pointer data() const Q_DECL_NOTHROW { return reinterpret_cast<const_pointer>(m_data); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR const storage_type *utf16() const Q_DECL_NOTHROW { return m_data; }
+
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar operator[](qssize_t n) const
+ { return Q_ASSERT(n >= 0), Q_ASSERT(n < size()), QChar(m_data[n]); }
+
+ //
+ // QString API
+ //
+
+ Q_REQUIRED_RESULT QByteArray toLatin1() const { return qConvertToLatin1(*this); }
+ Q_REQUIRED_RESULT QByteArray toUtf8() const { return qConvertToUtf8(*this); }
+ Q_REQUIRED_RESULT QByteArray toLocal8Bit() const { return qConvertToLocal8Bit(*this); }
+ Q_REQUIRED_RESULT inline QVector<uint> toUcs4() const; // defined in qvector.h
+
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar at(qssize_t n) const { return (*this)[n]; }
+
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView mid(qssize_t pos) const
+ { return Q_ASSERT(pos >= 0), Q_ASSERT(pos <= size()), QStringView(m_data + pos, m_size - pos); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView mid(qssize_t pos, qssize_t n) const
+ { return Q_ASSERT(pos >= 0), Q_ASSERT(n >= 0), Q_ASSERT(pos + n <= size()), QStringView(m_data + pos, n); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView left(qssize_t n) const
+ { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QStringView(m_data, n); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView right(qssize_t n) const
+ { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QStringView(m_data + m_size - n, n); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QStringView chopped(qssize_t n) const
+ { return Q_ASSERT(n >= 0), Q_ASSERT(n <= size()), QStringView(m_data, m_size - n); }
+
+ Q_DECL_RELAXED_CONSTEXPR void truncate(qssize_t n)
+ { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size = n; }
+ Q_DECL_RELAXED_CONSTEXPR void chop(qssize_t n)
+ { Q_ASSERT(n >= 0); Q_ASSERT(n <= size()); m_size -= n; }
+
+ Q_REQUIRED_RESULT QStringView trimmed() const Q_DECL_NOTHROW { return qTrimmed(*this); }
+
+ Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return qStartsWith(*this, s, cs); }
+ Q_REQUIRED_RESULT inline bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT bool startsWith(QChar c) const Q_DECL_NOTHROW
+ { return !empty() && front() == c; }
+ Q_REQUIRED_RESULT bool startsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+ { return qStartsWith(*this, QStringView(&c, 1), cs); }
+
+ Q_REQUIRED_RESULT bool endsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW
+ { return qEndsWith(*this, s, cs); }
+ Q_REQUIRED_RESULT inline bool endsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const Q_DECL_NOTHROW;
+ Q_REQUIRED_RESULT bool endsWith(QChar c) const Q_DECL_NOTHROW
+ { return !empty() && back() == c; }
+ Q_REQUIRED_RESULT bool endsWith(QChar c, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW
+ { return qEndsWith(*this, QStringView(&c, 1), cs); }
+
+ //
+ // STL compatibility API:
+ //
+ Q_REQUIRED_RESULT const_iterator begin() const Q_DECL_NOTHROW { return data(); }
+ Q_REQUIRED_RESULT const_iterator end() const Q_DECL_NOTHROW { return data() + size(); }
+ Q_REQUIRED_RESULT const_iterator cbegin() const Q_DECL_NOTHROW { return begin(); }
+ Q_REQUIRED_RESULT const_iterator cend() const Q_DECL_NOTHROW { return end(); }
+ Q_REQUIRED_RESULT const_reverse_iterator rbegin() const Q_DECL_NOTHROW { return const_reverse_iterator(end()); }
+ Q_REQUIRED_RESULT const_reverse_iterator rend() const Q_DECL_NOTHROW { return const_reverse_iterator(begin()); }
+ Q_REQUIRED_RESULT const_reverse_iterator crbegin() const Q_DECL_NOTHROW { return rbegin(); }
+ Q_REQUIRED_RESULT const_reverse_iterator crend() const Q_DECL_NOTHROW { return rend(); }
+
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool empty() const Q_DECL_NOTHROW { return size() == 0; }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar front() const { return Q_ASSERT(!empty()), QChar(m_data[0]); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar back() const { return Q_ASSERT(!empty()), QChar(m_data[m_size - 1]); }
+
+ //
+ // Qt compatibility API:
+ //
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool isNull() const Q_DECL_NOTHROW { return !m_data; }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR bool isEmpty() const Q_DECL_NOTHROW { return empty(); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR int length() const /* not nothrow! */
+ { return Q_ASSERT(int(size()) == size()), int(size()); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar first() const { return front(); }
+ Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QChar last() const { return back(); }
+private:
+ qssize_t m_size;
+ const storage_type *m_data;
+};
+Q_DECLARE_TYPEINFO(QStringView, Q_PRIMITIVE_TYPE);
+
+template <typename QStringLike, typename std::enable_if<
+ std::is_same<QStringLike, QString>::value || std::is_same<QStringLike, QStringRef>::value,
+ bool>::type = true>
+inline QStringView qToStringViewIgnoringNull(const QStringLike &s) Q_DECL_NOTHROW
+{ return QStringView(s.data(), s.size()); }
+
+QT_END_NAMESPACE
+
+#endif /* QSTRINGVIEW_H */
diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp
index c4cd76c59c..6a26993549 100644
--- a/src/corelib/tools/qtimezone.cpp
+++ b/src/corelib/tools/qtimezone.cpp
@@ -338,12 +338,9 @@ QTimeZone::QTimeZone(const QByteArray &ianaId)
*/
QTimeZone::QTimeZone(int offsetSeconds)
+ : d((offsetSeconds >= MinUtcOffsetSecs && offsetSeconds <= MaxUtcOffsetSecs)
+ ? new QUtcTimeZonePrivate(offsetSeconds) : nullptr)
{
- // offsetSeconds must fall between -14:00 and +14:00 hours
- if (offsetSeconds >= -50400 && offsetSeconds <= 50400)
- d = new QUtcTimeZonePrivate(offsetSeconds);
- else
- d = 0;
}
/*!
diff --git a/src/corelib/tools/qtimezone.h b/src/corelib/tools/qtimezone.h
index bd87139f5b..29d8a4dbe5 100644
--- a/src/corelib/tools/qtimezone.h
+++ b/src/corelib/tools/qtimezone.h
@@ -59,6 +59,14 @@ class QTimeZonePrivate;
class Q_CORE_EXPORT QTimeZone
{
public:
+ // Sane UTC offsets range from -14 to +14 hours:
+ enum {
+ // No known zone > 12 hrs West of Greenwich (Baker Island, USA)
+ MinUtcOffsetSecs = -14 * 3600,
+ // No known zone > 14 hrs East of Greenwich (Kiritimati, Christmas Island, Kiribati)
+ MaxUtcOffsetSecs = +14 * 3600
+ };
+
enum TimeType {
StandardTime = 0,
DaylightTime = 1,
diff --git a/src/corelib/tools/qtimezoneprivate.cpp b/src/corelib/tools/qtimezoneprivate.cpp
index 7b780ecf7d..e45dd48de0 100644
--- a/src/corelib/tools/qtimezoneprivate.cpp
+++ b/src/corelib/tools/qtimezoneprivate.cpp
@@ -258,6 +258,8 @@ QTimeZonePrivate::Data QTimeZonePrivate::dataForLocalTime(qint64 forLocalMSecs,
brackets the correct time and at most one DST transition.
*/
const qint64 sixteenHoursInMSecs(16 * 3600 * 1000);
+ Q_STATIC_ASSERT(-sixteenHoursInMSecs / 1000 < QTimeZone::MinUtcOffsetSecs
+ && sixteenHoursInMSecs / 1000 > QTimeZone::MaxUtcOffsetSecs);
/*
Offsets are Local - UTC, positive to the east of Greenwich, negative to
the west; DST offset always exceeds standard offset, when DST applies.
diff --git a/src/corelib/tools/qtimezoneprivate_data_p.h b/src/corelib/tools/qtimezoneprivate_data_p.h
index 6bbcb0e2cd..69b9417f19 100644
--- a/src/corelib/tools/qtimezoneprivate_data_p.h
+++ b/src/corelib/tools/qtimezoneprivate_data_p.h
@@ -114,12 +114,13 @@ struct QUtcData {
// GENERATED PART STARTS HERE
/*
- This part of the file was generated on 2016-03-19 from the
+ This part of the file was generated on 2017-05-23 from the
Common Locale Data Repository v29 supplemental/windowsZones.xml file $Revision: 12348 $
http://www.unicode.org/cldr/
- Do not change this data, only generate it using cldr2qtimezone.py.
+ Do not edit this code: run cldr2qtimezone.py on updated (or
+ edited) CLDR data; see qtbase/util/local_database/.
*/
// Windows ID Key, Country Enum, IANA ID Index
diff --git a/src/corelib/tools/qtimezoneprivate_icu.cpp b/src/corelib/tools/qtimezoneprivate_icu.cpp
index a7226f2720..5570ce7571 100644
--- a/src/corelib/tools/qtimezoneprivate_icu.cpp
+++ b/src/corelib/tools/qtimezoneprivate_icu.cpp
@@ -477,9 +477,10 @@ QList<QByteArray> QIcuTimeZonePrivate::availableTimeZoneIds() const
QList<QByteArray> QIcuTimeZonePrivate::availableTimeZoneIds(QLocale::Country country) const
{
- QByteArray regionCode = QLocalePrivate::countryToCode(country).toUtf8();
+ const QLatin1String regionCode = QLocalePrivate::countryToCode(country);
+ const QByteArray regionCodeUtf8 = QString(regionCode).toUtf8();
UErrorCode status = U_ZERO_ERROR;
- UEnumeration *uenum = ucal_openCountryTimeZones(regionCode, &status);
+ UEnumeration *uenum = ucal_openCountryTimeZones(regionCodeUtf8.data(), &status);
QList<QByteArray> result;
if (U_SUCCESS(status))
result = uenumToIdList(uenum);
diff --git a/src/corelib/tools/qtimezoneprivate_mac.mm b/src/corelib/tools/qtimezoneprivate_mac.mm
index 4e9a432fbf..876dc2d877 100644
--- a/src/corelib/tools/qtimezoneprivate_mac.mm
+++ b/src/corelib/tools/qtimezoneprivate_mac.mm
@@ -226,27 +226,79 @@ QTimeZonePrivate::Data QMacTimeZonePrivate::nextTransition(qint64 afterMSecsSinc
QTimeZonePrivate::Data QMacTimeZonePrivate::previousTransition(qint64 beforeMSecsSinceEpoch) const
{
- // No direct Mac API, so get all transitions since epoch and return the last one
- QList<int> secsList;
- if (beforeMSecsSinceEpoch > 0) {
- const int endSecs = beforeMSecsSinceEpoch / 1000.0;
- NSTimeInterval prevSecs = 0;
- NSTimeInterval nextSecs = 0;
- NSDate *nextDate = [NSDate dateWithTimeIntervalSince1970:nextSecs];
- // If invalid may return a nil date or an Epoch date
+ // The native API only lets us search forward, so we need to find an early-enough start:
+ const NSTimeInterval lowerBound = std::numeric_limits<NSTimeInterval>::min();
+ const qint64 endSecs = beforeMSecsSinceEpoch / 1000;
+ const int year = 366 * 24 * 3600; // a (long) year, in seconds
+ NSTimeInterval prevSecs = endSecs; // sentinel for later check
+ NSTimeInterval nextSecs = prevSecs - year;
+ NSTimeInterval tranSecs = lowerBound; // time at a transition; may be > endSecs
+
+ NSDate *nextDate = [NSDate dateWithTimeIntervalSince1970:nextSecs];
+ nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
+ if (nextDate != nil
+ && (tranSecs = [nextDate timeIntervalSince1970]) < endSecs) {
+ // There's a transition within the last year before endSecs:
+ nextSecs = tranSecs;
+ } else {
+ // Need to start our search earlier:
+ nextDate = [NSDate dateWithTimeIntervalSince1970:lowerBound];
nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
- nextSecs = [nextDate timeIntervalSince1970];
- while (nextDate != nil && nextSecs > prevSecs && nextSecs < endSecs) {
- secsList.append(nextSecs);
- prevSecs = nextSecs;
- nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
+ if (nextDate != nil) {
+ NSTimeInterval lateSecs = nextSecs;
nextSecs = [nextDate timeIntervalSince1970];
- }
+ Q_ASSERT(nextSecs <= endSecs - year || nextSecs == tranSecs);
+ /*
+ We're looking at the first ever transition for our zone, at
+ nextSecs (and our zone *does* have at least one transition). If
+ it's later than endSecs - year, then we must have found it on the
+ initial check and therefore set tranSecs to the same transition
+ time (which, we can infer here, is >= endSecs). In this case, we
+ won't enter the binary-chop loop, below.
+
+ In the loop, nextSecs < lateSecs < endSecs: we have a transition
+ at nextSecs and there is no transition between lateSecs and
+ endSecs. The loop narrows the interval between nextSecs and
+ lateSecs by looking for a transition after their mid-point; if it
+ finds one < endSecs, nextSecs moves to this transition; otherwise,
+ lateSecs moves to the mid-point. This soon enough narrows the gap
+ to within a year, after which walking forward one transition at a
+ time (the "Wind through" loop, below) is good enough.
+ */
+
+ // Binary chop to within a year of last transition before endSecs:
+ while (nextSecs + year < lateSecs) {
+ // Careful about overflow, not fussy about rounding errors:
+ NSTimeInterval middle = nextSecs / 2 + lateSecs / 2;
+ NSDate *split = [NSDate dateWithTimeIntervalSince1970:middle];
+ split = [m_nstz nextDaylightSavingTimeTransitionAfterDate:split];
+ if (split != nil
+ && (tranSecs = [split timeIntervalSince1970]) < endSecs) {
+ nextDate = split;
+ nextSecs = tranSecs;
+ } else {
+ lateSecs = middle;
+ }
+ }
+ Q_ASSERT(nextDate != nil);
+ // ... and nextSecs < endSecs unless first transition ever was >= endSecs.
+ } // else: we have no data - prevSecs is still endSecs, nextDate is still nil
}
- if (secsList.size() >= 1)
- return data(qint64(secsList.constLast()) * 1000);
- else
- return invalidData();
+ // Either nextDate is nil or nextSecs is at its transition.
+
+ // Wind through remaining transitions (spanning at most a year), one at a time:
+ while (nextDate != nil && nextSecs < endSecs) {
+ prevSecs = nextSecs;
+ nextDate = [m_nstz nextDaylightSavingTimeTransitionAfterDate:nextDate];
+ nextSecs = [nextDate timeIntervalSince1970];
+ if (nextSecs <= prevSecs) // presumably no later data available
+ break;
+ }
+ if (prevSecs < endSecs) // i.e. we did make it into that while loop
+ return data(qint64(prevSecs) * 1000);
+
+ // No transition data; or first transition later than requested time.
+ return invalidData();
}
QByteArray QMacTimeZonePrivate::systemTimeZoneId() const
diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp
index 1714c9802f..521475c2dd 100644
--- a/src/corelib/tools/qtimezoneprivate_tz.cpp
+++ b/src/corelib/tools/qtimezoneprivate_tz.cpp
@@ -134,8 +134,6 @@ struct QTzType {
int tz_gmtoff; // UTC offset in seconds
bool tz_isdst; // Is DST
quint8 tz_abbrind; // abbreviation list index
- bool tz_ttisgmt; // Is in UTC time
- bool tz_ttisstd; // Is in Standard time
};
Q_DECLARE_TYPEINFO(QTzType, Q_PRIMITIVE_TYPE);
@@ -234,9 +232,6 @@ static QVector<QTzType> parseTzTypes(QDataStream &ds, int tzh_typecnt)
// Parse Abbreviation Array Index, 1 byte
if (ds.status() == QDataStream::Ok)
ds >> type.tz_abbrind;
- // Set defaults in case not populated later
- type.tz_ttisgmt = false;
- type.tz_ttisstd = false;
if (ds.status() != QDataStream::Ok)
types.resize(i);
}
@@ -302,20 +297,24 @@ static QVector<QTzType> parseTzIndicators(QDataStream &ds, const QVector<QTzType
{
QVector<QTzType> result = types;
bool temp;
-
- // Parse tzh_ttisstdcnt x 1-byte standard/wall indicators
- for (int i = 0; i < tzh_ttisstdcnt && ds.status() == QDataStream::Ok; ++i) {
+ /*
+ Scan and discard indicators.
+
+ These indicators are only of use (by the date program) when "handling
+ POSIX-style time zone environment variables". The flags here say whether
+ the *specification* of the zone gave the time in UTC, local standard time
+ or local wall time; but whatever was specified has been digested for us,
+ already, by the zone-info compiler (zic), so that the tz_time values read
+ from the file (by parseTzTransitions) are all in UTC.
+ */
+
+ // Scan tzh_ttisstdcnt x 1-byte standard/wall indicators
+ for (int i = 0; i < tzh_ttisstdcnt && ds.status() == QDataStream::Ok; ++i)
ds >> temp;
- if (ds.status() == QDataStream::Ok)
- result[i].tz_ttisstd = temp;
- }
- // Parse tzh_ttisgmtcnt x 1-byte UTC/local indicators
- for (int i = 0; i < tzh_ttisgmtcnt && ds.status() == QDataStream::Ok; ++i) {
+ // Scan tzh_ttisgmtcnt x 1-byte UTC/local indicators
+ for (int i = 0; i < tzh_ttisgmtcnt && ds.status() == QDataStream::Ok; ++i)
ds >> temp;
- if (ds.status() == QDataStream::Ok)
- result[i].tz_ttisgmt = temp;
- }
return result;
}
@@ -790,14 +789,7 @@ void QTzTimeZonePrivate::init(const QByteArray &ianaId)
tran.ruleIndex = ruleIndex;
}
- // TODO convert to UTC if not in UTC
- if (tz_type.tz_ttisgmt)
- tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000;
- else if (tz_type.tz_ttisstd)
- tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000;
- else
- tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000;
-
+ tran.atMSecsSinceEpoch = tz_tran.tz_time * 1000;
m_tranTimes.append(tran);
}
diff --git a/src/corelib/tools/qtimezoneprivate_win.cpp b/src/corelib/tools/qtimezoneprivate_win.cpp
index f963e10333..a50227d3cc 100644
--- a/src/corelib/tools/qtimezoneprivate_win.cpp
+++ b/src/corelib/tools/qtimezoneprivate_win.cpp
@@ -386,7 +386,7 @@ static QLocale::Country userCountry()
const GEOID id = GetUserGeoID(GEOCLASS_NATION);
wchar_t code[3];
const int size = GetGeoInfo(id, GEO_ISO2, code, 3, 0);
- return (size == 3) ? QLocalePrivate::codeToCountry(reinterpret_cast<const QChar*>(code), size)
+ return (size == 3) ? QLocalePrivate::codeToCountry(QStringView(code, size))
: QLocale::AnyCountry;
}
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index d99eebd4b9..90311ac55b 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -56,9 +56,6 @@
QT_BEGIN_NAMESPACE
-template<class T, int Prealloc>
-class QPodList;
-
// Prealloc = 256 by default, specified in qcontainerfwd.h
template<class T, int Prealloc>
class QVarLengthArray
@@ -234,9 +231,9 @@ public:
inline const T &front() const { return first(); }
inline T &back() { return last(); }
inline const T &back() const { return last(); }
+ void shrink_to_fit() { squeeze(); }
private:
- friend class QPodList<T, Prealloc>;
void realloc(int size, int alloc);
int a; // capacity
diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc
index 127afcd069..be2bdeda07 100644
--- a/src/corelib/tools/qvarlengtharray.qdoc
+++ b/src/corelib/tools/qvarlengtharray.qdoc
@@ -190,6 +190,12 @@
\overload
*/
+/*! \fn void QVarLengthArray::shrink_to_fit()
+ \since 5.10
+
+ Same as squeeze(). Provided for STL-compatibility.
+*/
+
/*! \fn bool QVarLengthArray::isEmpty() const
Returns \c true if the array has size 0; otherwise returns \c false.
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 57e80ae125..2d12a95b4b 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -147,8 +147,8 @@ public:
void remove(int i, int n);
inline void removeFirst() { Q_ASSERT(!isEmpty()); erase(d->begin()); }
inline void removeLast();
- inline T takeFirst() { Q_ASSERT(!isEmpty()); T r = first(); removeFirst(); return r; }
- inline T takeLast() { Q_ASSERT(!isEmpty()); T r = last(); removeLast(); return r; }
+ T takeFirst() { Q_ASSERT(!isEmpty()); T r = std::move(first()); removeFirst(); return r; }
+ T takeLast() { Q_ASSERT(!isEmpty()); T r = std::move(last()); removeLast(); return r; }
QVector<T> &fill(const T &t, int size = -1);
@@ -180,7 +180,7 @@ public:
return true;
}
int length() const { return size(); }
- T takeAt(int i) { T t = at(i); remove(i); return t; }
+ T takeAt(int i) { T t = std::move((*this)[i]); remove(i); return t; }
void move(int from, int to)
{
Q_ASSERT_X(from >= 0 && from < size(), "QVector::move(int,int)", "'from' is out-of-range");
@@ -268,6 +268,7 @@ public:
inline const_reference front() const { return first(); }
inline reference back() { return last(); }
inline const_reference back() const { return last(); }
+ void shrink_to_fit() { squeeze(); }
// comfort
QVector<T> &operator+=(const QVector<T> &l);
@@ -994,6 +995,8 @@ Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPointF>;
Q_TEMPLATE_EXTERN template class Q_CORE_EXPORT QVector<QPoint>;
#endif
+QVector<uint> QStringView::toUcs4() const { return qConvertToUcs4(*this); }
+
QT_END_NAMESPACE
#endif // QVECTOR_H
diff --git a/src/corelib/tools/qvector.qdoc b/src/corelib/tools/qvector.qdoc
index 0ea47b1a1a..61fb3d494d 100644
--- a/src/corelib/tools/qvector.qdoc
+++ b/src/corelib/tools/qvector.qdoc
@@ -1124,6 +1124,13 @@
\overload
*/
+/*! \fn void QVector::shrink_to_fit()
+ \since 5.10
+
+ This function is provided for STL compatibility. It is equivalent
+ to squeeze().
+*/
+
/*! \fn bool QVector::empty() const
This function is provided for STL compatibility. It is equivalent
diff --git a/src/corelib/tools/qversionnumber.cpp b/src/corelib/tools/qversionnumber.cpp
index 97e5da8b3c..0f237bce87 100644
--- a/src/corelib/tools/qversionnumber.cpp
+++ b/src/corelib/tools/qversionnumber.cpp
@@ -406,10 +406,8 @@ QString QVersionNumber::toString() const
return version;
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
- \fn QVersionNumber QVersionNumber::fromString(const QString &string,
- int *suffixIndex)
-
Constructs a QVersionNumber from a specially formatted \a string of
non-negative decimal numbers delimited by '.'.
@@ -423,14 +421,53 @@ QString QVersionNumber::toString() const
*/
QVersionNumber QVersionNumber::fromString(const QString &string, int *suffixIndex)
{
- QVector<int> seg;
+ return fromString(QLatin1String(string.toLatin1()), suffixIndex);
+}
+#endif
+
+/*!
+ \since 5.10
+ \overload
+
+ Constructs a QVersionNumber from a specially formatted \a string of
+ non-negative decimal numbers delimited by '.'.
+
+ Once the numerical segments have been parsed, the remainder of the string
+ is considered to be the suffix string. The start index of that string will be
+ stored in \a suffixIndex if it is not null.
+
+ \snippet qversionnumber/main.cpp 3
+
+ \sa isNull()
+*/
+QVersionNumber QVersionNumber::fromString(QStringView string, int *suffixIndex)
+{
+ return fromString(QLatin1String(string.toLatin1()), suffixIndex);
+}
+
+/*!
+ \since 5.10
+ \overload
- const QByteArray cString(string.toLatin1());
+ Constructs a QVersionNumber from a specially formatted \a string of
+ non-negative decimal numbers delimited by '.'.
+
+ Once the numerical segments have been parsed, the remainder of the string
+ is considered to be the suffix string. The start index of that string will be
+ stored in \a suffixIndex if it is not null.
+
+ \snippet qversionnumber/main.cpp 3-latin1-1
+
+ \sa isNull()
+*/
+QVersionNumber QVersionNumber::fromString(QLatin1String string, int *suffixIndex)
+{
+ QVector<int> seg;
- const char *start = cString.constData();
+ const char *start = string.begin();
const char *end = start;
const char *lastGoodEnd = start;
- const char *endOfString = cString.constData() + cString.size();
+ const char *endOfString = string.end();
do {
bool ok = false;
@@ -443,7 +480,7 @@ QVersionNumber QVersionNumber::fromString(const QString &string, int *suffixInde
} while (start < endOfString && (end < endOfString && *end == '.'));
if (suffixIndex)
- *suffixIndex = int(lastGoodEnd - cString.constData());
+ *suffixIndex = int(lastGoodEnd - string.begin());
return QVersionNumber(qMove(seg));
}
diff --git a/src/corelib/tools/qversionnumber.h b/src/corelib/tools/qversionnumber.h
index d3cf743a67..3836bc2119 100644
--- a/src/corelib/tools/qversionnumber.h
+++ b/src/corelib/tools/qversionnumber.h
@@ -280,7 +280,11 @@ public:
Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber commonPrefix(const QVersionNumber &v1, const QVersionNumber &v2);
Q_REQUIRED_RESULT Q_CORE_EXPORT QString toString() const;
+#if QT_STRINGVIEW_LEVEL < 2
Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(const QString &string, int *suffixIndex = Q_NULLPTR);
+#endif
+ Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QLatin1String string, int *suffixIndex = nullptr);
+ Q_REQUIRED_RESULT Q_CORE_EXPORT static Q_DECL_PURE_FUNCTION QVersionNumber fromString(QStringView string, int *suffixIndex = nullptr);
private:
#ifndef QT_NO_DATASTREAM
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index b705d4221a..aa545497a2 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -39,7 +39,6 @@ HEADERS += \
tools/qmargins.h \
tools/qmessageauthenticationcode.h \
tools/qcontiguouscache.h \
- tools/qpodlist_p.h \
tools/qpair.h \
tools/qpoint.h \
tools/qqueue.h \
@@ -58,11 +57,14 @@ HEADERS += \
tools/qsize.h \
tools/qstack.h \
tools/qstring.h \
+ tools/qstringalgorithms.h \
tools/qstringalgorithms_p.h \
tools/qstringbuilder.h \
tools/qstringiterator_p.h \
tools/qstringlist.h \
+ tools/qstringliteral.h \
tools/qstringmatcher.h \
+ tools/qstringview.h \
tools/qtextboundaryfinder.h \
tools/qtimeline.h \
tools/qtools_p.h \
@@ -107,6 +109,7 @@ SOURCES += \
tools/qstring.cpp \
tools/qstringbuilder.cpp \
tools/qstringlist.cpp \
+ tools/qstringview.cpp \
tools/qtextboundaryfinder.cpp \
tools/qtimeline.cpp \
tools/qunicodetools.cpp \
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp
index af35193b13..f6ae3571ab 100644
--- a/src/corelib/xml/qxmlstream.cpp
+++ b/src/corelib/xml/qxmlstream.cpp
@@ -775,8 +775,8 @@ QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
tagStackStringStorage.reserve(32);
tagStackStringStorageSize = 0;
NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
- namespaceDeclaration.prefix = addToStringStorage(QLatin1String("xml"));
- namespaceDeclaration.namespaceUri = addToStringStorage(QLatin1String("http://www.w3.org/XML/1998/namespace"));
+ namespaceDeclaration.prefix = addToStringStorage(QStringViewLiteral("xml"));
+ namespaceDeclaration.namespaceUri = addToStringStorage(QStringViewLiteral("http://www.w3.org/XML/1998/namespace"));
initialTagStackStringStorageSize = tagStackStringStorageSize;
}
@@ -796,11 +796,17 @@ QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
reallocateStack();
entityResolver = 0;
init();
- entityHash.insert(QLatin1String("lt"), Entity::createLiteral(QLatin1String("<")));
- entityHash.insert(QLatin1String("gt"), Entity::createLiteral(QLatin1String(">")));
- entityHash.insert(QLatin1String("amp"), Entity::createLiteral(QLatin1String("&")));
- entityHash.insert(QLatin1String("apos"), Entity::createLiteral(QLatin1String("'")));
- entityHash.insert(QLatin1String("quot"), Entity::createLiteral(QLatin1String("\"")));
+#define ADD_PREDEFINED(n, v) \
+ do { \
+ Entity e = Entity::createLiteral(QLatin1String(n), QLatin1String(v)); \
+ entityHash.insert(qToStringViewIgnoringNull(e.name), std::move(e)); \
+ } while (false)
+ ADD_PREDEFINED("lt", "<");
+ ADD_PREDEFINED("gt", ">");
+ ADD_PREDEFINED("amp", "&");
+ ADD_PREDEFINED("apos", "'");
+ ADD_PREDEFINED("quot", "\"");
+#undef ADD_PREDEFINED
}
void QXmlStreamReaderPrivate::init()
@@ -1558,7 +1564,7 @@ QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
#if 1
if (namespaceProcessing && !prefix.isEmpty())
- raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix.toString()));
+ raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix));
#endif
return QStringRef();
@@ -1636,7 +1642,7 @@ void QXmlStreamReaderPrivate::resolveTag()
if (attributes[j].name() == attribute.name()
&& attributes[j].namespaceUri() == attribute.namespaceUri()
&& (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName()))
- raiseWellFormedError(QXmlStream::tr("Attribute '%1' redefined.").arg(attribute.qualifiedName().toString()));
+ raiseWellFormedError(QXmlStream::tr("Attribute '%1' redefined.").arg(attribute.qualifiedName()));
}
}
@@ -1798,20 +1804,19 @@ void QXmlStreamReaderPrivate::startDocument()
QStringRef value(symString(attrib.value));
if (prefix.isEmpty() && key == QLatin1String("encoding")) {
- const QString name(value.toString());
documentEncoding = value;
if(hasStandalone)
err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding.");
- if(!QXmlUtils::isEncName(name))
- err = QXmlStream::tr("%1 is an invalid encoding name.").arg(name);
+ if (!QXmlUtils::isEncName(value))
+ err = QXmlStream::tr("%1 is an invalid encoding name.").arg(value);
else {
#ifdef QT_NO_TEXTCODEC
readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
#else
- QTextCodec *const newCodec = QTextCodec::codecForName(name.toLatin1());
+ QTextCodec *const newCodec = QTextCodec::codecForName(value.toLatin1());
if (!newCodec)
- err = QXmlStream::tr("Encoding %1 is unsupported").arg(name);
+ err = QXmlStream::tr("Encoding %1 is unsupported").arg(value);
else if (newCodec != codec && !lockEncoding) {
codec = newCodec;
delete decoder;
@@ -1881,32 +1886,25 @@ void QXmlStreamReaderPrivate::parseError()
}
}
- error_message.clear ();
if (nexpected && nexpected < nmax) {
- bool first = true;
-
- for (int s = 0; s < nexpected; ++s) {
- if (first)
- error_message += QXmlStream::tr ("Expected ");
- else if (s == nexpected - 1)
- error_message += QLatin1String (nexpected > 2 ? ", or " : " or ");
- else
- error_message += QLatin1String (", ");
-
- first = false;
- error_message += QLatin1String("\'");
- error_message += QLatin1String (spell [expected[s]]);
- error_message += QLatin1String("\'");
+ //: '<first option>'
+ QString exp_str = QXmlStream::tr("'%1'", "expected").arg(QLatin1String(spell[expected[0]]));
+ if (nexpected == 2) {
+ //: <first option>, '<second option>'
+ exp_str = QXmlStream::tr("%1 or '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[1]]));
+ } else if (nexpected > 2) {
+ int s = 1;
+ for (; s < nexpected - 1; ++s) {
+ //: <options so far>, '<next option>'
+ exp_str = QXmlStream::tr("%1, '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[s]]));
+ }
+ //: <options so far>, or '<final option>'
+ exp_str = QXmlStream::tr("%1, or '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[s]]));
}
- error_message += QXmlStream::tr(", but got \'");
- error_message += QLatin1String(spell [token]);
- error_message += QLatin1String("\'");
+ error_message = QXmlStream::tr("Expected %1, but got '%2'.").arg(exp_str, QLatin1String(spell[token]));
} else {
- error_message += QXmlStream::tr("Unexpected \'");
- error_message += QLatin1String(spell [token]);
- error_message += QLatin1String("\'");
+ error_message = QXmlStream::tr("Unexpected '%1'.").arg(QLatin1String(spell[token]));
}
- error_message += QLatin1Char('.');
raiseWellFormedError(error_message);
}
diff --git a/src/corelib/xml/qxmlstream.g b/src/corelib/xml/qxmlstream.g
index 567d36d4b9..fd69a6e4af 100644
--- a/src/corelib/xml/qxmlstream.g
+++ b/src/corelib/xml/qxmlstream.g
@@ -201,23 +201,22 @@ public:
QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations;
QString tagStackStringStorage;
int tagStackStringStorageSize;
+ int initialTagStackStringStorageSize;
bool tagsDone;
inline QStringRef addToStringStorage(const QStringRef &s) {
- int pos = tagStackStringStorageSize;
- int sz = s.size();
- if (pos != tagStackStringStorage.size())
- tagStackStringStorage.resize(pos);
- tagStackStringStorage.insert(pos, s.unicode(), sz);
- tagStackStringStorageSize += sz;
- return QStringRef(&tagStackStringStorage, pos, sz);
+ return addToStringStorage(qToStringViewIgnoringNull(s));
}
inline QStringRef addToStringStorage(const QString &s) {
+ return addToStringStorage(qToStringViewIgnoringNull(s));
+ }
+ QStringRef addToStringStorage(QStringView s)
+ {
int pos = tagStackStringStorageSize;
int sz = s.size();
if (pos != tagStackStringStorage.size())
tagStackStringStorage.resize(pos);
- tagStackStringStorage.insert(pos, s.unicode(), sz);
+ tagStackStringStorage.append(s.data(), sz);
tagStackStringStorageSize += sz;
return QStringRef(&tagStackStringStorage, pos, sz);
}
@@ -259,20 +258,24 @@ public:
int readBufferPos;
QXmlStreamSimpleStack<uint> putStack;
struct Entity {
- Entity(const QString& str = QString())
- :value(str), external(false), unparsed(false), literal(false),
+ Entity() = default;
+ Entity(const QString &name, const QString &value)
+ : name(name), value(value), external(false), unparsed(false), literal(false),
hasBeenParsed(false), isCurrentlyReferenced(false){}
- static inline Entity createLiteral(const QString &entity)
- { Entity result(entity); result.literal = result.hasBeenParsed = true; return result; }
- QString value;
+ static inline Entity createLiteral(QLatin1String name, QLatin1String value)
+ { Entity result(name, value); result.literal = result.hasBeenParsed = true; return result; }
+ QString name, value;
uint external : 1;
uint unparsed : 1;
uint literal : 1;
uint hasBeenParsed : 1;
uint isCurrentlyReferenced : 1;
};
- QHash<QString, Entity> entityHash;
- QHash<QString, Entity> parameterEntityHash;
+ // these hash tables use a QStringView as a key to avoid creating QStrings
+ // just for lookup. The keys are usually views into Entity::name and thus
+ // are guaranteed to have the same lifetime as the referenced data:
+ QHash<QStringView, Entity> entityHash;
+ QHash<QStringView, Entity> parameterEntityHash;
QXmlStreamSimpleStack<Entity *>entityReferenceStack;
inline bool referenceEntity(Entity &entity) {
if (entity.isCurrentlyReferenced) {
@@ -425,6 +428,11 @@ public:
const Value &symbol = sym(index);
return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
}
+ QStringView symView(int index) const
+ {
+ const Value &symbol = sym(index);
+ return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
+ }
inline QStringRef symName(int index) {
const Value &symbol = sym(index);
return QStringRef(&textBuffer, symbol.pos, symbol.len);
@@ -455,7 +463,7 @@ public:
short token;
- ushort token_char;
+ uint token_char;
uint filterCarriageReturn();
inline uint getChar();
@@ -466,7 +474,7 @@ public:
void putStringLiteral(const QString &s);
void putReplacement(const QString &s);
void putReplacementInAttributeValue(const QString &s);
- ushort getChar_helper();
+ uint getChar_helper();
bool scanUntil(const char *str, short tokenToInject = -1);
bool scanString(const char *str, short tokenToInject, bool requireSpace = true);
@@ -525,10 +533,8 @@ bool QXmlStreamReaderPrivate::parse()
prefix.clear();
qualifiedName.clear();
namespaceUri.clear();
- if (publicNamespaceDeclarations.size())
- publicNamespaceDeclarations.clear();
- if (attributes.size())
- attributes.resize(0);
+ publicNamespaceDeclarations.clear();
+ attributes.clear();
if (isEmptyElement) {
setType(QXmlStreamReader::EndElement);
Tag &tag = tagStack_pop();
@@ -553,7 +559,7 @@ bool QXmlStreamReaderPrivate::parse()
dtdName.clear();
dtdPublicId.clear();
dtdSystemId.clear();
- // fall through
+ Q_FALLTHROUGH();
case QXmlStreamReader::Comment:
case QXmlStreamReader::Characters:
isCDATA = false;
@@ -579,13 +585,13 @@ bool QXmlStreamReaderPrivate::parse()
documentVersion.clear();
documentEncoding.clear();
#ifndef QT_NO_TEXTCODEC
- if (decoder->hasFailure()) {
+ if (decoder && decoder->hasFailure()) {
raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
readBuffer.clear();
return false;
}
#endif
- // fall through
+ Q_FALLTHROUGH();
default:
clearTextBuffer();
;
@@ -610,8 +616,8 @@ bool QXmlStreamReaderPrivate::parse()
if (token == -1 && - TERMINAL_COUNT != action_index[act]) {
uint cu = getChar();
token = NOTOKEN;
- token_char = cu;
- if (cu & 0xff0000) {
+ token_char = cu == ~0U ? cu : ushort(cu);
+ if ((cu != ~0U) && (cu & 0xff0000)) {
token = cu >> 16;
} else switch (token_char) {
case 0xfffe:
@@ -629,8 +635,8 @@ bool QXmlStreamReaderPrivate::parse()
} else {
break;
}
- // fall through
- case '\0': {
+ Q_FALLTHROUGH();
+ case ~0U: {
token = EOF_SYMBOL;
if (!tagsDone && !inParseEntity) {
int a = t_action(act, token);
@@ -644,6 +650,7 @@ bool QXmlStreamReaderPrivate::parse()
case '\n':
++lineNumber;
lastLineStart = characterOffset + readBufferPos;
+ Q_FALLTHROUGH();
case ' ':
case '\t':
token = SPACE;
@@ -1127,7 +1134,7 @@ entity_decl ::= entity_decl_external NDATA name space_opt RANGLE;
if (entityDeclaration.parameter)
raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration."));
}
- //fall through
+ Q_FALLTHROUGH();
./
entity_decl ::= entity_decl_external space_opt RANGLE;
@@ -1144,13 +1151,13 @@ entity_decl ::= entity_decl_start entity_value space_opt RANGLE;
EntityDeclaration &entityDeclaration = entityDeclarations.top();
if (!entityDeclaration.external)
entityDeclaration.value = symString(2);
- QString entityName = entityDeclaration.name.toString();
- QHash<QString, Entity> &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
- if (!hash.contains(entityName)) {
- Entity entity(entityDeclaration.value.toString());
+ auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
+ if (!hash.contains(qToStringViewIgnoringNull(entityDeclaration.name))) {
+ Entity entity(entityDeclaration.name.toString(),
+ entityDeclaration.value.toString());
entity.unparsed = (!entityDeclaration.notationName.isNull());
entity.external = entityDeclaration.external;
- hash.insert(entityName, entity);
+ hash.insert(qToStringViewIgnoringNull(entity.name), entity);
}
} break;
./
@@ -1164,12 +1171,12 @@ processing_instruction ::= LANGLE QUESTIONMARK name space;
processingInstructionTarget = symString(3);
if (scanUntil("?>")) {
processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
- const QString piTarget(processingInstructionTarget.toString());
- if (!piTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
+ if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
}
- else if(!QXmlUtils::isNCName(piTarget))
- raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.").arg(piTarget));
+ else if (!QXmlUtils::isNCName(processingInstructionTarget))
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.")
+ .arg(processingInstructionTarget));
} else if (type != QXmlStreamReader::Invalid){
resume($rule_number);
return false;
@@ -1182,7 +1189,7 @@ processing_instruction ::= LANGLE QUESTIONMARK name QUESTIONMARK RANGLE;
case $rule_number:
setType(QXmlStreamReader::ProcessingInstruction);
processingInstructionTarget = symString(3);
- if (!processingInstructionTarget.toString().compare(QLatin1String("xml"), Qt::CaseInsensitive))
+ if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive))
raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
break;
./
@@ -1281,7 +1288,7 @@ scan_content_char ::= content_char;
/.
case $rule_number:
isWhitespace = false;
- // fall through
+ Q_FALLTHROUGH();
./
scan_content_char ::= SPACE;
@@ -1379,8 +1386,8 @@ literal_content ::= literal_content_start;
public_literal ::= literal;
/.
case $rule_number: {
- if (!QXmlUtils::isPublicID(symString(1).toString())) {
- raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1).toString()));
+ if (!QXmlUtils::isPublicID(symString(1))) {
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1)));
resume($rule_number);
return false;
}
@@ -1567,7 +1574,7 @@ empty_element_tag ::= stag_start attribute_list_opt SLASH RANGLE;
/.
case $rule_number:
isEmptyElement = true;
- // fall through
+ Q_FALLTHROUGH();
./
@@ -1614,7 +1621,7 @@ entity_ref ::= AMPERSAND name SEMICOLON;
/.
case $rule_number: {
sym(1).len += sym(2).len + 1;
- QString reference = symString(2).toString();
+ QStringView reference = symView(2);
if (entityHash.contains(reference)) {
Entity &entity = entityHash[reference];
if (entity.unparsed) {
@@ -1635,7 +1642,7 @@ entity_ref ::= AMPERSAND name SEMICOLON;
}
if (entityResolver) {
- QString replacementText = resolveUndeclaredEntity(reference);
+ QString replacementText = resolveUndeclaredEntity(reference.toString());
if (!replacementText.isNull()) {
putReplacement(replacementText);
textBuffer.chop(2 + sym(2).len);
@@ -1656,7 +1663,7 @@ pereference ::= PERCENT name SEMICOLON;
/.
case $rule_number: {
sym(1).len += sym(2).len + 1;
- QString reference = symString(2).toString();
+ QStringView reference = symView(2);
if (parameterEntityHash.contains(reference)) {
referenceToParameterEntityDetected = true;
Entity &entity = parameterEntityHash[reference];
@@ -1669,7 +1676,7 @@ pereference ::= PERCENT name SEMICOLON;
clearSym();
}
} else if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2).toString()));
+ raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2)));
}
} break;
./
@@ -1687,7 +1694,7 @@ entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON;
/.
case $rule_number: {
sym(1).len += sym(2).len + 1;
- QString reference = symString(2).toString();
+ QStringView reference = symView(2);
if (entityHash.contains(reference)) {
Entity &entity = entityHash[reference];
if (entity.unparsed || entity.value.isNull()) {
@@ -1708,7 +1715,7 @@ entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON;
}
if (entityResolver) {
- QString replacementText = resolveUndeclaredEntity(reference);
+ QString replacementText = resolveUndeclaredEntity(reference.toString());
if (!replacementText.isNull()) {
putReplacement(replacementText);
textBuffer.chop(2 + sym(2).len);
diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h
index 9ef95c1fbe..5645d812eb 100644
--- a/src/corelib/xml/qxmlstream_p.h
+++ b/src/corelib/xml/qxmlstream_p.h
@@ -701,20 +701,18 @@ public:
bool tagsDone;
inline QStringRef addToStringStorage(const QStringRef &s) {
- int pos = tagStackStringStorageSize;
- int sz = s.size();
- if (pos != tagStackStringStorage.size())
- tagStackStringStorage.resize(pos);
- tagStackStringStorage.insert(pos, s.unicode(), sz);
- tagStackStringStorageSize += sz;
- return QStringRef(&tagStackStringStorage, pos, sz);
+ return addToStringStorage(qToStringViewIgnoringNull(s));
}
inline QStringRef addToStringStorage(const QString &s) {
+ return addToStringStorage(qToStringViewIgnoringNull(s));
+ }
+ QStringRef addToStringStorage(QStringView s)
+ {
int pos = tagStackStringStorageSize;
int sz = s.size();
if (pos != tagStackStringStorage.size())
tagStackStringStorage.resize(pos);
- tagStackStringStorage.insert(pos, s.unicode(), sz);
+ tagStackStringStorage.append(s.data(), sz);
tagStackStringStorageSize += sz;
return QStringRef(&tagStackStringStorage, pos, sz);
}
@@ -756,20 +754,24 @@ public:
int readBufferPos;
QXmlStreamSimpleStack<uint> putStack;
struct Entity {
- Entity(const QString& str = QString())
- :value(str), external(false), unparsed(false), literal(false),
+ Entity() = default;
+ Entity(const QString &name, const QString &value)
+ : name(name), value(value), external(false), unparsed(false), literal(false),
hasBeenParsed(false), isCurrentlyReferenced(false){}
- static inline Entity createLiteral(const QString &entity)
- { Entity result(entity); result.literal = result.hasBeenParsed = true; return result; }
- QString value;
+ static inline Entity createLiteral(QLatin1String name, QLatin1String value)
+ { Entity result(name, value); result.literal = result.hasBeenParsed = true; return result; }
+ QString name, value;
uint external : 1;
uint unparsed : 1;
uint literal : 1;
uint hasBeenParsed : 1;
uint isCurrentlyReferenced : 1;
};
- QHash<QString, Entity> entityHash;
- QHash<QString, Entity> parameterEntityHash;
+ // these hash tables use a QStringView as a key to avoid creating QStrings
+ // just for lookup. The keys are usually views into Entity::name and thus
+ // are guaranteed to have the same lifetime as the referenced data:
+ QHash<QStringView, Entity> entityHash;
+ QHash<QStringView, Entity> parameterEntityHash;
QXmlStreamSimpleStack<Entity *>entityReferenceStack;
inline bool referenceEntity(Entity &entity) {
if (entity.isCurrentlyReferenced) {
@@ -922,6 +924,11 @@ public:
const Value &symbol = sym(index);
return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
}
+ QStringView symView(int index) const
+ {
+ const Value &symbol = sym(index);
+ return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
+ }
inline QStringRef symName(int index) {
const Value &symbol = sym(index);
return QStringRef(&textBuffer, symbol.pos, symbol.len);
@@ -1492,13 +1499,13 @@ bool QXmlStreamReaderPrivate::parse()
EntityDeclaration &entityDeclaration = entityDeclarations.top();
if (!entityDeclaration.external)
entityDeclaration.value = symString(2);
- QString entityName = entityDeclaration.name.toString();
- QHash<QString, Entity> &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
- if (!hash.contains(entityName)) {
- Entity entity(entityDeclaration.value.toString());
+ auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash;
+ if (!hash.contains(qToStringViewIgnoringNull(entityDeclaration.name))) {
+ Entity entity(entityDeclaration.name.toString(),
+ entityDeclaration.value.toString());
entity.unparsed = (!entityDeclaration.notationName.isNull());
entity.external = entityDeclaration.external;
- hash.insert(entityName, entity);
+ hash.insert(qToStringViewIgnoringNull(entity.name), entity);
}
} break;
@@ -1508,12 +1515,12 @@ bool QXmlStreamReaderPrivate::parse()
processingInstructionTarget = symString(3);
if (scanUntil("?>")) {
processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2);
- const QString piTarget(processingInstructionTarget.toString());
- if (!piTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
+ if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) {
raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document."));
}
- else if(!QXmlUtils::isNCName(piTarget))
- raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.").arg(piTarget));
+ else if (!QXmlUtils::isNCName(processingInstructionTarget))
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.")
+ .arg(processingInstructionTarget));
} else if (type != QXmlStreamReader::Invalid){
resume(96);
return false;
@@ -1523,7 +1530,7 @@ bool QXmlStreamReaderPrivate::parse()
case 97:
setType(QXmlStreamReader::ProcessingInstruction);
processingInstructionTarget = symString(3);
- if (!processingInstructionTarget.toString().compare(QLatin1String("xml"), Qt::CaseInsensitive))
+ if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive))
raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name."));
break;
@@ -1637,8 +1644,8 @@ bool QXmlStreamReaderPrivate::parse()
break;
case 175: {
- if (!QXmlUtils::isPublicID(symString(1).toString())) {
- raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1).toString()));
+ if (!QXmlUtils::isPublicID(symString(1))) {
+ raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1)));
resume(175);
return false;
}
@@ -1793,7 +1800,7 @@ bool QXmlStreamReaderPrivate::parse()
case 240: {
sym(1).len += sym(2).len + 1;
- QString reference = symString(2).toString();
+ QStringView reference = symView(2);
if (entityHash.contains(reference)) {
Entity &entity = entityHash[reference];
if (entity.unparsed) {
@@ -1814,7 +1821,7 @@ bool QXmlStreamReaderPrivate::parse()
}
if (entityResolver) {
- QString replacementText = resolveUndeclaredEntity(reference);
+ QString replacementText = resolveUndeclaredEntity(reference.toString());
if (!replacementText.isNull()) {
putReplacement(replacementText);
textBuffer.chop(2 + sym(2).len);
@@ -1832,7 +1839,7 @@ bool QXmlStreamReaderPrivate::parse()
case 241: {
sym(1).len += sym(2).len + 1;
- QString reference = symString(2).toString();
+ QStringView reference = symView(2);
if (parameterEntityHash.contains(reference)) {
referenceToParameterEntityDetected = true;
Entity &entity = parameterEntityHash[reference];
@@ -1845,7 +1852,7 @@ bool QXmlStreamReaderPrivate::parse()
clearSym();
}
} else if (entitiesMustBeDeclared()) {
- raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2).toString()));
+ raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2)));
}
} break;
@@ -1855,7 +1862,7 @@ bool QXmlStreamReaderPrivate::parse()
case 243: {
sym(1).len += sym(2).len + 1;
- QString reference = symString(2).toString();
+ QStringView reference = symView(2);
if (entityHash.contains(reference)) {
Entity &entity = entityHash[reference];
if (entity.unparsed || entity.value.isNull()) {
@@ -1876,7 +1883,7 @@ bool QXmlStreamReaderPrivate::parse()
}
if (entityResolver) {
- QString replacementText = resolveUndeclaredEntity(reference);
+ QString replacementText = resolveUndeclaredEntity(reference.toString());
if (!replacementText.isNull()) {
putReplacement(replacementText);
textBuffer.chop(2 + sym(2).len);
diff --git a/src/corelib/xml/qxmlutils.cpp b/src/corelib/xml/qxmlutils.cpp
index 23caae2935..01c84251fd 100644
--- a/src/corelib/xml/qxmlutils.cpp
+++ b/src/corelib/xml/qxmlutils.cpp
@@ -227,19 +227,22 @@ bool QXmlUtils::isBaseChar(const QChar c)
\sa {http://www.w3.org/TR/REC-xml/#NT-EncName},
{Extensible Markup Language (XML) 1.0 (Fourth Edition), [81] EncName}
*/
-bool QXmlUtils::isEncName(const QString &encName)
+bool QXmlUtils::isEncName(QStringView encName)
{
// Valid encoding names are given by "[A-Za-z][A-Za-z0-9._\\-]*"
- const ushort *c = encName.utf16();
- int l = encName.length();
- if (l < 1 || !((c[0] >= 'a' && c[0] <= 'z') || (c[0] >= 'A' && c[0] <= 'Z')))
+ if (encName.isEmpty())
return false;
- for (int i = 1; i < l; ++i) {
- if ((c[i] >= 'a' && c[i] <= 'z')
- || (c[i] >= 'A' && c[i] <= 'Z')
- || (c[i] >= '0' && c[i] <= '9')
- || c[i] == '.' || c[i] == '_' || c[i] == '-')
+ const auto first = encName.front().unicode();
+ if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z')))
+ return false;
+ for (QChar ch : encName.mid(1)) {
+ const auto cp = ch.unicode();
+ if ((cp >= 'a' && cp <= 'z')
+ || (cp >= 'A' && cp <= 'Z')
+ || (cp >= '0' && cp <= '9')
+ || cp == '.' || cp == '_' || cp == '-') {
continue;
+ }
return false;
}
return true;
@@ -310,13 +313,10 @@ bool QXmlUtils::isNameChar(const QChar c)
\sa {http://www.w3.org/TR/REC-xml/#NT-PubidLiteral},
{Extensible Markup Language (XML) 1.0 (Fourth Edition), [12] PubidLiteral}
*/
-bool QXmlUtils::isPublicID(const QString &candidate)
+bool QXmlUtils::isPublicID(QStringView candidate)
{
- const int len = candidate.length();
-
- for(int i = 0; i < len; ++i)
- {
- const ushort cp = candidate.at(i).unicode();
+ for (QChar ch : candidate) {
+ const ushort cp = ch.unicode();
if ((cp >= 'a' && cp <= 'z')
|| (cp >= 'A' && cp <= 'Z')
@@ -369,7 +369,7 @@ bool QXmlUtils::isPublicID(const QString &candidate)
\sa {http://www.w3.org/TR/REC-xml-names/#NT-NCName},
{W3CNamespaces in XML 1.0 (Second Edition), [4] NCName}
*/
-bool QXmlUtils::isNCName(const QStringRef &ncName)
+bool QXmlUtils::isNCName(QStringView ncName)
{
if(ncName.isEmpty())
return false;
@@ -379,10 +379,7 @@ bool QXmlUtils::isNCName(const QStringRef &ncName)
if(!QXmlUtils::isLetter(first) && first.unicode() != '_' && first.unicode() != ':')
return false;
- const int len = ncName.size();
- for(int i = 0; i < len; ++i)
- {
- const QChar at = ncName.at(i);
+ for (QChar at : ncName) {
if(!QXmlUtils::isNameChar(at) || at == QLatin1Char(':'))
return false;
}
diff --git a/src/corelib/xml/qxmlutils_p.h b/src/corelib/xml/qxmlutils_p.h
index 6db347b3ee..db6bddd5be 100644
--- a/src/corelib/xml/qxmlutils_p.h
+++ b/src/corelib/xml/qxmlutils_p.h
@@ -68,13 +68,12 @@ class QXmlCharRange;
class Q_CORE_EXPORT QXmlUtils
{
public:
- static bool isEncName(const QString &encName);
+ static bool isEncName(QStringView encName);
static bool isChar(const QChar c);
static bool isNameChar(const QChar c);
static bool isLetter(const QChar c);
- static bool isNCName(const QStringRef &ncName);
- static inline bool isNCName(const QString &ncName) { return isNCName(QStringRef(&ncName)); }
- static bool isPublicID(const QString &candidate);
+ static bool isNCName(QStringView ncName);
+ static bool isPublicID(QStringView candidate);
private:
typedef const QXmlCharRange *RangeIter;
diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp
index b1f9be2c2a..ce55297abb 100644
--- a/src/dbus/qdbusserver.cpp
+++ b/src/dbus/qdbusserver.cpp
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
\a parent.
*/
QDBusServer::QDBusServer(const QString &address, QObject *parent)
- : QObject(parent), d(0)
+ : QObject(parent), d(nullptr)
{
if (address.isEmpty())
return;
@@ -83,7 +83,7 @@ QDBusServer::QDBusServer(const QString &address, QObject *parent)
localhost (elsewhere).
*/
QDBusServer::QDBusServer(QObject *parent)
- : QObject(parent)
+ : QObject(parent), d(nullptr)
{
#ifdef Q_OS_UNIX
// Use Unix sockets on Unix systems only
@@ -92,10 +92,8 @@ QDBusServer::QDBusServer(QObject *parent)
const QString address = QStringLiteral("tcp:");
#endif
- if (!qdbus_loadLibDBus()) {
- d = 0;
+ if (!qdbus_loadLibDBus())
return;
- }
QDBusConnectionManager *instance = QDBusConnectionManager::instance();
if (!instance)
diff --git a/src/gui/configure.json b/src/gui/configure.json
index 6fdeefe14a..9a7b78d536 100644
--- a/src/gui/configure.json
+++ b/src/gui/configure.json
@@ -39,7 +39,9 @@
"qpa-platform-guard": "boolean",
"sm": { "type": "boolean", "name": "sessionmanager" },
"tslib": "boolean",
+ "vulkan": "boolean",
"xcb": { "type": "enum", "values": [ "no", "yes", "qt", "system" ] },
+ "xcb-native-painting": "boolean",
"xcb-xlib": "boolean",
"xinput2": "boolean",
"xkb": "boolean",
@@ -393,6 +395,14 @@
"-lts"
]
},
+ "vulkan": {
+ "label": "Vulkan",
+ "test": "qpa/vulkan",
+ "sources": [
+ { "type": "pkgConfig", "args": "vulkan" },
+ { "type": "makeSpec", "spec": "VULKAN" }
+ ]
+ },
"wayland_server": {
"label": "Wayland Server",
"test": {
@@ -582,6 +592,13 @@
"sources": [
{ "type": "pkgConfig", "args": "xkbcommon xkbcommon-x11 >= 0.4.1" }
]
+ },
+ "xrender": {
+ "label": "XRender for native painting",
+ "test": "x11/xrender",
+ "sources": [
+ "-lXrender"
+ ]
}
},
@@ -798,6 +815,12 @@
},
"use": "opengl_es2"
},
+ "opengles32": {
+ "label": "OpenGL ES 3.2",
+ "type": "compile",
+ "test": "unix/opengles32",
+ "use": "opengl_es2"
+ },
"qpa_default_platform": {
"label": "default QPA platform",
"type": "qpaDefaultPlatform",
@@ -1014,6 +1037,14 @@
{ "type": "define", "name": "QT_OPENGL_ES_3_1" }
]
},
+ "opengles32": {
+ "label": "OpenGL ES 3.2",
+ "condition": "features.opengles31 && tests.opengles32",
+ "output": [
+ "publicFeature",
+ { "type": "define", "name": "QT_OPENGL_ES_3_2" }
+ ]
+ },
"opengl-desktop": {
"label": "Desktop OpenGL",
"enable": "input.opengl == 'desktop'",
@@ -1036,6 +1067,11 @@
"condition": "features.opengl-desktop || features.opengl-dynamic || features.opengles2",
"output": [ "publicFeature", "feature" ]
},
+ "vulkan": {
+ "label": "Vulkan",
+ "condition": "libs.vulkan",
+ "output": [ "publicFeature" ]
+ },
"openvg": {
"label": "OpenVG",
"condition": "libs.openvg",
@@ -1178,6 +1214,18 @@
"condition": "libs.xcb_glx",
"output": [ "privateFeature" ]
},
+ "xcb-native-painting": {
+ "label": "Native painting (experimental)",
+ "emitIf": "features.xcb",
+ "condition": "features.xcb-xlib && libs.xrender",
+ "output": [ "privateFeature" ]
+ },
+ "xrender": {
+ "label": "XRender for native painting",
+ "emitIf": "features.xcb && features.xcb-native-painting",
+ "condition": "features.xcb-native-painting",
+ "output": [ "privateFeature" ]
+ },
"xcb-render": {
"label": "XCB render",
"emitIf": "features.xcb",
@@ -1533,9 +1581,11 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
},
"opengles2",
"opengles3",
- "opengles31"
+ "opengles31",
+ "opengles32"
]
},
+ "vulkan",
"sessionmanager"
]
},
@@ -1578,7 +1628,7 @@ QMAKE_LIBDIR_OPENGL[_ES2] and QMAKE_LIBS_OPENGL[_ES2] in the mkspec for your pla
"section": "X11",
"condition": "features.xcb",
"entries": [
- "system-xcb", "egl_x11", "xinput2", "xkb", "xlib", "xcb-render", "xcb-glx", "xcb-xlib", "xkbcommon-system"
+ "system-xcb", "egl_x11", "xinput2", "xkb", "xlib", "xcb-render", "xcb-glx", "xcb-xlib", "xkbcommon-system", "xcb-native-painting"
]
},
{
diff --git a/src/gui/doc/qtgui.qdocconf b/src/gui/doc/qtgui.qdocconf
index bac93af775..3b3ebafc2d 100644
--- a/src/gui/doc/qtgui.qdocconf
+++ b/src/gui/doc/qtgui.qdocconf
@@ -49,6 +49,7 @@ sourcedirs += .. \
src/includes
exampledirs += ../../../examples/gui \
+ ../../../examples/vulkan \
snippets
imagedirs += images \
diff --git a/src/gui/doc/src/external-resources.qdoc b/src/gui/doc/src/external-resources.qdoc
index 480a4057be..0addbb21cd 100644
--- a/src/gui/doc/src/external-resources.qdoc
+++ b/src/gui/doc/src/external-resources.qdoc
@@ -60,3 +60,13 @@
\externalpage https://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html#directory_layout
\title Icon Theme Specification - Directory Layout
*/
+
+/*!
+ \externalpage https://www.khronos.org/vulkan/
+ \title Vulkan
+*/
+
+/*!
+ \externalpage https://www.lunarg.com/vulkan-sdk/
+ \title LunarG Vulkan SDK
+*/
diff --git a/src/gui/doc/src/qtgui.qdoc b/src/gui/doc/src/qtgui.qdoc
index a9fe520d5e..da3d419735 100644
--- a/src/gui/doc/src/qtgui.qdoc
+++ b/src/gui/doc/src/qtgui.qdoc
@@ -35,11 +35,11 @@
applications written with Qt.
The Qt GUI module provides classes for windowing system
- integration, event handling, OpenGL and OpenGL ES integration, 2D
- graphics, imaging, fonts and typography. These classes are used
- internally by Qt's user interface technologies and can also be
- used directly, for instance to write applications using low-level
- OpenGL ES graphics APIs.
+ integration, event handling, OpenGL and OpenGL ES integration,
+ Vulkan integration, 2D graphics, imaging, fonts and typography.
+ These classes are used internally by Qt's user interface technologies
+ and can also be used directly, for instance to write applications using
+ low-level OpenGL ES graphics APIs.
To include the definitions of the module's classes, use the
following directive:
@@ -170,6 +170,31 @@
+ \section1 Vulkan Integration
+
+ Qt 5.10 added support for \l {Vulkan}. This requires
+ the presence of the \l{LunarG Vulkan SDK}.
+
+ On Windows, the SDK sets the environment variable \c {VULKAN_SDK},
+ which will be detected by the \c {configure} script.
+
+ On Android, Vulkan headers were added in API level 24 of the NDK.
+
+ Relevant classes:
+
+ \list
+ \li QVulkanDeviceFunctions
+ \li QVulkanExtension
+ \li QVulkanFunctions
+ \li QVulkanInfoVector
+ \li QVulkanInstance
+ \li QVulkanWindow
+ \li QVulkanWindowRenderer
+ \endlist
+
+ For more information, see the \l{Hello Vulkan Widget Example}
+ and the \l {Hello Vulkan Window Example}.
+
\section1 Qt GUI Prior to Qt 5.0
Prior to Qt 5.0, the Qt GUI module was the monolithic container
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index f7d077e656..f8cec00b82 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -47,6 +47,7 @@ include(math3d/math3d.pri)
include(opengl/opengl.pri)
include(animation/animation.pri)
include(itemmodels/itemmodels.pri)
+include(vulkan/vulkan.pri)
QMAKE_LIBS += $$QMAKE_LIBS_GUI
diff --git a/src/gui/image/qbmphandler.cpp b/src/gui/image/qbmphandler.cpp
index 4350a5c192..c232a84e4f 100644
--- a/src/gui/image/qbmphandler.cpp
+++ b/src/gui/image/qbmphandler.cpp
@@ -49,10 +49,10 @@ QT_BEGIN_NAMESPACE
static void swapPixel01(QImage *image) // 1-bpp: swap 0 and 1 pixels
{
- int i;
+ qssize_t i;
if (image->depth() == 1 && image->colorCount() == 2) {
uint *p = (uint *)image->bits();
- int nbytes = image->byteCount();
+ qssize_t nbytes = static_cast<qssize_t>(image->sizeInBytes());
for (i=0; i<nbytes/4; i++) {
*p = ~*p;
p++;
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index fa4b4e01af..9b2e96d4b0 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -1469,8 +1469,13 @@ QString qt_findAtNxFile(const QString &baseFileName, qreal targetDevicePixelRati
return baseFileName;
int dotIndex = baseFileName.lastIndexOf(QLatin1Char('.'));
- if (dotIndex == -1) /* no dot */
+ if (dotIndex == -1) { /* no dot */
dotIndex = baseFileName.size(); /* append */
+ } else if (dotIndex >= 2 && baseFileName[dotIndex - 1] == QLatin1Char('9')
+ && baseFileName[dotIndex - 2] == QLatin1Char('.')) {
+ // If the file has a .9.* (9-patch image) extension, we must ensure that the @nx goes before it.
+ dotIndex -= 2;
+ }
QString atNxfileName = baseFileName;
atNxfileName.insert(dotIndex, QLatin1String("@2x"));
diff --git a/src/gui/image/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 349e0dfbe3..3cb6f46bd6 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -609,18 +609,18 @@ static int directorySizeDistance(const QIconDirInfo &dir, int iconsize, int icon
return INT_MAX;
}
-QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size, int scale)
+QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QThemeIconInfo &info, const QSize &size, int scale)
{
int iconsize = qMin(size.width(), size.height());
// Note that m_info.entries are sorted so that png-files
// come first
- const int numEntries = m_info.entries.size();
+ const int numEntries = info.entries.size();
// Search for exact matches first
for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = m_info.entries.at(i);
+ QIconLoaderEngineEntry *entry = info.entries.at(i);
if (directoryMatchesSize(entry->dir, iconsize, scale)) {
return entry;
}
@@ -630,7 +630,7 @@ QIconLoaderEngineEntry *QIconLoaderEngine::entryForSize(const QSize &size, int s
int minimalSize = INT_MAX;
QIconLoaderEngineEntry *closestMatch = 0;
for (int i = 0; i < numEntries; ++i) {
- QIconLoaderEngineEntry *entry = m_info.entries.at(i);
+ QIconLoaderEngineEntry *entry = info.entries.at(i);
int distance = directorySizeDistance(entry->dir, iconsize, scale);
if (distance < minimalSize) {
minimalSize = distance;
@@ -654,7 +654,7 @@ QSize QIconLoaderEngine::actualSize(const QSize &size, QIcon::Mode mode,
ensureLoaded();
- QIconLoaderEngineEntry *entry = entryForSize(size);
+ QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry) {
const QIconDirInfo &dir = entry->dir;
if (dir.type == QIconDirInfo::Scalable)
@@ -718,7 +718,7 @@ QPixmap QIconLoaderEngine::pixmap(const QSize &size, QIcon::Mode mode,
{
ensureLoaded();
- QIconLoaderEngineEntry *entry = entryForSize(size);
+ QIconLoaderEngineEntry *entry = entryForSize(m_info, size);
if (entry)
return entry->pixmap(size, mode, state);
@@ -767,7 +767,7 @@ void QIconLoaderEngine::virtual_hook(int id, void *data)
QIconEngine::ScaledPixmapArgument &arg = *reinterpret_cast<QIconEngine::ScaledPixmapArgument*>(data);
// QIcon::pixmap() multiplies size by the device pixel ratio.
const int integerScale = qCeil(arg.scale);
- QIconLoaderEngineEntry *entry = entryForSize(arg.size / integerScale, integerScale);
+ QIconLoaderEngineEntry *entry = entryForSize(m_info, arg.size / integerScale, integerScale);
arg.pixmap = entry ? entry->pixmap(arg.size, arg.mode, arg.state) : QPixmap();
}
break;
diff --git a/src/gui/image/qiconloader_p.h b/src/gui/image/qiconloader_p.h
index 5f3a3ef948..9398bca585 100644
--- a/src/gui/image/qiconloader_p.h
+++ b/src/gui/image/qiconloader_p.h
@@ -132,12 +132,13 @@ public:
bool read(QDataStream &in) Q_DECL_OVERRIDE;
bool write(QDataStream &out) const Q_DECL_OVERRIDE;
+ Q_GUI_EXPORT static QIconLoaderEngineEntry *entryForSize(const QThemeIconInfo &info, const QSize &size, int scale = 1);
+
private:
QString key() const Q_DECL_OVERRIDE;
bool hasIcon() const;
void ensureLoaded();
void virtual_hook(int id, void *data) Q_DECL_OVERRIDE;
- QIconLoaderEngineEntry *entryForSize(const QSize &size, int scale = 1);
QIconLoaderEngine(const QIconLoaderEngine &other);
QThemeIconInfo m_info;
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index b2e5ac93b1..4412e722f6 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -127,11 +127,11 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format)
const int bytes_per_line = ((width * depth + 31) >> 5) << 2; // bytes per scanline (must be multiple of 4)
// sanity check for potential overflows
- if (INT_MAX/depth < width
+ if (std::numeric_limits<int>::max()/depth < width
|| bytes_per_line <= 0
|| height <= 0
- || INT_MAX/uint(bytes_per_line) < height
- || INT_MAX/sizeof(uchar *) < uint(height))
+ || std::numeric_limits<qssize_t>::max()/uint(bytes_per_line) < height
+ || std::numeric_limits<int>::max()/sizeof(uchar *) < uint(height))
return 0;
QScopedPointer<QImageData> d(new QImageData);
@@ -452,7 +452,7 @@ bool QImageData::checkForAlphaPixels() const
used. For more information see the
\l {QImage#Image Formats}{Image Formats} section.
- The format(), bytesPerLine(), and byteCount() functions provide
+ The format(), bytesPerLine(), and sizeInBytes() functions provide
low-level information about the data stored in the image.
The cacheKey() function returns a number that uniquely
@@ -1448,26 +1448,43 @@ void QImage::setDevicePixelRatio(qreal scaleFactor)
/*!
\since 4.6
+ \obsolete
Returns the number of bytes occupied by the image data.
- \sa bytesPerLine(), bits(), {QImage#Image Information}{Image
+ Note this method should never be called on an image larger than 2 gigabytes.
+ Instead use sizeInBytes().
+
+ \sa sizeInBytes(), bytesPerLine(), bits(), {QImage#Image Information}{Image
Information}
*/
int QImage::byteCount() const
{
+ Q_ASSERT(!d || d->nbytes < std::numeric_limits<int>::max());
+ return d ? int(d->nbytes) : 0;
+}
+
+/*!
+ \since 5.10
+ Returns the image data size in bytes.
+
+ \sa byteCount(), bytesPerLine(), bits(), {QImage#Image Information}{Image
+ Information}
+*/
+qssize_t QImage::sizeInBytes() const
+{
return d ? d->nbytes : 0;
}
/*!
Returns the number of bytes per image scanline.
- This is equivalent to byteCount() / height().
+ This is equivalent to sizeInBytes() / height() if height() is non-zero.
\sa scanLine()
*/
int QImage::bytesPerLine() const
{
- return (d && d->height) ? d->nbytes / d->height : 0;
+ return d ? d->bytes_per_line : 0;
}
@@ -1594,7 +1611,7 @@ const uchar *QImage::constScanLine(int i) const
data, thus ensuring that this QImage is the only one using the
current return value.
- \sa scanLine(), byteCount(), constBits()
+ \sa scanLine(), sizeInBytes(), constBits()
*/
uchar *QImage::bits()
{
@@ -4675,12 +4692,12 @@ QImage QImage::transformed(const QTransform &matrix, Qt::TransformationMode mode
if (dImage.d->colortable.size() < 256) {
// colors are left in the color table, so pick that one as transparent
dImage.d->colortable.append(0x0);
- memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.byteCount());
+ memset(dImage.bits(), dImage.d->colortable.size() - 1, dImage.d->nbytes);
} else {
- memset(dImage.bits(), 0, dImage.byteCount());
+ memset(dImage.bits(), 0, dImage.d->nbytes);
}
} else
- memset(dImage.bits(), 0x00, dImage.byteCount());
+ memset(dImage.bits(), 0x00, dImage.d->nbytes);
if (target_format >= QImage::Format_RGB32) {
// Prevent QPainter from applying devicePixelRatio corrections
@@ -4785,7 +4802,7 @@ QDebug operator<<(QDebug dbg, const QImage &i)
if (i.colorCount())
dbg << ",colorCount=" << i.colorCount();
dbg << ",devicePixelRatio=" << i.devicePixelRatio()
- << ",bytesPerLine=" << i.bytesPerLine() << ",byteCount=" << i.byteCount();
+ << ",bytesPerLine=" << i.bytesPerLine() << ",sizeInBytes=" << i.sizeInBytes();
}
dbg << ')';
return dbg;
@@ -4807,7 +4824,7 @@ QDebug operator<<(QDebug dbg, const QImage &i)
Returns the number of bytes occupied by the image data.
- \sa byteCount()
+ \sa sizeInBytes()
*/
/*!
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 225ef3d2e8..eccff480bb 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -214,7 +214,10 @@ public:
const uchar *bits() const;
const uchar *constBits() const;
- int byteCount() const;
+#if QT_DEPRECATED_SINCE(5, 10)
+ QT_DEPRECATED int byteCount() const;
+#endif
+ qssize_t sizeInBytes() const;
uchar *scanLine(int);
const uchar *scanLine(int) const;
@@ -468,7 +471,7 @@ inline void QImage::setNumColors(int n)
inline int QImage::numBytes() const
{
- return byteCount();
+ return int(sizeInBytes());
}
#endif
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 50fad1566c..6abaa2887e 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -40,6 +40,7 @@
#include <private/qdrawhelper_p.h>
#include <private/qguiapplication_p.h>
#include <private/qcolorprofile_p.h>
+#include <private/qendian_p.h>
#include <private/qsimd_p.h>
#include <private/qimage_p.h>
#include <qendian.h>
@@ -126,8 +127,8 @@ static const uint *QT_FASTCALL convertRGB32FromARGB32PM(uint *buffer, const uint
return buffer;
}
-static const uint *QT_FASTCALL convertRGB32ToARGB32PM(uint *buffer, const uint *src, int count,
- const QVector<QRgb> *, QDitherInfo *)
+static const uint *QT_FASTCALL maskRGB32(uint *buffer, const uint *src, int count,
+ const QVector<QRgb> *, QDitherInfo *)
{
for (int i = 0; i < count; ++i)
buffer[i] = 0xff000000 |src[i];
@@ -160,8 +161,9 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
// If the source doesn't have an alpha channel, we can use the faster convertFromRGB32 method.
convertFromARGB32PM = destLayout->convertFromRGB32;
} else {
+ // The drawhelpers do not mask the alpha value in RGB32, we want to here.
if (src->format == QImage::Format_RGB32)
- convertToARGB32PM = convertRGB32ToARGB32PM;
+ convertToARGB32PM = maskRGB32;
if (dest->format == QImage::Format_RGB32) {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
@@ -171,6 +173,15 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
convertFromARGB32PM = convertRGB32FromARGB32PM;
}
}
+ if ((src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888) &&
+ destLayout->alphaWidth == 0 && destLayout->convertFromRGB32) {
+ // Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
+ convertToARGB32PM = qPixelLayouts[src->format + 1].convertToARGB32PM;
+ if (dest->format == QImage::Format_RGB32)
+ convertFromARGB32PM = maskRGB32;
+ else
+ convertFromARGB32PM = destLayout->convertFromRGB32;
+ }
QDitherInfo dither;
QDitherInfo *ditherPtr = 0;
if ((flags & Qt::PreferDither) && (flags & Qt::Dither_Mask) != Qt::ThresholdDither)
@@ -221,7 +232,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
convertFromARGB32PM = destLayout->convertFromRGB32;
} else {
if (data->format == QImage::Format_RGB32)
- convertToARGB32PM = convertRGB32ToARGB32PM;
+ convertToARGB32PM = maskRGB32;
if (dst_format == QImage::Format_RGB32) {
#ifdef QT_COMPILER_SUPPORTS_SSE4_1
if (qCpuHasFeature(SSE4_1))
@@ -231,6 +242,15 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
convertFromARGB32PM = convertRGB32FromARGB32PM;
}
}
+ if ((data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888) &&
+ destLayout->alphaWidth == 0 && destLayout->convertFromRGB32) {
+ // Avoid unnecessary premultiply and unpremultiply when converting from unpremultiplied src format.
+ convertToARGB32PM = qPixelLayouts[data->format + 1].convertToARGB32PM;
+ if (dst_format == QImage::Format_RGB32)
+ convertFromARGB32PM = maskRGB32;
+ else
+ convertFromARGB32PM = destLayout->convertFromRGB32;
+ }
QDitherInfo dither;
QDitherInfo *ditherPtr = 0;
if ((flags & Qt::PreferDither) && (flags & Qt::Dither_Mask) != Qt::ThresholdDither)
@@ -322,10 +342,10 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32(quint32 *dest_data, con
// Handle 4 pixels at a time 12 bytes input to 16 bytes output.
for (; pixel + 3 < len; pixel += 4) {
- const quint32 *src_packed = (const quint32 *) src_data;
- const quint32 src1 = qFromBigEndian(src_packed[0]);
- const quint32 src2 = qFromBigEndian(src_packed[1]);
- const quint32 src3 = qFromBigEndian(src_packed[2]);
+ const quint32_be *src_packed = reinterpret_cast<const quint32_be *>(src_data);
+ const quint32 src1 = src_packed[0];
+ const quint32 src2 = src_packed[1];
+ const quint32 src3 = src_packed[2];
dest_data[0] = 0xff000000 | (src1 >> 8);
dest_data[1] = 0xff000000 | (src1 << 16) | (src2 >> 16);
@@ -803,8 +823,8 @@ static bool convert_indexed8_to_ARGB_PM_inplace(QImageData *data, Qt::ImageConve
const int depth = 32;
- const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
- const int nbytes = dst_bytes_per_line * data->height;
+ const qssize_t dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
+ const qssize_t nbytes = dst_bytes_per_line * data->height;
uchar *const newData = (uchar *)realloc(data->data, nbytes);
if (!newData)
return false;
@@ -857,8 +877,8 @@ static bool convert_indexed8_to_ARGB_inplace(QImageData *data, Qt::ImageConversi
const int depth = 32;
- const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
- const int nbytes = dst_bytes_per_line * data->height;
+ const qssize_t dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
+ const qssize_t nbytes = dst_bytes_per_line * data->height;
uchar *const newData = (uchar *)realloc(data->data, nbytes);
if (!newData)
return false;
@@ -925,8 +945,8 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers
const int depth = 16;
- const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
- const int nbytes = dst_bytes_per_line * data->height;
+ const qssize_t dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
+ const qssize_t nbytes = dst_bytes_per_line * data->height;
uchar *const newData = (uchar *)realloc(data->data, nbytes);
if (!newData)
return false;
@@ -982,8 +1002,8 @@ static bool convert_RGB_to_RGB16_inplace(QImageData *data, Qt::ImageConversionFl
const int depth = 16;
- const int dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
- const int src_bytes_per_line = data->bytes_per_line;
+ const qssize_t dst_bytes_per_line = ((data->width * depth + 31) >> 5) << 2;
+ const qssize_t src_bytes_per_line = data->bytes_per_line;
quint32 *src_data = (quint32 *) data->data;
quint16 *dst_data = (quint16 *) data->data;
@@ -1237,9 +1257,9 @@ void dither_to_Mono(QImageData *dst, const QImageData *src,
}
uchar *dst_data = dst->data;
- int dst_bpl = dst->bytes_per_line;
+ qssize_t dst_bpl = dst->bytes_per_line;
const uchar *src_data = src->data;
- int src_bpl = src->bytes_per_line;
+ qssize_t src_bpl = src->bytes_per_line;
switch (dithermode) {
case Diffuse: {
@@ -1892,8 +1912,8 @@ static void convert_Indexed8_to_Alpha8(QImageData *dest, const QImageData *src,
if (simpleCase)
memcpy(dest->data, src->data, src->bytes_per_line * src->height);
else {
- int size = src->bytes_per_line * src->height;
- for (int i = 0; i < size; ++i) {
+ qssize_t size = src->bytes_per_line * src->height;
+ for (qssize_t i = 0; i < size; ++i) {
dest->data[i] = translate[src->data[i]];
}
}
@@ -1916,8 +1936,8 @@ static void convert_Indexed8_to_Grayscale8(QImageData *dest, const QImageData *s
if (simpleCase)
memcpy(dest->data, src->data, src->bytes_per_line * src->height);
else {
- int size = src->bytes_per_line * src->height;
- for (int i = 0; i < size; ++i) {
+ qssize_t size = src->bytes_per_line * src->height;
+ for (qssize_t i = 0; i < size; ++i) {
dest->data[i] = translate[src->data[i]];
}
}
diff --git a/src/gui/image/qimage_darwin.mm b/src/gui/image/qimage_darwin.mm
index 3764bef06b..a5c391ad21 100644
--- a/src/gui/image/qimage_darwin.mm
+++ b/src/gui/image/qimage_darwin.mm
@@ -130,7 +130,7 @@ CGImageRef QImage::toCGImage() const
auto deleter = [](void *image, const void *, size_t)
{ delete static_cast<QImage *>(image); };
QCFType<CGDataProviderRef> dataProvider =
- CGDataProviderCreateWithData(new QImage(*this), bits(), byteCount(), deleter);
+ CGDataProviderCreateWithData(new QImage(*this), bits(), sizeInBytes(), deleter);
QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index 775ab6d541..9ba4945dc5 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -71,12 +71,12 @@ struct Q_GUI_EXPORT QImageData { // internal image data
int width;
int height;
int depth;
- int nbytes; // number of bytes data
+ qssize_t nbytes; // number of bytes data
qreal devicePixelRatio;
QVector<QRgb> colortable;
uchar *data;
QImage::Format format;
- int bytes_per_line;
+ qssize_t bytes_per_line;
int ser_no; // serial number
int detach_no;
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 381ddb5b45..7a5a630495 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -565,6 +565,16 @@ bool QImageReaderPrivate::initHandler()
// probe the file extension
if (deleteDevice && !device->isOpen() && !device->open(QIODevice::ReadOnly) && autoDetectImageFormat) {
+ Q_ASSERT(qobject_cast<QFile*>(device) != 0); // future-proofing; for now this should always be the case, so...
+ QFile *file = static_cast<QFile *>(device);
+
+ if (file->error() == QFileDevice::ResourceError) {
+ // this is bad. we should abort the open attempt and note the failure.
+ imageReaderError = QImageReader::DeviceError;
+ errorString = file->errorString();
+ return false;
+ }
+
QList<QByteArray> extensions = QImageReader::supportedImageFormats();
if (!format.isEmpty()) {
// Try the most probable extension first
@@ -575,7 +585,6 @@ bool QImageReaderPrivate::initHandler()
int currentExtension = 0;
- QFile *file = static_cast<QFile *>(device);
QString fileName = file->fileName();
do {
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index ab15d8ee29..a39d204677 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -87,6 +87,9 @@
\value UnsupportedFormatError Qt does not support the requested
image format.
+ \value InvalidImageError An attempt was made to write an invalid QImage. An
+ example of an invalid image would be a null QImage.
+
\value UnknownError An unknown error occurred. If you get this
value after calling write(), it is most likely caused by a bug in
QImageWriter.
@@ -736,6 +739,13 @@ extern void qt_imageTransform(QImage &src, QImageIOHandler::Transformations orie
*/
bool QImageWriter::write(const QImage &image)
{
+ // Do this before canWrite, so it doesn't create a file if this fails.
+ if (Q_UNLIKELY(image.isNull())) {
+ d->imageWriterError = QImageWriter::InvalidImageError;
+ d->errorString = QImageWriter::tr("Image is empty");
+ return false;
+ }
+
if (!canWrite())
return false;
diff --git a/src/gui/image/qimagewriter.h b/src/gui/image/qimagewriter.h
index 58f8c51472..fd1fdd07e8 100644
--- a/src/gui/image/qimagewriter.h
+++ b/src/gui/image/qimagewriter.h
@@ -60,7 +60,8 @@ public:
enum ImageWriterError {
UnknownError,
DeviceError,
- UnsupportedFormatError
+ UnsupportedFormatError,
+ InvalidImageError
};
QImageWriter();
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index a1ca857daa..2ff9fb4e36 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -161,6 +161,8 @@
This signal is emitted by QMovie when the error \a error occurred during
playback. QMovie will stop the movie, and enter QMovie::NotRunning state.
+
+ \sa lastError(), lastErrorString()
*/
/*! \fn void QMovie::finished()
@@ -328,6 +330,8 @@ int QMoviePrivate::speedAdjustedDelay(int delay) const
*/
QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
{
+ Q_Q(QMovie);
+
if (frameNumber < 0)
return QFrameInfo(); // Invalid
@@ -356,7 +360,8 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
reader = new QImageReader(device, format);
else
reader = new QImageReader(absoluteFilePath, format);
- (void)reader->canRead(); // Provoke a device->open() call
+ if (!reader->canRead()) // Provoke a device->open() call
+ emit q->error(reader->error());
reader->device()->seek(initialDevicePos);
reader->setBackgroundColor(bgColor);
reader->setScaledSize(scaledSize);
@@ -523,8 +528,20 @@ void QMoviePrivate::_q_loadNextFrame(bool starting)
*/
bool QMoviePrivate::isValid() const
{
- return (greatestFrameNumber >= 0) // have we seen valid data
- || reader->canRead(); // or does the reader see valid data
+ Q_Q(const QMovie);
+
+ if (greatestFrameNumber >= 0)
+ return true; // have we seen valid data
+ bool canRead = reader->canRead();
+ if (!canRead) {
+ // let the consumer know it's broken
+ //
+ // ### the const_cast here is ugly, but 'const' of this method is
+ // technically wrong right now, since it may cause the underlying device
+ // to open.
+ emit const_cast<QMovie*>(q)->error(reader->error());
+ }
+ return canRead;
}
/*!
@@ -775,6 +792,8 @@ QImage QMovie::currentImage() const
/*!
Returns \c true if the movie is valid (e.g., the image data is readable and
the image format is supported); otherwise returns \c false.
+
+ For information about why the movie is not valid, see lastError().
*/
bool QMovie::isValid() const
{
@@ -783,6 +802,29 @@ bool QMovie::isValid() const
}
/*!
+ Returns the most recent error that occurred while attempting to read image data.
+
+ \sa lastErrorString()
+*/
+QImageReader::ImageReaderError QMovie::lastError() const
+{
+ Q_D(const QMovie);
+ return d->reader->error();
+}
+
+/*!
+ Returns a human-readable representation of the most recent error that occurred
+ while attempting to read image data.
+
+ \sa lastError()
+*/
+QString QMovie::lastErrorString() const
+{
+ Q_D(const QMovie);
+ return d->reader->errorString();
+}
+
+/*!
Returns the number of frames in the movie.
Certain animation formats do not support this feature, in which
diff --git a/src/gui/image/qmovie.h b/src/gui/image/qmovie.h
index 930d502892..ca559d491b 100644
--- a/src/gui/image/qmovie.h
+++ b/src/gui/image/qmovie.h
@@ -105,6 +105,8 @@ public:
QPixmap currentPixmap() const;
bool isValid() const;
+ QImageReader::ImageReaderError lastError() const;
+ QString lastErrorString() const;
bool jumpToFrame(int frameNumber);
int loopCount() const;
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index 7506e2e1a9..a9c3482209 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -1194,6 +1194,7 @@ QT_BEGIN_INCLUDE_NAMESPACE
#include "qpictureformatplugin.h"
QT_END_INCLUDE_NAMESPACE
+#if QT_DEPRECATED_SINCE(5, 0)
/*!
\obsolete
@@ -1279,6 +1280,7 @@ QList<QByteArray> QPicture::outputFormats()
{
return QPictureIO::outputFormats();
}
+#endif // QT_DEPRECATED_SINCE(5, 0)
/*****************************************************************************
QPictureIO member functions
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index 8da11caee4..2d505d1d06 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -90,11 +90,13 @@ public:
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &in, const QPicture &p);
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &in, QPicture &p);
- static const char* pictureFormat(const QString &fileName);
- static QList<QByteArray> inputFormats();
- static QList<QByteArray> outputFormats();
- static QStringList inputFormatList();
- static QStringList outputFormatList();
+#if QT_DEPRECATED_SINCE(5, 0)
+ static QT_DEPRECATED const char* pictureFormat(const QString &fileName);
+ static QT_DEPRECATED QList<QByteArray> inputFormats();
+ static QT_DEPRECATED QList<QByteArray> outputFormats();
+ static QT_DEPRECATED QStringList inputFormatList();
+ static QT_DEPRECATED QStringList outputFormatList();
+#endif // QT_DEPRECATED_SINCE(5, 0)
QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 0aa05a04e2..5b3e3985a7 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -596,44 +596,7 @@ void QPixmap::setMask(const QBitmap &mask)
return;
detach();
-
- QImage image = data->toImage();
- if (mask.size().isEmpty()) {
- if (image.depth() != 1) { // hw: ????
- image = image.convertToFormat(QImage::Format_RGB32);
- }
- } else {
- const int w = image.width();
- const int h = image.height();
-
- switch (image.depth()) {
- case 1: {
- const QImage imageMask = mask.toImage().convertToFormat(image.format());
- for (int y = 0; y < h; ++y) {
- const uchar *mscan = imageMask.scanLine(y);
- uchar *tscan = image.scanLine(y);
- int bytesPerLine = image.bytesPerLine();
- for (int i = 0; i < bytesPerLine; ++i)
- tscan[i] &= mscan[i];
- }
- break;
- }
- default: {
- const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
- image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
- for (int y = 0; y < h; ++y) {
- const uchar *mscan = imageMask.scanLine(y);
- QRgb *tscan = (QRgb *)image.scanLine(y);
- for (int x = 0; x < w; ++x) {
- if (!(mscan[x>>3] & (1 << (x&7))))
- tscan[x] = 0;
- }
- }
- break;
- }
- }
- }
- data->fromImage(image, Qt::AutoColor);
+ data->setMask(mask);
}
/*!
@@ -1496,37 +1459,7 @@ QPaintEngine *QPixmap::paintEngine() const
*/
QBitmap QPixmap::mask() const
{
- if (!data || !hasAlphaChannel())
- return QBitmap();
-
- const QImage img = toImage();
- bool shouldConvert = (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied);
- const QImage image = (shouldConvert ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
- const int w = image.width();
- const int h = image.height();
-
- QImage mask(w, h, QImage::Format_MonoLSB);
- if (mask.isNull()) // allocation failed
- return QBitmap();
-
- mask.setColorCount(2);
- mask.setColor(0, QColor(Qt::color0).rgba());
- mask.setColor(1, QColor(Qt::color1).rgba());
-
- const int bpl = mask.bytesPerLine();
-
- for (int y = 0; y < h; ++y) {
- const QRgb *src = reinterpret_cast<const QRgb*>(image.scanLine(y));
- uchar *dest = mask.scanLine(y);
- memset(dest, 0, bpl);
- for (int x = 0; x < w; ++x) {
- if (qAlpha(*src) > 0)
- dest[x >> 3] |= (1 << (x & 7));
- ++src;
- }
- }
-
- return QBitmap::fromImage(mask);
+ return data ? data->mask() : QBitmap();
}
/*!
diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp
index 950695a9d7..de32327071 100644
--- a/src/gui/image/qpixmap_blitter.cpp
+++ b/src/gui/image/qpixmap_blitter.cpp
@@ -190,8 +190,8 @@ void QBlittablePlatformPixmap::fromImage(const QImage &image,
uchar *mem = thisImg->bits();
const uchar *bits = correctFormatPic.constBits();
- int bytesCopied = 0;
- while (bytesCopied < correctFormatPic.byteCount()) {
+ qssize_t bytesCopied = 0;
+ while (bytesCopied < correctFormatPic.sizeInBytes()) {
memcpy(mem,bits,correctFormatPic.bytesPerLine());
mem += thisImg->bytesPerLine();
bits += correctFormatPic.bytesPerLine();
diff --git a/src/gui/image/qplatformpixmap.cpp b/src/gui/image/qplatformpixmap.cpp
index 00c21a5f54..b123afb4db 100644
--- a/src/gui/image/qplatformpixmap.cpp
+++ b/src/gui/image/qplatformpixmap.cpp
@@ -160,6 +160,82 @@ bool QPlatformPixmap::scroll(int dx, int dy, const QRect &rect)
return false;
}
+QBitmap QPlatformPixmap::mask() const
+{
+ if (!hasAlphaChannel())
+ return QBitmap();
+
+ const QImage img = toImage();
+ bool shouldConvert = (img.format() != QImage::Format_ARGB32 && img.format() != QImage::Format_ARGB32_Premultiplied);
+ const QImage image = (shouldConvert ? img.convertToFormat(QImage::Format_ARGB32_Premultiplied) : img);
+ const int w = image.width();
+ const int h = image.height();
+
+ QImage mask(w, h, QImage::Format_MonoLSB);
+ if (mask.isNull()) // allocation failed
+ return QBitmap();
+
+ mask.setColorCount(2);
+ mask.setColor(0, QColor(Qt::color0).rgba());
+ mask.setColor(1, QColor(Qt::color1).rgba());
+
+ const int bpl = mask.bytesPerLine();
+
+ for (int y = 0; y < h; ++y) {
+ const QRgb *src = reinterpret_cast<const QRgb*>(image.scanLine(y));
+ uchar *dest = mask.scanLine(y);
+ memset(dest, 0, bpl);
+ for (int x = 0; x < w; ++x) {
+ if (qAlpha(*src) > 0)
+ dest[x >> 3] |= (1 << (x & 7));
+ ++src;
+ }
+ }
+
+ return QBitmap::fromImage(mask);
+}
+
+void QPlatformPixmap::setMask(const QBitmap &mask)
+{
+ QImage image = toImage();
+ if (mask.size().isEmpty()) {
+ if (image.depth() != 1) { // hw: ????
+ image = image.convertToFormat(QImage::Format_RGB32);
+ }
+ } else {
+ const int w = image.width();
+ const int h = image.height();
+
+ switch (image.depth()) {
+ case 1: {
+ const QImage imageMask = mask.toImage().convertToFormat(image.format());
+ for (int y = 0; y < h; ++y) {
+ const uchar *mscan = imageMask.scanLine(y);
+ uchar *tscan = image.scanLine(y);
+ int bytesPerLine = image.bytesPerLine();
+ for (int i = 0; i < bytesPerLine; ++i)
+ tscan[i] &= mscan[i];
+ }
+ break;
+ }
+ default: {
+ const QImage imageMask = mask.toImage().convertToFormat(QImage::Format_MonoLSB);
+ image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+ for (int y = 0; y < h; ++y) {
+ const uchar *mscan = imageMask.scanLine(y);
+ QRgb *tscan = (QRgb *)image.scanLine(y);
+ for (int x = 0; x < w; ++x) {
+ if (!(mscan[x>>3] & (1 << (x&7))))
+ tscan[x] = 0;
+ }
+ }
+ break;
+ }
+ }
+ }
+ fromImage(image, Qt::AutoColor);
+}
+
QPixmap QPlatformPixmap::transformed(const QTransform &matrix,
Qt::TransformationMode mode) const
{
diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h
index 8513755cca..7635ac2949 100644
--- a/src/gui/image/qplatformpixmap.h
+++ b/src/gui/image/qplatformpixmap.h
@@ -69,7 +69,7 @@ public:
enum ClassId { RasterClass, DirectFBClass,
BlitterClass, Direct2DClass,
- CustomClass = 1024 };
+ X11Class, CustomClass = 1024 };
QPlatformPixmap(PixelType pixelType, int classId);
virtual ~QPlatformPixmap();
@@ -99,6 +99,9 @@ public:
virtual int metric(QPaintDevice::PaintDeviceMetric metric) const = 0;
virtual void fill(const QColor &color) = 0;
+ virtual QBitmap mask() const;
+ virtual void setMask(const QBitmap &mask);
+
virtual bool hasAlphaChannel() const = 0;
virtual QPixmap transformed(const QTransform &matrix,
Qt::TransformationMode mode) const;
@@ -144,6 +147,7 @@ protected:
private:
friend class QPixmap;
+ friend class QX11PlatformPixmap;
friend class QImagePixmapCleanupHooks; // Needs to set is_cached
friend class QOpenGLTextureCache; //Needs to check the reference count
friend class QExplicitlySharedDataPointer<QPlatformPixmap>;
@@ -159,7 +163,7 @@ private:
# define QT_XFORM_TYPE_MSBFIRST 0
# define QT_XFORM_TYPE_LSBFIRST 1
-extern bool qt_xForm_helper(const QTransform&, int, int, int, uchar*, int, int, int, const uchar*, int, int, int);
+Q_GUI_EXPORT bool qt_xForm_helper(const QTransform&, int, int, int, uchar*, int, int, int, const uchar*, int, int, int);
QT_END_NAMESPACE
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index ce7f7b8a0f..9c54b9ada4 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -42,6 +42,7 @@
#ifndef QT_NO_IMAGEFORMAT_XPM
#include <private/qcolor_p.h>
+#include <qbytearraymatcher.h>
#include <qimage.h>
#include <qmap.h>
#include <qtextstream.h>
@@ -1041,7 +1042,9 @@ bool qt_read_xpm_image_or_array(QIODevice *device, const char * const * source,
if ((readBytes = device->readLine(buf.data(), buf.size())) < 0)
return false;
- if (buf.indexOf("/* XPM") != 0) {
+ static Q_RELAXED_CONSTEXPR auto matcher = qMakeStaticByteArrayMatcher("/* XPM");
+
+ if (matcher.indexIn(buf) != 0) {
while (readBytes > 0) {
device->ungetChar(buf.at(readBytes - 1));
--readBytes;
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index cd8406b8dc..771f0fe93d 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -487,7 +487,7 @@ void QClipboard::setMimeData(QMimeData* src, Mode mode)
QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
if (!clipboard->supportsMode(mode)) {
if (src != 0) {
- qWarning("Data set on unsupported clipboard mode. QMimeData object will be deleted.");
+ qDebug("Data set on unsupported clipboard mode. QMimeData object will be deleted.");
src->deleteLater();
}
} else {
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index b7035d47c4..8ae9085d9f 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -471,6 +471,54 @@ QCursor::QCursor(Qt::CursorShape shape)
setShape(shape);
}
+/*!
+ \fn bool operator==(const QCursor &lhs, const QCursor &rhs)
+ \relates QCursor
+ \since 5.10
+
+ Equality operator. Returns \c true if \a lhs and \a rhs
+ have the same \l{QCursor::}{shape()} and, in the case of
+ \l{Qt::BitmapCursor}{bitmap cursors}, the same \l{QCursor::}{hotSpot()}
+ and either the same \l{QCursor::}{pixmap()} or the same
+ \l{QCursor::}{bitmap()} and \l{QCursor::}{mask()}.
+
+ \note When comparing bitmap cursors, this function only
+ compares the bitmaps' \l{QPixmap::cacheKey()}{cache keys},
+ not each pixel.
+
+ \sa operator!=(const QCursor &lhs, const QCursor &rhs)
+*/
+bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW
+{
+ if (lhs.d == rhs.d)
+ return true; // Copy or same shape
+
+ // Check pixmaps or bitmaps cache keys. Notice that having BitmapCursor
+ // shape implies either non-null pixmap or non-null bitmap and mask
+ if (lhs.shape() == Qt::BitmapCursor && rhs.shape() == Qt::BitmapCursor
+ && lhs.hotSpot() == rhs.hotSpot()) {
+ if (!lhs.d->pixmap.isNull())
+ return lhs.d->pixmap.cacheKey() == rhs.d->pixmap.cacheKey();
+
+ if (!rhs.d->pixmap.isNull())
+ return false;
+
+ return lhs.d->bm->cacheKey() == rhs.d->bm->cacheKey()
+ && lhs.d->bmm->cacheKey() == rhs.d->bmm->cacheKey();
+ }
+
+ return false;
+}
+
+/*!
+ \fn bool operator!=(const QCursor &lhs, const QCursor &rhs)
+ \relates QCursor
+ \since 5.10
+
+ Inequality operator. Returns the equivalent of !(\a lhs == \a rhs).
+
+ \sa operator==(const QCursor &lhs, const QCursor &rhs)
+*/
/*!
Returns the cursor shape identifier. The return value is one of
diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h
index c7e9188e5b..ccce3d84ef 100644
--- a/src/gui/kernel/qcursor.h
+++ b/src/gui/kernel/qcursor.h
@@ -112,10 +112,14 @@ public:
inline static void setPos(QScreen *screen, const QPoint &p) { setPos(screen, p.x(), p.y()); }
private:
+ friend Q_GUI_EXPORT bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW;
QCursorData *d;
};
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QCursor)
+Q_GUI_EXPORT bool operator==(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW;
+inline bool operator!=(const QCursor &lhs, const QCursor &rhs) Q_DECL_NOTHROW { return !(lhs == rhs); }
+
/*****************************************************************************
QCursor stream functions
*****************************************************************************/
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
index a59612474b..3af7f5c181 100644
--- a/src/gui/kernel/qdnd.cpp
+++ b/src/gui/kernel/qdnd.cpp
@@ -71,14 +71,11 @@ QDragManager *QDragManager::m_instance = 0;
QDragManager::QDragManager()
- : QObject(qApp), m_platformDropData(0), m_currentDropTarget(0),
+ : QObject(qApp), m_currentDropTarget(0),
m_platformDrag(QGuiApplicationPrivate::platformIntegration()->drag()),
m_object(0)
{
Q_ASSERT(!m_instance);
-
- if (m_platformDrag)
- m_platformDropData = m_platformDrag->platformDropData();
}
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index 6f2ec46252..eaf6c74fd4 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -134,7 +134,6 @@ public:
QObject *source() const;
private:
- QMimeData *m_platformDropData;
QObject *m_currentDropTarget;
QPlatformDrag *m_platformDrag;
QDrag *m_object;
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 680acb16e7..5000cc35dd 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -1525,7 +1525,11 @@ QMoveEvent::~QMoveEvent()
\ingroup events
Expose events are sent to windows when an area of the window is invalidated
- or window visibility in the windowing system changes.
+ or window exposure in the windowing system changes.
+
+ A Window with a client area that is completely covered by another window, or
+ is otherwise not visible may be considered obscured by Qt and may in such
+ cases not receive expose events.
The event handler QWindow::exposeEvent() receives expose events.
*/
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index f43329afd0..a29ddbe44e 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -164,8 +164,6 @@ QString *QGuiApplicationPrivate::desktopFileName = 0;
QPalette *QGuiApplicationPrivate::app_pal = 0; // default application palette
-Qt::MouseButtons QGuiApplicationPrivate::buttons = Qt::NoButton;
-
ulong QGuiApplicationPrivate::mousePressTime = 0;
Qt::MouseButton QGuiApplicationPrivate::mousePressButton = Qt::NoButton;
int QGuiApplicationPrivate::mousePressX = 0;
@@ -570,6 +568,15 @@ static QWindowGeometrySpecification windowGeometrySpecification = Q_WINDOW_GEOME
\li \c {dialogs=[xp|none]}, \c xp uses XP-style native dialogs and
\c none disables them.
\li \c {fontengine=freetype}, uses the FreeType font engine.
+ \li \c {menus=[native|none]}, controls the use of native menus.
+
+ Native menus are implemented using Win32 API and are simpler than
+ QMenu-based menus in for example that they do allow for placing
+ widgets on them or changing properties like fonts and do not
+ provide hover signals. They are mainly intended for Qt Quick.
+ By default, they will be used if the application is not an
+ instance of QApplication or for Qt Quick Controls 2
+ applications.
\endlist
For more information about the platform-specific arguments available for
@@ -1838,7 +1845,7 @@ void QGuiApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePriv
void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e)
{
QEvent::Type type;
- Qt::MouseButtons stateChange = e->buttons ^ buttons;
+ Qt::MouseButtons stateChange = e->buttons ^ mouse_buttons;
if (e->globalPos != QGuiApplicationPrivate::lastCursorPosition && (stateChange != Qt::NoButton)) {
// A mouse event should not change both position and buttons at the same time. Instead we
// should first send a move event followed by a button changed event. Since this is not the case
@@ -1847,7 +1854,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
e->window.data(), e->timestamp, e->type, e->localPos, e->globalPos, e->buttons, e->modifiers, e->source);
if (e->flags & QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic)
mouseButtonEvent.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
- e->buttons = buttons;
+ e->buttons = mouse_buttons;
processMouseEvent(e);
processMouseEvent(&mouseButtonEvent);
return;
@@ -1901,7 +1908,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
// Ignore mouse events that don't change the current state.
return;
}
- mouse_buttons = buttons = e->buttons;
+ mouse_buttons = e->buttons;
if (button & e->buttons) {
ulong doubleClickInterval = static_cast<ulong>(QGuiApplication::styleHints()->mouseDoubleClickInterval());
doubleClick = e->timestamp - mousePressTime < doubleClickInterval && button == mousePressButton;
@@ -1926,14 +1933,14 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
const QPointF nativeLocalPoint = QHighDpi::toNativePixels(localPoint, screen);
const QPointF nativeGlobalPoint = QHighDpi::toNativePixels(globalPoint, screen);
QMouseEvent ev(type, nativeLocalPoint, nativeLocalPoint, nativeGlobalPoint,
- button, buttons, e->modifiers, e->source);
+ button, mouse_buttons, e->modifiers, e->source);
ev.setTimestamp(e->timestamp);
cursor->pointerEvent(ev);
}
}
#endif
- QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers, e->source);
+ QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, mouse_buttons, e->modifiers, e->source);
ev.setTimestamp(e->timestamp);
if (window->d_func()->blockedByModalWindow && !qApp->d_func()->popupActive()) {
@@ -1967,7 +1974,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
point.state = Qt::TouchPointPressed;
} else if (type == QEvent::MouseButtonRelease && button == Qt::LeftButton) {
point.state = Qt::TouchPointReleased;
- } else if (type == QEvent::MouseMove && (buttons & Qt::LeftButton)) {
+ } else if (type == QEvent::MouseMove && (mouse_buttons & Qt::LeftButton)) {
point.state = Qt::TouchPointMoved;
} else {
return;
@@ -1988,7 +1995,7 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
if (!e->window.isNull() || e->nullWindow()) { // QTBUG-36364, check if window closed in response to press
const QEvent::Type doubleClickType = frameStrut ? QEvent::NonClientAreaMouseButtonDblClick : QEvent::MouseButtonDblClick;
QMouseEvent dblClickEvent(doubleClickType, localPoint, localPoint, globalPoint,
- button, buttons, e->modifiers, e->source);
+ button, mouse_buttons, e->modifiers, e->source);
dblClickEvent.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(window, &dblClickEvent);
}
@@ -2022,7 +2029,7 @@ void QGuiApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::Wh
}
QWheelEvent ev(localPoint, globalPoint, e->pixelDelta, e->angleDelta, e->qt4Delta, e->qt4Orientation,
- buttons, e->modifiers, e->phase, e->source, e->inverted);
+ mouse_buttons, e->modifiers, e->phase, e->source, e->inverted);
ev.setTimestamp(e->timestamp);
QGuiApplication::sendSpontaneousEvent(window, &ev);
#else
@@ -2206,7 +2213,7 @@ void QGuiApplicationPrivate::processWindowScreenChangedEvent(QWindowSystemInterf
}
// we may have changed scaling, so trigger resize event if needed
if (window->handle()) {
- QWindowSystemInterfacePrivate::GeometryChangeEvent gce(window, QHighDpi::fromNativePixels(window->handle()->geometry(), window), QRect());
+ QWindowSystemInterfacePrivate::GeometryChangeEvent gce(window, QHighDpi::fromNativePixels(window->handle()->geometry(), window));
processGeometryChangeEvent(&gce);
}
}
@@ -2231,35 +2238,46 @@ void QGuiApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePr
if (!window)
return;
- QRect newRect = e->newGeometry;
- QRect oldRect = e->oldGeometry.isNull() ? window->d_func()->geometry : e->oldGeometry;
-
- bool isResize = oldRect.size() != newRect.size();
- bool isMove = oldRect.topLeft() != newRect.topLeft();
-
- window->d_func()->geometry = newRect;
+ const QRect lastReportedGeometry = window->d_func()->geometry;
+ const QRect requestedGeometry = e->requestedGeometry;
+ const QRect actualGeometry = e->newGeometry;
+
+ // We send size and move events only if the geometry has changed from
+ // what was last reported, or if the user tried to set a new geometry,
+ // but the window manager responded by keeping the old geometry. In the
+ // latter case we send move/resize events with the same geometry as the
+ // last reported geometry, to indicate that the window wasn't moved or
+ // resized. Note that this logic does not apply to the property changes
+ // of the window, as we don't treat them as part of this request/response
+ // protocol of QWindow/QPA.
+ const bool isResize = actualGeometry.size() != lastReportedGeometry.size()
+ || requestedGeometry.size() != actualGeometry.size();
+ const bool isMove = actualGeometry.topLeft() != lastReportedGeometry.topLeft()
+ || requestedGeometry.topLeft() != actualGeometry.topLeft();
+
+ window->d_func()->geometry = actualGeometry;
if (isResize || window->d_func()->resizeEventPending) {
- QResizeEvent e(newRect.size(), oldRect.size());
+ QResizeEvent e(actualGeometry.size(), lastReportedGeometry.size());
QGuiApplication::sendSpontaneousEvent(window, &e);
window->d_func()->resizeEventPending = false;
- if (oldRect.width() != newRect.width())
- window->widthChanged(newRect.width());
- if (oldRect.height() != newRect.height())
- window->heightChanged(newRect.height());
+ if (actualGeometry.width() != lastReportedGeometry.width())
+ window->widthChanged(actualGeometry.width());
+ if (actualGeometry.height() != lastReportedGeometry.height())
+ window->heightChanged(actualGeometry.height());
}
if (isMove) {
//### frame geometry
- QMoveEvent e(newRect.topLeft(), oldRect.topLeft());
+ QMoveEvent e(actualGeometry.topLeft(), lastReportedGeometry.topLeft());
QGuiApplication::sendSpontaneousEvent(window, &e);
- if (oldRect.x() != newRect.x())
- window->xChanged(newRect.x());
- if (oldRect.y() != newRect.y())
- window->yChanged(newRect.y());
+ if (actualGeometry.x() != lastReportedGeometry.x())
+ window->xChanged(actualGeometry.x());
+ if (actualGeometry.y() != lastReportedGeometry.y())
+ window->yChanged(actualGeometry.y());
}
}
@@ -2479,7 +2497,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
e->timestamp,
synthIt->pos,
synthIt->screenPos,
- buttons & ~Qt::LeftButton,
+ mouse_buttons & ~Qt::LeftButton,
e->modifiers,
Qt::MouseEventSynthesizedByQt);
fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
@@ -2694,7 +2712,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
QWindowSystemInterfacePrivate::MouseEvent fake(w, e->timestamp,
touchPoint.pos(),
touchPoint.screenPos(),
- b | (buttons & ~Qt::LeftButton),
+ b | (mouse_buttons & ~Qt::LeftButton),
e->modifiers,
Qt::MouseEventSynthesizedByQt);
fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
@@ -3534,6 +3552,22 @@ static inline void applyCursor(const QList<QWindow *> &l, const QCursor &c)
}
}
+static inline void applyOverrideCursor(const QList<QScreen *> &screens, const QCursor &c)
+{
+ for (QScreen *screen : screens) {
+ if (QPlatformCursor *cursor = screen->handle()->cursor())
+ cursor->setOverrideCursor(c);
+ }
+}
+
+static inline void clearOverrideCursor(const QList<QScreen *> &screens)
+{
+ for (QScreen *screen : screens) {
+ if (QPlatformCursor *cursor = screen->handle()->cursor())
+ cursor->clearOverrideCursor();
+ }
+}
+
static inline void applyWindowCursor(const QList<QWindow *> &l)
{
for (int i = 0; i < l.size(); ++i) {
@@ -3578,7 +3612,10 @@ void QGuiApplication::setOverrideCursor(const QCursor &cursor)
{
CHECK_QAPP_INSTANCE()
qGuiApp->d_func()->cursor_list.prepend(cursor);
- applyCursor(QGuiApplicationPrivate::window_list, cursor);
+ if (QPlatformCursor::capabilities().testFlag(QPlatformCursor::OverrideCursor))
+ applyOverrideCursor(QGuiApplicationPrivate::screen_list, cursor);
+ else
+ applyCursor(QGuiApplicationPrivate::window_list, cursor);
}
/*!
@@ -3600,9 +3637,15 @@ void QGuiApplication::restoreOverrideCursor()
qGuiApp->d_func()->cursor_list.removeFirst();
if (qGuiApp->d_func()->cursor_list.size() > 0) {
QCursor c(qGuiApp->d_func()->cursor_list.value(0));
- applyCursor(QGuiApplicationPrivate::window_list, c);
+ if (QPlatformCursor::capabilities().testFlag(QPlatformCursor::OverrideCursor))
+ applyOverrideCursor(QGuiApplicationPrivate::screen_list, c);
+ else
+ applyCursor(QGuiApplicationPrivate::window_list, c);
} else {
- applyWindowCursor(QGuiApplicationPrivate::window_list);
+ if (QPlatformCursor::capabilities().testFlag(QPlatformCursor::OverrideCursor))
+ clearOverrideCursor(QGuiApplicationPrivate::screen_list);
+ else
+ applyWindowCursor(QGuiApplicationPrivate::window_list);
}
}
#endif// QT_NO_CURSOR
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 3804667ef3..014ed861df 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -201,7 +201,6 @@ public:
virtual bool isWindowBlocked(QWindow *window, QWindow **blockingWindow = 0) const;
virtual bool popupActive() { return false; }
- static Qt::MouseButtons buttons;
static ulong mousePressTime;
static Qt::MouseButton mousePressButton;
static int mousePressX;
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index 01a308372e..9a3d1b0d3a 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -56,7 +56,6 @@
#if defined(Q_OS_MACX)
#include <QtCore/private/qcore_mac_p.h>
-#include <Carbon/Carbon.h>
#endif
#include <algorithm>
@@ -70,6 +69,13 @@ struct MacSpecialKey {
ushort macSymbol;
};
+// Unicode code points for the glyphs associated with these keys
+// Defined by Carbon headers but not anywhere in Cocoa
+static const int kShiftUnicode = 0x21E7;
+static const int kControlUnicode = 0x2303;
+static const int kOptionUnicode = 0x2325;
+static const int kCommandUnicode = 0x2318;
+
static const int NumEntries = 21;
static const MacSpecialKey entries[NumEntries] = {
{ Qt::Key_Escape, 0x238B },
@@ -1002,7 +1008,6 @@ int QKeySequence::assign(const QString &ks)
int QKeySequence::assign(const QString &ks, QKeySequence::SequenceFormat format)
{
QString keyseq = ks;
- QString part;
int n = 0;
int p = 0, diff = 0;
@@ -1027,9 +1032,9 @@ int QKeySequence::assign(const QString &ks, QKeySequence::SequenceFormat format)
}
}
}
- part = keyseq.left(-1 == p ? keyseq.length() : p - diff);
+ QString part = keyseq.left(-1 == p ? keyseq.length() : p - diff);
keyseq = keyseq.right(-1 == p ? 0 : keyseq.length() - (p + 1));
- d->key[n] = QKeySequencePrivate::decodeString(part, format);
+ d->key[n] = QKeySequencePrivate::decodeString(std::move(part), format);
++n;
}
return n;
@@ -1055,10 +1060,10 @@ int QKeySequence::decodeString(const QString &str)
return QKeySequencePrivate::decodeString(str, NativeText);
}
-int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::SequenceFormat format)
+int QKeySequencePrivate::decodeString(QString accel, QKeySequence::SequenceFormat format)
{
int ret = 0;
- QString accel = str.toLower();
+ accel = std::move(accel).toLower();
bool nativeText = (format == QKeySequence::NativeText);
QVector<QModifKeyName> *gmodifs;
@@ -1094,7 +1099,6 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence
<< QModifKeyName(Qt::KeypadModifier, QLatin1String("num+"));
}
}
- if (!gmodifs) return ret;
QVector<QModifKeyName> modifs;
diff --git a/src/gui/kernel/qkeysequence_p.h b/src/gui/kernel/qkeysequence_p.h
index 8ba86c31b8..fbcab5d34e 100644
--- a/src/gui/kernel/qkeysequence_p.h
+++ b/src/gui/kernel/qkeysequence_p.h
@@ -85,7 +85,7 @@ public:
static QString encodeString(int key, QKeySequence::SequenceFormat format);
// used in dbusmenu
Q_GUI_EXPORT static QString keyName(int key, QKeySequence::SequenceFormat format);
- static int decodeString(const QString &keyStr, QKeySequence::SequenceFormat format);
+ static int decodeString(QString accel, QKeySequence::SequenceFormat format);
};
#endif // QT_NO_SHORTCUT
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index 307bc5e62f..4f8276aa87 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -121,14 +121,16 @@ public:
/*!
- Creates an offscreen surface for the \a targetScreen.
+ \since 5.10
+
+ Creates an offscreen surface for the \a targetScreen with the given \a parent.
The underlying platform surface is not created until create() is called.
\sa setScreen(), create()
*/
-QOffscreenSurface::QOffscreenSurface(QScreen *targetScreen)
- : QObject(*new QOffscreenSurfacePrivate(), 0)
+QOffscreenSurface::QOffscreenSurface(QScreen *targetScreen, QObject *parent)
+ : QObject(*new QOffscreenSurfacePrivate(), parent)
, QSurface(Offscreen)
{
Q_D(QOffscreenSurface);
@@ -143,6 +145,18 @@ QOffscreenSurface::QOffscreenSurface(QScreen *targetScreen)
connect(d->screen, SIGNAL(destroyed(QObject*)), this, SLOT(screenDestroyed(QObject*)));
}
+/*!
+ Creates an offscreen surface for the \a targetScreen.
+
+ The underlying platform surface is not created until create() is called.
+
+ \sa setScreen(), create()
+*/
+QOffscreenSurface::QOffscreenSurface(QScreen *targetScreen)
+ : QOffscreenSurface(targetScreen, nullptr)
+{
+}
+
/*!
Destroys the offscreen surface.
diff --git a/src/gui/kernel/qoffscreensurface.h b/src/gui/kernel/qoffscreensurface.h
index 35c498c89a..3295ae0d40 100644
--- a/src/gui/kernel/qoffscreensurface.h
+++ b/src/gui/kernel/qoffscreensurface.h
@@ -57,7 +57,8 @@ class Q_GUI_EXPORT QOffscreenSurface : public QObject, public QSurface
Q_DECLARE_PRIVATE(QOffscreenSurface)
public:
-
+ // ### Qt 6: merge overloads
+ explicit QOffscreenSurface(QScreen *screen, QObject *parent);
explicit QOffscreenSurface(QScreen *screen = Q_NULLPTR);
virtual ~QOffscreenSurface();
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 3dc06ae60e..406fcdd226 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -1676,6 +1676,61 @@ void QOpenGLMultiGroupSharedResource::cleanup(QOpenGLContextGroup *group, QOpenG
m_groups.removeOne(group);
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QOpenGLVersionProfile &vp)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << "QOpenGLVersionProfile(";
+ if (vp.isValid()) {
+ debug << vp.version().first << '.' << vp.version().second
+ << ", profile=" << vp.profile();
+ } else {
+ debug << "invalid";
+ }
+ debug << ')';
+ return debug;
+}
+
+QDebug operator<<(QDebug debug, const QOpenGLContext *ctx)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug.noquote();
+ debug << "QOpenGLContext(";
+ if (ctx) {
+ debug << static_cast<const void *>(ctx);
+ if (ctx->isValid()) {
+ debug << ", nativeHandle=" << ctx->nativeHandle()
+ << ", format=" << ctx->format();
+ if (const QSurface *sf = ctx->surface())
+ debug << ", surface=" << sf;
+ if (const QScreen *s = ctx->screen())
+ debug << ", screen=\"" << s->name() << '"';
+ } else {
+ debug << ", invalid";
+ }
+ } else {
+ debug << '0';
+ }
+ debug << ')';
+ return debug;
+}
+
+QDebug operator<<(QDebug debug, const QOpenGLContextGroup *cg)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << "QOpenGLContextGroup(";
+ if (cg)
+ debug << cg->shares();
+ else
+ debug << '0';
+ debug << ')';
+ return debug;
+}
+#endif // QT_NO_DEBUG_STREAM
+
#include "moc_qopenglcontext.cpp"
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qopenglcontext.h b/src/gui/kernel/qopenglcontext.h
index 3ec9ce3188..07153db84e 100644
--- a/src/gui/kernel/qopenglcontext.h
+++ b/src/gui/kernel/qopenglcontext.h
@@ -69,6 +69,7 @@
QT_BEGIN_NAMESPACE
+class QDebug;
class QOpenGLContextPrivate;
class QOpenGLContextGroupPrivate;
class QOpenGLFunctions;
@@ -249,6 +250,12 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_screenDestroyed(QObject *object))
};
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QOpenGLVersionProfile &vp);
+Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QOpenGLContext *ctx);
+Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QOpenGLContextGroup *cg);
+#endif // !QT_NO_DEBUG_STREAM
+
QT_END_NAMESPACE
#endif // QT_NO_OPENGL
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index a992793246..665cc430cc 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -388,7 +388,7 @@ static void qt_palette_from_color(QPalette &pal, const QColor &button)
\warning Some styles do not use the palette for all drawing, for
instance, if they make use of native theme engines. This is the
- case for both the Windows XP, Windows Vista, and the \macos
+ case for both the Windows Vista and the \macos
styles.
\sa QApplication::setPalette(), QWidget::setPalette(), QColor
@@ -1115,14 +1115,14 @@ void QPalette::setColorGroup(ColorGroup cg, const QBrush &foreground, const QBru
Q_GUI_EXPORT QPalette qt_fusionPalette()
{
- QColor backGround(239, 235, 231);
+ QColor backGround(239, 239, 239);
QColor light = backGround.lighter(150);
QColor mid(backGround.darker(130));
QColor midLight = mid.lighter(110);
QColor base = Qt::white;
QColor disabledBase(backGround);
QColor dark = backGround.darker(150);
- QColor darkDisabled = QColor(209, 200, 191).darker(110);
+ QColor darkDisabled = QColor(209, 209, 209).darker(110);
QColor text = Qt::black;
QColor hightlightedText = Qt::white;
QColor disabledText = QColor(190, 190, 190);
@@ -1145,7 +1145,7 @@ Q_GUI_EXPORT QPalette qt_fusionPalette()
fusionPalette.setBrush(QPalette::Active, QPalette::Highlight, QColor(48, 140, 198));
fusionPalette.setBrush(QPalette::Inactive, QPalette::Highlight, QColor(48, 140, 198));
- fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 141, 126));
+ fusionPalette.setBrush(QPalette::Disabled, QPalette::Highlight, QColor(145, 145, 145));
return fusionPalette;
}
diff --git a/src/gui/kernel/qplatformcursor.cpp b/src/gui/kernel/qplatformcursor.cpp
index af0214e016..e6cf6a8216 100644
--- a/src/gui/kernel/qplatformcursor.cpp
+++ b/src/gui/kernel/qplatformcursor.cpp
@@ -95,6 +95,17 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \enum QPlatformCursor::Capability
+ \since 5.10
+
+ \value OverrideCursor Indicates that the platform implements
+ QPlatformCursor::setOverrideCursor() and
+ QPlatformCursor::clearOverrideCursor().
+*/
+
+QPlatformCursor::Capabilities QPlatformCursor::m_capabilities = 0;
+
+/*!
\fn QPlatformCursor::QPlatformCursor()
Constructs a QPlatformCursor.
@@ -659,4 +670,34 @@ void QPlatformCursorImage::set(const uchar *data, const uchar *mask,
\brief Return the cursor's hotspot
*/
+#ifndef QT_NO_CURSOR
+/*!
+ Reimplement this function in subclass to set an override cursor
+ on the associated screen and return true to indicate success.
+
+ This function can be implemented on platforms where the cursor is a
+ property of the application or the screen rather than a property
+ of the window. On these platforms, the OverrideCursor capability
+ should be set.
+
+ \sa QGuiApplication::setOverrideCursor(), Capabilities
+
+ \since 5.10
+*/
+void QPlatformCursor::setOverrideCursor(const QCursor &)
+{
+}
+
+/*!
+ Reimplement this function in subclass to clear the override cursor.
+
+ \sa QGuiApplication::clearOverrideCursor(), Capabilities
+
+ \since 5.10
+*/
+void QPlatformCursor::clearOverrideCursor()
+{
+}
+#endif // QT_NO_CURSOR
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformcursor.h b/src/gui/kernel/qplatformcursor.h
index dddd9e5831..40e8a562f8 100644
--- a/src/gui/kernel/qplatformcursor.h
+++ b/src/gui/kernel/qplatformcursor.h
@@ -78,21 +78,36 @@ private:
class Q_GUI_EXPORT QPlatformCursor : public QObject {
public:
+ enum Capability {
+ OverrideCursor = 0x1
+ };
+ Q_DECLARE_FLAGS(Capabilities, Capability)
+
QPlatformCursor();
// input methods
virtual void pointerEvent(const QMouseEvent & event) { Q_UNUSED(event); }
#ifndef QT_NO_CURSOR
virtual void changeCursor(QCursor * windowCursor, QWindow * window) = 0;
-#endif
+ virtual void setOverrideCursor(const QCursor &);
+ virtual void clearOverrideCursor();
+#endif // QT_NO_CURSOR
virtual QPoint pos() const;
virtual void setPos(const QPoint &pos);
+ static Capabilities capabilities() { return m_capabilities; }
+ static void setCapabilities(Capabilities c) { m_capabilities = c; }
+ static void setCapability(Capability c) { m_capabilities.setFlag(c); }
+
private:
friend void qt_qpa_set_cursor(QWidget * w, bool force);
friend class QApplicationPrivate;
+
+ static Capabilities m_capabilities;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformCursor::Capabilities)
+
QT_END_NAMESPACE
#endif // QPLATFORMCURSOR_H
diff --git a/src/gui/kernel/qplatformdialoghelper.cpp b/src/gui/kernel/qplatformdialoghelper.cpp
index 01cf98c7c9..ad134ebe7f 100644
--- a/src/gui/kernel/qplatformdialoghelper.cpp
+++ b/src/gui/kernel/qplatformdialoghelper.cpp
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
*/
-static const int buttonRoleLayouts[2][5][14] =
+static const int buttonRoleLayouts[2][6][14] =
{
// Qt::Horizontal
{
@@ -92,7 +92,15 @@ static const int buttonRoleLayouts[2][5][14] =
// MacModelessLayout
{ QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::ApplyRole, QPlatformDialogHelper::ActionRole, QPlatformDialogHelper::Stretch,
QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL,
- QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL }
+ QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL },
+
+ // AndroidLayout (neutral, stretch, dismissive, affirmative)
+ // https://material.io/guidelines/components/dialogs.html#dialogs-specs
+ { QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::ApplyRole, QPlatformDialogHelper::ActionRole,
+ QPlatformDialogHelper::Stretch, QPlatformDialogHelper::RejectRole | QPlatformDialogHelper::Reverse,
+ QPlatformDialogHelper::NoRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::DestructiveRole | QPlatformDialogHelper::Reverse,
+ QPlatformDialogHelper::AlternateRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::AcceptRole | QPlatformDialogHelper::Reverse,
+ QPlatformDialogHelper::YesRole | QPlatformDialogHelper::Reverse, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL }
},
// Qt::Vertical
@@ -120,10 +128,20 @@ static const int buttonRoleLayouts[2][5][14] =
// MacModelessLayout
{ QPlatformDialogHelper::ActionRole, QPlatformDialogHelper::ApplyRole, QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::Stretch,
QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL,
- QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL }
+ QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL },
+
+ // AndroidLayout
+ // (affirmative
+ // dismissive
+ // neutral)
+ // https://material.io/guidelines/components/dialogs.html#dialogs-specs
+ { QPlatformDialogHelper::YesRole, QPlatformDialogHelper::AcceptRole, QPlatformDialogHelper::AlternateRole, QPlatformDialogHelper::DestructiveRole,
+ QPlatformDialogHelper::NoRole, QPlatformDialogHelper::RejectRole, QPlatformDialogHelper::Stretch, QPlatformDialogHelper::ActionRole, QPlatformDialogHelper::ApplyRole,
+ QPlatformDialogHelper::ResetRole, QPlatformDialogHelper::HelpRole, QPlatformDialogHelper::EOL, QPlatformDialogHelper::EOL }
}
};
+
QPlatformDialogHelper::QPlatformDialogHelper()
{
qRegisterMetaType<StandardButton>();
@@ -917,6 +935,8 @@ const int *QPlatformDialogHelper::buttonLayout(Qt::Orientation orientation, Butt
policy = MacLayout;
#elif defined (Q_OS_LINUX) || defined (Q_OS_UNIX)
policy = KdeLayout;
+#elif defined (Q_OS_ANDROID)
+ policy = AndroidLayout;
#else
policy = WinLayout;
#endif
diff --git a/src/gui/kernel/qplatformdialoghelper.h b/src/gui/kernel/qplatformdialoghelper.h
index ed88c19c84..f58dcf17f0 100644
--- a/src/gui/kernel/qplatformdialoghelper.h
+++ b/src/gui/kernel/qplatformdialoghelper.h
@@ -141,13 +141,14 @@ public:
Q_ENUM(ButtonRole)
enum ButtonLayout {
- // keep this in sync with QDialogButtonBox::ButtonLayout and QMessageBox::ButtonLayout
+ // keep this in sync with QDialogButtonBox::ButtonLayout
UnknownLayout = -1,
WinLayout,
MacLayout,
KdeLayout,
GnomeLayout,
- MacModelessLayout
+ MacModelessLayout,
+ AndroidLayout
};
QPlatformDialogHelper();
diff --git a/src/gui/kernel/qplatformdrag.h b/src/gui/kernel/qplatformdrag.h
index 560f984a5b..54e6a667fe 100644
--- a/src/gui/kernel/qplatformdrag.h
+++ b/src/gui/kernel/qplatformdrag.h
@@ -95,7 +95,6 @@ public:
virtual ~QPlatformDrag();
QDrag *currentDrag() const;
- virtual QMimeData *platformDropData() = 0;
virtual Qt::DropAction drag(QDrag *m_drag) = 0;
virtual void cancelDrag();
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index fe1861e08b..873ec3a33b 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -237,6 +237,10 @@ QPlatformServices *QPlatformIntegration::services() const
is required to have this capability.
\value ApplicationIcon The platform supports setting the application icon. (since 5.5)
+
+ \value TopStackedNativeChildWindows The platform supports native child windows via
+ QWindowContainer without having to punch a transparent hole in the
+ backingstore. (since 5.10)
*/
/*!
@@ -260,7 +264,8 @@ QPlatformServices *QPlatformIntegration::services() const
bool QPlatformIntegration::hasCapability(Capability cap) const
{
- return cap == NonFullScreenWindows || cap == NativeWidgets || cap == WindowManagement;
+ return cap == NonFullScreenWindows || cap == NativeWidgets || cap == WindowManagement
+ || cap == TopStackedNativeChildWindows;
}
QPlatformPixmap *QPlatformIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
@@ -387,6 +392,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
return false;
case ShowIsMaximized:
return false;
+ case ShowShortcutsInContextMenus:
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::ShowShortcutsInContextMenus);
case PasswordMaskDelay:
return QPlatformTheme::defaultThemeHint(QPlatformTheme::PasswordMaskDelay);
case PasswordMaskCharacter:
@@ -622,4 +629,26 @@ void QPlatformIntegration::setApplicationIcon(const QIcon &icon) const
Q_UNUSED(icon);
}
+#if QT_CONFIG(vulkan)
+
+/*!
+ Factory function for QPlatformVulkanInstance. The \a instance parameter is a
+ pointer to the instance for which a platform-specific backend needs to be
+ created.
+
+ Returns a pointer to a QPlatformOpenGLContext instance or \c NULL if the context could
+ not be created.
+
+ \sa QVulkanInstance
+ \since 5.10
+*/
+QPlatformVulkanInstance *QPlatformIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
+{
+ Q_UNUSED(instance);
+ qWarning("This plugin does not support createPlatformVulkanInstance");
+ return nullptr;
+}
+
+#endif // QT_CONFIG(vulkan)
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 0449e0b4c8..eeaa7574f7 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -78,6 +78,8 @@ class QPlatformSessionManager;
class QKeyEvent;
class QPlatformOffscreenSurface;
class QOffscreenSurface;
+class QPlatformVulkanInstance;
+class QVulkanInstance;
class Q_GUI_EXPORT QPlatformIntegration
{
@@ -99,7 +101,8 @@ public:
RasterGLSurface,
AllGLFunctionsQueryable,
ApplicationIcon,
- SwitchableWidgetComposition
+ SwitchableWidgetComposition,
+ TopStackedNativeChildWindows
};
virtual ~QPlatformIntegration() { }
@@ -160,6 +163,7 @@ public:
ItemViewActivateItemOnSingleClick,
UiEffects,
WheelScrollLines,
+ ShowShortcutsInContextMenus,
};
virtual QVariant styleHint(StyleHint hint) const;
@@ -188,6 +192,10 @@ public:
virtual void beep() const;
+#if QT_CONFIG(vulkan)
+ virtual QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const;
+#endif
+
protected:
void screenAdded(QPlatformScreen *screen, bool isPrimary = false);
void destroyScreen(QPlatformScreen *screen);
diff --git a/src/gui/kernel/qplatformmenu.cpp b/src/gui/kernel/qplatformmenu.cpp
index 1eb146dd0f..0d76f2039d 100644
--- a/src/gui/kernel/qplatformmenu.cpp
+++ b/src/gui/kernel/qplatformmenu.cpp
@@ -45,6 +45,37 @@
QT_BEGIN_NAMESPACE
+QPlatformMenuItem::QPlatformMenuItem()
+{
+ m_tag = reinterpret_cast<quintptr>(this);
+}
+
+void QPlatformMenuItem::setTag(quintptr tag)
+{
+ m_tag = tag;
+}
+
+quintptr QPlatformMenuItem::tag() const
+{
+ return m_tag;
+}
+
+QPlatformMenu::QPlatformMenu()
+{
+ m_tag = reinterpret_cast<quintptr>(this);
+}
+
+void QPlatformMenu::setTag(quintptr tag)
+{
+ m_tag = tag;
+}
+
+quintptr QPlatformMenu::tag() const
+{
+ return m_tag;
+
+}
+
QPlatformMenuItem *QPlatformMenu::createMenuItem() const
{
return QGuiApplicationPrivate::platformTheme()->createPlatformMenuItem();
diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h
index f8561445b1..e3fa5c71b1 100644
--- a/src/gui/kernel/qplatformmenu.h
+++ b/src/gui/kernel/qplatformmenu.h
@@ -62,6 +62,8 @@ class Q_GUI_EXPORT QPlatformMenuItem : public QObject
{
Q_OBJECT
public:
+ QPlatformMenuItem();
+
// copied from, and must stay in sync with, QAction menu roles.
enum MenuRole { NoRole = 0, TextHeuristicRole, ApplicationSpecificRole, AboutQtRole,
AboutRole, PreferencesRole, QuitRole,
@@ -71,8 +73,8 @@ public:
RoleCount };
Q_ENUM(MenuRole)
- virtual void setTag(quintptr tag) = 0;
- virtual quintptr tag()const = 0;
+ virtual void setTag(quintptr tag);
+ virtual quintptr tag() const;
virtual void setText(const QString &text) = 0;
virtual void setIcon(const QIcon &icon) = 0;
@@ -94,12 +96,17 @@ public:
Q_SIGNALS:
void activated();
void hovered();
+
+private:
+ quintptr m_tag;
};
class Q_GUI_EXPORT QPlatformMenu : public QObject
{
Q_OBJECT
public:
+ QPlatformMenu();
+
enum MenuType { DefaultMenu = 0, EditMenu };
Q_ENUM(MenuType)
@@ -108,8 +115,8 @@ public:
virtual void syncMenuItem(QPlatformMenuItem *menuItem) = 0;
virtual void syncSeparatorsCollapsible(bool enable) = 0;
- virtual void setTag(quintptr tag) = 0;
- virtual quintptr tag()const = 0;
+ virtual void setTag(quintptr tag);
+ virtual quintptr tag() const;
virtual void setText(const QString &text) = 0;
virtual void setIcon(const QIcon &icon) = 0;
@@ -138,6 +145,9 @@ public:
Q_SIGNALS:
void aboutToShow();
void aboutToHide();
+
+private:
+ quintptr m_tag;
};
class Q_GUI_EXPORT QPlatformMenuBar : public QObject
diff --git a/src/gui/kernel/qplatformsystemtrayicon.cpp b/src/gui/kernel/qplatformsystemtrayicon.cpp
index 5481997b3c..296beda0f9 100644
--- a/src/gui/kernel/qplatformsystemtrayicon.cpp
+++ b/src/gui/kernel/qplatformsystemtrayicon.cpp
@@ -140,10 +140,19 @@ QPlatformSystemTrayIcon::~QPlatformSystemTrayIcon()
*/
/*!
+ \fn void QPlatformSystemTrayIcon::contextMenuRequested(QPoint globalPos, const QPlatformScreen *screen)
+ This signal is emitted when the context menu is requested.
+ In particular, on platforms where createMenu() returns nullptr,
+ its emission will cause QSystemTrayIcon to show a QMenu-based menu.
+ \sa activated()
+ \since 5.10
+*/
+
+/*!
\fn void QPlatformSystemTrayIcon::activated(QPlatformSystemTrayIcon::ActivationReason reason)
This signal is emitted when the user activates the system tray icon.
\a reason specifies the reason for activation.
- \sa QSystemTrayIcon::ActivationReason
+ \sa QSystemTrayIcon::ActivationReason, contextMenuRequested()
*/
/*!
diff --git a/src/gui/kernel/qplatformsystemtrayicon.h b/src/gui/kernel/qplatformsystemtrayicon.h
index c52dbfbd78..948a6c099d 100644
--- a/src/gui/kernel/qplatformsystemtrayicon.h
+++ b/src/gui/kernel/qplatformsystemtrayicon.h
@@ -49,6 +49,7 @@
QT_BEGIN_NAMESPACE
class QPlatformMenu;
+class QPlatformScreen;
class QIcon;
class QString;
class QRect;
@@ -88,6 +89,7 @@ public:
Q_SIGNALS:
void activated(QPlatformSystemTrayIcon::ActivationReason reason);
+ void contextMenuRequested(QPoint globalPos, const QPlatformScreen *screen);
void messageClicked();
};
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index 878f656f2e..ebf65eda12 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -161,6 +161,8 @@ QT_BEGIN_NAMESPACE
The default value is double the MouseDoubleClickDistance, or 10 logical pixels
if that is not specified.
+ \value ShowShortcutsInContextMenus (bool) Whether to display shortcut key sequences in context menus.
+
\sa themeHint(), QStyle::pixelMetric()
*/
@@ -516,6 +518,8 @@ QVariant QPlatformTheme::defaultThemeHint(ThemeHint hint)
return QVariant(QStringList());
case QPlatformTheme::StyleNames:
return QVariant(QStringList());
+ case QPlatformTheme::ShowShortcutsInContextMenus:
+ return QVariant(false);
case TextCursorWidth:
return QVariant(1);
case DropShadow:
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index 2ba2f8669f..f4ff418db6 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -115,7 +115,8 @@ public:
MousePressAndHoldInterval,
MouseDoubleClickDistance,
WheelScrollLines,
- TouchDoubleTapDistance
+ TouchDoubleTapDistance,
+ ShowShortcutsInContextMenus
};
enum DialogType {
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 5062bd1e77..ae39411729 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -71,6 +71,17 @@ QPlatformWindow::~QPlatformWindow()
}
/*!
+ Called as part of QWindow::create(), after constructing
+ the window. Platforms should prefer to do initialization
+ here instead of in the constructor, as the platform window
+ object will be fully constructed, and associated to the
+ corresponding QWindow, allowing synchronous event delivery.
+*/
+void QPlatformWindow::initialize()
+{
+}
+
+/*!
Returns the window which belongs to the QPlatformWindow
*/
QWindow *QPlatformWindow::window() const
@@ -105,10 +116,18 @@ QSurfaceFormat QPlatformWindow::format() const
}
/*!
- This function is called by Qt whenever a window is moved or the window is resized. The resize
- can happen programatically(from ie. user application) or by the window manager. This means that
- there is no need to call this function specifically from the window manager callback, instead
- call QWindowSystemInterface::handleGeometryChange(QWindow *w, const QRect &newRect);
+ This function is called by Qt whenever a window is moved or resized using the QWindow API.
+
+ Unless you also override QPlatformWindow::geometry(), you need to call the baseclass
+ implementation of this function in any override of QPlatformWindow::setGeometry(), as
+ QWindow::geometry() is expected to report back the set geometry until a confirmation
+ (or rejection) of the new geometry comes back from the window manager and is reported
+ via QWindowSystemInterface::handleGeometryChange().
+
+ Window move/resizes can also be triggered spontaneously by the window manager, or as a
+ response to an earlier requested move/resize via the Qt APIs. There is no need to call
+ this function from the window manager callback, instead call
+ QWindowSystemInterface::handleGeometryChange().
The position(x, y) part of the rect might be inclusive or exclusive of the window frame
as returned by frameMargins(). You can detect this in the plugin by checking
@@ -261,7 +280,7 @@ QPoint QPlatformWindow::mapFromGlobal(const QPoint &pos) const
Qt::WindowActive can be ignored.
*/
-void QPlatformWindow::setWindowState(Qt::WindowState)
+void QPlatformWindow::setWindowState(Qt::WindowStates)
{
}
diff --git a/src/gui/kernel/qplatformwindow.h b/src/gui/kernel/qplatformwindow.h
index 8af8791bb4..95d8af760c 100644
--- a/src/gui/kernel/qplatformwindow.h
+++ b/src/gui/kernel/qplatformwindow.h
@@ -74,6 +74,8 @@ public:
explicit QPlatformWindow(QWindow *window);
virtual ~QPlatformWindow();
+ virtual void initialize();
+
QWindow *window() const;
QPlatformWindow *parent() const;
@@ -89,7 +91,7 @@ public:
virtual void setVisible(bool visible);
virtual void setWindowFlags(Qt::WindowFlags flags);
- virtual void setWindowState(Qt::WindowState state);
+ virtual void setWindowState(Qt::WindowStates state);
virtual WId winId() const;
virtual void setParent(const QPlatformWindow *window);
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index 96f75f37eb..479e228e27 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -384,6 +384,10 @@ QRect QScreen::geometry() const
The available geometry is the geometry excluding window manager reserved areas
such as task bars and system menus.
+
+ Note, on X11 this will return the true available geometry only on systems with one monitor and
+ if window manager has set _NET_WORKAREA atom. In all other cases this is equal to geometry().
+ This is a limitation in X11 window manager specification.
*/
QRect QScreen::availableGeometry() const
{
diff --git a/src/gui/kernel/qsimpledrag.cpp b/src/gui/kernel/qsimpledrag.cpp
index fc62273325..481971f21a 100644
--- a/src/gui/kernel/qsimpledrag.cpp
+++ b/src/gui/kernel/qsimpledrag.cpp
@@ -353,13 +353,6 @@ QSimpleDrag::QSimpleDrag() : m_current_window(0)
{
}
-QMimeData *QSimpleDrag::platformDropData()
-{
- if (drag())
- return drag()->mimeData();
- return 0;
-}
-
void QSimpleDrag::startDrag()
{
QBasicDrag::startDrag();
diff --git a/src/gui/kernel/qsimpledrag_p.h b/src/gui/kernel/qsimpledrag_p.h
index 0b8a0bc703..45c13e43b2 100644
--- a/src/gui/kernel/qsimpledrag_p.h
+++ b/src/gui/kernel/qsimpledrag_p.h
@@ -125,7 +125,6 @@ class Q_GUI_EXPORT QSimpleDrag : public QBasicDrag
{
public:
QSimpleDrag();
- virtual QMimeData *platformDropData() Q_DECL_OVERRIDE;
protected:
virtual void startDrag() Q_DECL_OVERRIDE;
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 85c0768e35..0850228ee5 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -365,6 +365,17 @@ bool QStyleHints::showIsMaximized() const
}
/*!
+ \property QStyleHints::showShortcutsInContextMenus
+ \since 5.10
+ \brief \c true if the platform normally shows shortcut key sequences in
+ context menus, otherwise \c false.
+*/
+bool QStyleHints::showShortcutsInContextMenus() const
+{
+ return themeableHint(QPlatformTheme::ShowShortcutsInContextMenus, QPlatformIntegration::ShowShortcutsInContextMenus).toBool();
+}
+
+/*!
\property QStyleHints::passwordMaskDelay
\brief the time, in milliseconds, a typed letter is displayed unshrouded
in a text input field in password mode.
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index b9bf428edd..2c2e048b15 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -64,6 +64,7 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_PROPERTY(bool setFocusOnTouchRelease READ setFocusOnTouchRelease STORED false CONSTANT FINAL)
Q_PROPERTY(bool showIsFullScreen READ showIsFullScreen STORED false CONSTANT FINAL)
Q_PROPERTY(bool showIsMaximized READ showIsMaximized STORED false CONSTANT FINAL)
+ Q_PROPERTY(bool showShortcutsInContextMenus READ showShortcutsInContextMenus STORED false CONSTANT FINAL)
Q_PROPERTY(int startDragDistance READ startDragDistance NOTIFY startDragDistanceChanged FINAL)
Q_PROPERTY(int startDragTime READ startDragTime NOTIFY startDragTimeChanged FINAL)
Q_PROPERTY(int startDragVelocity READ startDragVelocity STORED false CONSTANT FINAL)
@@ -90,6 +91,7 @@ public:
int cursorFlashTime() const;
bool showIsFullScreen() const;
bool showIsMaximized() const;
+ bool showShortcutsInContextMenus() const;
int passwordMaskDelay() const;
QChar passwordMaskCharacter() const;
qreal fontSmoothingGamma() const;
diff --git a/src/gui/kernel/qsurface.cpp b/src/gui/kernel/qsurface.cpp
index 3cdd11de8c..63651ee822 100644
--- a/src/gui/kernel/qsurface.cpp
+++ b/src/gui/kernel/qsurface.cpp
@@ -78,6 +78,8 @@ QT_BEGIN_NAMESPACE
requires the use of private API.
\value OpenVGSurface The surface is an OpenVG compatible surface and can be used
in conjunction with OpenVG contexts.
+ \value VulkanSurface The surface is a Vulkan compatible surface and can be used
+ in conjunction with the Vulkan graphics API.
*/
diff --git a/src/gui/kernel/qsurface.h b/src/gui/kernel/qsurface.h
index a96b7a6422..7e09449d12 100644
--- a/src/gui/kernel/qsurface.h
+++ b/src/gui/kernel/qsurface.h
@@ -66,6 +66,7 @@ public:
OpenGLSurface,
RasterGLSurface,
OpenVGSurface,
+ VulkanSurface
};
virtual ~QSurface();
diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp
index 000d727380..574310f554 100644
--- a/src/gui/kernel/qsurfaceformat.cpp
+++ b/src/gui/kernel/qsurfaceformat.cpp
@@ -73,6 +73,7 @@ public:
, major(2)
, minor(0)
, swapInterval(1) // default to vsync
+ , colorSpace(QSurfaceFormat::DefaultColorSpace)
{
}
@@ -91,7 +92,8 @@ public:
profile(other->profile),
major(other->major),
minor(other->minor),
- swapInterval(other->swapInterval)
+ swapInterval(other->swapInterval),
+ colorSpace(other->colorSpace)
{
}
@@ -110,6 +112,7 @@ public:
int major;
int minor;
int swapInterval;
+ QSurfaceFormat::ColorSpace colorSpace;
};
/*!
@@ -124,6 +127,12 @@ public:
contains surface configuration parameters such as OpenGL profile and
version for rendering, whether or not to enable stereo buffers, and swap
behaviour.
+
+ \note When troubleshooting context or window format issues, it can be
+ helpful to enable the logging category \c{qt.qpa.gl}. Depending on the
+ platform, this may print useful debug information when it comes to OpenGL
+ initialization and the native visual or framebuffer configurations which
+ QSurfaceFormat gets mapped to.
*/
/*!
@@ -199,6 +208,22 @@ public:
*/
/*!
+ \enum QSurfaceFormat::ColorSpace
+
+ This enum is used to specify the preferred color space, controlling if the
+ window's associated default framebuffer is able to do updates and blending
+ in a given encoding instead of the standard linear operations.
+
+ \value DefaultColorSpace The default, unspecified color space.
+
+ \value sRGBColorSpace When \c{GL_ARB_framebuffer_sRGB} or
+ \c{GL_EXT_framebuffer_sRGB} is supported by the platform and this value is
+ set, the window will be created with an sRGB-capable default
+ framebuffer. Note that some platforms may return windows with a sRGB-capable
+ default framebuffer even when not requested explicitly.
+ */
+
+/*!
Constructs a default initialized QSurfaceFormat.
\note By default OpenGL 2.0 is requested since this provides the highest
@@ -736,6 +761,47 @@ int QSurfaceFormat::swapInterval() const
return d->swapInterval;
}
+/*!
+ Sets the preferred \a colorSpace.
+
+ For example, this allows requesting windows with default framebuffers that
+ are sRGB-capable on platforms that support it.
+
+ \note When the requested color space is not supported by the platform, the
+ request is ignored. Query the QSurfaceFormat after window creation to verify
+ if the color space request could be honored or not.
+
+ \note This setting controls if the default framebuffer of the window is
+ capable of updates and blending in a given color space. It does not change
+ applications' output by itself. The applications' rendering code will still
+ have to opt in via the appropriate OpenGL calls to enable updates and
+ blending to be performed in the given color space instead of using the
+ standard linear operations.
+
+ \since 5.10
+
+ \sa colorSpace()
+ */
+void QSurfaceFormat::setColorSpace(ColorSpace colorSpace)
+{
+ if (d->colorSpace != colorSpace) {
+ detach();
+ d->colorSpace = colorSpace;
+ }
+}
+
+/*!
+ \return the color space.
+
+ \since 5.10
+
+ \sa setColorSpace()
+*/
+QSurfaceFormat::ColorSpace QSurfaceFormat::colorSpace() const
+{
+ return d->colorSpace;
+}
+
Q_GLOBAL_STATIC(QSurfaceFormat, qt_default_surface_format)
/*!
@@ -841,6 +907,7 @@ QDebug operator<<(QDebug dbg, const QSurfaceFormat &f)
<< ", samples " << d->numSamples
<< ", swapBehavior " << d->swapBehavior
<< ", swapInterval " << d->swapInterval
+ << ", colorSpace " << d->colorSpace
<< ", profile " << d->profile
<< ')';
diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h
index 246163609e..ed63eb8bbf 100644
--- a/src/gui/kernel/qsurfaceformat.h
+++ b/src/gui/kernel/qsurfaceformat.h
@@ -85,6 +85,12 @@ public:
};
Q_ENUM(OpenGLContextProfile)
+ enum ColorSpace {
+ DefaultColorSpace,
+ sRGBColorSpace
+ };
+ Q_ENUM(ColorSpace)
+
QSurfaceFormat();
/*implicit*/ QSurfaceFormat(FormatOptions options);
QSurfaceFormat(const QSurfaceFormat &other);
@@ -145,6 +151,9 @@ public:
int swapInterval() const;
void setSwapInterval(int interval);
+ ColorSpace colorSpace() const;
+ void setColorSpace(ColorSpace colorSpace);
+
static void setDefaultFormat(const QSurfaceFormat &format);
static QSurfaceFormat defaultFormat();
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index cf4a75dfce..1d8d6dfc95 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -116,7 +116,7 @@ QT_BEGIN_NAMESPACE
application, isExposed() will simply return the same value as isVisible().
QWindow::Visibility queried through visibility() is a convenience API
- combining the functions of visible() and windowState().
+ combining the functions of visible() and windowStates().
\section1 Rendering
@@ -317,34 +317,100 @@ void QWindow::setVisibility(Visibility v)
}
}
-void QWindowPrivate::updateVisibility()
+/*
+ Subclasses may override this function to run custom setVisible
+ logic. Subclasses that do so must call the base class implementation
+ at some point to make the native window visible, and must not
+ call QWindow::setVisble() since that will recurse back here.
+*/
+void QWindowPrivate::setVisible(bool visible)
{
Q_Q(QWindow);
- QWindow::Visibility old = visibility;
+ if (this->visible != visible) {
+ this->visible = visible;
+ emit q->visibleChanged(visible);
+ updateVisibility();
+ } else if (platformWindow) {
+ // Visibility hasn't changed, and the platform window is in sync
+ return;
+ }
+
+ if (!platformWindow) {
+ // If we have a parent window, but the parent hasn't been created yet, we
+ // can defer creation until the parent is created or we're re-parented.
+ if (parentWindow && !parentWindow->handle())
+ return;
+
+ // We only need to create the window if it's being shown
+ if (visible)
+ q->create();
+ }
if (visible) {
- switch (windowState) {
- case Qt::WindowMinimized:
- visibility = QWindow::Minimized;
- break;
- case Qt::WindowMaximized:
- visibility = QWindow::Maximized;
- break;
- case Qt::WindowFullScreen:
- visibility = QWindow::FullScreen;
- break;
- case Qt::WindowNoState:
- visibility = QWindow::Windowed;
- break;
- default:
- Q_ASSERT(false);
- break;
+ // remove posted quit events when showing a new window
+ QCoreApplication::removePostedEvents(qApp, QEvent::Quit);
+
+ if (q->type() == Qt::Window) {
+ QGuiApplicationPrivate *app_priv = QGuiApplicationPrivate::instance();
+ QString &firstWindowTitle = app_priv->firstWindowTitle;
+ if (!firstWindowTitle.isEmpty()) {
+ q->setTitle(firstWindowTitle);
+ firstWindowTitle = QString();
+ }
+ if (!app_priv->forcedWindowIcon.isNull())
+ q->setIcon(app_priv->forcedWindowIcon);
+
+ // Handling of the -qwindowgeometry, -geometry command line arguments
+ static bool geometryApplied = false;
+ if (!geometryApplied) {
+ geometryApplied = true;
+ QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(q);
+ }
}
- } else {
- visibility = QWindow::Hidden;
+
+ QShowEvent showEvent;
+ QGuiApplication::sendEvent(q, &showEvent);
}
+ if (q->isModal()) {
+ if (visible)
+ QGuiApplicationPrivate::showModalWindow(q);
+ else
+ QGuiApplicationPrivate::hideModalWindow(q);
+ }
+
+#ifndef QT_NO_CURSOR
+ if (visible && (hasCursor || QGuiApplication::overrideCursor()))
+ applyCursor();
+#endif
+
+ if (platformWindow)
+ platformWindow->setVisible(visible);
+
+ if (!visible) {
+ QHideEvent hideEvent;
+ QGuiApplication::sendEvent(q, &hideEvent);
+ }
+}
+
+void QWindowPrivate::updateVisibility()
+{
+ Q_Q(QWindow);
+
+ QWindow::Visibility old = visibility;
+
+ if (!visible)
+ visibility = QWindow::Hidden;
+ else if (windowState & Qt::WindowMinimized)
+ visibility = QWindow::Minimized;
+ else if (windowState & Qt::WindowFullScreen)
+ visibility = QWindow::FullScreen;
+ else if (windowState & Qt::WindowMaximized)
+ visibility = QWindow::Maximized;
+ else
+ visibility = QWindow::Windowed;
+
if (visibility != old)
emit q->visibilityChanged(visibility);
}
@@ -443,6 +509,8 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
return;
}
+ platformWindow->initialize();
+
QObjectList childObjects = q->children();
for (int i = 0; i < childObjects.size(); i ++) {
QObject *object = childObjects.at(i);
@@ -525,71 +593,7 @@ void QWindow::setVisible(bool visible)
{
Q_D(QWindow);
- if (d->visible != visible) {
- d->visible = visible;
- emit visibleChanged(visible);
- d->updateVisibility();
- } else if (d->platformWindow) {
- // Visibility hasn't changed, and the platform window is in sync
- return;
- }
-
- if (!d->platformWindow) {
- // If we have a parent window, but the parent hasn't been created yet, we
- // can defer creation until the parent is created or we're re-parented.
- if (parent() && !parent()->handle())
- return;
-
- // We only need to create the window if it's being shown
- if (visible)
- create();
- }
-
- if (visible) {
- // remove posted quit events when showing a new window
- QCoreApplication::removePostedEvents(qApp, QEvent::Quit);
-
- if (type() == Qt::Window) {
- QGuiApplicationPrivate *app_priv = QGuiApplicationPrivate::instance();
- QString &firstWindowTitle = app_priv->firstWindowTitle;
- if (!firstWindowTitle.isEmpty()) {
- setTitle(firstWindowTitle);
- firstWindowTitle = QString();
- }
- if (!app_priv->forcedWindowIcon.isNull())
- setIcon(app_priv->forcedWindowIcon);
-
- // Handling of the -qwindowgeometry, -geometry command line arguments
- static bool geometryApplied = false;
- if (!geometryApplied) {
- geometryApplied = true;
- QGuiApplicationPrivate::applyWindowGeometrySpecificationTo(this);
- }
- }
-
- QShowEvent showEvent;
- QGuiApplication::sendEvent(this, &showEvent);
- }
-
- if (isModal()) {
- if (visible)
- QGuiApplicationPrivate::showModalWindow(this);
- else
- QGuiApplicationPrivate::hideModalWindow(this);
- }
-
-#ifndef QT_NO_CURSOR
- if (visible && (d->hasCursor || QGuiApplication::overrideCursor()))
- d->applyCursor();
-#endif
-
- if (d->platformWindow)
- d->platformWindow->setVisible(visible);
-
- if (!visible) {
- QHideEvent hideEvent;
- QGuiApplication::sendEvent(this, &hideEvent);
- }
+ d->setVisible(visible);
}
bool QWindow::isVisible() const
@@ -1060,15 +1064,12 @@ qreal QWindow::opacity() const
The window manager may or may not choose to display any areas of the window
not included in the mask, thus it is the application's responsibility to
clear to transparent the areas that are not part of the mask.
-
- Setting the mask before the window has been created has no effect.
*/
void QWindow::setMask(const QRegion &region)
{
Q_D(QWindow);
- if (!d->platformWindow)
- return;
- d->platformWindow->setMask(QHighDpi::toNativeLocalRegion(region, this));
+ if (d->platformWindow)
+ d->platformWindow->setMask(QHighDpi::toNativeLocalRegion(region, this));
d->mask = region;
}
@@ -1215,6 +1216,17 @@ qreal QWindow::devicePixelRatio() const
return d->platformWindow->devicePixelRatio() * QHighDpiScaling::factor(this);
}
+Qt::WindowState QWindowPrivate::effectiveState(Qt::WindowStates state)
+{
+ if (state & Qt::WindowMinimized)
+ return Qt::WindowMinimized;
+ else if (state & Qt::WindowFullScreen)
+ return Qt::WindowFullScreen;
+ else if (state & Qt::WindowMaximized)
+ return Qt::WindowMaximized;
+ return Qt::WindowNoState;
+}
+
/*!
\brief set the screen-occupation state of the window
@@ -1223,31 +1235,69 @@ qreal QWindow::devicePixelRatio() const
The enum value Qt::WindowActive is not an accepted parameter.
- \sa showNormal(), showFullScreen(), showMinimized(), showMaximized()
+ \sa showNormal(), showFullScreen(), showMinimized(), showMaximized(), setWindowStates()
*/
void QWindow::setWindowState(Qt::WindowState state)
{
- if (state == Qt::WindowActive) {
- qWarning("QWindow::setWindowState does not accept Qt::WindowActive");
- return;
- }
+ setWindowStates(state);
+}
+
+/*!
+ \brief set the screen-occupation state of the window
+ \since 5.10
+
+ The window \a state represents whether the window appears in the
+ windowing system as maximized, minimized and/or fullscreen.
+
+ The window can be in a combination of several states. For example, if
+ the window is both minimized and maximized, the window will appear
+ minimized, but clicking on the task bar entry will restore it to the
+ maximized state.
+
+ The enum value Qt::WindowActive should not be set.
+ \sa showNormal(), showFullScreen(), showMinimized(), showMaximized()
+ */
+void QWindow::setWindowStates(Qt::WindowStates state)
+{
Q_D(QWindow);
+ if (state & Qt::WindowActive) {
+ qWarning("QWindow::setWindowStates does not accept Qt::WindowActive");
+ state &= ~Qt::WindowActive;
+ }
+
if (d->platformWindow)
d->platformWindow->setWindowState(state);
d->windowState = state;
- emit windowStateChanged(d->windowState);
+ emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
d->updateVisibility();
}
/*!
\brief the screen-occupation state of the window
- \sa setWindowState()
+ \sa setWindowState(), windowStates()
*/
Qt::WindowState QWindow::windowState() const
{
Q_D(const QWindow);
+ return QWindowPrivate::effectiveState(d->windowState);
+}
+
+/*!
+ \brief the screen-occupation state of the window
+ \since 5.10
+
+ The window can be in a combination of several states. For example, if
+ the window is both minimized and maximized, the window will appear
+ minimized, but clicking on the task bar entry will restore it to
+ the maximized state.
+
+ \sa setWindowStates()
+*/
+Qt::WindowStates QWindow::windowStates() const
+{
+ Q_D(const QWindow);
return d->windowState;
}
@@ -1255,7 +1305,7 @@ Qt::WindowState QWindow::windowState() const
\fn QWindow::windowStateChanged(Qt::WindowState windowState)
This signal is emitted when the \a windowState changes, either
- by being set explicitly with setWindowState(), or automatically when
+ by being set explicitly with setWindowStates(), or automatically when
the user clicks one of the titlebar buttons or by other means.
*/
@@ -2000,42 +2050,42 @@ void QWindow::hide()
/*!
Shows the window as minimized.
- Equivalent to calling setWindowState(Qt::WindowMinimized) and then
+ Equivalent to calling setWindowStates(Qt::WindowMinimized) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showMinimized()
{
- setWindowState(Qt::WindowMinimized);
+ setWindowStates(Qt::WindowMinimized);
setVisible(true);
}
/*!
Shows the window as maximized.
- Equivalent to calling setWindowState(Qt::WindowMaximized) and then
+ Equivalent to calling setWindowStates(Qt::WindowMaximized) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showMaximized()
{
- setWindowState(Qt::WindowMaximized);
+ setWindowStates(Qt::WindowMaximized);
setVisible(true);
}
/*!
Shows the window as fullscreen.
- Equivalent to calling setWindowState(Qt::WindowFullScreen) and then
+ Equivalent to calling setWindowStates(Qt::WindowFullScreen) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showFullScreen()
{
- setWindowState(Qt::WindowFullScreen);
+ setWindowStates(Qt::WindowFullScreen);
setVisible(true);
#if !defined Q_OS_QNX // On QNX this window will be activated anyway from libscreen
// activating it here before libscreen activates it causes problems
@@ -2046,14 +2096,14 @@ void QWindow::showFullScreen()
/*!
Shows the window as normal, i.e. neither maximized, minimized, nor fullscreen.
- Equivalent to calling setWindowState(Qt::WindowNoState) and then
+ Equivalent to calling setWindowStates(Qt::WindowNoState) and then
setVisible(true).
- \sa setWindowState(), setVisible()
+ \sa setWindowStates(), setVisible()
*/
void QWindow::showNormal()
{
- setWindowState(Qt::WindowNoState);
+ setWindowStates(Qt::WindowNoState);
setVisible(true);
}
@@ -2249,7 +2299,7 @@ bool QWindow::event(QEvent *ev)
case QEvent::WindowStateChange: {
Q_D(QWindow);
- emit windowStateChanged(d->windowState);
+ emit windowStateChanged(QWindowPrivate::effectiveState(d->windowState));
d->updateVisibility();
break;
}
@@ -2765,6 +2815,30 @@ QDebug operator<<(QDebug debug, const QWindow *window)
}
#endif // !QT_NO_DEBUG_STREAM
+#if QT_CONFIG(vulkan)
+
+/*!
+ Associates this window with the specified Vulkan \a instance.
+
+ \a instance must stay valid as long as this QWindow instance exists.
+ */
+void QWindow::setVulkanInstance(QVulkanInstance *instance)
+{
+ Q_D(QWindow);
+ d->vulkanInstance = instance;
+}
+
+/*!
+ \return the associrated Vulkan instance or \c null if there is none.
+ */
+QVulkanInstance *QWindow::vulkanInstance() const
+{
+ Q_D(const QWindow);
+ return d->vulkanInstance;
+}
+
+#endif // QT_CONFIG(vulkan)
+
QT_END_NAMESPACE
#include "moc_qwindow.cpp"
diff --git a/src/gui/kernel/qwindow.h b/src/gui/kernel/qwindow.h
index db8e828e70..4a874caacb 100644
--- a/src/gui/kernel/qwindow.h
+++ b/src/gui/kernel/qwindow.h
@@ -88,6 +88,9 @@ class QWindowContainer;
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
#endif
+#if QT_CONFIG(vulkan)
+class QVulkanInstance;
+#endif
class Q_GUI_EXPORT QWindow : public QObject, public QSurface
{
@@ -189,7 +192,9 @@ public:
qreal devicePixelRatio() const;
Qt::WindowState windowState() const;
+ Qt::WindowStates windowStates() const;
void setWindowState(Qt::WindowState state);
+ void setWindowStates(Qt::WindowStates states);
void setTransientParent(QWindow *parent);
QWindow *transientParent() const;
@@ -267,6 +272,11 @@ public:
static QWindow *fromWinId(WId id);
+#if QT_CONFIG(vulkan)
+ void setVulkanInstance(QVulkanInstance *instance);
+ QVulkanInstance *vulkanInstance() const;
+#endif
+
public Q_SLOTS:
Q_REVISION(1) void requestActivate();
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index dd282a671d..9b8e2c47e4 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -105,6 +105,9 @@ public:
, hasCursor(false)
#endif
, compositing(false)
+#if QT_CONFIG(vulkan)
+ , vulkanInstance(nullptr)
+#endif
{
isWindow = true;
}
@@ -129,6 +132,7 @@ public:
virtual QWindow *eventReceiver() { Q_Q(QWindow); return q; }
+ virtual void setVisible(bool visible);
void updateVisibility();
void _q_clearAlert();
@@ -151,6 +155,8 @@ public:
static QWindowPrivate *get(QWindow *window) { return window->d_func(); }
+ static Qt::WindowState effectiveState(Qt::WindowStates);
+
QWindow::SurfaceType surfaceType;
Qt::WindowFlags windowFlags;
QWindow *parentWindow;
@@ -163,7 +169,7 @@ public:
QString windowFilePath;
QIcon windowIcon;
QRect geometry;
- Qt::WindowState windowState;
+ Qt::WindowStates windowState;
QWindow::Visibility visibility;
bool resizeEventPending;
bool receivedExpose;
@@ -194,6 +200,10 @@ public:
bool compositing;
QElapsedTimer lastComposeTime;
+
+#if QT_CONFIG(vulkan)
+ QVulkanInstance *vulkanInstance;
+#endif
};
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 34519cd91b..85b2aae7dd 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -66,7 +66,7 @@ extern QPointer<QWindow> qt_last_mouse_receiver;
// ------------------- QWindowSystemInterfacePrivate -------------------
-/*!
+/*
Handles a window system event asynchronously by posting the event to Qt Gui.
This function posts the event on the window system event queue and wakes the
@@ -82,7 +82,7 @@ bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterfa
return true;
}
-/*!
+/*
Handles a window system event synchronously.
Qt Gui will process the event immediately. The return value indicates if Qt
@@ -112,7 +112,7 @@ bool QWindowSystemInterfacePrivate::handleWindowSystemEvent<QWindowSystemInterfa
return accepted;
}
-/*!
+/*
Handles a window system event.
By default this function posts the event on the window system event queue and
@@ -247,14 +247,14 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowActivated, QWindow *window, Qt::Fo
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowState newState, int oldState)
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt::WindowStates newState, int oldState)
{
Q_ASSERT(window);
if (oldState < Qt::WindowNoState)
oldState = window->windowState();
QWindowSystemInterfacePrivate::WindowStateChangedEvent *e =
- new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowState(oldState));
+ new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowStates(oldState));
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
@@ -273,12 +273,25 @@ void QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationState
QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
}
-/*!
- If \a oldRect is null, Qt will use the previously reported geometry instead.
- */
-QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect, const QRect &oldRect)
+QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow *window, const QRect &newGeometry)
+ : WindowSystemEvent(GeometryChange)
+ , window(window)
+ , requestedGeometry(window->handle() ? window->handle()->QPlatformWindow::geometry() : QRect())
+ , newGeometry(newGeometry)
{
- QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window), QHighDpi::fromNativePixels(oldRect, window));
+}
+
+QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect)
+{
+ Q_ASSERT(window);
+ QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window));
+ if (window->handle()) {
+ // Persist the new geometry so that QWindow::geometry() can be queried in the resize event
+ window->handle()->QPlatformWindow::setGeometry(newRect);
+ // FIXME: This does not work during platform window creation, where the QWindow does not
+ // have its handle set up yet. Platforms that deliver events during window creation need
+ // to handle the persistence manually, e.g. by overriding geometry().
+ }
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
@@ -290,6 +303,23 @@ QWindowSystemInterfacePrivate::ExposeEvent::ExposeEvent(QWindow *window, const Q
{
}
+/*! \internal
+ Handles an expose event.
+
+ The platform plugin sends expose events when an area of the window
+ is invalidated or window exposure changes. \a region is in window
+ local coordinates. An empty region indicates that the window is
+ obscured, but note that the exposed property of the QWindow will be set
+ based on what QPlatformWindow::isExposed() returns at the time of this call,
+ not based on what the region is. // FIXME: this should probably be fixed.
+
+ The platform plugin may omit sending expose events (or send obscure
+ events) for windows that are on screen but where the client area is
+ completely covered by other windows or otherwise not visible. Expose
+ event consumers can then use this to disable updates for such windows.
+ This is required behavior on platforms where OpenGL swapbuffers stops
+ blocking for obscured windows (like macOS).
+*/
QT_DEFINE_QPA_EVENT_HANDLER(void, handleExposeEvent, QWindow *window, const QRegion &region)
{
QWindowSystemInterfacePrivate::ExposeEvent *e =
@@ -445,9 +475,13 @@ QWindowSystemInterfacePrivate::WheelEvent::WheelEvent(QWindow *window, ulong tim
{
}
+#if QT_DEPRECATED_SINCE(5, 10)
void QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods) {
unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
handleWheelEvent(window, time, local, global, d, o, mods);
+QT_WARNING_POP
}
void QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods)
@@ -455,6 +489,7 @@ void QWindowSystemInterface::handleWheelEvent(QWindow *window, ulong timestamp,
QPoint point = (o == Qt::Vertical) ? QPoint(0, d) : QPoint(d, 0);
handleWheelEvent(window, timestamp, local, global, QPoint(), point, mods);
}
+#endif // QT_DEPRECATED_SINCE(5, 10)
void QWindowSystemInterface::handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods, Qt::ScrollPhase phase, Qt::MouseEventSource source)
{
@@ -768,6 +803,7 @@ void QWindowSystemInterface::handleTabletEvent(QWindow *window, const QPointF &l
xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
}
+#if QT_DEPRECATED_SINCE(5, 10)
void QWindowSystemInterface::handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global,
int device, int pointerType, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
@@ -785,6 +821,7 @@ void QWindowSystemInterface::handleTabletEvent(QWindow *window, bool down, const
handleTabletEvent(window, local, global, device, pointerType, (down ? Qt::LeftButton : Qt::NoButton), pressure,
xTilt, yTilt, tangentialPressure, rotation, z, uid, modifiers);
}
+#endif // QT_DEPRECATED_SINCE(5, 10)
void QWindowSystemInterface::handleTabletEnterProximityEvent(ulong timestamp, int device, int pointerType, qint64 uid)
{
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index e582787dd9..7ea7b072f0 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -121,9 +121,10 @@ public:
Qt::MouseEventSource source = Qt::MouseEventNotSynthesized,
bool inverted = false);
- // Wheel event compatibility functions. Will be removed: do not use.
- static void handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier);
- static void handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier);
+#if QT_DEPRECATED_SINCE(5, 10)
+ QT_DEPRECATED static void handleWheelEvent(QWindow *window, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier);
+ QT_DEPRECATED static void handleWheelEvent(QWindow *window, ulong timestamp, const QPointF &local, const QPointF &global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier);
+#endif
struct TouchPoint {
TouchPoint() : id(0), uniqueId(-1), pressure(0), rotation(0), state(Qt::TouchPointStationary) { }
@@ -159,7 +160,7 @@ public:
// rect is relative to parent
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleGeometryChange(QWindow *window, const QRect &newRect, const QRect &oldRect = QRect());
+ static void handleGeometryChange(QWindow *window, const QRect &newRect);
// region is in local coordinates, do not confuse with geometry which is parent-relative
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
@@ -176,7 +177,7 @@ public:
static void handleWindowActivated(QWindow *window, Qt::FocusReason r = Qt::OtherFocusReason);
template<typename Delivery = QWindowSystemInterface::DefaultDelivery>
- static void handleWindowStateChanged(QWindow *window, Qt::WindowState newState, int oldState = -1);
+ static void handleWindowStateChanged(QWindow *window, Qt::WindowStates newState, int oldState = -1);
static void handleWindowScreenChanged(QWindow *window, QScreen *newScreen);
static void handleApplicationStateChanged(Qt::ApplicationState newState, bool forcePropagate = false);
@@ -208,14 +209,16 @@ public:
int device, int pointerType, Qt::MouseButtons buttons, qreal pressure, int xTilt, int yTilt,
qreal tangentialPressure, qreal rotation, int z, qint64 uid,
Qt::KeyboardModifiers modifiers = Qt::NoModifier);
- static void handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global,
- int device, int pointerType, qreal pressure, int xTilt, int yTilt,
- qreal tangentialPressure, qreal rotation, int z, qint64 uid,
- Qt::KeyboardModifiers modifiers = Qt::NoModifier); // ### remove in Qt 6
- static void handleTabletEvent(QWindow *window, bool down, const QPointF &local, const QPointF &global,
- int device, int pointerType, qreal pressure, int xTilt, int yTilt,
- qreal tangentialPressure, qreal rotation, int z, qint64 uid,
- Qt::KeyboardModifiers modifiers = Qt::NoModifier); // ### remove in Qt 6
+#if QT_DEPRECATED_SINCE(5, 10)
+ QT_DEPRECATED static void handleTabletEvent(QWindow *window, ulong timestamp, bool down, const QPointF &local, const QPointF &global,
+ int device, int pointerType, qreal pressure, int xTilt, int yTilt,
+ qreal tangentialPressure, qreal rotation, int z, qint64 uid,
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier);
+ QT_DEPRECATED static void handleTabletEvent(QWindow *window, bool down, const QPointF &local, const QPointF &global,
+ int device, int pointerType, qreal pressure, int xTilt, int yTilt,
+ qreal tangentialPressure, qreal rotation, int z, qint64 uid,
+ Qt::KeyboardModifiers modifiers = Qt::NoModifier);
+#endif
static void handleTabletEnterProximityEvent(ulong timestamp, int device, int pointerType, qint64 uid);
static void handleTabletEnterProximityEvent(int device, int pointerType, qint64 uid);
static void handleTabletLeaveProximityEvent(ulong timestamp, int device, int pointerType, qint64 uid);
diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h
index 0f350fb2d2..ef993501f8 100644
--- a/src/gui/kernel/qwindowsysteminterface_p.h
+++ b/src/gui/kernel/qwindowsysteminterface_p.h
@@ -131,12 +131,10 @@ public:
class GeometryChangeEvent : public WindowSystemEvent {
public:
- GeometryChangeEvent(QWindow *window, const QRect &newGeometry, const QRect &oldGeometry)
- : WindowSystemEvent(GeometryChange), window(window), newGeometry(newGeometry), oldGeometry(oldGeometry)
- { }
+ GeometryChangeEvent(QWindow *window, const QRect &newGeometry);
QPointer<QWindow> window;
+ QRect requestedGeometry;
QRect newGeometry;
- QRect oldGeometry;
};
class EnterEvent : public WindowSystemEvent {
@@ -168,13 +166,13 @@ public:
class WindowStateChangedEvent : public WindowSystemEvent {
public:
- WindowStateChangedEvent(QWindow *_window, Qt::WindowState _newState, Qt::WindowState _oldState)
+ WindowStateChangedEvent(QWindow *_window, Qt::WindowStates _newState, Qt::WindowStates _oldState)
: WindowSystemEvent(WindowStateChanged), window(_window), newState(_newState), oldState(_oldState)
{ }
QPointer<QWindow> window;
- Qt::WindowState newState;
- Qt::WindowState oldState;
+ Qt::WindowStates newState;
+ Qt::WindowStates oldState;
};
class WindowScreenChangedEvent : public WindowSystemEvent {
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
index 6b18e1ab03..d016f07522 100644
--- a/src/gui/math3d/qmatrix4x4.cpp
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -1128,7 +1128,7 @@ void QMatrix4x4::rotate(float angle, float x, float y, float z)
s = 0.0f;
c = -1.0f;
} else {
- float a = angle * M_PI / 180.0f;
+ float a = qDegreesToRadians(angle);
c = std::cos(a);
s = std::sin(a);
}
@@ -1237,7 +1237,7 @@ void QMatrix4x4::projectedRotate(float angle, float x, float y, float z)
s = 0.0f;
c = -1.0f;
} else {
- float a = angle * M_PI / 180.0f;
+ float a = qDegreesToRadians(angle);
c = std::cos(a);
s = std::sin(a);
}
@@ -1496,7 +1496,7 @@ void QMatrix4x4::perspective(float verticalAngle, float aspectRatio, float nearP
// Construct the projection.
QMatrix4x4 m(1);
- float radians = (verticalAngle / 2.0f) * M_PI / 180.0f;
+ float radians = qDegreesToRadians(verticalAngle / 2.0f);
float sine = std::sin(radians);
if (sine == 0.0f)
return;
diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp
index e3262c8830..fe1b0425a8 100644
--- a/src/gui/math3d/qquaternion.cpp
+++ b/src/gui/math3d/qquaternion.cpp
@@ -408,7 +408,7 @@ QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D& axis, float angle)
// http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56
// We normalize the result just in case the values are close
// to zero, as suggested in the above FAQ.
- float a = (angle / 2.0f) * M_PI / 180.0f;
+ float a = qDegreesToRadians(angle / 2.0f);
float s = std::sin(a);
float c = std::cos(a);
QVector3D ax = axis.normalized();
@@ -467,7 +467,7 @@ QQuaternion QQuaternion::fromAxisAndAngle
y /= length;
z /= length;
}
- float a = (angle / 2.0f) * M_PI / 180.0f;
+ float a = qDegreesToRadians(angle / 2.0f);
float s = std::sin(a);
float c = std::cos(a);
return QQuaternion(c, x * s, y * s, z * s).normalized();
diff --git a/src/gui/opengl/qopengl.h b/src/gui/opengl/qopengl.h
index b5df68a3aa..f6c350ba0b 100644
--- a/src/gui/opengl/qopengl.h
+++ b/src/gui/opengl/qopengl.h
@@ -101,7 +101,9 @@ typedef void* GLeglImageOES;
# define QGL_TEMP_GLEXT_PROTO
# endif
-# if defined(QT_OPENGL_ES_3_1)
+# if defined(QT_OPENGL_ES_3_2)
+# include <GLES3/gl32.h>
+# elif defined(QT_OPENGL_ES_3_1)
# include <GLES3/gl31.h>
# elif defined(QT_OPENGL_ES_3)
# include <GLES3/gl3.h>
diff --git a/src/gui/opengl/qopenglextrafunctions.h b/src/gui/opengl/qopenglextrafunctions.h
index 1b36068588..81716fb8d3 100644
--- a/src/gui/opengl/qopenglextrafunctions.h
+++ b/src/gui/opengl/qopenglextrafunctions.h
@@ -52,6 +52,11 @@
#undef MemoryBarrier
#endif
+// GLES build without having included gl32.h -> GLDEBUGPROC is still need for the protos, define it here
+#if defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_3_2)
+typedef void (QOPENGLF_APIENTRYP *GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,const void *userParam);
+#endif
+
QT_BEGIN_NAMESPACE
class QOpenGLExtraFunctionsPrivate;
@@ -230,6 +235,50 @@ class QOpenGLExtraFunctionsPrivate;
#undef glVertexAttribBinding
#undef glVertexBindingDivisor
+#undef glBlendBarrier
+#undef glCopyImageSubData
+#undef glDebugMessageControl
+#undef glDebugMessageInsert
+#undef glDebugMessageCallback
+#undef glGetDebugMessageLog
+#undef glPushDebugGroup
+#undef glPopDebugGroup
+#undef glObjectLabel
+#undef glGetObjectLabel
+#undef glGetObjectPtrLabel
+#undef glGetPointerv
+#undef glEnablei
+#undef glDisablei
+#undef glBlendEquationi
+#undef glBlendEquationSeparatei
+#undef glBlendFunci
+#undef glBlendFuncSeparatei
+#undef glColorMaski
+#undef glIsEnabledi
+#undef glDrawElementsBaseVertex
+#undef glDrawRangeElementsBaseVertex
+#undef glDrawElementsInstancedBaseVertex
+#undef glFrameBufferTexture
+#undef glPrimitiveBoundingBox
+#undef glGetGraphicsResetStatus
+#undef glReadnPixels
+#undef glGetnUniformfv
+#undef glGetnUniformiv
+#undef glGetnUniformuiv
+#undef glMinSampleShading
+#undef glPatchParameteri
+#undef glTexParameterIiv
+#undef glTexParameterIuiv
+#undef glGetTexParameterIiv
+#undef glGetTexParameterIuiv
+#undef glSamplerParameterIiv
+#undef glSamplerParameterIuiv
+#undef glGetSamplerParameterIiv
+#undef glGetSamplerParameterIuiv
+#undef glTexBuffer
+#undef glTexBufferRange
+#undef glTexStorage3DMultisample
+
class Q_GUI_EXPORT QOpenGLExtraFunctions : public QOpenGLFunctions
{
Q_DECLARE_PRIVATE(QOpenGLExtraFunctions)
@@ -415,6 +464,52 @@ public:
void glVertexAttribBinding(GLuint attribindex, GLuint bindingindex);
void glVertexBindingDivisor(GLuint bindingindex, GLuint divisor);
+ // GLES 3.2
+ void glBlendBarrier(void);
+ void glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth);
+ void glDebugMessageControl(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
+ void glDebugMessageInsert(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
+ void glDebugMessageCallback(GLDEBUGPROC callback, const void *userParam);
+ GLuint glGetDebugMessageLog(GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
+ void glPushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar *message);
+ void glPopDebugGroup(void);
+ void glObjectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
+ void glGetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
+ void glObjectPtrLabel(const void *ptr, GLsizei length, const GLchar *label);
+ void glGetObjectPtrLabel(const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
+ void glGetPointerv(GLenum pname, void **params);
+ void glEnablei(GLenum target, GLuint index);
+ void glDisablei(GLenum target, GLuint index);
+ void glBlendEquationi(GLuint buf, GLenum mode);
+ void glBlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeAlpha);
+ void glBlendFunci(GLuint buf, GLenum src, GLenum dst);
+ void glBlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+ void glColorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a);
+ GLboolean glIsEnabledi(GLenum target, GLuint index);
+ void glDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+ void glDrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices, GLint basevertex);
+ void glDrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei instancecount, GLint basevertex);
+ void glFramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level);
+ void glPrimitiveBoundingBox(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
+ GLenum glGetGraphicsResetStatus(void);
+ void glReadnPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+ void glGetnUniformfv(GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
+ void glGetnUniformiv(GLuint program, GLint location, GLsizei bufSize, GLint *params);
+ void glGetnUniformuiv(GLuint program, GLint location, GLsizei bufSize, GLuint *params);
+ void glMinSampleShading(GLfloat value);
+ void glPatchParameteri(GLenum pname, GLint value);
+ void glTexParameterIiv(GLenum target, GLenum pname, const GLint *params);
+ void glTexParameterIuiv(GLenum target, GLenum pname, const GLuint *params);
+ void glGetTexParameterIiv(GLenum target, GLenum pname, GLint *params);
+ void glGetTexParameterIuiv(GLenum target, GLenum pname, GLuint *params);
+ void glSamplerParameterIiv(GLuint sampler, GLenum pname, const GLint *param);
+ void glSamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint *param);
+ void glGetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint *params);
+ void glGetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint *params);
+ void glTexBuffer(GLenum target, GLenum internalformat, GLuint buffer);
+ void glTexBufferRange(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size);
+ void glTexStorage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations);
+
private:
static bool isInitialized(const QOpenGLExtraFunctionsPrivate *d) { return d != Q_NULLPTR; }
};
@@ -615,6 +710,50 @@ public:
F(void, VertexAttribIFormat, (GLuint attribindex, GLint size, GLenum type, GLuint relativeoffset)) \
F(void, VertexAttribBinding, (GLuint attribindex, GLuint bindingindex)) \
F(void, VertexBindingDivisor, (GLuint bindingindex, GLuint divisor)) \
+ F(void, BlendBarrier, (void)) \
+ F(void, BlendEquationSeparatei, (GLuint buf, GLenum modeRGB, GLenum modeAlpha)) \
+ F(void, BlendEquationi, (GLuint buf, GLenum mode)) \
+ F(void, BlendFuncSeparatei, (GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)) \
+ F(void, BlendFunci, (GLuint buf, GLenum src, GLenum dst)) \
+ F(void, ColorMaski, (GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)) \
+ F(void, CopyImageSubData, (GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)) \
+ F(void, DebugMessageCallback, (GLDEBUGPROC callback, const void * userParam)) \
+ F(void, DebugMessageControl, (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled)) \
+ F(void, DebugMessageInsert, (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf)) \
+ F(void, Disablei, (GLenum target, GLuint index)) \
+ F(void, DrawElementsBaseVertex, (GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex)) \
+ F(void, DrawElementsInstancedBaseVertex, (GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex)) \
+ F(void, DrawRangeElementsBaseVertex, (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex)) \
+ F(void, Enablei, (GLenum target, GLuint index)) \
+ F(void, FramebufferTexture, (GLenum target, GLenum attachment, GLuint texture, GLint level)) \
+ F(GLuint, GetDebugMessageLog, (GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog)) \
+ F(GLenum, GetGraphicsResetStatus, (void)) \
+ F(void, GetObjectLabel, (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar* label)) \
+ F(void, GetObjectPtrLabel, (const void * ptr, GLsizei bufSize, GLsizei* length, GLchar* label)) \
+ F(void, GetPointerv, (GLenum pname, void ** params)) \
+ F(void, GetSamplerParameterIiv, (GLuint sampler, GLenum pname, GLint* params)) \
+ F(void, GetSamplerParameterIuiv, (GLuint sampler, GLenum pname, GLuint* params)) \
+ F(void, GetTexParameterIiv, (GLenum target, GLenum pname, GLint* params)) \
+ F(void, GetTexParameterIuiv, (GLenum target, GLenum pname, GLuint* params)) \
+ F(void, GetnUniformfv, (GLuint program, GLint location, GLsizei bufSize, GLfloat* params)) \
+ F(void, GetnUniformiv, (GLuint program, GLint location, GLsizei bufSize, GLint* params)) \
+ F(void, GetnUniformuiv, (GLuint program, GLint location, GLsizei bufSize, GLuint* params)) \
+ F(GLboolean, IsEnabledi, (GLenum target, GLuint index)) \
+ F(void, MinSampleShading, (GLfloat value)) \
+ F(void, ObjectLabel, (GLenum identifier, GLuint name, GLsizei length, const GLchar * label)) \
+ F(void, ObjectPtrLabel, (const void * ptr, GLsizei length, const GLchar * label)) \
+ F(void, PatchParameteri, (GLenum pname, GLint value)) \
+ F(void, PopDebugGroup, (void)) \
+ F(void, PrimitiveBoundingBox, (GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW)) \
+ F(void, PushDebugGroup, (GLenum source, GLuint id, GLsizei length, const GLchar * message)) \
+ F(void, ReadnPixels, (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data)) \
+ F(void, SamplerParameterIiv, (GLuint sampler, GLenum pname, const GLint * param)) \
+ F(void, SamplerParameterIuiv, (GLuint sampler, GLenum pname, const GLuint * param)) \
+ F(void, TexBuffer, (GLenum target, GLenum internalformat, GLuint buffer)) \
+ F(void, TexBufferRange, (GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)) \
+ F(void, TexParameterIiv, (GLenum target, GLenum pname, const GLint * params)) \
+ F(void, TexParameterIuiv, (GLenum target, GLenum pname, const GLuint * params)) \
+ F(void, TexStorage3DMultisample, (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations)) \
QT_OPENGL_DECLARE(QT_OPENGL_EXTRA_FUNCTIONS)
};
@@ -2013,6 +2152,363 @@ inline void QOpenGLExtraFunctions::glVertexBindingDivisor(GLuint bindingindex, G
Q_OPENGL_FUNCTIONS_DEBUG
}
+// GLES 3.2
+
+inline void QOpenGLExtraFunctions::glBlendBarrier()
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.BlendBarrier();
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glBlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeAlpha)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.BlendEquationSeparatei(buf, modeRGB, modeAlpha);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glBlendEquationi(GLuint buf, GLenum mode)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.BlendEquationi(buf, mode);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glBlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.BlendFuncSeparatei(buf, srcRGB, dstRGB, srcAlpha, dstAlpha);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glBlendFunci(GLuint buf, GLenum src, GLenum dst)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.BlendFunci(buf, src, dst);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glColorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.ColorMaski(index, r, g, b, a);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.CopyImageSubData(srcName, srcTarget, srcLevel, srcX, srcY, srcZ, dstName, dstTarget, dstLevel, dstX, dstY, dstZ, srcWidth, srcHeight, srcDepth);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glDebugMessageCallback(GLDEBUGPROC callback, const void * userParam)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.DebugMessageCallback(callback, userParam);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glDebugMessageControl(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.DebugMessageControl(source, type, severity, count, ids, enabled);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glDebugMessageInsert(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.DebugMessageInsert(source, type, id, severity, length, buf);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glDisablei(GLenum target, GLuint index)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.Disablei(target, index);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.DrawElementsBaseVertex(mode, count, type, indices, basevertex);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glDrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.DrawElementsInstancedBaseVertex(mode, count, type, indices, instancecount, basevertex);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glDrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.DrawRangeElementsBaseVertex(mode, start, end, count, type, indices, basevertex);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glEnablei(GLenum target, GLuint index)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.Enablei(target, index);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glFramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.FramebufferTexture(target, attachment, texture, level);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline GLuint QOpenGLExtraFunctions::glGetDebugMessageLog(GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ GLuint result = d->f.GetDebugMessageLog(count, bufSize, sources, types, ids, severities, lengths, messageLog);
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline GLenum QOpenGLExtraFunctions::glGetGraphicsResetStatus()
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ GLenum result = d->f.GetGraphicsResetStatus();
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline void QOpenGLExtraFunctions::glGetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar* label)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.GetObjectLabel(identifier, name, bufSize, length, label);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glGetObjectPtrLabel(const void * ptr, GLsizei bufSize, GLsizei* length, GLchar* label)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.GetObjectPtrLabel(ptr, bufSize, length, label);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glGetPointerv(GLenum pname, void ** params)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.GetPointerv(pname, params);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glGetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint* params)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.GetSamplerParameterIiv(sampler, pname, params);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glGetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint* params)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.GetSamplerParameterIuiv(sampler, pname, params);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glGetTexParameterIiv(GLenum target, GLenum pname, GLint* params)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.GetTexParameterIiv(target, pname, params);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glGetTexParameterIuiv(GLenum target, GLenum pname, GLuint* params)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.GetTexParameterIuiv(target, pname, params);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glGetnUniformfv(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.GetnUniformfv(program, location, bufSize, params);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glGetnUniformiv(GLuint program, GLint location, GLsizei bufSize, GLint* params)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.GetnUniformiv(program, location, bufSize, params);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glGetnUniformuiv(GLuint program, GLint location, GLsizei bufSize, GLuint* params)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.GetnUniformuiv(program, location, bufSize, params);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline GLboolean QOpenGLExtraFunctions::glIsEnabledi(GLenum target, GLuint index)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ GLboolean result = d->f.IsEnabledi(target, index);
+ Q_OPENGL_FUNCTIONS_DEBUG
+ return result;
+}
+
+inline void QOpenGLExtraFunctions::glMinSampleShading(GLfloat value)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.MinSampleShading(value);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glObjectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar * label)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.ObjectLabel(identifier, name, length, label);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glObjectPtrLabel(const void * ptr, GLsizei length, const GLchar * label)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.ObjectPtrLabel(ptr, length, label);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glPatchParameteri(GLenum pname, GLint value)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.PatchParameteri(pname, value);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glPopDebugGroup()
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.PopDebugGroup();
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glPrimitiveBoundingBox(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.PrimitiveBoundingBox(minX, minY, minZ, minW, maxX, maxY, maxZ, maxW);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glPushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar * message)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.PushDebugGroup(source, id, length, message);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glReadnPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.ReadnPixels(x, y, width, height, format, type, bufSize, data);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glSamplerParameterIiv(GLuint sampler, GLenum pname, const GLint * param)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.SamplerParameterIiv(sampler, pname, param);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glSamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint * param)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.SamplerParameterIuiv(sampler, pname, param);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glTexBuffer(GLenum target, GLenum internalformat, GLuint buffer)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.TexBuffer(target, internalformat, buffer);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glTexBufferRange(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.TexBufferRange(target, internalformat, buffer, offset, size);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glTexParameterIiv(GLenum target, GLenum pname, const GLint * params)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.TexParameterIiv(target, pname, params);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glTexParameterIuiv(GLenum target, GLenum pname, const GLuint * params)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.TexParameterIuiv(target, pname, params);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
+inline void QOpenGLExtraFunctions::glTexStorage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations)
+{
+ Q_D(QOpenGLExtraFunctions);
+ Q_ASSERT(QOpenGLExtraFunctions::isInitialized(d));
+ d->f.TexStorage3DMultisample(target, samples, internalformat, width, height, depth, fixedsamplelocations);
+ Q_OPENGL_FUNCTIONS_DEBUG
+}
+
QT_END_NAMESPACE
#undef QT_OPENGL_DECLARE_FUNCTIONS
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index e724efab37..5e3537e47b 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -2213,17 +2213,17 @@ QT_OPENGL_IMPLEMENT(QOpenGLFunctionsPrivate, QT_OPENGL_FUNCTIONS)
/*!
\class QOpenGLExtraFunctions
- \brief The QOpenGLExtraFunctions class provides cross-platform access to the OpenGL ES 3.0 and 3.1 API.
+ \brief The QOpenGLExtraFunctions class provides cross-platform access to the OpenGL ES 3.0, 3.1 and 3.2 API.
\since 5.6
\ingroup painting-3D
\inmodule QtGui
- This subclass of QOpenGLFunctions includes the OpenGL ES 3.0 and 3.1
- functions. These will only work when an OpenGL ES 3.0 or 3.1 context, or an
+ This subclass of QOpenGLFunctions includes the OpenGL ES 3.0, 3.1 and 3.2
+ functions. These will only work when an OpenGL ES 3.x context, or an
OpenGL context of a version containing the functions in question either in
- core or as extension, is in use. This allows developing GLES 3.0 and 3.1
+ core or as extension, is in use. This allows developing GLES 3.x
applications in a cross-platform manner: development can happen on a desktop
- platform with OpenGL 3.x or 4.x, deploying to a real GLES 3.1 device later
+ platform with OpenGL 3.x or 4.x, deploying to a true GLES 3.x device later
on will require no or minimal changes to the application.
\note This class is different from the versioned OpenGL wrappers, for
@@ -4469,6 +4469,578 @@ QT_OPENGL_IMPLEMENT(QOpenGLFunctionsPrivate, QT_OPENGL_FUNCTIONS)
*/
/*!
+ \fn void QOpenGLExtraFunctions::glBlendBarrier(void)
+
+ Convenience function that calls glBlendBarrier().
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glBlendBarrier.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glBlendEquationSeparatei(GLuint buf, GLenum modeRGB, GLenum modeAlpha)
+
+ Convenience function that calls glBlendEquationSeparatei(\a buf, \a modeRGB, \a modeAlpha).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glBlendEquationSeparatei.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glBlendEquationi(GLuint buf, GLenum mode)
+
+ Convenience function that calls glBlendEquationi(\a buf, \a mode).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glBlendEquationi.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glBlendFuncSeparatei(GLuint buf, GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+
+ Convenience function that calls glBlendFuncSeparatei(\a buf, \a srcRGB, \a dstRGB, \a srcAlpha, \a dstAlpha).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glBlendFuncSeparatei.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glBlendFunci(GLuint buf, GLenum src, GLenum dst)
+
+ Convenience function that calls glBlendFunci(\a buf, \a src, \a dst).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glBlendFunci.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glColorMaski(GLuint index, GLboolean r, GLboolean g, GLboolean b, GLboolean a)
+
+ Convenience function that calls glColorMaski(\a index, \a r, \a g, \a b, \a a).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glColorMaski.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glCopyImageSubData(GLuint srcName, GLenum srcTarget, GLint srcLevel, GLint srcX, GLint srcY, GLint srcZ, GLuint dstName, GLenum dstTarget, GLint dstLevel, GLint dstX, GLint dstY, GLint dstZ, GLsizei srcWidth, GLsizei srcHeight, GLsizei srcDepth)
+
+ Convenience function that calls glCopyImageSubData(\a srcName, \a srcTarget, \a srcLevel, \a srcX, \a srcY, \a srcZ, \a dstName, \a dstTarget, \a dstLevel, \a dstX, \a dstY, \a dstZ, \a srcWidth, \a srcHeight, \a srcDepth).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glCopyImageSubData.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glDebugMessageCallback(GLDEBUGPROC callback, const void * userParam)
+
+ Convenience function that calls glDebugMessageCallback(\a callback, \a userParam).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glDebugMessageCallback.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glDebugMessageControl(GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint * ids, GLboolean enabled)
+
+ Convenience function that calls glDebugMessageControl(\a source, \a type, \a severity, \a count, \a ids, \a enabled).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glDebugMessageControl.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glDebugMessageInsert(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar * buf)
+
+ Convenience function that calls glDebugMessageInsert(\a source, \a type, \a id, \a severity, \a length, \a buf).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glDebugMessageInsert.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glDisablei(GLenum target, GLuint index)
+
+ Convenience function that calls glDisablei(\a target, \a index).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glDisablei.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type, const void * indices, GLint basevertex)
+
+ Convenience function that calls glDrawElementsBaseVertex(\a mode, \a count, \a type, \a indices, \a basevertex).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glDrawElementsBaseVertex.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glDrawElementsInstancedBaseVertex(GLenum mode, GLsizei count, GLenum type, const void * indices, GLsizei instancecount, GLint basevertex)
+
+ Convenience function that calls glDrawElementsInstancedBaseVertex(\a mode, \a count, \a type, \a indices, \a instancecount, \a basevertex).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glDrawElementsInstancedBaseVertex.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glDrawRangeElementsBaseVertex(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void * indices, GLint basevertex)
+
+ Convenience function that calls glDrawRangeElementsBaseVertex(\a mode, \a start, \a end, \a count, \a type, \a indices, \a basevertex).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glDrawRangeElementsBaseVertex.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glEnablei(GLenum target, GLuint index)
+
+ Convenience function that calls glEnablei(\a target, \a index).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glEnablei.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glFramebufferTexture(GLenum target, GLenum attachment, GLuint texture, GLint level)
+
+ Convenience function that calls glFramebufferTexture(\a target, \a attachment, \a texture, \a level).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glFramebufferTexture.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetDebugMessageLog(GLuint count, GLsizei bufSize, GLenum* sources, GLenum* types, GLuint* ids, GLenum* severities, GLsizei* lengths, GLchar* messageLog)
+
+ Convenience function that calls glGetDebugMessageLog(\a count, \a bufSize, \a sources, \a types, \a ids, \a severities, \a lengths, \a messageLog).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetDebugMessageLog.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetGraphicsResetStatus(void)
+
+ Convenience function that calls glGetGraphicsResetStatus().
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetGraphicsResetStatus.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetObjectLabel(GLenum identifier, GLuint name, GLsizei bufSize, GLsizei* length, GLchar* label)
+
+ Convenience function that calls glGetObjectLabel(\a identifier, \a name, \a bufSize, \a length, \a label).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetObjectLabel.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetObjectPtrLabel(const void * ptr, GLsizei bufSize, GLsizei* length, GLchar* label)
+
+ Convenience function that calls glGetObjectPtrLabel(\a ptr, \a bufSize, \a length, \a label).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetObjectPtrLabel.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetPointerv(GLenum pname, void ** params)
+
+ Convenience function that calls glGetPointerv(\a pname, \a params).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetPointerv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetSamplerParameterIiv(GLuint sampler, GLenum pname, GLint* params)
+
+ Convenience function that calls glGetSamplerParameterIiv(\a sampler, \a pname, \a params).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetSamplerParameterIiv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetSamplerParameterIuiv(GLuint sampler, GLenum pname, GLuint* params)
+
+ Convenience function that calls glGetSamplerParameterIuiv(\a sampler, \a pname, \a params).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetSamplerParameterIuiv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetTexParameterIiv(GLenum target, GLenum pname, GLint* params)
+
+ Convenience function that calls glGetTexParameterIiv(\a target, \a pname, \a params).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetTexParameterIiv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetTexParameterIuiv(GLenum target, GLenum pname, GLuint* params)
+
+ Convenience function that calls glGetTexParameterIuiv(\a target, \a pname, \a params).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetTexParameterIuiv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetnUniformfv(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+
+ Convenience function that calls glGetnUniformfv(\a program, \a location, \a bufSize, \a params).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetnUniformfv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetnUniformiv(GLuint program, GLint location, GLsizei bufSize, GLint* params)
+
+ Convenience function that calls glGetnUniformiv(\a program, \a location, \a bufSize, \a params).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetnUniformiv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glGetnUniformuiv(GLuint program, GLint location, GLsizei bufSize, GLuint* params)
+
+ Convenience function that calls glGetnUniformuiv(\a program, \a location, \a bufSize, \a params).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glGetnUniformuiv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glIsEnabledi(GLenum target, GLuint index)
+
+ Convenience function that calls glIsEnabledi(\a target, \a index).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glIsEnabledi.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glMinSampleShading(GLfloat value)
+
+ Convenience function that calls glMinSampleShading(\a value).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glMinSampleShading.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glObjectLabel(GLenum identifier, GLuint name, GLsizei length, const GLchar * label)
+
+ Convenience function that calls glObjectLabel(\a identifier, \a name, \a length, \a label).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glObjectLabel.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glObjectPtrLabel(const void * ptr, GLsizei length, const GLchar * label)
+
+ Convenience function that calls glObjectPtrLabel(\a ptr, \a length, \a label).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glObjectPtrLabel.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glPatchParameteri(GLenum pname, GLint value)
+
+ Convenience function that calls glPatchParameteri(\a pname, \a value).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glPatchParameteri.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glPopDebugGroup(void)
+
+ Convenience function that calls glPopDebugGroup().
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glPopDebugGroup.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glPrimitiveBoundingBox(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW)
+
+ Convenience function that calls glPrimitiveBoundingBox(\a minX, \a minY, \a minZ, \a minW, \a maxX, \a maxY, \a maxZ, \a maxW).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glPrimitiveBoundingBox.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glPushDebugGroup(GLenum source, GLuint id, GLsizei length, const GLchar * message)
+
+ Convenience function that calls glPushDebugGroup(\a source, \a id, \a length, \a message).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glPushDebugGroup.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glReadnPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void * data)
+
+ Convenience function that calls glReadnPixels(\a x, \a y, \a width, \a height, \a format, \a type, \a bufSize, \a data).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glReadnPixels.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glSamplerParameterIiv(GLuint sampler, GLenum pname, const GLint * param)
+
+ Convenience function that calls glSamplerParameterIiv(\a sampler, \a pname, \a param).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glSamplerParameterIiv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glSamplerParameterIuiv(GLuint sampler, GLenum pname, const GLuint * param)
+
+ Convenience function that calls glSamplerParameterIuiv(\a sampler, \a pname, \a param).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glSamplerParameterIuiv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glTexBuffer(GLenum target, GLenum internalformat, GLuint buffer)
+
+ Convenience function that calls glTexBuffer(\a target, \a internalformat, \a buffer).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glTexBuffer.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glTexBufferRange(GLenum target, GLenum internalformat, GLuint buffer, GLintptr offset, GLsizeiptr size)
+
+ Convenience function that calls glTexBufferRange(\a target, \a internalformat, \a buffer, \a offset, \a size).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glTexBufferRange.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glTexParameterIiv(GLenum target, GLenum pname, const GLint * params)
+
+ Convenience function that calls glTexParameterIiv(\a target, \a pname, \a params).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glTexParameterIiv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glTexParameterIuiv(GLenum target, GLenum pname, const GLuint * params)
+
+ Convenience function that calls glTexParameterIuiv(\a target, \a pname, \a params).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glTexParameterIuiv.xml}{${NAME}()}.
+*/
+
+/*!
+ \fn void QOpenGLExtraFunctions::glTexStorage3DMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLboolean fixedsamplelocations)
+
+ Convenience function that calls glTexStorage3DMultisample(\a target, \a samples, \a internalformat, \a width, \a height, \a depth, \a fixedsamplelocations).
+
+ This function is only available in OpenGL ES 3.x, or OpenGL 3.x or 4.x contexts. When running
+ with plain OpenGL, the function is only usable when the given profile and version contains the
+ function either in core or as an extension.
+
+ For more information, see the OpenGL ES 3.2 documentation for
+ \l{http://www.khronos.org/opengles/sdk/docs/man32/glTexStorage3DMultisample.xml}{${NAME}()}.
+*/
+
+/*!
\fn bool QOpenGLExtraFunctions::isInitialized(const QOpenGLExtraFunctionsPrivate *d)
\internal
*/
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index 766d4a327a..3563f1b5d3 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -43,6 +43,7 @@
#include "qopenglfunctions.h"
#include <QtGui/qcolor.h>
#include <QtGui/qopenglcontext.h>
+#include <QtCore/qdebug.h>
#include <private/qobject_p.h>
#include <private/qopenglcontext_p.h>
@@ -190,11 +191,20 @@ void QOpenGLTexturePrivate::destroy()
return;
}
QOpenGLContext *currentContext = QOpenGLContext::currentContext();
- if (!currentContext || !QOpenGLContext::areSharing(currentContext, context)) {
- qWarning("Texture is not valid in the current context.\n"
+ if (!currentContext) {
+ qWarning("QOpenGLTexturePrivate::destroy() called without a current context.\n"
"Texture has not been destroyed");
return;
}
+ if (!QOpenGLContext::areSharing(currentContext, context)) {
+
+ qWarning("QOpenGLTexturePrivate::destroy() called but texture context %p"
+ " is not shared with current context %p.\n"
+ "Texture has not been destroyed",
+ static_cast<const void *>(context),
+ static_cast<const void *>(currentContext));
+ return;
+ }
functions->glDeleteTextures(1, &textureId);
@@ -4661,4 +4671,40 @@ float QOpenGLTexture::levelofDetailBias() const
return d->levelOfDetailBias;
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QOpenGLTexture *t)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << "QOpenGLTexture(";
+ if (t) {
+ const QOpenGLTexturePrivate *d = t->d_ptr.data();
+ debug << d->target << ", bindingTarget=" << d->bindingTarget
+ << ", size=[" << d->dimensions[0]
+ << ", " << d->dimensions[1];
+ if (d->target == QOpenGLTexture::Target3D)
+ debug << ", " << d->dimensions[2];
+ debug << "], format=" << d->format << ", formatClass=" << d->formatClass;
+ if (t->isCreated())
+ debug << ", textureId=" << d->textureId;
+ if (t->isBound())
+ debug << ", [bound]";
+ if (t->isTextureView())
+ debug << ", [view]";
+ if (d->fixedSamplePositions)
+ debug << ", [fixedSamplePositions]";
+ debug << ", mipLevels=" << d->requestedMipLevels << ", layers=" << d->layers
+ << ", faces=" << d->faces << ", samples=" << d->samples
+ << ", depthStencilMode=" << d->depthStencilMode << ", comparisonFunction="
+ << d->comparisonFunction << ", comparisonMode=" << d->comparisonMode
+ << ", features=" << d->features << ", minificationFilter=" << d->minFilter
+ << ", magnificationFilter=" << d->magFilter << ", wrapMode=" << d->wrapModes[0];
+ } else {
+ debug << '0';
+ }
+ debug << ')';
+ return debug;
+}
+#endif // QT_NO_DEBUG_STREAM
+
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopengltexture.h b/src/gui/opengl/qopengltexture.h
index 6e6f7ef1f2..12d9b91603 100644
--- a/src/gui/opengl/qopengltexture.h
+++ b/src/gui/opengl/qopengltexture.h
@@ -50,6 +50,7 @@
QT_BEGIN_NAMESPACE
+class QDebug;
class QOpenGLTexturePrivate;
class QOpenGLPixelTransferOptions;
@@ -613,6 +614,10 @@ public:
void setLevelofDetailBias(float bias);
float levelofDetailBias() const;
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QOpenGLTexture *t);
+#endif
+
private:
Q_DISABLE_COPY(QOpenGLTexture)
Q_DECLARE_PRIVATE(QOpenGLTexture)
@@ -621,6 +626,10 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QOpenGLTexture::Features)
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug debug, const QOpenGLTexture *t);
+#endif
+
QT_END_NAMESPACE
#endif // QT_NO_OPENGL
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 63e345545c..9ff0b5f5e5 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -99,6 +99,9 @@ SOURCES += \
painting/qplatformbackingstore.cpp \
painting/qpathsimplifier.cpp
+RESOURCES += \
+ painting/qpdf.qrc
+
darwin {
HEADERS += painting/qcoregraphics_p.h
SOURCES += painting/qcoregraphics.mm
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 53349dcef4..d2c0912878 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -90,50 +90,6 @@ public:
*/
/*!
- Flushes the given \a region from the specified window \a win onto the
- screen.
-
- Note that the \a offset parameter is currently unused.
-*/
-void QBackingStore::flush(const QRegion &region, QWindow *win, const QPoint &offset)
-{
- if (!win)
- win = window();
- if (!win->handle()) {
- qWarning() << "QBackingStore::flush() called for "
- << win << " which does not have a handle.";
- return;
- }
-
-#ifdef QBACKINGSTORE_DEBUG
- if (win && win->isTopLevel() && !qt_window_private(win)->receivedExpose) {
- qWarning().nospace() << "QBackingStore::flush() called with non-exposed window "
- << win << ", behavior is undefined";
- }
-#endif
-
- Q_ASSERT(win == this->window() || this->window()->isAncestorOf(win, QWindow::ExcludeTransients));
-
- d_ptr->platformBackingStore->flush(win, QHighDpi::toNativeLocalRegion(region, win),
- QHighDpi::toNativeLocalPosition(offset, win));
-}
-
-/*!
- \fn QPaintDevice* QBackingStore::paintDevice()
-
- Implement this function to return the appropriate paint device.
-*/
-QPaintDevice *QBackingStore::paintDevice()
-{
- QPaintDevice *device = d_ptr->platformBackingStore->paintDevice();
-
- if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image)
- return d_ptr->highDpiBackingstore.data();
-
- return device;
-}
-
-/*!
Constructs an empty surface for the given top-level \a window.
*/
QBackingStore::QBackingStore(QWindow *window)
@@ -161,8 +117,10 @@ QWindow* QBackingStore::window() const
}
/*!
- This function is called before painting onto the surface begins,
- with the \a region in which the painting will occur.
+ Begins painting on the backing store surface in the given \a region.
+
+ You should call this function before using the paintDevice() to
+ paint.
\sa endPaint(), paintDevice()
*/
@@ -203,7 +161,26 @@ void QBackingStore::beginPaint(const QRegion &region)
}
/*!
- This function is called after painting onto the surface has ended.
+ Returns the paint device for this surface.
+
+ \warning The device is only valid between calls to beginPaint() and
+ endPaint(). You should not cache the returned value.
+*/
+QPaintDevice *QBackingStore::paintDevice()
+{
+ QPaintDevice *device = d_ptr->platformBackingStore->paintDevice();
+
+ if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image)
+ return d_ptr->highDpiBackingstore.data();
+
+ return device;
+}
+
+/*!
+ Ends painting.
+
+ You should call this function after painting with the paintDevice()
+ has ended.
\sa beginPaint(), paintDevice()
*/
@@ -213,9 +190,50 @@ void QBackingStore::endPaint()
}
/*!
- Sets the size of the windowsurface to be \a size.
+ Flushes the given \a region from the specified \a window onto the
+ screen.
+
+ The \a window must either be the top level window represented by
+ this backingstore, or a non-transient child of that window. Passing
+ \c nullptr falls back to using the backingstore's top level window.
+
+ If the \a window is a child window, the \a region should be in child window
+ coordinates, and the \a offset should be the child window's offset in relation
+ to the backingstore's top level window.
+
+ You should call this function after ending painting with endPaint().
+
+ \sa QWindow::transientParent()
+*/
+void QBackingStore::flush(const QRegion &region, QWindow *window, const QPoint &offset)
+{
+ QWindow *topLevelWindow = this->window();
+
+ if (!window)
+ window = topLevelWindow;
+ if (!window->handle()) {
+ qWarning() << "QBackingStore::flush() called for "
+ << window << " which does not have a handle.";
+ return;
+ }
+
+#ifdef QBACKINGSTORE_DEBUG
+ if (window && window->isTopLevel() && !qt_window_private(window)->receivedExpose) {
+ qWarning().nospace() << "QBackingStore::flush() called with non-exposed window "
+ << window << ", behavior is undefined";
+ }
+#endif
+
+ Q_ASSERT(window == topLevelWindow || topLevelWindow->isAncestorOf(window, QWindow::ExcludeTransients));
+
+ d_ptr->platformBackingStore->flush(window, QHighDpi::toNativeLocalRegion(region, window),
+ QHighDpi::toNativeLocalPosition(offset, window));
+}
+
+/*!
+ Sets the size of the window surface to \a size.
- \sa size()
+ \sa size()
*/
void QBackingStore::resize(const QSize &size)
{
@@ -224,7 +242,7 @@ void QBackingStore::resize(const QSize &size)
}
/*!
- Returns the current size of the windowsurface.
+ Returns the current size of the window surface.
*/
QSize QBackingStore::size() const
{
@@ -252,7 +270,7 @@ bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
}
/*!
- Set \a region as the static contents of this window.
+ Set \a region as the static contents of this window.
*/
void QBackingStore::setStaticContents(const QRegion &region)
{
@@ -260,8 +278,8 @@ void QBackingStore::setStaticContents(const QRegion &region)
}
/*!
- Returns a pointer to the QRegion that has the static contents
- of this window.
+ Returns a QRegion representing the area of the window that
+ has static contents.
*/
QRegion QBackingStore::staticContents() const
{
@@ -269,8 +287,7 @@ QRegion QBackingStore::staticContents() const
}
/*!
- Returns a boolean indicating if this window
- has static contents or not.
+ Returns a boolean indicating if this window has static contents or not.
*/
bool QBackingStore::hasStaticContents() const
{
@@ -325,7 +342,7 @@ void Q_GUI_EXPORT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPo
}
/*!
- Returns a pointer to the QPlatformBackingStore implementation
+ Returns a pointer to the QPlatformBackingStore implementation
*/
QPlatformBackingStore *QBackingStore::handle() const
{
diff --git a/src/gui/painting/qbackingstore.h b/src/gui/painting/qbackingstore.h
index 2ba6e1c906..ed37e11a5b 100644
--- a/src/gui/painting/qbackingstore.h
+++ b/src/gui/painting/qbackingstore.h
@@ -66,9 +66,7 @@ public:
QPaintDevice *paintDevice();
- // 'window' can be a child window, in which case 'region' is in child window coordinates and
- // offset is the (child) window's offset in relation to the window surface.
- void flush(const QRegion &region, QWindow *window = Q_NULLPTR, const QPoint &offset = QPoint());
+ void flush(const QRegion &region, QWindow *window = nullptr, const QPoint &offset = QPoint());
void resize(const QSize &size);
QSize size() const;
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index cc3ee76f0d..5c13308d94 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -100,7 +100,7 @@ const uchar *qt_patternForBrush(int brushStyle, bool invert)
return pat_tbl[brushStyle - Qt::Dense1Pattern][invert];
}
-QPixmap qt_pixmapForBrush(int brushStyle, bool invert)
+Q_GUI_EXPORT QPixmap qt_pixmapForBrush(int brushStyle, bool invert)
{
QPixmap pm;
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index 9e1785c11d..855f245396 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -79,7 +79,7 @@ static inline int hex2int(char s)
return h < 0 ? h : (h << 4) | h;
}
-static bool get_hex_rgb(const char *name, int len, QRgb *rgb)
+static bool get_hex_rgb(const char *name, size_t len, QRgb *rgb)
{
if (name[0] != '#')
return false;
@@ -124,12 +124,12 @@ bool qt_get_hex_rgb(const char *name, QRgb *rgb)
return get_hex_rgb(name, qstrlen(name), rgb);
}
-static bool get_hex_rgb(const QChar *str, int len, QRgb *rgb)
+static bool get_hex_rgb(const QChar *str, size_t len, QRgb *rgb)
{
if (len > 13)
return false;
char tmp[16];
- for (int i = 0; i < len; ++i)
+ for (size_t i = 0; i < len; ++i)
tmp[i] = str[i].toLatin1();
tmp[len] = 0;
return get_hex_rgb(tmp, len, rgb);
@@ -858,6 +858,7 @@ QString QColor::name(NameFormat format) const
return QString();
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
Sets the RGB value of this QColor to \a name, which may be in one
of these formats:
@@ -883,6 +884,17 @@ QString QColor::name(NameFormat format) const
void QColor::setNamedColor(const QString &name)
{
+ setColorFromString(qToStringViewIgnoringNull(name));
+}
+#endif
+
+/*!
+ \overload
+ \since 5.10
+*/
+
+void QColor::setNamedColor(QStringView name)
+{
setColorFromString(name);
}
@@ -896,6 +908,7 @@ void QColor::setNamedColor(QLatin1String name)
setColorFromString(name);
}
+#if QT_STRINGVIEW_LEVEL < 2
/*!
\since 4.7
@@ -909,7 +922,17 @@ void QColor::setNamedColor(QLatin1String name)
*/
bool QColor::isValidColor(const QString &name)
{
- return !name.isEmpty() && QColor().setColorFromString(name);
+ return isValidColor(qToStringViewIgnoringNull(name));
+}
+#endif
+
+/*!
+ \overload
+ \since 5.10
+*/
+bool QColor::isValidColor(QStringView name) Q_DECL_NOTHROW
+{
+ return name.size() && QColor().setColorFromString(name);
}
/*!
@@ -922,7 +945,7 @@ bool QColor::isValidColor(QLatin1String name) Q_DECL_NOTHROW
}
template <typename String>
-bool QColor::setColorFromString(const String &name)
+bool QColor::setColorFromString(String name)
{
if (!name.size()) {
invalidate();
diff --git a/src/gui/painting/qcolor.h b/src/gui/painting/qcolor.h
index 83a93e25ea..0c5ebcbda9 100644
--- a/src/gui/painting/qcolor.h
+++ b/src/gui/painting/qcolor.h
@@ -72,7 +72,10 @@ public:
inline QColor(int r, int g, int b, int a = 255);
QColor(QRgb rgb) Q_DECL_NOTHROW;
QColor(QRgba64 rgba64) Q_DECL_NOTHROW;
+#if QT_STRINGVIEW_LEVEL < 2
inline QColor(const QString& name);
+#endif
+ explicit inline QColor(QStringView name);
inline QColor(const char *aname) : QColor(QLatin1String(aname)) {}
inline QColor(QLatin1String name);
QColor(Spec spec) Q_DECL_NOTHROW;
@@ -95,7 +98,10 @@ public:
QString name() const;
QString name(NameFormat format) const;
+#if QT_STRINGVIEW_LEVEL < 2
void setNamedColor(const QString& name);
+#endif
+ void setNamedColor(QStringView name);
void setNamedColor(QLatin1String name);
static QStringList colorNames();
@@ -221,14 +227,17 @@ public:
operator QVariant() const;
+#if QT_STRINGVIEW_LEVEL < 2
static bool isValidColor(const QString &name);
+#endif
+ static bool isValidColor(QStringView) Q_DECL_NOTHROW;
static bool isValidColor(QLatin1String) Q_DECL_NOTHROW;
private:
void invalidate() Q_DECL_NOTHROW;
template <typename String>
- bool setColorFromString(const String &name);
+ bool setColorFromString(String name);
Spec cspec;
union {
@@ -280,8 +289,13 @@ inline QColor::QColor(int r, int g, int b, int a)
inline QColor::QColor(QLatin1String aname)
{ setNamedColor(aname); }
+inline QColor::QColor(QStringView aname)
+{ setNamedColor(aname); }
+
+#if QT_STRINGVIEW_LEVEL < 2
inline QColor::QColor(const QString& aname)
{ setNamedColor(aname); }
+#endif
#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
inline QColor::QColor(const QColor &acolor) Q_DECL_NOTHROW
diff --git a/src/gui/painting/qcompositionfunctions.cpp b/src/gui/painting/qcompositionfunctions.cpp
index 6d2cb9aadb..ee05f810f1 100644
--- a/src/gui/painting/qcompositionfunctions.cpp
+++ b/src/gui/painting/qcompositionfunctions.cpp
@@ -855,6 +855,10 @@ struct QFullCoverage {
{
*dest = src;
}
+ inline void store(QRgba64 *dest, const QRgba64 src) const
+ {
+ *dest = src;
+ }
};
struct QPartialCoverage {
@@ -868,6 +872,10 @@ struct QPartialCoverage {
{
*dest = INTERPOLATE_PIXEL_255(src, ca, *dest, ica);
}
+ inline void store(QRgba64 *dest, const QRgba64 src) const
+ {
+ *dest = interpolate255(src, ca, *dest, ica);
+ }
private:
const uint ca;
@@ -879,6 +887,11 @@ static inline int mix_alpha(int da, int sa)
return 255 - ((255 - sa) * (255 - da) >> 8);
}
+static inline uint mix_alpha_rgb64(uint da, uint sa)
+{
+ return 65535 - ((65535 - sa) * (65535 - da) >> 16);
+}
+
/*
Dca' = Sca.Da + Dca.Sa + Sca.(1 - Da) + Dca.(1 - Sa)
= Sca + Dca
@@ -897,17 +910,6 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl(uint *dest, int
}
}
-template <typename T>
-Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Plus_impl_rgb64(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
-{
- QRgba64 s = color;
- for (int i = 0; i < length; ++i) {
- QRgba64 d = dest[i];
- d = comp_func_Plus_one_pixel(d, s);
- coverage.store(&dest[i], d);
- }
-}
-
void QT_FASTCALL comp_func_solid_Plus(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -986,6 +988,11 @@ static inline int multiply_op(int dst, int src, int da, int sa)
return qt_div_255(src * dst + src * (255 - da) + dst * (255 - sa));
}
+static inline uint multiply_op_rgb64(uint dst, uint src, uint da, uint sa)
+{
+ return qt_div_65535(src * dst + src * (65535 - da) + dst * (65535 - sa));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest, int length, uint color, const T &coverage)
{
@@ -1011,6 +1018,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(uint *dest,
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Multiply_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a, b) multiply_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1019,6 +1049,14 @@ void QT_FASTCALL comp_func_solid_Multiply(uint *dest, int length, uint color, ui
comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_Multiply_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Multiply_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Multiply_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1042,6 +1080,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(uint *Q_DECL_REST
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Multiply_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) multiply_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_Multiply(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1050,6 +1109,14 @@ void QT_FASTCALL comp_func_Multiply(uint *Q_DECL_RESTRICT dest, const uint *Q_DE
comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_Multiply_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Multiply_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Multiply_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
/*
Dca' = (Sca.Da + Dca.Sa - Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
= Sca + Dca - Sca.Dca
@@ -1079,6 +1146,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(uint *dest, i
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Screen_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a, b) 65535 - qt_div_65535((65535-a) * (65535-b))
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1087,6 +1177,14 @@ void QT_FASTCALL comp_func_solid_Screen(uint *dest, int length, uint color, uint
comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_Screen_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Screen_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Screen_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1110,6 +1208,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(uint *Q_DECL_RESTRI
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Screen_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) 65535 - (((65535-a) * (65535-b)) >> 16)
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1118,6 +1237,14 @@ void QT_FASTCALL comp_func_Screen(uint *dest, const uint *src, int length, uint
comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_Screen_rgb64(QRgba64 *dest, const QRgba64 *src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Screen_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Screen_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
/*
if 2.Dca < Da
Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1133,6 +1260,15 @@ static inline int overlay_op(int dst, int src, int da, int sa)
return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp);
}
+static inline uint overlay_op_rgb64(uint dst, uint src, uint da, uint sa)
+{
+ const uint temp = src * (65535 - da) + dst * (65535 - sa);
+ if (2 * dst < da)
+ return qt_div_65535(2 * src * dst + temp);
+ else
+ return qt_div_65535(sa * da - 2 * (da - dst) * (sa - src) + temp);
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest, int length, uint color, const T &coverage)
{
@@ -1158,6 +1294,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(uint *dest,
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Overlay_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a, b) overlay_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1166,6 +1325,14 @@ void QT_FASTCALL comp_func_solid_Overlay(uint *dest, int length, uint color, uin
comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_Overlay_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Overlay_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Overlay_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1189,6 +1356,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(uint *Q_DECL_RESTR
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Overlay_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) overlay_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_Overlay(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1197,6 +1385,14 @@ void QT_FASTCALL comp_func_Overlay(uint *Q_DECL_RESTRICT dest, const uint *Q_DEC
comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_Overlay_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Overlay_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Overlay_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
/*
Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
Da' = Sa + Da - Sa.Da
@@ -1206,6 +1402,11 @@ static inline int darken_op(int dst, int src, int da, int sa)
return qt_div_255(qMin(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa));
}
+static inline uint darken_op_rgb64(uint dst, uint src, uint da, uint sa)
+{
+ return qt_div_65535(qMin(src * da, dst * sa) + src * (65535 - da) + dst * (65535 - sa));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, int length, uint color, const T &coverage)
{
@@ -1231,6 +1432,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(uint *dest, i
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Darken_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a, b) darken_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1239,6 +1463,14 @@ void QT_FASTCALL comp_func_solid_Darken(uint *dest, int length, uint color, uint
comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_Darken_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Darken_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Darken_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1262,6 +1494,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(uint *Q_DECL_RESTRI
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Darken_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) darken_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_Darken(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1270,6 +1523,14 @@ void QT_FASTCALL comp_func_Darken(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL
comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_Darken_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Darken_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Darken_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
/*
Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa)
Da' = Sa + Da - Sa.Da
@@ -1279,6 +1540,11 @@ static inline int lighten_op(int dst, int src, int da, int sa)
return qt_div_255(qMax(src * da, dst * sa) + src * (255 - da) + dst * (255 - sa));
}
+static inline uint lighten_op_rgb64(uint dst, uint src, uint da, uint sa)
+{
+ return qt_div_65535(qMax(src * da, dst * sa) + src * (65535 - da) + dst * (65535 - sa));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest, int length, uint color, const T &coverage)
{
@@ -1304,6 +1570,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(uint *dest,
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Lighten_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a, b) lighten_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1312,6 +1601,14 @@ void QT_FASTCALL comp_func_solid_Lighten(uint *dest, int length, uint color, uin
comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_Lighten_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Lighten_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Lighten_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1335,6 +1632,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(uint *Q_DECL_RESTR
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Lighten_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) lighten_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_Lighten(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1343,6 +1661,14 @@ void QT_FASTCALL comp_func_Lighten(uint *Q_DECL_RESTRICT dest, const uint *Q_DEC
comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_Lighten_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Lighten_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Lighten_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
/*
if Sca.Da + Dca.Sa >= Sa.Da
Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1362,6 +1688,19 @@ static inline int color_dodge_op(int dst, int src, int da, int sa)
return qt_div_255(255 * dst_sa / (255 - 255 * src / sa) + temp);
}
+static inline uint color_dodge_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
+{
+ const qint64 sa_da = sa * da;
+ const qint64 dst_sa = dst * sa;
+ const qint64 src_da = src * da;
+
+ const qint64 temp = src * (65535 - da) + dst * (65535 - sa);
+ if (src_da + dst_sa >= sa_da)
+ return qt_div_65535(sa_da + temp);
+ else
+ return qt_div_65535(65535 * dst_sa / (65535 - 65535 * src / sa) + temp);
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *dest, int length, uint color, const T &coverage)
{
@@ -1387,6 +1726,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(uint *des
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorDodge_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a,b) color_dodge_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1395,6 +1757,14 @@ void QT_FASTCALL comp_func_solid_ColorDodge(uint *dest, int length, uint color,
comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_ColorDodge_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_ColorDodge_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_ColorDodge_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1418,6 +1788,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(uint *Q_DECL_RE
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorDodge_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) color_dodge_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_ColorDodge(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1426,6 +1817,14 @@ void QT_FASTCALL comp_func_ColorDodge(uint *Q_DECL_RESTRICT dest, const uint *Q_
comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_ColorDodge_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_ColorDodge_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_ColorDodge_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
/*
if Sca.Da + Dca.Sa <= Sa.Da
Dca' = Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1445,6 +1844,19 @@ static inline int color_burn_op(int dst, int src, int da, int sa)
return qt_div_255(sa * (src_da + dst_sa - sa_da) / src + temp);
}
+static inline uint color_burn_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
+{
+ const qint64 src_da = src * da;
+ const qint64 dst_sa = dst * sa;
+ const qint64 sa_da = sa * da;
+
+ const qint64 temp = src * (65535 - da) + dst * (65535 - sa);
+
+ if (src == 0 || src_da + dst_sa <= sa_da)
+ return qt_div_65535(temp);
+ return qt_div_65535(sa * (src_da + dst_sa - sa_da) / src + temp);
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest, int length, uint color, const T &coverage)
{
@@ -1470,6 +1882,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(uint *dest
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_ColorBurn_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a, b) color_burn_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1478,6 +1913,14 @@ void QT_FASTCALL comp_func_solid_ColorBurn(uint *dest, int length, uint color, u
comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_ColorBurn_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_ColorBurn_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_ColorBurn_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1501,6 +1944,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(uint *Q_DECL_RES
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_ColorBurn_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) color_burn_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_ColorBurn(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1509,6 +1973,14 @@ void QT_FASTCALL comp_func_ColorBurn(uint *Q_DECL_RESTRICT dest, const uint *Q_D
comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_ColorBurn_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_ColorBurn_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_ColorBurn_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
/*
if 2.Sca < Sa
Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1525,6 +1997,16 @@ static inline uint hardlight_op(int dst, int src, int da, int sa)
return qt_div_255(sa * da - 2 * (da - dst) * (sa - src) + temp);
}
+static inline uint hardlight_op_rgb64(uint dst, uint src, uint da, uint sa)
+{
+ const uint temp = src * (65535 - da) + dst * (65535 - sa);
+
+ if (2 * src < sa)
+ return qt_div_65535(2 * src * dst + temp);
+ else
+ return qt_div_65535(sa * da - 2 * (da - dst) * (sa - src) + temp);
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest, int length, uint color, const T &coverage)
{
@@ -1550,6 +2032,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(uint *dest
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_HardLight_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a, b) hardlight_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1558,6 +2063,14 @@ void QT_FASTCALL comp_func_solid_HardLight(uint *dest, int length, uint color, u
comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_HardLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_HardLight_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_HardLight_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1581,6 +2094,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(uint *Q_DECL_RES
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_HardLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) hardlight_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_HardLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1589,6 +2123,14 @@ void QT_FASTCALL comp_func_HardLight(uint *Q_DECL_RESTRICT dest, const uint *Q_D
comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_HardLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_HardLight_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_HardLight_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
/*
if 2.Sca <= Sa
Dca' = Dca.(Sa + (2.Sca - Sa).(1 - Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa)
@@ -1612,6 +2154,22 @@ static inline int soft_light_op(int dst, int src, int da, int sa)
}
}
+static inline uint soft_light_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
+{
+ const qint64 src2 = src << 1;
+ const qint64 dst_np = da != 0 ? (65535 * dst) / da : 0;
+ const qint64 temp = (src * (65535 - da) + dst * (65535 - sa)) * 65535;
+ const qint64 factor = qint64(65535) * 65535;
+
+ if (src2 < sa)
+ return (dst * (sa * 65535 + (src2 - sa) * (65535 - dst_np)) + temp) / factor;
+ else if (4 * dst <= da)
+ return (dst * sa * 65535 + da * (src2 - sa) * ((((16 * dst_np - 12 * 65535) * dst_np + 3 * factor) * dst_np) / factor) + temp) / factor;
+ else {
+ return (dst * sa * 65535 + da * (src2 - sa) * (int(qSqrt(qreal(dst_np * 65535))) - dst_np) + temp) / factor;
+ }
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest, int length, uint color, const T &coverage)
{
@@ -1637,6 +2195,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(uint *dest
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_SoftLight_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a, b) soft_light_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1645,6 +2226,14 @@ void QT_FASTCALL comp_func_solid_SoftLight(uint *dest, int length, uint color, u
comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_SoftLight_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_SoftLight_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_SoftLight_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1668,6 +2257,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(uint *Q_DECL_RES
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_SoftLight_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) soft_light_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1676,6 +2286,14 @@ void QT_FASTCALL comp_func_SoftLight(uint *Q_DECL_RESTRICT dest, const uint *Q_D
comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_SoftLight_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_SoftLight_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_SoftLight_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
/*
Dca' = abs(Dca.Sa - Sca.Da) + Sca.(1 - Da) + Dca.(1 - Sa)
= Sca + Dca - 2.min(Sca.Da, Dca.Sa)
@@ -1685,6 +2303,11 @@ static inline int difference_op(int dst, int src, int da, int sa)
return src + dst - qt_div_255(2 * qMin(src * da, dst * sa));
}
+static inline uint difference_op_rgb64(qint64 dst, qint64 src, qint64 da, qint64 sa)
+{
+ return src + dst - qt_div_65535(2 * qMin(src * da, dst * sa));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *dest, int length, uint color, const T &coverage)
{
@@ -1710,6 +2333,29 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(uint *des
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_solid_Difference_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a, b) difference_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1718,6 +2364,14 @@ void QT_FASTCALL comp_func_solid_Difference(uint *dest, int length, uint color,
comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_Difference_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Difference_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Difference_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1741,6 +2395,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(uint *Q_DECL_RE
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Difference_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) difference_op_rgb64(a, b, da, sa)
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_Difference(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1749,6 +2424,14 @@ void QT_FASTCALL comp_func_Difference(uint *Q_DECL_RESTRICT dest, const uint *Q_
comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_Difference_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Difference_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Difference_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
/*
Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa)
*/
@@ -1777,6 +2460,30 @@ Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_imp
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void QT_FASTCALL comp_func_solid_Exclusion_impl(QRgba64 *dest, int length, QRgba64 color, const T &coverage)
+{
+ uint sa = color.alpha();
+ uint sr = color.red();
+ uint sg = color.green();
+ uint sb = color.blue();
+
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ uint da = d.alpha();
+
+#define OP(a, b) (a + b - qt_div_65535(2*(qint64(a)*b)))
+ uint r = OP( d.red(), sr);
+ uint b = OP( d.blue(), sb);
+ uint g = OP(d.green(), sg);
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
+
void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, uint const_alpha)
{
if (const_alpha == 255)
@@ -1785,6 +2492,14 @@ void QT_FASTCALL comp_func_solid_Exclusion(uint *dest, int length, uint color, u
comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_solid_Exclusion_rgb64(QRgba64 *dest, int length, QRgba64 color, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_solid_Exclusion_impl(dest, length, color, QFullCoverage());
+ else
+ comp_func_solid_Exclusion_impl(dest, length, color, QPartialCoverage(const_alpha));
+}
+
template <typename T>
Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, const T &coverage)
{
@@ -1808,6 +2523,27 @@ Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(uint *Q_DECL_RES
}
}
+template <typename T>
+Q_STATIC_TEMPLATE_FUNCTION inline void comp_func_Exclusion_impl(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, const T &coverage)
+{
+ for (int i = 0; i < length; ++i) {
+ QRgba64 d = dest[i];
+ QRgba64 s = src[i];
+
+ uint da = d.alpha();
+ uint sa = s.alpha();
+
+#define OP(a, b) (a + b - ((qint64(a)*b) >> 15))
+ uint r = OP( d.red(), s.red());
+ uint b = OP( d.blue(), s.blue());
+ uint g = OP(d.green(), s.green());
+ uint a = mix_alpha_rgb64(da, sa);
+#undef OP
+
+ coverage.store(&dest[i], qRgba64(r, g, b, a));
+ }
+}
+
void QT_FASTCALL comp_func_Exclusion(uint *Q_DECL_RESTRICT dest, const uint *Q_DECL_RESTRICT src, int length, uint const_alpha)
{
if (const_alpha == 255)
@@ -1816,6 +2552,14 @@ void QT_FASTCALL comp_func_Exclusion(uint *Q_DECL_RESTRICT dest, const uint *Q_D
comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha));
}
+void QT_FASTCALL comp_func_Exclusion_rgb64(QRgba64 *Q_DECL_RESTRICT dest, const QRgba64 *Q_DECL_RESTRICT src, int length, uint const_alpha)
+{
+ if (const_alpha == 255)
+ comp_func_Exclusion_impl(dest, src, length, QFullCoverage());
+ else
+ comp_func_Exclusion_impl(dest, src, length, QPartialCoverage(const_alpha));
+}
+
void QT_FASTCALL rasterop_solid_SourceOrDestination(uint *dest,
int length,
uint color,
@@ -2177,8 +2921,17 @@ CompositionFunctionSolid64 qt_functionForModeSolid64_C[] = {
comp_func_solid_DestinationAtop_rgb64,
comp_func_solid_XOR_rgb64,
comp_func_solid_Plus_rgb64,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
+ comp_func_solid_Multiply_rgb64,
+ comp_func_solid_Screen_rgb64,
+ comp_func_solid_Overlay_rgb64,
+ comp_func_solid_Darken_rgb64,
+ comp_func_solid_Lighten_rgb64,
+ comp_func_solid_ColorDodge_rgb64,
+ comp_func_solid_ColorBurn_rgb64,
+ comp_func_solid_HardLight_rgb64,
+ comp_func_solid_SoftLight_rgb64,
+ comp_func_solid_Difference_rgb64,
+ comp_func_solid_Exclusion_rgb64,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
@@ -2238,8 +2991,17 @@ CompositionFunction64 qt_functionForMode64_C[] = {
comp_func_DestinationAtop_rgb64,
comp_func_XOR_rgb64,
comp_func_Plus_rgb64,
- 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0,
+ comp_func_Multiply_rgb64,
+ comp_func_Screen_rgb64,
+ comp_func_Overlay_rgb64,
+ comp_func_Darken_rgb64,
+ comp_func_Lighten_rgb64,
+ comp_func_ColorDodge_rgb64,
+ comp_func_ColorBurn_rgb64,
+ comp_func_HardLight_rgb64,
+ comp_func_SoftLight_rgb64,
+ comp_func_Difference_rgb64,
+ comp_func_Exclusion_rgb64,
0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0
};
diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm
index c4fb8afc64..a234a12bf0 100644
--- a/src/gui/painting/qcoregraphics.mm
+++ b/src/gui/painting/qcoregraphics.mm
@@ -66,7 +66,7 @@ CGImageRef qt_mac_toCGImageMask(const QImage &image)
static const auto deleter = [](void *image, const void *, size_t) { delete static_cast<QImage *>(image); };
QCFType<CGDataProviderRef> dataProvider =
CGDataProviderCreateWithData(new QImage(image), image.bits(),
- image.byteCount(), deleter);
+ image.sizeInBytes(), deleter);
return CGImageMaskCreate(image.width(), image.height(), 8, image.depth(),
image.bytesPerLine(), dataProvider, NULL, false);
diff --git a/src/gui/painting/qcosmeticstroker.cpp b/src/gui/painting/qcosmeticstroker.cpp
index bcb243db6a..436a62d486 100644
--- a/src/gui/painting/qcosmeticstroker.cpp
+++ b/src/gui/painting/qcosmeticstroker.cpp
@@ -292,7 +292,7 @@ void QCosmeticStroker::setup()
color = multiplyAlpha256(state->penData.solid.color, opacity).toArgb32();
QRasterBuffer *buffer = state->penData.rasterBuffer;
pixels = (uint *)buffer->buffer();
- ppl = buffer->bytesPerLine()>>2;
+ ppl = buffer->stride<quint32>();
}
// line drawing produces different results with different clips, so
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 5c6c91f0ba..ebfe1162f4 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -55,10 +55,13 @@
#endif
#include <private/qguiapplication_p.h>
#include <private/qrgba64_p.h>
+#include <qloggingcategory.h>
#include <qmath.h>
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcQtGuiDrawHelper, "qt.gui.drawhelper")
+
#define MASK(src, a) src = BYTE_MUL(src, a)
/*
@@ -1042,7 +1045,7 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
{ 10, 20, 10, 10, 10, 0, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderBGR>, convertA2RGB30PMFromARGB32PM<PixelOrderBGR>, convertRGB30FromRGB32<PixelOrderBGR>, convertA2RGB30PMToARGB64PM<PixelOrderBGR> }, // Format_A2BGR30_Premultiplied
{ 10, 0, 10, 10, 10, 20, 0, 30, false, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertRGB30FromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_RGB30
{ 10, 0, 10, 10, 10, 20, 2, 30, true, QPixelLayout::BPP32, convertA2RGB30PMToARGB32PM<PixelOrderRGB>, convertA2RGB30PMFromARGB32PM<PixelOrderRGB>, convertRGB30FromRGB32<PixelOrderRGB>, convertA2RGB30PMToARGB64PM<PixelOrderRGB> }, // Format_A2RGB30_Premultiplied
- { 0, 0, 0, 0, 0, 0, 8, 0, false, QPixelLayout::BPP8, convertAlpha8ToRGB32, convertAlpha8FromARGB32PM, 0, convertAlpha8ToRGB64 }, // Format_Alpha8
+ { 0, 0, 0, 0, 0, 0, 8, 0, true, QPixelLayout::BPP8, convertAlpha8ToRGB32, convertAlpha8FromARGB32PM, 0, convertAlpha8ToRGB64 }, // Format_Alpha8
{ 0, 0, 0, 0, 0, 0, 0, 0, false, QPixelLayout::BPP8, convertGrayscale8ToRGB32, convertGrayscale8FromARGB32PM, convertGrayscale8FromRGB32, convertGrayscale8ToRGB64 } // Format_Grayscale8
};
@@ -2375,7 +2378,7 @@ static void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper(uint
__m128i v_fy = _mm_setr_epi32(fy, fy + fdy, fy + fdy + fdy, fy + fdy + fdy + fdy);
const uchar *textureData = image.imageData;
- const int bytesPerLine = image.bytesPerLine;
+ const qssize_t bytesPerLine = image.bytesPerLine;
const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(bytesPerLine/4), _MM_SHUFFLE(0, 0, 0, 0));
while (b < boundedEnd - 3) {
@@ -2658,6 +2661,241 @@ static const uint * QT_FASTCALL fetchTransformedBilinearARGB32PM(uint *buffer, c
return buffer;
}
+template<TextureBlendType blendType, QPixelLayout::BPP bpp>
+static void QT_FASTCALL fetchTransformedBilinear_simple_upscale_helper(uint *b, uint *end, const QTextureData &image,
+ int &fx, int &fy, int fdx, int /*fdy*/)
+{
+ const QPixelLayout *layout = &qPixelLayouts[image.format];
+ const QVector<QRgb> *clut = image.colorTable;
+ Q_ASSERT(bpp == QPixelLayout::BPPNone || bpp == layout->bpp);
+ // When templated 'fetch' should be inlined at compile time:
+ const FetchPixelsFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixels[layout->bpp] : fetchPixels<bpp>;
+ const ConvertFunc convertToARGB32PM = layout->convertToARGB32PM;
+
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
+ const uchar *s1 = image.scanLine(y1);
+ const uchar *s2 = image.scanLine(y2);
+
+ int disty = (fy & 0x0000ffff) >> 8;
+ int idisty = 256 - disty;
+ int x = fx >> 16;
+ int length = end - b;
+
+ // The idea is first to do the interpolation between the row s1 and the row s2
+ // into an intermediate buffer, then we interpolate between two pixel of this buffer.
+ // +1 for the last pixel to interpolate with, and +1 for rounding errors.
+ uint buf1[buffer_size + 2];
+ uint buf2[buffer_size + 2];
+ const uint *ptr1;
+ const uint *ptr2;
+
+ int count = (qint64(length) * fdx + fixed_scale - 1) / fixed_scale + 2;
+ Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case
+
+ if (blendType == BlendTransformedBilinearTiled) {
+ x %= image.width;
+ if (x < 0)
+ x += image.width;
+ int len1 = qMin(count, image.width - x);
+ int len2 = qMin(x, count - len1);
+
+ ptr1 = fetch(buf1, s1, x, len1);
+ ptr1 = convertToARGB32PM(buf1, ptr1, len1, clut, 0);
+ ptr2 = fetch(buf2, s2, x, len1);
+ ptr2 = convertToARGB32PM(buf2, ptr2, len1, clut, 0);
+ for (int i = 0; i < len1; ++i) {
+ uint t = ptr1[i];
+ uint b = ptr2[i];
+ buf1[i] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ buf2[i] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ }
+
+ if (len2) {
+ ptr1 = fetch(buf1 + len1, s1, 0, len2);
+ ptr1 = convertToARGB32PM(buf1 + len1, ptr1, len2, clut, 0);
+ ptr2 = fetch(buf2 + len1, s2, 0, len2);
+ ptr2 = convertToARGB32PM(buf2 + len1, ptr2, len2, clut, 0);
+ for (int i = 0; i < len2; ++i) {
+ uint t = ptr1[i];
+ uint b = ptr2[i];
+ buf1[i + len1] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ buf2[i + len1] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ }
+ }
+ for (int i = image.width; i < count; ++i) {
+ buf1[i] = buf1[i - image.width];
+ buf2[i] = buf2[i - image.width];
+ }
+ } else {
+ int start = qMax(x, image.x1);
+ int end = qMin(x + count, image.x2);
+ int len = qMax(1, end - start);
+ int leading = start - x;
+
+ ptr1 = fetch(buf1 + leading, s1, start, len);
+ ptr1 = convertToARGB32PM(buf1 + leading, ptr1, len, clut, 0);
+ ptr2 = fetch(buf2 + leading, s2, start, len);
+ ptr2 = convertToARGB32PM(buf2 + leading, ptr2, len, clut, 0);
+
+ for (int i = 0; i < len; ++i) {
+ uint t = ptr1[i];
+ uint b = ptr2[i];
+ buf1[i + leading] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ buf2[i + leading] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
+ }
+
+ for (int i = 0; i < leading; ++i) {
+ buf1[i] = buf1[leading];
+ buf2[i] = buf2[leading];
+ }
+ for (int i = leading + len; i < count; ++i) {
+ buf1[i] = buf1[i - 1];
+ buf2[i] = buf2[i - 1];
+ }
+ }
+
+ // Now interpolate the values from the intermediate_buffer to get the final result.
+ fx &= fixed_scale - 1;
+ Q_ASSERT((fx >> 16) == 0);
+ while (b < end) {
+ int x1 = (fx >> 16);
+ int x2 = x1 + 1;
+ Q_ASSERT(x1 >= 0);
+ Q_ASSERT(x2 < count);
+
+ int distx = (fx & 0x0000ffff) >> 8;
+ int idistx = 256 - distx;
+ int rb = ((buf1[x1] * idistx + buf1[x2] * distx) >> 8) & 0xff00ff;
+ int ag = (buf2[x1] * idistx + buf2[x2] * distx) & 0xff00ff00;
+ *b++ = rb | ag;
+ fx += fdx;
+ }
+}
+
+
+typedef void (QT_FASTCALL *BilinearFastTransformFetcher)(uint *buf1, uint *buf2, const int len, const QTextureData &image,
+ int fx, int fy, const int fdx, const int fdy);
+
+template<TextureBlendType blendType, QPixelLayout::BPP bpp>
+static void QT_FASTCALL fetchTransformedBilinear_fetcher(uint *buf1, uint *buf2, const int len, const QTextureData &image,
+ int fx, int fy, const int fdx, const int fdy)
+{
+ const QPixelLayout &layout = qPixelLayouts[image.format];
+ Q_ASSERT(bpp == QPixelLayout::BPPNone || bpp == layout.bpp);
+ // When templated 'fetch1' should be inlined at compile time:
+ const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout.bpp] : fetchPixel<bpp>;
+ if (fdy == 0) {
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
+ const uchar *s1 = image.scanLine(y1);
+ const uchar *s2 = image.scanLine(y2);
+
+ int i = 0;
+ if (blendType == BlendTransformedBilinear) {
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ if (x1 != x2)
+ break;
+ buf1[i * 2 + 0] = buf1[i * 2 + 1] = fetch1(s1, x1);
+ buf2[i * 2 + 0] = buf2[i * 2 + 1] = fetch1(s2, x1);
+ fx += fdx;
+ }
+ int fastLen = len;
+ if (fdx > 0)
+ fastLen = qMin(fastLen, int((qint64(image.x2 - 1) * fixed_scale - fx) / fdx));
+ else if (fdx < 0)
+ fastLen = qMin(fastLen, int((qint64(image.x1) * fixed_scale - fx) / fdx));
+
+ for (; i < fastLen; ++i) {
+ int x = (fx >> 16);
+ buf1[i * 2 + 0] = fetch1(s1, x);
+ buf1[i * 2 + 1] = fetch1(s1, x + 1);
+ buf2[i * 2 + 0] = fetch1(s2, x);
+ buf2[i * 2 + 1] = fetch1(s2, x + 1);
+ fx += fdx;
+ }
+ }
+
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ buf1[i * 2 + 0] = fetch1(s1, x1);
+ buf1[i * 2 + 1] = fetch1(s1, x2);
+ buf2[i * 2 + 0] = fetch1(s2, x1);
+ buf2[i * 2 + 1] = fetch1(s2, x2);
+ fx += fdx;
+ }
+ } else {
+ int i = 0;
+ if (blendType == BlendTransformedBilinear) {
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
+ if (x1 != x2 && y1 != y2)
+ break;
+ const uchar *s1 = image.scanLine(y1);
+ const uchar *s2 = image.scanLine(y2);
+ buf1[i * 2 + 0] = fetch1(s1, x1);
+ buf1[i * 2 + 1] = fetch1(s1, x2);
+ buf2[i * 2 + 0] = fetch1(s2, x1);
+ buf2[i * 2 + 1] = fetch1(s2, x2);
+ fx += fdx;
+ fy += fdy;
+ }
+ int fastLen = len;
+ if (fdx > 0)
+ fastLen = qMin(fastLen, int((qint64(image.x2 - 1) * fixed_scale - fx) / fdx));
+ else if (fdx < 0)
+ fastLen = qMin(fastLen, int((qint64(image.x1) * fixed_scale - fx) / fdx));
+ if (fdy > 0)
+ fastLen = qMin(fastLen, int((qint64(image.y2 - 1) * fixed_scale - fy) / fdy));
+ else if (fdy < 0)
+ fastLen = qMin(fastLen, int((qint64(image.y1) * fixed_scale - fy) / fdy));
+
+ for (; i < fastLen; ++i) {
+ int x = (fx >> 16);
+ int y = (fy >> 16);
+ const uchar *s1 = image.scanLine(y);
+ const uchar *s2 = s1 + image.bytesPerLine;
+ buf1[i * 2 + 0] = fetch1(s1, x);
+ buf1[i * 2 + 1] = fetch1(s1, x + 1);
+ buf2[i * 2 + 0] = fetch1(s2, x);
+ buf2[i * 2 + 1] = fetch1(s2, x + 1);
+ fx += fdx;
+ fy += fdy;
+ }
+ }
+
+ for (; i < len; ++i) {
+ int x1 = (fx >> 16);
+ int x2;
+ int y1 = (fy >> 16);
+ int y2;
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
+
+ const uchar *s1 = image.scanLine(y1);
+ const uchar *s2 = image.scanLine(y2);
+ buf1[i * 2 + 0] = fetch1(s1, x1);
+ buf1[i * 2 + 1] = fetch1(s1, x2);
+ buf2[i * 2 + 0] = fetch1(s2, x1);
+ buf2[i * 2 + 1] = fetch1(s2, x2);
+ fx += fdx;
+ fy += fdy;
+ }
+ }
+}
+
// blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled
template<TextureBlendType blendType, QPixelLayout::BPP bpp>
static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *,
@@ -2665,19 +2903,7 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
{
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
const QVector<QRgb> *clut = data->texture.colorTable;
- if (bpp != QPixelLayout::BPPNone) // Like this to not ICE on GCC 5.3.1
- Q_ASSERT(layout->bpp == bpp);
- // When templated 'fetch' should be inlined at compile time:
- const FetchPixelsFunc fetch = (bpp == QPixelLayout::BPPNone) ? qFetchPixels[layout->bpp] : FetchPixelsFunc(fetchPixels<bpp>);
- const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : FetchPixelFunc(fetchPixel<bpp>);
-
- int image_width = data->texture.width;
- int image_height = data->texture.height;
-
- int image_x1 = data->texture.x1;
- int image_y1 = data->texture.y1;
- int image_x2 = data->texture.x2 - 1;
- int image_y2 = data->texture.y2 - 1;
+ Q_ASSERT(bpp == QPixelLayout::BPPNone || layout->bpp == bpp);
const qreal cx = x + qreal(0.5);
const qreal cy = y + qreal(0.5);
@@ -2693,203 +2919,80 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
fx -= half_point;
fy -= half_point;
- if (fdy == 0) { //simple scale, no rotation
- int y1 = (fy >> 16);
- int y2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
-
+ if (fdy == 0) { // simple scale, no rotation or shear
if (fdx <= fixed_scale && fdx > 0) { // scale up on X
- int disty = (fy & 0x0000ffff) >> 8;
- int idisty = 256 - disty;
- int x = fx >> 16;
-
- // The idea is first to do the interpolation between the row s1 and the row s2
- // into an intermediate buffer, then we interpolate between two pixel of this buffer.
- // +1 for the last pixel to interpolate with, and +1 for rounding errors.
- uint buf1[buffer_size + 2];
- uint buf2[buffer_size + 2];
- const uint *ptr1;
- const uint *ptr2;
-
- int count = (qint64(length) * fdx + fixed_scale - 1) / fixed_scale + 2;
- Q_ASSERT(count <= buffer_size + 2); //length is supposed to be <= buffer_size and data->m11 < 1 in this case
-
- if (blendType == BlendTransformedBilinearTiled) {
- x %= image_width;
- if (x < 0)
- x += image_width;
- int len1 = qMin(count, image_width - x);
- int len2 = qMin(x, count - len1);
-
- ptr1 = fetch(buf1, s1, x, len1);
- ptr1 = layout->convertToARGB32PM(buf1, ptr1, len1, clut, 0);
- ptr2 = fetch(buf2, s2, x, len1);
- ptr2 = layout->convertToARGB32PM(buf2, ptr2, len1, clut, 0);
- for (int i = 0; i < len1; ++i) {
- uint t = ptr1[i];
- uint b = ptr2[i];
- buf1[i] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
- buf2[i] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
- }
-
- if (len2) {
- ptr1 = fetch(buf1 + len1, s1, 0, len2);
- ptr1 = layout->convertToARGB32PM(buf1 + len1, ptr1, len2, clut, 0);
- ptr2 = fetch(buf2 + len1, s2, 0, len2);
- ptr2 = layout->convertToARGB32PM(buf2 + len1, ptr2, len2, clut, 0);
- for (int i = 0; i < len2; ++i) {
- uint t = ptr1[i];
- uint b = ptr2[i];
- buf1[i + len1] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
- buf2[i + len1] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
- }
- }
- for (int i = image_width; i < count; ++i) {
- buf1[i] = buf1[i - image_width];
- buf2[i] = buf2[i - image_width];
- }
- } else {
- int start = qMax(x, image_x1);
- int end = qMin(x + count, image_x2 + 1);
- int len = qMax(1, end - start);
- int leading = start - x;
-
- ptr1 = fetch(buf1 + leading, s1, start, len);
- ptr1 = layout->convertToARGB32PM(buf1 + leading, ptr1, len, clut, 0);
- ptr2 = fetch(buf2 + leading, s2, start, len);
- ptr2 = layout->convertToARGB32PM(buf2 + leading, ptr2, len, clut, 0);
-
- for (int i = 0; i < len; ++i) {
- uint t = ptr1[i];
- uint b = ptr2[i];
- buf1[i + leading] = (((t & 0xff00ff) * idisty + (b & 0xff00ff) * disty) >> 8) & 0xff00ff;
- buf2[i + leading] = ((((t >> 8) & 0xff00ff) * idisty + ((b >> 8) & 0xff00ff) * disty) >> 8) & 0xff00ff;
- }
-
- for (int i = 0; i < leading; ++i) {
- buf1[i] = buf1[leading];
- buf2[i] = buf2[leading];
- }
- for (int i = leading + len; i < count; ++i) {
- buf1[i] = buf1[i - 1];
- buf2[i] = buf2[i - 1];
- }
- }
-
- // Now interpolate the values from the intermediate_buffer to get the final result.
- fx &= fixed_scale - 1;
- Q_ASSERT((fx >> 16) == 0);
- for (int i = 0; i < length; ++i) {
- int x1 = (fx >> 16);
- int x2 = x1 + 1;
- Q_ASSERT(x1 >= 0);
- Q_ASSERT(x2 < count);
-
- int distx = (fx & 0x0000ffff) >> 8;
- int idistx = 256 - distx;
- int rb = ((buf1[x1] * idistx + buf1[x2] * distx) >> 8) & 0xff00ff;
- int ag = (buf2[x1] * idistx + buf2[x2] * distx) & 0xff00ff00;
- buffer[i] = rb | ag;
- fx += fdx;
- }
+ fetchTransformedBilinear_simple_upscale_helper<blendType, bpp>(buffer, buffer + length, data->texture, fx, fy, fdx, fdy);
} else {
+ const BilinearFastTransformFetcher fetcher = fetchTransformedBilinear_fetcher<blendType,bpp>;
+
uint buf1[buffer_size];
uint buf2[buffer_size];
uint *b = buffer;
while (length) {
int len = qMin(length, buffer_size / 2);
- int fracX = fx;
- for (int i = 0; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- buf1[i * 2 + 0] = fetch1(s1, x1);
- buf1[i * 2 + 1] = fetch1(s1, x2);
- buf2[i * 2 + 0] = fetch1(s2, x1);
- buf2[i * 2 + 1] = fetch1(s2, x2);
- fx += fdx;
- }
+ fetcher(buf1, buf2, len, data->texture, fx, fy, fdx, 0);
layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0);
layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0);
if ((fdx < 0 && fdx > -(fixed_scale / 8)) || qAbs(data->m22) < qreal(1./8.)) { // scale up more than 8x
int disty = (fy & 0x0000ffff) >> 8;
for (int i = 0; i < len; ++i) {
- int distx = (fracX & 0x0000ffff) >> 8;
+ int distx = (fx & 0x0000ffff) >> 8;
b[i] = interpolate_4_pixels(buf1 + i * 2, buf2 + i * 2, distx, disty);
- fracX += fdx;
+ fx += fdx;
}
- } else { //scale down
+ } else {
int disty = ((fy & 0x0000ffff) + 0x0800) >> 12;
for (int i = 0; i < len; ++i) {
uint tl = buf1[i * 2 + 0];
uint tr = buf1[i * 2 + 1];
uint bl = buf2[i * 2 + 0];
uint br = buf2[i * 2 + 1];
- int distx = ((fracX & 0x0000ffff) + 0x0800) >> 12;
+ int distx = ((fx & 0x0000ffff) + 0x0800) >> 12;
b[i] = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
- fracX += fdx;
+ fx += fdx;
}
}
length -= len;
b += len;
}
}
- } else { //rotation
+ } else { // rotation or shear
+ const BilinearFastTransformFetcher fetcher = fetchTransformedBilinear_fetcher<blendType,bpp>;
+
uint buf1[buffer_size];
uint buf2[buffer_size];
uint *b = buffer;
-
while (length) {
int len = qMin(length, buffer_size / 2);
- int fracX = fx;
- int fracY = fy;
- for (int i = 0; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- int y1 = (fy >> 16);
- int y2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
-
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
- buf1[i * 2 + 0] = fetch1(s1, x1);
- buf1[i * 2 + 1] = fetch1(s1, x2);
- buf2[i * 2 + 0] = fetch1(s2, x1);
- buf2[i * 2 + 1] = fetch1(s2, x2);
- fx += fdx;
- fy += fdy;
- }
+ fetcher(buf1, buf2, len, data->texture, fx, fy, fdx, fdy);
layout->convertToARGB32PM(buf1, buf1, len * 2, clut, 0);
layout->convertToARGB32PM(buf2, buf2, len * 2, clut, 0);
- if (qAbs(data->m11) < qreal(1./8.) || qAbs(data->m22) < qreal(1./8.) ) {
- //if we are zooming more than 8 times, we use 8bit precision for the position.
+ if (qAbs(data->m11) < qreal(1./8.)|| qAbs(data->m22) < qreal(1./8.)) {
+ // If we are zooming more than 8 times, we use 8bit precision for the position.
for (int i = 0; i < len; ++i) {
- int distx = (fracX & 0x0000ffff) >> 8;
- int disty = (fracY & 0x0000ffff) >> 8;
+ int distx = (fx & 0x0000ffff) >> 8;
+ int disty = (fy & 0x0000ffff) >> 8;
b[i] = interpolate_4_pixels(buf1 + i * 2, buf2 + i * 2, distx, disty);
- fracX += fdx;
- fracY += fdy;
+ fx += fdx;
+ fy += fdy;
}
} else {
- //we are zooming less than 8x, use 4bit precision
+ // We are zooming less than 8x, use 4bit precision
for (int i = 0; i < len; ++i) {
uint tl = buf1[i * 2 + 0];
uint tr = buf1[i * 2 + 1];
uint bl = buf2[i * 2 + 0];
uint br = buf2[i * 2 + 1];
- int distx = ((fracX & 0x0000ffff) + 0x0800) >> 12;
- int disty = ((fracY & 0x0000ffff) + 0x0800) >> 12;
+ int distx = ((fx & 0x0000ffff) + 0x0800) >> 12;
+ int disty = ((fy & 0x0000ffff) + 0x0800) >> 12;
b[i] = interpolate_4_pixels_16(tl, tr, bl, br, distx, disty);
- fracX += fdx;
- fracY += fdy;
+ fx += fdx;
+ fy += fdy;
}
}
@@ -2898,6 +3001,11 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
}
}
} else {
+ // When templated 'fetch' should be inlined at compile time:
+ const FetchPixelFunc fetch1 = (bpp == QPixelLayout::BPPNone) ? qFetchPixel[layout->bpp] : fetchPixel<bpp>;
+
+ const QTextureData &image = data->texture;
+
const qreal fdx = data->m11;
const qreal fdy = data->m12;
const qreal fdw = data->m13;
@@ -2928,8 +3036,8 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
distxs[i] = int((px - x1) * 256);
distys[i] = int((py - y1) * 256);
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
@@ -2970,21 +3078,9 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
const QPixelLayout *layout = &qPixelLayouts[data->texture.format];
const QVector<QRgb> *clut = data->texture.colorTable;
- int image_width = data->texture.width;
- int image_height = data->texture.height;
-
- int image_x1 = data->texture.x1;
- int image_y1 = data->texture.y1;
- int image_x2 = data->texture.x2 - 1;
- int image_y2 = data->texture.y2 - 1;
-
const qreal cx = x + qreal(0.5);
const qreal cy = y + qreal(0.5);
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
-
if (data->fast_matrix) {
// The increment pr x in the scanline
int fdx = (int)(data->m11 * fixed_scale);
@@ -2996,14 +3092,13 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
fx -= half_point;
fy -= half_point;
+ const BilinearFastTransformFetcher fetcher =
+ (layout->bpp == QPixelLayout::BPP32)
+ ? fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPP32>
+ : fetchTransformedBilinear_fetcher<blendType, QPixelLayout::BPPNone>;
+
if (fdy == 0) { //simple scale, no rotation
- int y1 = (fy >> 16);
- int y2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
- FetchPixelFunc fetch = qFetchPixel[layout->bpp];
uint sbuf1[buffer_size];
uint sbuf2[buffer_size];
quint64 buf1[buffer_size];
@@ -3011,84 +3106,19 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
QRgba64 *b = buffer;
while (length) {
int len = qMin(length, buffer_size / 2);
- int fracX = fx;
- int i = 0;
int disty = (fy & 0x0000ffff);
#if defined(__SSE2__)
const __m128i vdy = _mm_set1_epi16(disty);
const __m128i vidy = _mm_set1_epi16(0x10000 - disty);
- if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) {
- for (; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- if (x1 != x2)
- break;
- sbuf1[i * 2 + 0] = sbuf1[i * 2 + 1] = ((const uint*)s1)[x1];
- sbuf2[i * 2 + 0] = sbuf2[i * 2 + 1] = ((const uint*)s2)[x1];
- fx += fdx;
- }
- int fastLen;
- if (fdx > 0)
- fastLen = qMin(len, int((image_x2 - (fx >> 16)) / data->m11));
- else
- fastLen = qMin(len, int((image_x1 - (fx >> 16)) / data->m11));
- fastLen -= 3;
-
- const __m128i v_fdx = _mm_set1_epi32(fdx*4);
- __m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx);
- for (; i < fastLen; i += 4) {
- int offset = _mm_extract_epi16(v_fx, 1);
- sbuf1[i * 2 + 0] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 1] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 0] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 1] = ((const uint*)s2)[offset + 1];
- offset = _mm_extract_epi16(v_fx, 3);
- sbuf1[i * 2 + 2] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 3] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 2] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 3] = ((const uint*)s2)[offset + 1];
- offset = _mm_extract_epi16(v_fx, 5);
- sbuf1[i * 2 + 4] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 5] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 4] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 5] = ((const uint*)s2)[offset + 1];
- offset = _mm_extract_epi16(v_fx, 7);
- sbuf1[i * 2 + 6] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 7] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 6] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 7] = ((const uint*)s2)[offset + 1];
- v_fx = _mm_add_epi32(v_fx, v_fdx);
- }
- fx = _mm_cvtsi128_si32(v_fx);
- }
#endif
- for (; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
-
- if (layout->bpp == QPixelLayout::BPP32) {
- sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
- sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
- sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
- sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
-
- } else {
- sbuf1[i * 2 + 0] = fetch(s1, x1);
- sbuf1[i * 2 + 1] = fetch(s1, x2);
- sbuf2[i * 2 + 0] = fetch(s2, x1);
- sbuf2[i * 2 + 1] = fetch(s2, x2);
- }
+ fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
- fx += fdx;
- }
layout->convertToARGB64PM((QRgba64 *)buf1, sbuf1, len * 2, clut, 0);
if (disty)
layout->convertToARGB64PM((QRgba64 *)buf2, sbuf2, len * 2, clut, 0);
for (int i = 0; i < len; ++i) {
- int distx = (fracX & 0x0000ffff);
+ int distx = (fx & 0x0000ffff);
#if defined(__SSE2__)
__m128i vt = _mm_loadu_si128((const __m128i*)(buf1 + i*2));
if (disty) {
@@ -3107,13 +3137,12 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
#else
b[i] = interpolate_4_pixels_rgb64((QRgba64 *)buf1 + i*2, (QRgba64 *)buf2 + i*2, distx, disty);
#endif
- fracX += fdx;
+ fx += fdx;
}
length -= len;
b += len;
}
} else { //rotation
- FetchPixelFunc fetch = qFetchPixel[layout->bpp];
uint sbuf1[buffer_size];
uint sbuf2[buffer_size];
quint64 buf1[buffer_size];
@@ -3123,117 +3152,18 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
while (b < end) {
int len = qMin(length, buffer_size / 2);
- int fracX = fx;
- int fracY = fy;
- int i = 0;
-#if defined(__SSE2__)
- if (blendType != BlendTransformedBilinearTiled && layout->bpp == QPixelLayout::BPP32) {
- for (; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- int y1 = (fy >> 16);
- int y2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
- if (x1 != x2 && y1 != y2)
- break;
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
- sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
- sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
- sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
- sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
- fx += fdx;
- fy += fdy;
- }
- int fastLen = len;
- if (fdx > 0)
- fastLen = qMin(fastLen, int((qint64(image_x2) * fixed_scale - fx) / fdx));
- else if (fdx < 0)
- fastLen = qMin(fastLen, int((qint64(image_x1) * fixed_scale - fx) / fdx));
- if (fdy > 0)
- fastLen = qMin(fastLen, int((qint64(image_y2) * fixed_scale - fy) / fdy));
- else if (fdy < 0)
- fastLen = qMin(fastLen, int((qint64(image_y1) * fixed_scale - fy) / fdy));
- fastLen -= 3;
-
- const __m128i v_fdx = _mm_set1_epi32(fdx*4);
- const __m128i v_fdy = _mm_set1_epi32(fdy*4);
- __m128i v_fx = _mm_setr_epi32(fx, fx + fdx, fx + fdx + fdx, fx + fdx + fdx + fdx);
- __m128i v_fy = _mm_setr_epi32(fy, fy + fdy, fy + fdy + fdy, fy + fdy + fdy + fdy);
- const int bytesPerLine = data->texture.bytesPerLine;
- const uchar *s1 = data->texture.imageData;
- const uchar *s2 = s1 + bytesPerLine;
- const __m128i vbpl = _mm_shufflelo_epi16(_mm_cvtsi32_si128(bytesPerLine/4), _MM_SHUFFLE(0, 0, 0, 0));
- for (; i < fastLen; i += 4) {
- const __m128i vy = _mm_packs_epi32(_mm_srai_epi32(v_fy, 16), _mm_setzero_si128());
- __m128i voffset = _mm_unpacklo_epi16(_mm_mullo_epi16(vy, vbpl), _mm_mulhi_epu16(vy, vbpl));
- voffset = _mm_add_epi32(voffset, _mm_srli_epi32(v_fx, 16));
-
- int offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
- sbuf1[i * 2 + 0] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 1] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 0] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 1] = ((const uint*)s2)[offset + 1];
- offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
- sbuf1[i * 2 + 2] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 3] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 2] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 3] = ((const uint*)s2)[offset + 1];
- offset = _mm_cvtsi128_si32(voffset); voffset = _mm_srli_si128(voffset, 4);
- sbuf1[i * 2 + 4] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 5] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 4] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 5] = ((const uint*)s2)[offset + 1];
- offset = _mm_cvtsi128_si32(voffset);
- sbuf1[i * 2 + 6] = ((const uint*)s1)[offset];
- sbuf1[i * 2 + 7] = ((const uint*)s1)[offset + 1];
- sbuf2[i * 2 + 6] = ((const uint*)s2)[offset];
- sbuf2[i * 2 + 7] = ((const uint*)s2)[offset + 1];
-
- v_fx = _mm_add_epi32(v_fx, v_fdx);
- v_fy = _mm_add_epi32(v_fy, v_fdy);
- }
- fx = _mm_cvtsi128_si32(v_fx);
- fy = _mm_cvtsi128_si32(v_fy);
- }
-#endif
- for (; i < len; ++i) {
- int x1 = (fx >> 16);
- int x2;
- int y1 = (fy >> 16);
- int y2;
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
-
- if (layout->bpp == QPixelLayout::BPP32) {
- sbuf1[i * 2 + 0] = ((const uint*)s1)[x1];
- sbuf1[i * 2 + 1] = ((const uint*)s1)[x2];
- sbuf2[i * 2 + 0] = ((const uint*)s2)[x1];
- sbuf2[i * 2 + 1] = ((const uint*)s2)[x2];
-
- } else {
- sbuf1[i * 2 + 0] = fetch(s1, x1);
- sbuf1[i * 2 + 1] = fetch(s1, x2);
- sbuf2[i * 2 + 0] = fetch(s2, x1);
- sbuf2[i * 2 + 1] = fetch(s2, x2);
- }
+ fetcher(sbuf1, sbuf2, len, data->texture, fx, fy, fdx, fdy);
- fx += fdx;
- fy += fdy;
- }
layout->convertToARGB64PM((QRgba64 *)buf1, sbuf1, len * 2, clut, 0);
layout->convertToARGB64PM((QRgba64 *)buf2, sbuf2, len * 2, clut, 0);
for (int i = 0; i < len; ++i) {
- int distx = (fracX & 0x0000ffff);
- int disty = (fracY & 0x0000ffff);
+ int distx = (fx & 0x0000ffff);
+ int disty = (fy & 0x0000ffff);
b[i] = interpolate_4_pixels_rgb64((QRgba64 *)buf1 + i*2, (QRgba64 *)buf2 + i*2, distx, disty);
- fracX += fdx;
- fracY += fdy;
+ fx += fdx;
+ fy += fdy;
}
length -= len;
@@ -3241,6 +3171,12 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
}
}
} else {
+ const QTextureData &image = data->texture;
+
+ const qreal fdx = data->m11;
+ const qreal fdy = data->m12;
+ const qreal fdw = data->m13;
+
qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
@@ -3270,8 +3206,8 @@ static const QRgba64 *QT_FASTCALL fetchTransformedBilinear64(QRgba64 *buffer, co
distxs[i] = int((px - x1) * (1<<16));
distys[i] = int((py - y1) * (1<<16));
- fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- fetchTransformedBilinear_pixelBounds<blendType>(image_height, image_y1, image_y2, y1, y2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.width, image.x1, image.x2 - 1, x1, x2);
+ fetchTransformedBilinear_pixelBounds<blendType>(image.height, image.y1, image.y2 - 1, y1, y2);
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
@@ -3842,7 +3778,7 @@ void blend_color_generic_rgb64(int count, const QSpan *spans, void *userData)
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
Operator op = getOperator(data, spans, count);
if (!op.funcSolid64) {
- qDebug("unsupported 64bit blend attempted");
+ qCDebug(lcQtGuiDrawHelper, "blend_color_generic_rgb64: unsupported 64bit blend attempted, falling back to 32-bit");
return blend_color_generic(count, spans, userData);
}
@@ -4080,7 +4016,7 @@ static void blend_src_generic_rgb64(int count, const QSpan *spans, void *userDat
if (blend64.isSupported())
handleSpans(count, spans, data, blend64);
else {
- qDebug("blend_src_generic_rgb64: unsupported 64-bit blend attempted");
+ qCDebug(lcQtGuiDrawHelper, "blend_src_generic_rgb64: unsupported 64-bit blend attempted, falling back to 32-bit");
BlendSrcGeneric blend32(data, op);
handleSpans(count, spans, data, blend32);
}
@@ -4137,7 +4073,7 @@ static void blend_untransformed_generic_rgb64(int count, const QSpan *spans, voi
Operator op = getOperator(data, spans, count);
if (!op.func64) {
- qWarning("Unsupported blend");
+ qCDebug(lcQtGuiDrawHelper, "blend_untransformed_generic_rgb64: unsupported 64-bit blend attempted, falling back to 32-bit");
return blend_untransformed_generic(count, spans, userData);
}
quint64 buffer[buffer_size];
@@ -4378,7 +4314,7 @@ static void blend_tiled_generic_rgb64(int count, const QSpan *spans, void *userD
Operator op = getOperator(data, spans, count);
if (!op.func64) {
- qDebug("unsupported rgb64 blend");
+ qCDebug(lcQtGuiDrawHelper, "blend_tiled_generic_rgb64: unsupported 64-bit blend attempted, falling back to 32-bit");
return blend_tiled_generic(count, spans, userData);
}
quint64 buffer[buffer_size];
@@ -5014,7 +4950,7 @@ static void blend_transformed_tiled_argb(int count, const QSpan *spans, void *us
int image_width = data->texture.width;
int image_height = data->texture.height;
- const int scanline_offset = data->texture.bytesPerLine / 4;
+ const qssize_t scanline_offset = data->texture.bytesPerLine / 4;
if (data->fast_matrix) {
// The increment pr x in the scanline
@@ -5354,7 +5290,7 @@ inline void qt_bitmapblit_template(QRasterBuffer *rasterBuffer,
int mapWidth, int mapHeight, int mapStride)
{
DST *dest = reinterpret_cast<DST *>(rasterBuffer->scanLine(y)) + x;
- const int destStride = rasterBuffer->bytesPerLine() / sizeof(DST);
+ const int destStride = rasterBuffer->stride<DST>();
if (mapWidth > 8) {
while (mapHeight--) {
@@ -5668,7 +5604,7 @@ void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
if (!clip) {
quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
- const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16);
+ const int destStride = rasterBuffer->stride<quint16>();
while (mapHeight--) {
for (int i = 0; i < mapWidth; ++i)
alphamapblend_quint16(map[i], dest, i, c);
@@ -5743,7 +5679,7 @@ static void qt_alphamapblit_argb32(QRasterBuffer *rasterBuffer,
const QClipData *clip, bool useGammaCorrection)
{
const quint32 c = color.toArgb32();
- const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32);
+ const int destStride = rasterBuffer->stride<quint32>();
if (color.isTransparent())
return;
@@ -5939,7 +5875,7 @@ static void qt_alphargbblit_argb32(QRasterBuffer *rasterBuffer,
if (!clip) {
quint32 *dst = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x;
- const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32);
+ const int destStride = rasterBuffer->stride<quint32>();
while (mapHeight--) {
for (int i = 0; i < mapWidth; ++i) {
const uint coverage = src[i];
diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp
index a7e03a7bb3..a378fca749 100644
--- a/src/gui/painting/qdrawhelper_avx2.cpp
+++ b/src/gui/painting/qdrawhelper_avx2.cpp
@@ -682,7 +682,7 @@ void QT_FASTCALL fetchTransformedBilinearARGB32PM_fast_rotate_helper_avx2(uint *
v_fy = _mm256_add_epi32(v_fy, _mm256_mullo_epi32(_mm256_set1_epi32(fdy), v_index));
const uchar *textureData = image.imageData;
- const int bytesPerLine = image.bytesPerLine;
+ const qssize_t bytesPerLine = image.bytesPerLine;
const __m256i vbpl = _mm256_set1_epi16(bytesPerLine/4);
while (b < boundedEnd - 7) {
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index ccfc9a2889..2be10d2cfb 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -293,7 +293,7 @@ struct QTextureData
int y1;
int x2;
int y2;
- int bytesPerLine;
+ qssize_t bytesPerLine;
QImage::Format format;
const QVector<QRgb> *colorTable;
bool hasAlpha;
@@ -847,7 +847,7 @@ inline void qt_memfill(T *dest, T value, int count)
template <class T> Q_STATIC_TEMPLATE_FUNCTION
inline void qt_rectfill(T *dest, T value,
- int x, int y, int width, int height, int stride)
+ int x, int y, int width, int height, qssize_t stride)
{
char *d = reinterpret_cast<char*>(dest + x) + y * stride;
if (uint(stride) == (width * sizeof(T))) {
diff --git a/src/gui/painting/qdrawhelper_sse2.cpp b/src/gui/painting/qdrawhelper_sse2.cpp
index 3013d2cf3e..bfe2080298 100644
--- a/src/gui/painting/qdrawhelper_sse2.cpp
+++ b/src/gui/painting/qdrawhelper_sse2.cpp
@@ -341,7 +341,7 @@ void qt_bitmapblit32_sse2_base(QRasterBuffer *rasterBuffer, int x, int y,
const uchar *src, int width, int height, int stride)
{
quint32 *dest = reinterpret_cast<quint32*>(rasterBuffer->scanLine(y)) + x;
- const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint32);
+ const int destStride = rasterBuffer->stride<quint32>();
const __m128i c128 = _mm_set1_epi32(color);
const __m128i maskmask1 = _mm_set_epi32(0x10101010, 0x20202020,
@@ -407,7 +407,7 @@ void qt_bitmapblit16_sse2(QRasterBuffer *rasterBuffer, int x, int y,
{
const quint16 c = qConvertRgb32To16(color.toArgb32());
quint16 *dest = reinterpret_cast<quint16*>(rasterBuffer->scanLine(y)) + x;
- const int destStride = rasterBuffer->bytesPerLine() / sizeof(quint16);
+ const int destStride = rasterBuffer->stride<quint32>();
const __m128i c128 = _mm_set1_epi16(c);
QT_WARNING_DISABLE_MSVC(4309) // truncation of constant value
diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp
index 586b71557e..e6686e3721 100644
--- a/src/gui/painting/qemulationpaintengine.cpp
+++ b/src/gui/painting/qemulationpaintengine.cpp
@@ -72,6 +72,14 @@ QPainterState *QEmulationPaintEngine::createState(QPainterState *orig) const
return real_engine->createState(orig);
}
+static inline void combineXForm(QBrush *brush, const QRectF &r)
+{
+ QTransform t = brush->transform();
+ t.translate(r.x(), r.y());
+ t.scale(r.width(), r.height());
+ brush->setTransform(t);
+}
+
void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
{
QPainterState *s = state();
@@ -84,26 +92,14 @@ void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
Qt::BrushStyle style = qbrush_style(brush);
if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
- const QGradient *g = brush.gradient();
-
- if (g->coordinateMode() > QGradient::LogicalMode) {
- if (g->coordinateMode() == QGradient::StretchToDeviceMode) {
- QBrush copy = brush;
- QTransform mat = copy.transform();
- mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height());
- copy.setTransform(mat);
- real_engine->fill(path, copy);
- return;
- } else if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
- QBrush copy = brush;
- QTransform mat = copy.transform();
- QRectF r = path.controlPointRect();
- mat.translate(r.x(), r.y());
- mat.scale(r.width(), r.height());
- copy.setTransform(mat);
- real_engine->fill(path, copy);
- return;
- }
+ QGradient::CoordinateMode coMode = brush.gradient()->coordinateMode();
+ if (coMode > QGradient::LogicalMode) {
+ QBrush copy = brush;
+ const QPaintDevice *d = real_engine->painter()->device();
+ QRectF r = (coMode == QGradient::ObjectBoundingMode) ? path.controlPointRect() : QRectF(0, 0, d->width(), d->height());
+ combineXForm(&copy, r);
+ real_engine->fill(path, copy);
+ return;
}
}
@@ -124,27 +120,15 @@ void QEmulationPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
QBrush brush = pen.brush();
QPen copy = pen;
Qt::BrushStyle style = qbrush_style(brush);
- if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern) {
- const QGradient *g = brush.gradient();
-
- if (g->coordinateMode() > QGradient::LogicalMode) {
- if (g->coordinateMode() == QGradient::StretchToDeviceMode) {
- QTransform mat = brush.transform();
- mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height());
- brush.setTransform(mat);
- copy.setBrush(brush);
- real_engine->stroke(path, copy);
- return;
- } else if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
- QTransform mat = brush.transform();
- QRectF r = path.controlPointRect();
- mat.translate(r.x(), r.y());
- mat.scale(r.width(), r.height());
- brush.setTransform(mat);
- copy.setBrush(brush);
- real_engine->stroke(path, copy);
- return;
- }
+ if (style >= Qt::LinearGradientPattern && style <= Qt::ConicalGradientPattern ) {
+ QGradient::CoordinateMode coMode = brush.gradient()->coordinateMode();
+ if (coMode > QGradient::LogicalMode) {
+ const QPaintDevice *d = real_engine->painter()->device();
+ QRectF r = (coMode == QGradient::ObjectBoundingMode) ? path.controlPointRect() : QRectF(0, 0, d->width(), d->height());
+ combineXForm(&brush, r);
+ copy.setBrush(brush);
+ real_engine->stroke(path, copy);
+ return;
}
}
@@ -179,18 +163,16 @@ void QEmulationPaintEngine::drawTextItem(const QPointF &p, const QTextItem &text
QGradient g = *s->pen.brush().gradient();
if (g.coordinateMode() > QGradient::LogicalMode) {
- QTransform mat = s->pen.brush().transform();
- if (g.coordinateMode() == QGradient::StretchToDeviceMode) {
- mat.scale(real_engine->painter()->device()->width(), real_engine->painter()->device()->height());
- } else if (g.coordinateMode() == QGradient::ObjectBoundingMode) {
- const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
- QRectF r(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal());
- mat.translate(r.x(), r.y());
- mat.scale(r.width(), r.height());
- }
+ QBrush copy = s->pen.brush();
+ const QPaintDevice *d = real_engine->painter()->device();
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+ QRectF r = (g.coordinateMode() == QGradient::ObjectBoundingMode) ?
+ QRectF(p.x(), p.y() - ti.ascent.toReal(), ti.width.toReal(), (ti.ascent + ti.descent + 1).toReal()) :
+ QRectF(0, 0, d->width(), d->height());
+ combineXForm(&copy, r);
g.setCoordinateMode(QGradient::LogicalMode);
QBrush brush(g);
- brush.setTransform(mat);
+ brush.setTransform(copy.transform());
s->pen.setBrush(brush);
penChanged();
real_engine->drawTextItem(p, textItem);
diff --git a/src/gui/painting/qgrayraster.c b/src/gui/painting/qgrayraster.c
index 4a135e25d8..0143e9b602 100644
--- a/src/gui/painting/qgrayraster.c
+++ b/src/gui/painting/qgrayraster.c
@@ -43,7 +43,7 @@
/* */
/* A new `perfect' anti-aliasing renderer (body). */
/* */
-/* Copyright 2000-2001, 2002, 2003 by */
+/* Copyright 2000-2016 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* */
/* This file is part of the FreeType project, and may only be used, */
@@ -119,10 +119,6 @@
/* */
/*************************************************************************/
-/* experimental support for gamma correction within the rasterizer */
-#define xxxGRAYS_USE_GAMMA
-
-
/*************************************************************************/
/* */
/* The macro QT_FT_COMPONENT is used in trace mode. It is an implicit */
@@ -133,6 +129,28 @@
#define QT_FT_COMPONENT trace_smooth
+/* Auxiliary macros for token concatenation. */
+#define QT_FT_ERR_XCAT( x, y ) x ## y
+#define QT_FT_ERR_CAT( x, y ) QT_FT_ERR_XCAT( x, y )
+
+#define QT_FT_BEGIN_STMNT do {
+#define QT_FT_END_STMNT } while ( 0 )
+
+#define QT_FT_MAX( a, b ) ( (a) > (b) ? (a) : (b) )
+#define QT_FT_ABS( a ) ( (a) < 0 ? -(a) : (a) )
+
+
+/*
+ * Approximate sqrt(x*x+y*y) using the `alpha max plus beta min'
+ * algorithm. We use alpha = 1, beta = 3/8, giving us results with a
+ * largest error less than 7% compared to the exact value.
+ */
+#define QT_FT_HYPOT( x, y ) \
+ ( x = QT_FT_ABS( x ), \
+ y = QT_FT_ABS( y ), \
+ x > y ? x + ( 3 * y >> 3 ) \
+ : y + ( 3 * x >> 3 ) )
+
#define ErrRaster_MemoryOverflow -4
#if defined(VXWORKS)
@@ -150,6 +168,9 @@
#define qt_ft_longjmp longjmp
#define qt_ft_jmp_buf jmp_buf
+#include <stddef.h>
+typedef ptrdiff_t QT_FT_PtrDist;
+
#define ErrRaster_Invalid_Mode -2
#define ErrRaster_Invalid_Outline -1
#define ErrRaster_Invalid_Argument -3
@@ -169,15 +190,10 @@
#define QT_FT_UNUSED( x ) (void) x
- /* Disable the tracing mechanism for simplicity -- developers can */
- /* activate it easily by redefining these two macros. */
-#ifndef QT_FT_ERROR
-#define QT_FT_ERROR( x ) do ; while ( 0 ) /* nothing */
-#endif
-
-#ifndef QT_FT_TRACE
-#define QT_FT_TRACE( x ) do ; while ( 0 ) /* nothing */
-#endif
+#define QT_FT_TRACE5( x ) do { } while ( 0 ) /* nothing */
+#define QT_FT_TRACE7( x ) do { } while ( 0 ) /* nothing */
+#define QT_FT_ERROR( x ) do { } while ( 0 ) /* nothing */
+#define QT_FT_THROW( e ) QT_FT_ERR_CAT( ErrRaster_, e )
#ifndef QT_FT_MEM_SET
#define QT_FT_MEM_SET( d, s, c ) qt_ft_memset( d, s, c )
@@ -187,9 +203,6 @@
#define QT_FT_MEM_ZERO( dest, count ) QT_FT_MEM_SET( dest, 0, count )
#endif
- /* define this to dump debugging information */
-#define xxxDEBUG_GRAYS
-
#define RAS_ARG PWorker worker
#define RAS_ARG_ PWorker worker,
@@ -199,26 +212,47 @@
#define ras (*worker)
-
/* must be at least 6 bits! */
#define PIXEL_BITS 8
#define ONE_PIXEL ( 1L << PIXEL_BITS )
-#define PIXEL_MASK ( -1L << PIXEL_BITS )
#define TRUNC( x ) ( (TCoord)( (x) >> PIXEL_BITS ) )
-#define SUBPIXELS( x ) ( (TPos)(x) * ( 1 << PIXEL_BITS ) )
+#define SUBPIXELS( x ) ( (TPos)(x) * ONE_PIXEL )
#define FLOOR( x ) ( (x) & -ONE_PIXEL )
#define CEILING( x ) ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
#define ROUND( x ) ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
#if PIXEL_BITS >= 6
-#define UPSCALE( x ) ( (x) * ( 1 << ( PIXEL_BITS - 6 ) ) )
+#define UPSCALE( x ) ( (x) * ( ONE_PIXEL >> 6 ) )
#define DOWNSCALE( x ) ( (x) >> ( PIXEL_BITS - 6 ) )
#else
#define UPSCALE( x ) ( (x) >> ( 6 - PIXEL_BITS ) )
-#define DOWNSCALE( x ) ( (x) << ( 6 - PIXEL_BITS ) )
+#define DOWNSCALE( x ) ( (x) * ( 64 >> PIXEL_BITS ) )
#endif
+/* Compute `dividend / divisor' and return both its quotient and */
+/* remainder, cast to a specific type. This macro also ensures that */
+/* the remainder is always positive. */
+#define QT_FT_DIV_MOD( type, dividend, divisor, quotient, remainder ) \
+QT_FT_BEGIN_STMNT \
+ (quotient) = (type)( (dividend) / (divisor) ); \
+ (remainder) = (type)( (dividend) % (divisor) ); \
+ if ( (remainder) < 0 ) \
+ { \
+ (quotient)--; \
+ (remainder) += (type)(divisor); \
+ } \
+QT_FT_END_STMNT
+
+ /* These macros speed up repetitive divisions by replacing them */
+ /* with multiplications and right shifts. */
+#define QT_FT_UDIVPREP( b ) \
+ long b ## _r = (long)( ULONG_MAX >> PIXEL_BITS ) / ( b )
+#define QT_FT_UDIV( a, b ) \
+ ( ( (unsigned long)( a ) * (unsigned long)( b ## _r ) ) >> \
+ ( sizeof( long ) * CHAR_BIT - PIXEL_BITS ) )
+
+
/*************************************************************************/
/* */
/* TYPE DEFINITIONS */
@@ -228,28 +262,9 @@
/* need to define them to "float" or "double" when experimenting with */
/* new algorithms */
- typedef int TCoord; /* integer scanline/pixel coordinate */
- typedef int TPos; /* sub-pixel coordinate */
-
- /* determine the type used to store cell areas. This normally takes at */
- /* least PIXEL_BITS*2 + 1 bits. On 16-bit systems, we need to use */
- /* `long' instead of `int', otherwise bad things happen */
-
-#if PIXEL_BITS <= 7
-
- typedef int TArea;
-
-#else /* PIXEL_BITS >= 8 */
-
- /* approximately determine the size of integers using an ANSI-C header */
-#if QT_FT_UINT_MAX == 0xFFFFU
- typedef long TArea;
-#else
- typedef int TArea;
-#endif
-
-#endif /* PIXEL_BITS >= 8 */
-
+ typedef long TCoord; /* integer scanline/pixel coordinate */
+ typedef long TPos; /* sub-pixel coordinate */
+ typedef long TArea ; /* cell areas, coordinate products */
/* maximal number of gray spans in a call to the span callback */
#define QT_FT_MAX_GRAY_SPANS 256
@@ -279,17 +294,11 @@
int invalid;
PCell cells;
- int max_cells;
- int num_cells;
+ QT_FT_PtrDist max_cells;
+ QT_FT_PtrDist num_cells;
- TCoord cx, cy;
TPos x, y;
- TPos last_ey;
-
- QT_FT_Vector bez_stack[32 * 3 + 1];
- int lev_stack[32];
-
QT_FT_Outline outline;
QT_FT_Bitmap target;
QT_FT_BBox clip_box;
@@ -302,8 +311,6 @@
int band_size;
int band_shoot;
- int conic_level;
- int cubic_level;
qt_ft_jmp_buf jump_buffer;
@@ -311,7 +318,7 @@
long buffer_size;
PCell* ycells;
- int ycount;
+ TPos ycount;
int skip_spans;
} TWorker, *PWorker;
@@ -341,7 +348,7 @@
/* */
static void
gray_init_cells( RAS_ARG_ void* buffer,
- long byte_size )
+ long byte_size )
{
ras.buffer = buffer;
ras.buffer_size = byte_size;
@@ -404,31 +411,25 @@
/* */
/* Record the current cell in the table. */
/* */
- static void
- gray_record_cell( RAS_ARG )
+ static PCell
+ gray_find_cell( RAS_ARG )
{
PCell *pcell, cell;
- int x = ras.ex;
+ TPos x = ras.ex;
- if ( ras.invalid || !( ras.area | ras.cover ) )
- return;
- if ( x > ras.max_ex )
- x = ras.max_ex;
+ if ( x > ras.count_ex )
+ x = ras.count_ex;
pcell = &ras.ycells[ras.ey];
-
for (;;)
{
cell = *pcell;
if ( cell == NULL || cell->x > x )
break;
- if ( cell->x == x ) {
- cell->area += ras.area;
- cell->cover += ras.cover;
- return;
- }
+ if ( cell->x == x )
+ goto Exit;
pcell = &cell->next;
}
@@ -438,11 +439,28 @@
cell = ras.cells + ras.num_cells++;
cell->x = x;
- cell->area = ras.area;
- cell->cover = ras.cover;
+ cell->area = 0;
+ cell->cover = 0;
cell->next = *pcell;
*pcell = cell;
+
+ Exit:
+ return cell;
+ }
+
+
+ static void
+ gray_record_cell( RAS_ARG )
+ {
+ if ( ras.area | ras.cover )
+ {
+ PCell cell = gray_find_cell( RAS_VAR );
+
+
+ cell->area += ras.area;
+ cell->cover += ras.cover;
+ }
}
@@ -488,8 +506,8 @@
ras.ey = ey;
}
- ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
- ex >= ras.count_ex );
+ ras.invalid = ( (unsigned int)ey >= (unsigned int)ras.count_ey ||
+ ex >= ras.count_ex );
}
@@ -511,12 +529,13 @@
ras.cover = 0;
ras.ex = ex - ras.min_ex;
ras.ey = ey - ras.min_ey;
- ras.last_ey = SUBPIXELS( ey );
ras.invalid = 0;
gray_set_cell( RAS_VAR_ ex, ey );
}
+// The new render-line implementation is not yet used
+#if 1
/*************************************************************************/
/* */
@@ -529,9 +548,9 @@
TPos x2,
TCoord y2 )
{
- TCoord ex1, ex2, fx1, fx2, delta;
+ TCoord ex1, ex2, fx1, fx2, delta, mod;
int p, first, dx;
- int incr, lift, mod, rem;
+ int incr;
dx = x2 - x1;
@@ -573,13 +592,7 @@
dx = -dx;
}
- delta = (TCoord)( p / dx );
- mod = (TCoord)( p % dx );
- if ( mod < 0 )
- {
- delta--;
- mod += (TCoord)dx;
- }
+ QT_FT_DIV_MOD( TCoord, p, dx, delta, mod );
ras.area += (TArea)( fx1 + first ) * delta;
ras.cover += delta;
@@ -590,14 +603,11 @@
if ( ex1 != ex2 )
{
- p = ONE_PIXEL * ( y2 - y1 + delta );
- lift = (TCoord)( p / dx );
- rem = (TCoord)( p % dx );
- if ( rem < 0 )
- {
- lift--;
- rem += (TCoord)dx;
- }
+ TCoord lift, rem;
+
+
+ p = ONE_PIXEL * ( y2 - y1 + delta );
+ QT_FT_DIV_MOD( TCoord, p, dx, lift, rem );
mod -= (int)dx;
@@ -633,38 +643,24 @@
gray_render_line( RAS_ARG_ TPos to_x,
TPos to_y )
{
- TCoord ey1, ey2, fy1, fy2;
+ TCoord ey1, ey2, fy1, fy2, mod;
TPos dx, dy, x, x2;
int p, first;
- int delta, rem, mod, lift, incr;
+ int delta, rem, lift, incr;
- ey1 = TRUNC( ras.last_ey );
+ ey1 = TRUNC( ras.y );
ey2 = TRUNC( to_y ); /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
- fy1 = (TCoord)( ras.y - ras.last_ey );
+ fy1 = (TCoord)( ras.y - SUBPIXELS( ey1 ) );
fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
dx = to_x - ras.x;
dy = to_y - ras.y;
- /* XXX: we should do something about the trivial case where dx == 0, */
- /* as it happens very often! */
-
/* perform vertical clipping */
- {
- TCoord min, max;
-
-
- min = ey1;
- max = ey2;
- if ( ey1 > ey2 )
- {
- min = ey2;
- max = ey1;
- }
- if ( min >= ras.max_ey || max < ras.min_ey )
- goto End;
- }
+ if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
+ ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
+ goto End;
/* everything is on a single scanline */
if ( ey1 == ey2 )
@@ -771,13 +767,7 @@
if ( ey1 != ey2 )
{
p = ONE_PIXEL * dx;
- lift = (int)( p / dy );
- rem = (int)( p % dy );
- if ( rem < 0 )
- {
- lift--;
- rem += (int)dy;
- }
+ QT_FT_DIV_MOD( int, p, dy, lift, rem );
mod -= (int)dy;
while ( ey1 != ey2 )
@@ -808,10 +798,147 @@
End:
ras.x = to_x;
ras.y = to_y;
- ras.last_ey = SUBPIXELS( ey2 );
}
+#else
+
+ /*************************************************************************/
+ /* */
+ /* Render a straight line across multiple cells in any direction. */
+ /* */
+ static void
+ gray_render_line( RAS_ARG_ TPos to_x,
+ TPos to_y )
+ {
+ TPos dx, dy, fx1, fy1, fx2, fy2;
+ TCoord ex1, ex2, ey1, ey2;
+
+
+ ex1 = TRUNC( ras.x );
+ ex2 = TRUNC( to_x );
+ ey1 = TRUNC( ras.y );
+ ey2 = TRUNC( to_y );
+
+ /* perform vertical clipping */
+ if ( ( ey1 >= ras.max_ey && ey2 >= ras.max_ey ) ||
+ ( ey1 < ras.min_ey && ey2 < ras.min_ey ) )
+ goto End;
+
+ dx = to_x - ras.x;
+ dy = to_y - ras.y;
+
+ fx1 = ras.x - SUBPIXELS( ex1 );
+ fy1 = ras.y - SUBPIXELS( ey1 );
+
+ if ( ex1 == ex2 && ey1 == ey2 ) /* inside one cell */
+ ;
+ else if ( dy == 0 ) /* ex1 != ex2 */ /* any horizontal line */
+ {
+ ex1 = ex2;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ }
+ else if ( dx == 0 )
+ {
+ if ( dy > 0 ) /* vertical line up */
+ do
+ {
+ fy2 = ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * fx1 * 2;
+ fy1 = 0;
+ ey1++;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ey1 != ey2 );
+ else /* vertical line down */
+ do
+ {
+ fy2 = 0;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * fx1 * 2;
+ fy1 = ONE_PIXEL;
+ ey1--;
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ey1 != ey2 );
+ }
+ else /* any other line */
+ {
+ TArea prod = dx * fy1 - dy * fx1;
+ QT_FT_UDIVPREP( dx );
+ QT_FT_UDIVPREP( dy );
+
+
+ /* The fundamental value `prod' determines which side and the */
+ /* exact coordinate where the line exits current cell. It is */
+ /* also easily updated when moving from one cell to the next. */
+ do
+ {
+ if ( prod <= 0 &&
+ prod - dx * ONE_PIXEL > 0 ) /* left */
+ {
+ fx2 = 0;
+ fy2 = (TPos)QT_FT_UDIV( -prod, -dx );
+ prod -= dy * ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = ONE_PIXEL;
+ fy1 = fy2;
+ ex1--;
+ }
+ else if ( prod - dx * ONE_PIXEL <= 0 &&
+ prod - dx * ONE_PIXEL + dy * ONE_PIXEL > 0 ) /* up */
+ {
+ prod -= dx * ONE_PIXEL;
+ fx2 = (TPos)QT_FT_UDIV( -prod, dy );
+ fy2 = ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = fx2;
+ fy1 = 0;
+ ey1++;
+ }
+ else if ( prod - dx * ONE_PIXEL + dy * ONE_PIXEL <= 0 &&
+ prod + dy * ONE_PIXEL >= 0 ) /* right */
+ {
+ prod += dy * ONE_PIXEL;
+ fx2 = ONE_PIXEL;
+ fy2 = (TPos)QT_FT_UDIV( prod, dx );
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = 0;
+ fy1 = fy2;
+ ex1++;
+ }
+ else /* ( prod + dy * ONE_PIXEL < 0 &&
+ prod > 0 ) down */
+ {
+ fx2 = (TPos)QT_FT_UDIV( prod, -dy );
+ fy2 = 0;
+ prod += dx * ONE_PIXEL;
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+ fx1 = fx2;
+ fy1 = ONE_PIXEL;
+ ey1--;
+ }
+
+ gray_set_cell( RAS_VAR_ ex1, ey1 );
+ } while ( ex1 != ex2 || ey1 != ey2 );
+ }
+
+ fx2 = to_x - SUBPIXELS( ex2 );
+ fy2 = to_y - SUBPIXELS( ey2 );
+
+ ras.cover += ( fy2 - fy1 );
+ ras.area += ( fy2 - fy1 ) * ( fx1 + fx2 );
+
+ End:
+ ras.x = to_x;
+ ras.y = to_y;
+ }
+
+#endif
+
static void
gray_split_conic( QT_FT_Vector* base )
{
@@ -836,52 +963,11 @@
gray_render_conic( RAS_ARG_ const QT_FT_Vector* control,
const QT_FT_Vector* to )
{
+ QT_FT_Vector bez_stack[16 * 2 + 1]; /* enough to accommodate bisections */
+ QT_FT_Vector* arc = bez_stack;
TPos dx, dy;
- int top, level;
- int* levels;
- QT_FT_Vector* arc;
-
-
- dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
-
- level = 1;
- dx = dx / ras.conic_level;
- while ( dx > 0 )
- {
- dx >>= 2;
- level++;
- }
+ int draw, split;
- /* a shortcut to speed things up */
- if ( level <= 1 )
- {
- /* we compute the mid-point directly in order to avoid */
- /* calling gray_split_conic() */
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = UPSCALE( to->x );
- to_y = UPSCALE( to->y );
- mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
- mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
-
- return;
- }
-
- arc = ras.bez_stack;
- levels = ras.lev_stack;
- top = 0;
- levels[0] = level;
arc[0].x = UPSCALE( to->x );
arc[0].y = UPSCALE( to->y );
@@ -890,54 +976,51 @@
arc[2].x = ras.x;
arc[2].y = ras.y;
- while ( top >= 0 )
+ /* short-cut the arc that crosses the current band */
+ if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
+ TRUNC( arc[1].y ) >= ras.max_ey &&
+ TRUNC( arc[2].y ) >= ras.max_ey ) ||
+ ( TRUNC( arc[0].y ) < ras.min_ey &&
+ TRUNC( arc[1].y ) < ras.min_ey &&
+ TRUNC( arc[2].y ) < ras.min_ey ) )
{
- level = levels[top];
- if ( level > 1 )
- {
- /* check that the arc crosses the current band */
- TPos min, max, y;
-
-
- min = max = arc[0].y;
-
- y = arc[1].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
+ ras.x = arc[0].x;
+ ras.y = arc[0].y;
+ return;
+ }
- y = arc[2].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
+ dx = QT_FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
+ dy = QT_FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
+ if ( dx < dy )
+ dx = dy;
- if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
- goto Draw;
+ /* We can calculate the number of necessary bisections because */
+ /* each bisection predictably reduces deviation exactly 4-fold. */
+ /* Even 32-bit deviation would vanish after 16 bisections. */
+ draw = 1;
+ while ( dx > ONE_PIXEL / 4 )
+ {
+ dx >>= 2;
+ draw <<= 1;
+ }
+ /* We use decrement counter to count the total number of segments */
+ /* to draw starting from 2^level. Before each draw we split as */
+ /* many times as there are trailing zeros in the counter. */
+ do
+ {
+ split = 1;
+ while ( ( draw & split ) == 0 )
+ {
gray_split_conic( arc );
arc += 2;
- top++;
- levels[top] = levels[top - 1] = level - 1;
- continue;
+ split <<= 1;
}
- Draw:
- {
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = arc[0].x;
- to_y = arc[0].y;
- mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
- mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
-
- top--;
- arc -= 2;
- }
- }
+ gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+ arc -= 2;
- return;
+ } while ( --draw );
}
@@ -974,60 +1057,13 @@
const QT_FT_Vector* control2,
const QT_FT_Vector* to )
{
- TPos dx, dy, da, db;
- int top, level;
- int* levels;
- QT_FT_Vector* arc;
+ QT_FT_Vector bez_stack[16 * 3 + 1]; /* enough to accommodate bisections */
+ QT_FT_Vector* arc = bez_stack;
+ TPos dx, dy, dx_, dy_;
+ TPos dx1, dy1, dx2, dy2;
+ TPos L, s, s_limit;
- dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
- da = dx;
-
- dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
- if ( dx < 0 )
- dx = -dx;
- dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->y + control2->y );
- if ( dy < 0 )
- dy = -dy;
- if ( dx < dy )
- dx = dy;
- db = dx;
-
- level = 1;
- da = da / ras.cubic_level;
- db = db / ras.conic_level;
- while ( da > 0 || db > 0 )
- {
- da >>= 2;
- db >>= 3;
- level++;
- }
-
- if ( level <= 1 )
- {
- TPos to_x, to_y, mid_x, mid_y;
-
-
- to_x = UPSCALE( to->x );
- to_y = UPSCALE( to->y );
- mid_x = ( ras.x + to_x +
- 3 * UPSCALE( control1->x + control2->x ) ) / 8;
- mid_y = ( ras.y + to_y +
- 3 * UPSCALE( control1->y + control2->y ) ) / 8;
-
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
- return;
- }
-
- arc = ras.bez_stack;
arc[0].x = UPSCALE( to->x );
arc[0].y = UPSCALE( to->y );
arc[1].x = UPSCALE( control2->x );
@@ -1037,56 +1073,77 @@
arc[3].x = ras.x;
arc[3].y = ras.y;
- levels = ras.lev_stack;
- top = 0;
- levels[0] = level;
+ /* short-cut the arc that crosses the current band */
+ if ( ( TRUNC( arc[0].y ) >= ras.max_ey &&
+ TRUNC( arc[1].y ) >= ras.max_ey &&
+ TRUNC( arc[2].y ) >= ras.max_ey &&
+ TRUNC( arc[3].y ) >= ras.max_ey ) ||
+ ( TRUNC( arc[0].y ) < ras.min_ey &&
+ TRUNC( arc[1].y ) < ras.min_ey &&
+ TRUNC( arc[2].y ) < ras.min_ey &&
+ TRUNC( arc[3].y ) < ras.min_ey ) )
+ {
+ ras.x = arc[0].x;
+ ras.y = arc[0].y;
+ return;
+ }
- while ( top >= 0 )
+ for (;;)
{
- level = levels[top];
- if ( level > 1 )
- {
- /* check that the arc crosses the current band */
- TPos min, max, y;
-
-
- min = max = arc[0].y;
- y = arc[1].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- y = arc[2].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- y = arc[3].y;
- if ( y < min ) min = y;
- if ( y > max ) max = y;
- if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
- goto Draw;
- gray_split_cubic( arc );
- arc += 3;
- top ++;
- levels[top] = levels[top - 1] = level - 1;
- continue;
- }
+ /* Decide whether to split or draw. See `Rapid Termination */
+ /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
+ /* F. Hain, at */
+ /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
- Draw:
- {
- TPos to_x, to_y, mid_x, mid_y;
+ /* dx and dy are x and y components of the P0-P3 chord vector. */
+ dx = dx_ = arc[3].x - arc[0].x;
+ dy = dy_ = arc[3].y - arc[0].y;
- to_x = arc[0].x;
- to_y = arc[0].y;
- mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
- mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
+ L = QT_FT_HYPOT( dx_, dy_ );
- gray_render_line( RAS_VAR_ mid_x, mid_y );
- gray_render_line( RAS_VAR_ to_x, to_y );
- top --;
- arc -= 3;
- }
- }
+ /* Avoid possible arithmetic overflow below by splitting. */
+ if ( L > 32767 )
+ goto Split;
+
+ /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
+ s_limit = L * (TPos)( ONE_PIXEL / 6 );
+
+ /* s is L * the perpendicular distance from P1 to the line P0-P3. */
+ dx1 = arc[1].x - arc[0].x;
+ dy1 = arc[1].y - arc[0].y;
+ s = QT_FT_ABS( dy * dx1 - dx * dy1 );
+
+ if ( s > s_limit )
+ goto Split;
+
+ /* s is L * the perpendicular distance from P2 to the line P0-P3. */
+ dx2 = arc[2].x - arc[0].x;
+ dy2 = arc[2].y - arc[0].y;
+ s = QT_FT_ABS( dy * dx2 - dx * dy2 );
+
+ if ( s > s_limit )
+ goto Split;
+
+ /* Split super curvy segments where the off points are so far
+ from the chord that the angles P0-P1-P3 or P0-P2-P3 become
+ acute as detected by appropriate dot products. */
+ if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 ||
+ dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 )
+ goto Split;
- return;
+ gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+
+ if ( arc == bez_stack )
+ return;
+
+ arc -= 3;
+ continue;
+
+ Split:
+ gray_split_cubic( arc );
+ arc += 3;
+ }
}
@@ -1099,7 +1156,8 @@
/* record current cell, if any */
- gray_record_cell( worker );
+ if ( !ras.invalid )
+ gray_record_cell( worker );
/* start to a new position */
x = UPSCALE( to->x );
@@ -1107,15 +1165,15 @@
gray_start_cell( worker, TRUNC( x ), TRUNC( y ) );
- worker->x = x;
- worker->y = y;
+ ras.x = x;
+ ras.y = y;
return 0;
}
static void
- gray_render_span( int count,
+ gray_render_span( int count,
const QT_FT_Span* spans,
- PWorker worker )
+ PWorker worker )
{
unsigned char* p;
QT_FT_Bitmap* map = &worker->target;
@@ -1127,34 +1185,30 @@
/* first of all, compute the scanline offset */
p = (unsigned char*)map->buffer - spans->y * map->pitch;
if ( map->pitch >= 0 )
- p += ( map->rows - 1 ) * map->pitch;
+ p += ( map->rows - 1 ) * (unsigned int)map->pitch;
if ( coverage )
{
+ unsigned char* q = p + spans->x;
+
+
/* For small-spans it is faster to do it by ourselves than
* calling `memset'. This is mainly due to the cost of the
* function call.
*/
- if ( spans->len >= 8 )
- QT_FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
- else
+ switch ( spans->len )
{
- unsigned char* q = p + spans->x;
-
-
- switch ( spans->len )
- {
- case 7: *q++ = (unsigned char)coverage; Q_FALLTHROUGH();
- case 6: *q++ = (unsigned char)coverage; Q_FALLTHROUGH();
- case 5: *q++ = (unsigned char)coverage; Q_FALLTHROUGH();
- case 4: *q++ = (unsigned char)coverage; Q_FALLTHROUGH();
- case 3: *q++ = (unsigned char)coverage; Q_FALLTHROUGH();
- case 2: *q++ = (unsigned char)coverage; Q_FALLTHROUGH();
- case 1: *q = (unsigned char)coverage;
- default:
- ;
- }
+ case 7: *q++ = coverage; Q_FALLTHROUGH();
+ case 6: *q++ = coverage; Q_FALLTHROUGH();
+ case 5: *q++ = coverage; Q_FALLTHROUGH();
+ case 4: *q++ = coverage; Q_FALLTHROUGH();
+ case 3: *q++ = coverage; Q_FALLTHROUGH();
+ case 2: *q++ = coverage; Q_FALLTHROUGH();
+ case 1: *q = coverage; Q_FALLTHROUGH();
+ case 0: break;
+ default:
+ QT_FT_MEM_SET( q, coverage, spans->len );
}
}
}
@@ -1167,9 +1221,7 @@
TPos area,
int acount )
{
- QT_FT_Span* span;
- int coverage;
- int skip;
+ int coverage;
/* compute the coverage line's coverage, depending on the */
@@ -1202,14 +1254,24 @@
x += (TCoord)ras.min_ex;
/* QT_FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
- if ( x >= 32768 )
+ if ( x >= 32767 )
x = 32767;
+ /* QT_FT_Span.y is a 16-bit short, so limit our coordinates appropriately */
+ if ( y >= 32767 )
+ y = 32767;
+
if ( coverage )
{
+ QT_FT_Span* span;
+ int count;
+ int skip;
+
+
/* see whether we can add this span to the current list */
- span = ras.gray_spans + ras.num_gray_spans - 1;
- if ( ras.num_gray_spans > 0 &&
+ count = ras.num_gray_spans;
+ span = ras.gray_spans + count - 1;
+ if ( count > 0 &&
span->y == y &&
(int)span->x + span->len == (int)x &&
span->coverage == coverage )
@@ -1218,9 +1280,9 @@
return;
}
- if ( ras.num_gray_spans >= QT_FT_MAX_GRAY_SPANS )
+ if ( count >= QT_FT_MAX_GRAY_SPANS )
{
- if ( ras.render_span && ras.num_gray_spans > ras.skip_spans )
+ if ( ras.render_span && count > ras.skip_spans )
{
skip = ras.skip_spans > 0 ? ras.skip_spans : 0;
ras.render_span( ras.num_gray_spans - skip,
@@ -1302,6 +1364,8 @@
if ( ras.num_cells == 0 )
return;
+ QT_FT_TRACE7(( "gray_sweep: start\n" ));
+
for ( yindex = 0; yindex < ras.ycount; yindex++ )
{
PCell cell = ras.ycells[yindex];
@@ -1331,6 +1395,8 @@
gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
ras.count_ex - x );
}
+
+ QT_FT_TRACE7(( "gray_sweep: end\n" ));
}
/*************************************************************************/
@@ -1364,7 +1430,7 @@
/* */
static
int QT_FT_Outline_Decompose( const QT_FT_Outline* outline,
- void* user )
+ void* user )
{
#undef SCALED
#define SCALED( x ) (x)
@@ -1382,6 +1448,9 @@
int error;
char tag; /* current point's state */
+ if ( !outline )
+ return ErrRaster_Invalid_Outline;
+
first = 0;
for ( n = 0; n < outline->n_contours; n++ )
@@ -1390,16 +1459,17 @@
last = outline->contours[n];
+ if ( last < 0 )
+ goto Invalid_Outline;
limit = outline->points + last;
- v_start = outline->points[first];
- v_last = outline->points[last];
-
+ v_start = outline->points[first];
v_start.x = SCALED( v_start.x );
v_start.y = SCALED( v_start.y );
- v_last.x = SCALED( v_last.x );
- v_last.y = SCALED( v_last.y );
+ v_last = outline->points[last];
+ v_last.x = SCALED( v_last.x );
+ v_last.y = SCALED( v_last.y );
v_control = v_start;
@@ -1435,6 +1505,8 @@
tags--;
}
+ QT_FT_TRACE5(( " move to (%.2f, %.2f)\n",
+ v_start.x / 64.0, v_start.y / 64.0 ));
error = gray_move_to( &v_start, user );
if ( error )
goto Exit;
@@ -1455,6 +1527,8 @@
vec.x = SCALED( point->x );
vec.y = SCALED( point->y );
+ QT_FT_TRACE5(( " line to (%.2f, %.2f)\n",
+ vec.x / 64.0, vec.y / 64.0 ));
gray_render_line(user, UPSCALE(vec.x), UPSCALE(vec.y));
continue;
}
@@ -1480,6 +1554,10 @@
if ( tag == QT_FT_CURVE_TAG_ON )
{
+ QT_FT_TRACE5(( " conic to (%.2f, %.2f)"
+ " with control (%.2f, %.2f)\n",
+ vec.x / 64.0, vec.y / 64.0,
+ v_control.x / 64.0, v_control.y / 64.0 ));
gray_render_conic(user, &v_control, &vec);
continue;
}
@@ -1490,11 +1568,20 @@
v_middle.x = ( v_control.x + vec.x ) / 2;
v_middle.y = ( v_control.y + vec.y ) / 2;
+ QT_FT_TRACE5(( " conic to (%.2f, %.2f)"
+ " with control (%.2f, %.2f)\n",
+ v_middle.x / 64.0, v_middle.y / 64.0,
+ v_control.x / 64.0, v_control.y / 64.0 ));
gray_render_conic(user, &v_control, &v_middle);
+
v_control = vec;
goto Do_Conic;
}
+ QT_FT_TRACE5(( " conic to (%.2f, %.2f)"
+ " with control (%.2f, %.2f)\n",
+ v_start.x / 64.0, v_start.y / 64.0,
+ v_control.x / 64.0, v_control.y / 64.0 ));
gray_render_conic(user, &v_control, &v_start);
goto Close;
}
@@ -1525,10 +1612,20 @@
vec.x = SCALED( point->x );
vec.y = SCALED( point->y );
+ QT_FT_TRACE5(( " cubic to (%.2f, %.2f)"
+ " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
+ vec.x / 64.0, vec.y / 64.0,
+ vec1.x / 64.0, vec1.y / 64.0,
+ vec2.x / 64.0, vec2.y / 64.0 ));
gray_render_cubic(user, &vec1, &vec2, &vec);
continue;
}
+ QT_FT_TRACE5(( " cubic to (%.2f, %.2f)"
+ " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
+ v_start.x / 64.0, v_start.y / 64.0,
+ vec1.x / 64.0, vec1.y / 64.0,
+ vec2.x / 64.0, vec2.y / 64.0 ));
gray_render_cubic(user, &vec1, &vec2, &v_start);
goto Close;
}
@@ -1536,15 +1633,19 @@
}
/* close the contour with a line segment */
+ QT_FT_TRACE5(( " line to (%.2f, %.2f)\n",
+ v_start.x / 64.0, v_start.y / 64.0 ));
gray_render_line(user, UPSCALE(v_start.x), UPSCALE(v_start.y));
Close:
first = last + 1;
}
+ QT_FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
return 0;
Exit:
+ QT_FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
return error;
Invalid_Outline:
@@ -1557,7 +1658,6 @@
} TBand;
-
static int
gray_convert_glyph_inner( RAS_ARG )
{
@@ -1566,7 +1666,8 @@
if ( qt_ft_setjmp( ras.jump_buffer ) == 0 )
{
error = QT_FT_Outline_Decompose( &ras.outline, &ras );
- gray_record_cell( RAS_VAR );
+ if ( !ras.invalid )
+ gray_record_cell( RAS_VAR );
}
else
{
@@ -1608,29 +1709,12 @@
ras.count_ex = ras.max_ex - ras.min_ex;
ras.count_ey = ras.max_ey - ras.min_ey;
- /* simple heuristic used to speed-up the bezier decomposition -- see */
- /* the code in gray_render_conic() and gray_render_cubic() for more */
- /* details */
- ras.conic_level = 32;
- ras.cubic_level = 16;
-
- {
- int level = 0;
-
-
- if ( ras.count_ex > 24 || ras.count_ey > 24 )
- level++;
- if ( ras.count_ex > 120 || ras.count_ey > 120 )
- level++;
-
- ras.conic_level <<= level;
- ras.cubic_level <<= level;
- }
-
- /* setup vertical bands */
+ /* set up vertical bands */
num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
- if ( num_bands == 0 ) num_bands = 1;
- if ( num_bands >= 39 ) num_bands = 39;
+ if ( num_bands == 0 )
+ num_bands = 1;
+ if ( num_bands >= 39 )
+ num_bands = 39;
ras.band_shoot = 0;
@@ -1764,11 +1848,14 @@
if (raster->buffer_allocated_size < MINIMUM_POOL_SIZE )
return ErrRaster_OutOfMemory;
+ if ( !outline )
+ return ErrRaster_Invalid_Outline;
+
/* return immediately if the outline is empty */
if ( outline->n_points == 0 || outline->n_contours <= 0 )
return 0;
- if ( !outline || !outline->contours || !outline->points )
+ if ( !outline->contours || !outline->points )
return ErrRaster_Invalid_Outline;
if ( outline->n_points !=
diff --git a/src/gui/painting/qpagedpaintdevice.cpp b/src/gui/painting/qpagedpaintdevice.cpp
index 22ec981134..1c7d6471b6 100644
--- a/src/gui/painting/qpagedpaintdevice.cpp
+++ b/src/gui/painting/qpagedpaintdevice.cpp
@@ -243,6 +243,18 @@ QPagedPaintDevicePrivate *QPagedPaintDevice::dd()
Starts a new page. Returns \c true on success.
*/
+/*!
+ \enum QPagedPaintDevice::PdfVersion
+
+ The PdfVersion enum describes the version of the PDF file that
+ is produced by QPrinter or QPdfWriter.
+
+ \value PdfVersion_1_4 A PDF 1.4 compatible document is produced.
+
+ \value PdfVersion_A1b A PDF/A-1b compatible document is produced.
+
+ \since 5.10
+*/
/*!
Sets the size of the a page to \a size.
diff --git a/src/gui/painting/qpagedpaintdevice.h b/src/gui/painting/qpagedpaintdevice.h
index c516f6a963..66dd6fa8cf 100644
--- a/src/gui/painting/qpagedpaintdevice.h
+++ b/src/gui/painting/qpagedpaintdevice.h
@@ -213,6 +213,8 @@ public:
Envelope10 = Comm10E
};
+ enum PdfVersion { PdfVersion_1_4, PdfVersion_A1b };
+
// ### Qt6 Make these virtual
bool setPageLayout(const QPageLayout &pageLayout);
bool setPageSize(const QPageSize &pageSize);
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index ddea168e72..f42fd4ff87 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -547,8 +547,8 @@ void qt_fill_tile(QPixmap *tile, const QPixmap &pixmap)
}
}
-void qt_draw_tile(QPaintEngine *gc, qreal x, qreal y, qreal w, qreal h,
- const QPixmap &pixmap, qreal xOffset, qreal yOffset)
+Q_GUI_EXPORT void qt_draw_tile(QPaintEngine *gc, qreal x, qreal y, qreal w, qreal h,
+ const QPixmap &pixmap, qreal xOffset, qreal yOffset)
{
qreal yPos, xPos, drawH, drawW, yOff, xOff;
yPos = y;
@@ -929,11 +929,11 @@ QPoint QPaintEngine::coordinateOffset() const
void QPaintEngine::setSystemClip(const QRegion &region)
{
Q_D(QPaintEngine);
- d->systemClip = region;
+ d->baseSystemClip = region;
// Be backward compatible and only call d->systemStateChanged()
// if we currently have a system transform/viewport set.
+ d->updateSystemClip();
if (d->hasSystemTransform || d->hasSystemViewport) {
- d->transformSystemClip();
d->systemStateChanged();
}
}
diff --git a/src/gui/painting/qpaintengine_p.h b/src/gui/painting/qpaintengine_p.h
index 9d511f9bad..8ac3fcff5c 100644
--- a/src/gui/painting/qpaintengine_p.h
+++ b/src/gui/painting/qpaintengine_p.h
@@ -71,6 +71,7 @@ public:
QPaintDevice *pdev;
QPaintEngine *q_ptr;
+ QRegion baseSystemClip;
QRegion systemClip;
QRect systemRect;
QRegion systemViewport;
@@ -79,8 +80,9 @@ public:
uint hasSystemTransform : 1;
uint hasSystemViewport : 1;
- inline void transformSystemClip()
+ inline void updateSystemClip()
{
+ systemClip = baseSystemClip;
if (systemClip.isEmpty())
return;
@@ -104,15 +106,30 @@ public:
inline void setSystemTransform(const QTransform &xform)
{
systemTransform = xform;
- if ((hasSystemTransform = !xform.isIdentity()) || hasSystemViewport)
- transformSystemClip();
- systemStateChanged();
+ hasSystemTransform = !xform.isIdentity();
+ updateSystemClip();
+ if (q_ptr->state)
+ systemStateChanged();
}
inline void setSystemViewport(const QRegion &region)
{
systemViewport = region;
hasSystemViewport = !systemViewport.isEmpty();
+ updateSystemClip();
+ if (q_ptr->state)
+ systemStateChanged();
+ }
+
+ inline void setSystemTransformAndViewport(const QTransform &xform, const QRegion &region)
+ {
+ systemTransform = xform;
+ hasSystemTransform = !xform.isIdentity();
+ systemViewport = region;
+ hasSystemViewport = !systemViewport.isEmpty();
+ updateSystemClip();
+ if (q_ptr->state)
+ systemStateChanged();
}
virtual void systemStateChanged() { }
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index f99a247270..5db4e5a919 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -993,7 +993,7 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt,
Q_ASSERT(img.depth() >= 8);
- int srcBPL = img.bytesPerLine();
+ qssize_t srcBPL = img.bytesPerLine();
const uchar *srcBits = img.bits();
int srcSize = img.depth() >> 3; // This is the part that is incompatible with lower than 8-bit..
int iw = img.width();
@@ -1042,7 +1042,7 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt,
// call the blend function...
int dstSize = rasterBuffer->bytesPerPixel();
- int dstBPL = rasterBuffer->bytesPerLine();
+ qssize_t dstBPL = rasterBuffer->bytesPerLine();
func(rasterBuffer->buffer() + x * dstSize + y * dstBPL, dstBPL,
srcBits, srcBPL,
iw, ih,
@@ -2317,8 +2317,8 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe
clippedSourceRect = clippedSourceRect.intersected(img.rect());
- uint dbpl = d->rasterBuffer->bytesPerLine();
- uint sbpl = img.bytesPerLine();
+ const qssize_t dbpl = d->rasterBuffer->bytesPerLine();
+ const qssize_t sbpl = img.bytesPerLine();
uchar *dst = d->rasterBuffer->buffer();
uint bpp = img.depth() >> 3;
@@ -2827,7 +2827,7 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs,
cache->fillInPendingGlyphs();
const QImage &image = cache->image();
- int bpl = image.bytesPerLine();
+ qssize_t bpl = image.bytesPerLine();
int depth = image.depth();
int rightShift = 0;
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index d0b82b3a93..e2e0f821e3 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -457,6 +457,8 @@ public:
int height() const { return m_height; }
int bytesPerLine() const { return bytes_per_line; }
int bytesPerPixel() const { return bytes_per_pixel; }
+ template<typename T>
+ int stride() { return bytes_per_line / sizeof(T); }
uchar *buffer() const { return m_buffer; }
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index b186182c34..667c3b0fb5 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -5850,6 +5850,7 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
if (!d->engine || str.isEmpty() || pen().style() == Qt::NoPen)
return;
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (tf & Qt::TextBypassShaping) {
// Skip complex shaping, shape using glyph advances only
int len = str.length();
@@ -5863,6 +5864,7 @@ void QPainter::drawText(const QPointF &p, const QString &str, int tf, int justif
drawTextItem(p, gf);
return;
}
+#endif
QStackTextEngine engine(str, d->state->font);
engine.option.setTextDirection(d->state->layoutDirection);
@@ -7417,7 +7419,7 @@ void qt_format_text(const QFont &fnt, const QRectF &_r,
if (option->flags() & QTextOption::IncludeTrailingSpaces)
tf |= Qt::TextIncludeTrailingSpaces;
- if (option->tabStop() >= 0 || !option->tabArray().isEmpty())
+ if (option->tabStopDistance() >= 0 || !option->tabArray().isEmpty())
tf |= Qt::TextExpandTabs;
}
@@ -7534,8 +7536,8 @@ start_lengthVariant:
engine.option = *option;
}
- if (engine.option.tabStop() < 0 && tabstops > 0)
- engine.option.setTabStop(tabstops);
+ if (engine.option.tabStopDistance() < 0 && tabstops > 0)
+ engine.option.setTabStopDistance(tabstops);
if (engine.option.tabs().isEmpty() && ta) {
QList<qreal> tabs;
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index afeb198953..2b892159c5 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -42,16 +42,20 @@
#ifndef QT_NO_PDF
#include "qplatformdefs.h"
-#include <qdebug.h>
-#include <qfile.h>
-#include <qtemporaryfile.h>
+
+#include <private/qfont_p.h>
#include <private/qmath_p.h>
#include <private/qpainter_p.h>
-#include <qnumeric.h>
-#include "private/qfont_p.h"
+
+#include <qbuffer.h>
+#include <qcryptographichash.h>
+#include <qdatetime.h>
+#include <qdebug.h>
+#include <qfile.h>
#include <qimagewriter.h>
-#include "qbuffer.h"
-#include "QtCore/qdatetime.h"
+#include <qnumeric.h>
+#include <qtemporaryfile.h>
+#include <quuid.h>
#ifndef QT_NO_COMPRESS
#include <zlib.h>
@@ -79,6 +83,45 @@ inline QPaintEngine::PaintEngineFeatures qt_pdf_decide_features()
return f;
}
+extern bool qt_isExtendedRadialGradient(const QBrush &brush);
+
+// helper function to remove transparency from brush in PDF/A-1b mode
+static void removeTransparencyFromBrush(QBrush &brush)
+{
+ if (brush.style() == Qt::SolidPattern) {
+ QColor color = brush.color();
+ if (color.alpha() != 255) {
+ color.setAlpha(255);
+ brush.setColor(color);
+ }
+
+ return;
+ }
+
+ if (qt_isExtendedRadialGradient(brush)) {
+ brush = QBrush(Qt::black); // the safest we can do so far...
+ return;
+ }
+
+ if (brush.style() == Qt::LinearGradientPattern
+ || brush.style() == Qt::RadialGradientPattern
+ || brush.style() == Qt::ConicalGradientPattern) {
+
+ QGradientStops stops = brush.gradient()->stops();
+ for (int i = 0; i < stops.size(); ++i) {
+ if (stops[i].second.alpha() != 255)
+ stops[i].second.setAlpha(255);
+ }
+
+ const_cast<QGradient*>(brush.gradient())->setStops(stops);
+ return;
+ }
+
+ if (brush.style() == Qt::TexturePattern) {
+ // handled inside QPdfEnginePrivate::addImage() already
+ return;
+ }
+}
/* also adds a space at the end of the number */
@@ -1042,7 +1085,22 @@ void QPdfEngine::updateState(const QPaintEngineState &state)
d->stroker.matrix = state.transform();
if (flags & DirtyPen) {
- d->pen = state.pen();
+ if (d->pdfVersion == QPdfEngine::Version_A1b) {
+ QPen pen = state.pen();
+
+ QColor penColor = pen.color();
+ if (penColor.alpha() != 255)
+ penColor.setAlpha(255);
+ pen.setColor(penColor);
+
+ QBrush penBrush = pen.brush();
+ removeTransparencyFromBrush(penBrush);
+ pen.setBrush(penBrush);
+
+ d->pen = pen;
+ } else {
+ d->pen = state.pen();
+ }
d->hasPen = d->pen.style() != Qt::NoPen;
d->stroker.setPen(d->pen, state.renderHints());
QBrush penBrush = d->pen.brush();
@@ -1054,7 +1112,13 @@ void QPdfEngine::updateState(const QPaintEngineState &state)
d->stroker.setPen(d->pen, state.renderHints());
}
if (flags & DirtyBrush) {
- d->brush = state.brush();
+ if (d->pdfVersion == QPdfEngine::Version_A1b) {
+ QBrush brush = state.brush();
+ removeTransparencyFromBrush(brush);
+ d->brush = brush;
+ } else {
+ d->brush = state.brush();
+ }
if (d->brush.color().alpha() == 0 && d->brush.style() == Qt::SolidPattern)
d->brush.setStyle(Qt::NoBrush);
d->hasBrush = d->brush.style() != Qt::NoBrush;
@@ -1286,6 +1350,12 @@ int QPdfEngine::resolution() const
return d->resolution;
}
+void QPdfEngine::setPdfVersion(PdfVersion version)
+{
+ Q_D(QPdfEngine);
+ d->pdfVersion = version;
+}
+
void QPdfEngine::setPageLayout(const QPageLayout &pageLayout)
{
Q_D(QPdfEngine);
@@ -1364,6 +1434,7 @@ int QPdfEngine::metric(QPaintDevice::PaintDeviceMetric metricType) const
QPdfEnginePrivate::QPdfEnginePrivate()
: clipEnabled(false), allClipped(false), hasPen(true), hasBrush(false), simplePen(false),
+ pdfVersion(QPdfEngine::Version_1_4),
outDevice(0), ownsDevice(false),
embedFonts(true),
grayscale(false),
@@ -1465,16 +1536,38 @@ void QPdfEnginePrivate::writeHeader()
addXrefEntry(0,false);
xprintf("%%PDF-1.4\n");
+ xprintf("%%\303\242\303\243\n");
writeInfo();
+ int metaDataObj = -1;
+ int outputIntentObj = -1;
+ if (pdfVersion == QPdfEngine::Version_A1b) {
+ metaDataObj = writeXmpMetaData();
+ outputIntentObj = writeOutputIntent();
+ }
+
catalog = addXrefEntry(-1);
pageRoot = requestObject();
- xprintf("<<\n"
- "/Type /Catalog\n"
- "/Pages %d 0 R\n"
- ">>\n"
- "endobj\n", pageRoot);
+
+ // catalog
+ {
+ QByteArray catalog;
+ QPdf::ByteStream s(&catalog);
+ s << "<<\n"
+ << "/Type /Catalog\n"
+ << "/Pages " << pageRoot << "0 R\n";
+
+ if (pdfVersion == QPdfEngine::Version_A1b) {
+ s << "/OutputIntents [" << outputIntentObj << "0 R]\n";
+ s << "/Metadata " << metaDataObj << "0 R\n";
+ }
+
+ s << ">>\n"
+ << "endobj\n";
+
+ write(catalog);
+ }
// graphics state
graphicsState = addXrefEntry(-1);
@@ -1527,6 +1620,95 @@ void QPdfEnginePrivate::writeInfo()
"endobj\n");
}
+int QPdfEnginePrivate::writeXmpMetaData()
+{
+ const int metaDataObj = addXrefEntry(-1);
+
+ const QString producer(QString::fromLatin1("Qt " QT_VERSION_STR));
+
+ const QDateTime now = QDateTime::currentDateTime();
+ const QDate date = now.date();
+ const QTime time = now.time();
+
+ QString timeStr;
+ timeStr.sprintf("%d-%02d-%02dT%02d:%02d:%02d", date.year(), date.month(), date.day(),
+ time.hour(), time.minute(), time.second());
+
+ const int offset = now.offsetFromUtc();
+ const int hours = (offset / 60) / 60;
+ const int mins = (offset / 60) % 60;
+ QString tzStr;
+ if (offset < 0)
+ tzStr.sprintf("-%02d:%02d", -hours, -mins);
+ else if (offset > 0)
+ tzStr.sprintf("+%02d:%02d", hours , mins);
+ else
+ tzStr = QLatin1String("Z");
+
+ const QString metaDataDate = timeStr + tzStr;
+
+ QFile metaDataFile(QLatin1String(":/qpdf/qpdfa_metadata.xml"));
+ metaDataFile.open(QIODevice::ReadOnly);
+ const QByteArray metaDataContent = QString::fromUtf8(metaDataFile.readAll()).arg(producer.toHtmlEscaped(),
+ title.toHtmlEscaped(),
+ creator.toHtmlEscaped(),
+ metaDataDate).toUtf8();
+ xprintf("<<\n"
+ "/Type /Metadata /Subtype /XML\n"
+ "/Length %d\n"
+ ">>\n"
+ "stream\n", metaDataContent.size());
+ write(metaDataContent);
+ xprintf("\nendstream\n"
+ "endobj\n");
+
+ return metaDataObj;
+}
+
+int QPdfEnginePrivate::writeOutputIntent()
+{
+ const int colorProfile = addXrefEntry(-1);
+ {
+ QFile colorProfileFile(QLatin1String(":/qpdf/sRGB2014.icc"));
+ colorProfileFile.open(QIODevice::ReadOnly);
+ const QByteArray colorProfileData = colorProfileFile.readAll();
+
+ QByteArray data;
+ QPdf::ByteStream s(&data);
+ int length_object = requestObject();
+
+ s << "<<\n";
+ s << "/N 3\n";
+ s << "/Alternate /DeviceRGB\n";
+ s << "/Length " << length_object << "0 R\n";
+ s << "/Filter /FlateDecode\n";
+ s << ">>\n";
+ s << "stream\n";
+ write(data);
+ const int len = writeCompressed(colorProfileData);
+ write("\nendstream\n"
+ "endobj\n");
+ addXrefEntry(length_object);
+ xprintf("%d\n"
+ "endobj\n", len);
+ }
+
+ const int outputIntent = addXrefEntry(-1);
+ {
+ xprintf("<<\n");
+ xprintf("/Type /OutputIntent\n");
+ xprintf("/S/GTS_PDFA1\n");
+ xprintf("/OutputConditionIdentifier (sRGB_IEC61966-2-1_black_scaled)\n");
+ xprintf("/DestOutputProfile %d 0 R\n", colorProfile);
+ xprintf("/Info(sRGB IEC61966 v2.1 with black scaling)\n");
+ xprintf("/RegistryName(http://www.color.org)\n");
+ xprintf(">>\n");
+ xprintf("endobj\n");
+ }
+
+ return outputIntent;
+}
+
void QPdfEnginePrivate::writePageRoot()
{
addXrefEntry(pageRoot);
@@ -1568,6 +1750,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
int fontstream = requestObject();
int cidfont = requestObject();
int toUnicode = requestObject();
+ int cidset = requestObject();
QFontEngine::Properties properties = font->fontEngine->properties();
QByteArray postscriptName = properties.postscriptName.replace(' ', '_');
@@ -1597,7 +1780,8 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
"/CapHeight " << properties.capHeight.toReal()*scale << "\n"
"/StemV " << properties.lineWidth.toReal()*scale << "\n"
"/FontFile2 " << fontstream << "0 R\n"
- ">> endobj\n";
+ "/CIDSet " << cidset << "0 R\n"
+ ">>\nendobj\n";
write(descriptor);
}
{
@@ -1615,7 +1799,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
"stream\n";
write(header);
int len = writeCompressed(fontData);
- write("endstream\n"
+ write("\nendstream\n"
"endobj\n");
addXrefEntry(length_object);
xprintf("%d\n"
@@ -1642,7 +1826,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
xprintf("<< /Length %d >>\n"
"stream\n", touc.length());
write(touc);
- write("endstream\n"
+ write("\nendstream\n"
"endobj\n");
}
{
@@ -1659,6 +1843,29 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
"endobj\n";
write(font);
}
+ {
+ QByteArray cidSetStream(font->nGlyphs() / 8 + 1, 0);
+ int byteCounter = 0;
+ int bitCounter = 0;
+ for (int i = 0; i < font->nGlyphs(); ++i) {
+ cidSetStream.data()[byteCounter] |= (1 << (7 - bitCounter));
+
+ bitCounter++;
+ if (bitCounter == 8) {
+ bitCounter = 0;
+ byteCounter++;
+ }
+ }
+
+ addXrefEntry(cidset);
+ xprintf("<<\n");
+ xprintf("/Length %d\n", cidSetStream.size());
+ xprintf(">>\n");
+ xprintf("stream\n");
+ write(cidSetStream);
+ xprintf("\nendstream\n");
+ xprintf("endobj\n");
+ }
}
@@ -1748,7 +1955,7 @@ void QPdfEnginePrivate::writePage()
xprintf("stream\n");
QIODevice *content = currentPage->stream();
int len = writeCompressed(content);
- xprintf("endstream\n"
+ xprintf("\nendstream\n"
"endobj\n");
addXrefEntry(pageStreamLength);
@@ -1768,15 +1975,28 @@ void QPdfEnginePrivate::writeTail()
for (int i = 1; i < xrefPositions.size()-1; ++i)
xprintf("%010d 00000 n \n", xrefPositions[i]);
- xprintf("trailer\n"
- "<<\n"
- "/Size %d\n"
- "/Info %d 0 R\n"
- "/Root %d 0 R\n"
- ">>\n"
- "startxref\n%d\n"
- "%%%%EOF\n",
- xrefPositions.size()-1, info, catalog, xrefPositions.constLast());
+ {
+ QByteArray trailer;
+ QPdf::ByteStream s(&trailer);
+
+ s << "trailer\n"
+ << "<<\n"
+ << "/Size " << xrefPositions.size() - 1 << "\n"
+ << "/Info " << info << "0 R\n"
+ << "/Root " << catalog << "0 R\n";
+
+ if (pdfVersion == QPdfEngine::Version_A1b) {
+ const QString uniqueId = QUuid::createUuid().toString();
+ const QByteArray fileIdentifier = QCryptographicHash::hash(uniqueId.toLatin1(), QCryptographicHash::Md5).toHex();
+ s << "/ID [ <" << fileIdentifier << "> <" << fileIdentifier << "> ]\n";
+ }
+
+ s << ">>\n"
+ << "startxref\n" << xrefPositions.constLast() << "\n"
+ << "%%EOF\n";
+
+ write(trailer);
+ }
}
int QPdfEnginePrivate::addXrefEntry(int object, bool printostr)
@@ -1794,7 +2014,13 @@ int QPdfEnginePrivate::addXrefEntry(int object, bool printostr)
return object;
}
-void QPdfEnginePrivate::printString(const QString &string) {
+void QPdfEnginePrivate::printString(const QString &string)
+{
+ if (string.isEmpty()) {
+ write("()");
+ return;
+ }
+
// The 'text string' type in PDF is encoded either as PDFDocEncoding, or
// Unicode UTF-16 with a Unicode byte order mark as the first character
// (0xfeff), with the high-order byte first.
@@ -1976,7 +2202,7 @@ int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height,
xprintf(">>\nstream\n");
len = writeCompressed(data);
}
- xprintf("endstream\n"
+ xprintf("\nendstream\n"
"endobj\n");
addXrefEntry(lenobj);
xprintf("%d\n"
@@ -2303,7 +2529,7 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QTransform &matrix,
">>\n"
"stream\n"
<< content
- << "endstream\n"
+ << "\nendstream\n"
"endobj\n";
int softMaskFormObject = addXrefEntry(-1);
@@ -2412,7 +2638,7 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
">>\n"
"stream\n"
<< pattern
- << "endstream\n"
+ << "\nendstream\n"
"endobj\n";
int patternObj = addXrefEntry(-1);
@@ -2443,6 +2669,23 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_n
QImage image = img;
QImage::Format format = image.format();
+
+ if (pdfVersion == QPdfEngine::Version_A1b) {
+ if (image.hasAlphaChannel()) {
+ // transparent images are not allowed in PDF/A-1b, so we convert it to
+ // a format without alpha channel first
+
+ QImage alphaLessImage(image.width(), image.height(), QImage::Format_RGB32);
+ alphaLessImage.fill(Qt::white);
+
+ QPainter p(&alphaLessImage);
+ p.drawImage(0, 0, image);
+
+ image = alphaLessImage;
+ format = image.format();
+ }
+ }
+
if (image.depth() == 1 && *bitmap && is_monochrome(img.colorTable())) {
if (format == QImage::Format_MonoLSB)
image = image.convertToFormat(QImage::Format_Mono);
diff --git a/src/gui/painting/qpdf.qrc b/src/gui/painting/qpdf.qrc
new file mode 100644
index 0000000000..56359c775b
--- /dev/null
+++ b/src/gui/painting/qpdf.qrc
@@ -0,0 +1,7 @@
+<!DOCTYPE RCC>
+<RCC version="1.0">
+ <qresource prefix="qpdf/">
+ <file>qpdfa_metadata.xml</file>
+ <file alias="sRGB2014.icc">../../3rdparty/icc/sRGB2014.icc</file>
+ </qresource>
+</RCC>
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index a6aa2940c8..f5bb4e17a8 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -168,6 +168,12 @@ class Q_GUI_EXPORT QPdfEngine : public QPaintEngine
Q_DECLARE_PRIVATE(QPdfEngine)
friend class QPdfWriter;
public:
+ enum PdfVersion
+ {
+ Version_1_4,
+ Version_A1b
+ };
+
QPdfEngine();
QPdfEngine(QPdfEnginePrivate &d);
~QPdfEngine() {}
@@ -177,6 +183,8 @@ public:
void setResolution(int resolution);
int resolution() const;
+ void setPdfVersion(PdfVersion version);
+
// reimplementations QPaintEngine
bool begin(QPaintDevice *pdev) Q_DECL_OVERRIDE;
bool end() Q_DECL_OVERRIDE;
@@ -258,6 +266,7 @@ public:
bool hasBrush;
bool simplePen;
qreal opacity;
+ QPdfEngine::PdfVersion pdfVersion;
QHash<QFontEngine::FaceId, QFontSubset *> fonts;
@@ -286,6 +295,8 @@ private:
int createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha);
void writeInfo();
+ int writeXmpMetaData();
+ int writeOutputIntent();
void writePageRoot();
void writeFonts();
void embedFont(QFontSubset *font);
diff --git a/src/gui/painting/qpdfa_metadata.xml b/src/gui/painting/qpdfa_metadata.xml
new file mode 100644
index 0000000000..5e5c57f1c6
--- /dev/null
+++ b/src/gui/painting/qpdfa_metadata.xml
@@ -0,0 +1,16 @@
+<?xpacket begin='' id='W5M0MpCehiHzreSzNTczkc9d'?>
+<x:xmpmeta xmlns:x="adobe:ns:meta/">
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
+ <rdf:Description xmlns:dc="http://purl.org/dc/elements/1.1/" rdf:about="">
+ <dc:title>
+ <rdf:Alt>
+ <rdf:li xml:lang="x-default">%2</rdf:li>
+ </rdf:Alt>
+ </dc:title>
+ </rdf:Description>
+ <rdf:Description xmlns:xmp="http://ns.adobe.com/xap/1.0/" rdf:about="" xmp:CreatorTool="%3" xmp:CreateDate="%4" xmp:ModifyDate="%4"/>
+ <rdf:Description xmlns:pdf="http://ns.adobe.com/pdf/1.3/" rdf:about="" pdf:Producer="%1"/>
+ <rdf:Description xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/" rdf:about="" pdfaid:part="1" pdfaid:conformance="B"/>
+ </rdf:RDF>
+</x:xmpmeta>
+<?xpacket end='w'?>
diff --git a/src/gui/painting/qpdfwriter.cpp b/src/gui/painting/qpdfwriter.cpp
index edf2950a67..5af465edeb 100644
--- a/src/gui/painting/qpdfwriter.cpp
+++ b/src/gui/painting/qpdfwriter.cpp
@@ -56,6 +56,7 @@ public:
{
engine = new QPdfEngine();
output = 0;
+ pdfVersion = QPdfWriter::PdfVersion_1_4;
}
~QPdfWriterPrivate()
{
@@ -65,6 +66,7 @@ public:
QPdfEngine *engine;
QFile *output;
+ QPdfWriter::PdfVersion pdfVersion;
};
class QPdfPagedPaintDevicePrivate : public QPagedPaintDevicePrivate
@@ -177,6 +179,35 @@ QPdfWriter::~QPdfWriter()
}
/*!
+ \since 5.10
+
+ Sets the PDF version for this writer to \a version.
+
+ If \a version is the same value as currently set then no change will be made.
+*/
+void QPdfWriter::setPdfVersion(PdfVersion version)
+{
+ Q_D(QPdfWriter);
+
+ if (d->pdfVersion == version)
+ return;
+
+ d->pdfVersion = version;
+ d->engine->setPdfVersion(d->pdfVersion == QPdfWriter::PdfVersion_1_4 ? QPdfEngine::Version_1_4 : QPdfEngine::Version_A1b);
+}
+
+/*!
+ \since 5.10
+
+ Returns the PDF version for this writer. The default is \c PdfVersion_1_4.
+*/
+QPdfWriter::PdfVersion QPdfWriter::pdfVersion() const
+{
+ Q_D(const QPdfWriter);
+ return d->pdfVersion;
+}
+
+/*!
Returns the title of the document.
*/
QString QPdfWriter::title() const
diff --git a/src/gui/painting/qpdfwriter.h b/src/gui/painting/qpdfwriter.h
index 17c73dd480..b260805b2b 100644
--- a/src/gui/painting/qpdfwriter.h
+++ b/src/gui/painting/qpdfwriter.h
@@ -61,6 +61,9 @@ public:
explicit QPdfWriter(QIODevice *device);
~QPdfWriter();
+ void setPdfVersion(PdfVersion version);
+ PdfVersion pdfVersion() const;
+
QString title() const;
void setTitle(const QString &title);
diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp
index 8215255cf5..6cb115afba 100644
--- a/src/gui/painting/qplatformbackingstore.cpp
+++ b/src/gui/painting/qplatformbackingstore.cpp
@@ -70,6 +70,13 @@
#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
#endif
+#ifndef GL_FRAMEBUFFER_SRB
+#define GL_FRAMEBUFFER_SRGB 0x8DB9
+#endif
+#ifndef GL_FRAMEBUFFER_SRGB_CAPABLE
+#define GL_FRAMEBUFFER_SRGB_CAPABLE 0x8DBA
+#endif
+
QT_BEGIN_NAMESPACE
class QPlatformBackingStorePrivate
@@ -227,17 +234,6 @@ void QPlatformTextureList::clear()
windows.
*/
-/*!
- \fn void QPlatformBackingStore::flush(QWindow *window, const QRegion &region,
- const QPoint &offset)
-
- Flushes the given \a region from the specified \a window onto the
- screen.
-
- The \a offset parameter is relative to the origin of the backing
- store image.
-*/
-
#ifndef QT_NO_OPENGL
static inline QRect deviceRect(const QRect &rect, QWindow *window)
@@ -274,7 +270,7 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
}
static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect,
- QOpenGLTextureBlitter *blitter, const QPoint &offset)
+ QOpenGLTextureBlitter *blitter, const QPoint &offset, bool canUseSrgb)
{
const QRect clipRect = textures->clipRect(idx);
if (clipRect.isEmpty())
@@ -294,7 +290,15 @@ static void blitTextureForWidget(const QPlatformTextureList *textures, int idx,
deviceRect(rectInWindow, window).size(),
QOpenGLTextureBlitter::OriginBottomLeft);
+ QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions();
+ const bool srgb = textures->flags(idx).testFlag(QPlatformTextureList::TextureIsSrgb);
+ if (srgb && canUseSrgb)
+ funcs->glEnable(GL_FRAMEBUFFER_SRGB);
+
blitter->blit(textures->textureId(idx), target, source);
+
+ if (srgb && canUseSrgb)
+ funcs->glDisable(GL_FRAMEBUFFER_SRGB);
}
/*!
@@ -340,10 +344,23 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
const QRect deviceWindowRect = deviceRect(QRect(QPoint(), window->size()), window);
const QPoint deviceWindowOffset = deviceOffset(offset, window);
+ bool canUseSrgb = false;
+ // If there are any sRGB textures in the list, check if the destination
+ // framebuffer is sRGB capable.
+ for (int i = 0; i < textures->count(); ++i) {
+ if (textures->flags(i).testFlag(QPlatformTextureList::TextureIsSrgb)) {
+ GLint cap = 0;
+ funcs->glGetIntegerv(GL_FRAMEBUFFER_SRGB_CAPABLE, &cap);
+ if (cap)
+ canUseSrgb = true;
+ break;
+ }
+ }
+
// Textures for renderToTexture widgets.
for (int i = 0; i < textures->count(); ++i) {
if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
- blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset);
+ blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb);
}
// Backingstore texture with the normal widgets.
@@ -412,7 +429,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &regi
// Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set.
for (int i = 0; i < textures->count(); ++i) {
if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop))
- blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset);
+ blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset, canUseSrgb);
}
funcs->glDisable(GL_BLEND);
diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h
index ec56aaa002..9956c032a9 100644
--- a/src/gui/painting/qplatformbackingstore.h
+++ b/src/gui/painting/qplatformbackingstore.h
@@ -78,7 +78,8 @@ class Q_GUI_EXPORT QPlatformTextureList : public QObject
Q_DECLARE_PRIVATE(QPlatformTextureList)
public:
enum Flag {
- StacksOnTop = 0x01
+ StacksOnTop = 0x01,
+ TextureIsSrgb = 0x02
};
Q_DECLARE_FLAGS(Flags, Flag)
@@ -116,8 +117,6 @@ public:
virtual QPaintDevice *paintDevice() = 0;
- // 'window' can be a child window, in which case 'region' is in child window coordinates and
- // offset is the (child) window's offset in relation to the window surface.
virtual void flush(QWindow *window, const QRegion &region, const QPoint &offset) = 0;
#ifndef QT_NO_OPENGL
virtual void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
diff --git a/src/gui/painting/qpolygon.cpp b/src/gui/painting/qpolygon.cpp
index 126b752811..3bf6004fcc 100644
--- a/src/gui/painting/qpolygon.cpp
+++ b/src/gui/painting/qpolygon.cpp
@@ -909,6 +909,8 @@ QPolygon QPolygon::united(const QPolygon &r) const
Set operations on polygons will treat the polygons as
areas. Non-closed polygons will be treated as implicitly closed.
+
+ \sa intersects()
*/
QPolygon QPolygon::intersected(const QPolygon &r) const
@@ -938,6 +940,26 @@ QPolygon QPolygon::subtracted(const QPolygon &r) const
}
/*!
+ \since 5.10
+
+ Returns \c true if the current polygon intersects at any point the given polygon \a p.
+ Also returns \c true if the current polygon contains or is contained by any part of \a p.
+
+ Set operations on polygons will treat the polygons as
+ areas. Non-closed polygons will be treated as implicitly closed.
+
+ \sa intersected()
+*/
+
+bool QPolygon::intersects(const QPolygon &p) const
+{
+ QPainterPath subject; subject.addPolygon(*this);
+ QPainterPath clip; clip.addPolygon(p);
+
+ return subject.intersects(clip);
+}
+
+/*!
\since 4.3
Returns a polygon which is the union of this polygon and \a r.
@@ -964,6 +986,7 @@ QPolygonF QPolygonF::united(const QPolygonF &r) const
Set operations on polygons will treat the polygons as
areas. Non-closed polygons will be treated as implicitly closed.
+ \sa intersects()
*/
QPolygonF QPolygonF::intersected(const QPolygonF &r) const
@@ -992,6 +1015,26 @@ QPolygonF QPolygonF::subtracted(const QPolygonF &r) const
}
/*!
+ \since 5.10
+
+ Returns \c true if the current polygon intersects at any point the given polygon \a p.
+ Also returns \c true if the current polygon contains or is contained by any part of \a p.
+
+ Set operations on polygons will treat the polygons as
+ areas. Non-closed polygons will be treated as implicitly closed.
+
+ \sa intersected()
+*/
+
+bool QPolygonF::intersects(const QPolygonF &p) const
+{
+ QPainterPath subject; subject.addPolygon(*this);
+ QPainterPath clip; clip.addPolygon(p);
+
+ return subject.intersects(clip);
+}
+
+/*!
Returns the polygon as a QVariant.
*/
diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h
index f192e8d10b..8e74a499fd 100644
--- a/src/gui/painting/qpolygon.h
+++ b/src/gui/painting/qpolygon.h
@@ -98,6 +98,8 @@ public:
Q_REQUIRED_RESULT QPolygon united(const QPolygon &r) const;
Q_REQUIRED_RESULT QPolygon intersected(const QPolygon &r) const;
Q_REQUIRED_RESULT QPolygon subtracted(const QPolygon &r) const;
+
+ bool intersects(const QPolygon &r) const;
};
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QPolygon)
@@ -175,6 +177,8 @@ public:
Q_REQUIRED_RESULT QPolygonF united(const QPolygonF &r) const;
Q_REQUIRED_RESULT QPolygonF intersected(const QPolygonF &r) const;
Q_REQUIRED_RESULT QPolygonF subtracted(const QPolygonF &r) const;
+
+ bool intersects(const QPolygonF &r) const;
};
Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QPolygonF)
diff --git a/src/gui/text/qdistancefield.cpp b/src/gui/text/qdistancefield.cpp
index 064c2aca7f..af13b96c32 100644
--- a/src/gui/text/qdistancefield.cpp
+++ b/src/gui/text/qdistancefield.cpp
@@ -436,7 +436,7 @@ static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vert
const quint32 *indices, int indexCount, qint32 value)
{
Q_ASSERT(indexCount != 0);
- typedef QVarLengthArray<quint8, 16> ScanLine;
+ typedef QVarLengthArray<quint16, 16> ScanLine;
QVarLengthArray<ScanLine, 128> scans(height);
int first = 0;
for (int i = 1; i < indexCount; ++i) {
@@ -461,16 +461,16 @@ static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vert
for (int y = fromY; y < toY; ++y) {
quint32 c = quint32(x >> 8);
if (c < quint32(width))
- scans[y].append(quint8(c));
+ scans[y].append(quint16(c));
x += dx;
}
}
for (int i = 0; i < height; ++i) {
- quint8 *scanline = scans[i].data();
+ quint16 *scanline = scans[i].data();
int size = scans[i].size();
for (int j = 1; j < size; ++j) {
int k = j;
- quint8 value = scanline[k];
+ quint16 value = scanline[k];
for (; k != 0 && value < scanline[k - 1]; --k)
scanline[k] = scanline[k - 1];
scanline[k] = value;
@@ -478,7 +478,7 @@ static void drawPolygons(qint32 *bits, int width, int height, const QPoint *vert
qint32 *line = bits + i * width;
int j = 0;
for (; j + 1 < size; j += 2) {
- for (quint8 x = scanline[j]; x < scanline[j + 1]; ++x)
+ for (quint16 x = scanline[j]; x < scanline[j + 1]; ++x)
line[x] = value;
}
if (j < size) {
@@ -516,7 +516,7 @@ static void makeDistanceField(QDistanceFieldData *data, const QPainterPath &path
for (int i = 0; i < imgWidth * imgHeight; ++i)
bits[i] = exteriorColor;
- const qreal angleStep = qreal(15 * 3.141592653589793238 / 180);
+ const qreal angleStep = qDegreesToRadians(qreal(15));
const QPoint rotation(qRound(qCos(angleStep) * 0x4000),
qRound(qSin(angleStep) * 0x4000)); // 2:14 signed
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 7f3ed3adaa..f0a5053196 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -1312,6 +1312,11 @@ QFont::StyleHint QFont::styleHint() const
looking font that contains the character. The NoFontMerging flag disables this feature.
Please note that enabling this flag will not prevent Qt from automatically picking a
suitable font when the selected font does not support the writing system of the text.
+ \value PreferNoShaping Sometimes, a font will apply complex rules to a set of characters in
+ order to display them correctly. In some writing systems, such as Brahmic scripts, this is
+ required in order for the text to be legible, but in e.g. Latin script, it is merely
+ a cosmetic feature. The PreferNoShaping flag will disable all such features when they
+ are not required, which will improve performance in most cases.
Any of these may be OR-ed with one of these flags:
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index 6f0dd27fbe..9c250c82c3 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -68,6 +68,7 @@ public:
Monospace,
Fantasy
};
+ Q_ENUM(StyleHint)
enum StyleStrategy {
PreferDefault = 0x0001,
@@ -82,6 +83,7 @@ public:
OpenGLCompatible = 0x0200,
ForceIntegerMetrics = 0x0400,
NoSubpixelAntialias = 0x0800,
+ PreferNoShaping = 0x1000,
NoFontMerging = 0x8000
};
Q_ENUM(StyleStrategy)
@@ -92,6 +94,7 @@ public:
PreferVerticalHinting = 2,
PreferFullHinting = 3
};
+ Q_ENUM(HintingPreference)
// Mapping OpenType weight value.
enum Weight {
@@ -105,12 +108,14 @@ public:
ExtraBold = 81, // 800
Black = 87 // 900
};
+ Q_ENUM(Weight)
enum Style {
StyleNormal,
StyleItalic,
StyleOblique
};
+ Q_ENUM(Style)
enum Stretch {
AnyStretch = 0,
@@ -124,6 +129,7 @@ public:
ExtraExpanded = 150,
UltraExpanded = 200
};
+ Q_ENUM(Stretch)
enum Capitalization {
MixedCase,
@@ -132,11 +138,13 @@ public:
SmallCaps,
Capitalize
};
+ Q_ENUM(Capitalization)
enum SpacingType {
PercentageSpacing,
AbsoluteSpacing
};
+ Q_ENUM(SpacingType)
enum ResolveProperties {
FamilyResolved = 0x0001,
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 596c79fd05..e4f9b8b9d4 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -359,10 +359,8 @@ bool QFontEngine::supportsScript(QChar::Script script) const
// ### TODO: This only works for scripts that require OpenType. More generally
// for scripts that do not require OpenType we should just look at the list of
// supported writing systems in the font's OS/2 table.
- if (!((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala)
- || script == QChar::Script_Khmer || script == QChar::Script_Nko)) {
+ if (!scriptRequiresOpenType(script))
return true;
- }
#if QT_CONFIG(harfbuzz)
if (qt_useHarfbuzzNG()) {
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 514e9424b2..1ae2e86a93 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -242,6 +242,12 @@ public:
void *harfbuzzFace() const;
bool supportsScript(QChar::Script script) const;
+ inline static bool scriptRequiresOpenType(QChar::Script script)
+ {
+ return ((script >= QChar::Script_Syriac && script <= QChar::Script_Sinhala)
+ || script == QChar::Script_Khmer || script == QChar::Script_Nko);
+ }
+
virtual int getPointInOutline(glyph_t glyph, int flags, quint32 point, QFixed *xpos, QFixed *ypos, quint32 *nPoints);
void clearGlyphCache(const void *key);
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 8067969f56..5675d6921d 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -541,6 +541,7 @@ int QFontMetrics::width(const QString &text, int len, int flags) const
if (len == 0)
return 0;
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
if (flags & Qt::TextBypassShaping) {
// Skip complex shaping, only use advances
int numGlyphs = len;
@@ -554,6 +555,7 @@ int QFontMetrics::width(const QString &text, int len, int flags) const
width += glyphs.advances[i];
return qRound(width);
}
+#endif
QStackTextEngine layout(text, QFont(d.data()));
return qRound(layout.width(0, len));
diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp
index 92eeaf7919..f5fc562e13 100644
--- a/src/gui/text/qfontsubset.cpp
+++ b/src/gui/text/qfontsubset.cpp
@@ -136,7 +136,7 @@ QByteArray QFontSubset::widthArray() const
QByteArray width;
QPdf::ByteStream s(&width);
- QFixed scale = QFixed(1000)/emSquare;
+ const qreal scale = 1000.0/emSquare.toInt();
QFixed defWidth = widths[0];
//qDebug("defWidth=%d, scale=%f", defWidth.toInt(), scale.toReal());
@@ -145,7 +145,7 @@ QByteArray QFontSubset::widthArray() const
defWidth = 0;
}
if (defWidth > 0) {
- s << "/DW " << (defWidth*scale).toInt();
+ s << "/DW " << qRound(defWidth.toInt() * scale);
} else {
s << "/W [";
for (int g = 0; g < nGlyphs();) {
@@ -174,11 +174,11 @@ QByteArray QFontSubset::widthArray() const
if (endnonlinear > start) {
s << start << '[';
for (int i = start; i < endnonlinear; ++i)
- s << (widths[i]*scale).toInt();
+ s << qRound(widths[i].toInt() * scale);
s << "]\n";
}
if (startLinear)
- s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << '\n';
+ s << startLinear << g - 1 << qRound(widths[startLinear].toInt() * scale) << '\n';
}
s << "]\n";
}
diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h
index 00dfccc144..e6a196d865 100644
--- a/src/gui/text/qstatictext.h
+++ b/src/gui/text/qstatictext.h
@@ -62,7 +62,7 @@ public:
};
QStaticText();
- QStaticText(const QString &text);
+ explicit QStaticText(const QString &text);
QStaticText(const QStaticText &other);
#ifdef Q_COMPILER_RVALUE_REFS
QStaticText &operator=(QStaticText &&other) Q_DECL_NOTHROW { swap(other); return *this; }
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index f8215f92e9..db0650d154 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -71,7 +71,7 @@
QT_BEGIN_NAMESPACE
-Q_CORE_EXPORT unsigned int qt_int_sqrt(unsigned int n);
+Q_CORE_EXPORT Q_DECL_CONST_FUNCTION unsigned int qt_int_sqrt(unsigned int n);
/*!
Returns \c true if the string \a text is likely to be rich text;
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 7341fa8e83..66e038122c 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -203,7 +203,7 @@ QTextDocumentPrivate::QTextDocumentPrivate()
inContentsChange = false;
blockCursorAdjustment = false;
- defaultTextOption.setTabStop(80); // same as in qtextengine.cpp
+ defaultTextOption.setTabStopDistance(80); // same as in qtextengine.cpp
defaultTextOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
defaultCursorMoveStyle = Qt::LogicalMoveStyle;
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 4d24fb50af..faddb3552d 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1005,20 +1005,53 @@ void QTextEngine::shapeText(int item) const
QFontEngine *fontEngine = this->fontEngine(si, &si.ascent, &si.descent, &si.leading);
+ bool kerningEnabled;
+ bool letterSpacingIsAbsolute;
+ bool shapingEnabled;
+ QFixed letterSpacing, wordSpacing;
+#ifndef QT_NO_RAWFONT
+ if (useRawFont) {
+ QTextCharFormat f = format(&si);
+ kerningEnabled = f.fontKerning();
+ shapingEnabled = QFontEngine::scriptRequiresOpenType(QChar::Script(si.analysis.script))
+ || (f.fontStyleStrategy() & QFont::PreferNoShaping) == 0;
+ wordSpacing = QFixed::fromReal(f.fontWordSpacing());
+ letterSpacing = QFixed::fromReal(f.fontLetterSpacing());
+ letterSpacingIsAbsolute = true;
+ } else
+#endif
+ {
+ QFont font = this->font(si);
+ kerningEnabled = font.d->kerning;
+ shapingEnabled = QFontEngine::scriptRequiresOpenType(QChar::Script(si.analysis.script))
+ || (font.d->request.styleStrategy & QFont::PreferNoShaping) == 0;
+ letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute;
+ letterSpacing = font.d->letterSpacing;
+ wordSpacing = font.d->wordSpacing;
+
+ if (letterSpacingIsAbsolute && letterSpacing.value())
+ letterSpacing *= font.d->dpi / qt_defaultDpiY();
+ }
+
// split up the item into parts that come from different font engines
// k * 3 entries, array[k] == index in string, array[k + 1] == index in glyphs, array[k + 2] == engine index
QVector<uint> itemBoundaries;
itemBoundaries.reserve(24);
- if (fontEngine->type() == QFontEngine::Multi) {
+
+ QGlyphLayout initialGlyphs = availableGlyphs(&si);
+ int nGlyphs = initialGlyphs.numGlyphs;
+ if (fontEngine->type() == QFontEngine::Multi || !shapingEnabled) {
// ask the font engine to find out which glyphs (as an index in the specific font)
// to use for the text in one item.
- QGlyphLayout initialGlyphs = availableGlyphs(&si);
-
- int nGlyphs = initialGlyphs.numGlyphs;
- QFontEngine::ShaperFlags shaperFlags(QFontEngine::GlyphIndicesOnly);
+ QFontEngine::ShaperFlags shaperFlags =
+ shapingEnabled
+ ? QFontEngine::GlyphIndicesOnly
+ : QFontEngine::ShaperFlag(0);
if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags))
Q_UNREACHABLE();
+ }
+ if (fontEngine->type() == QFontEngine::Multi) {
uint lastEngine = ~0u;
for (int i = 0, glyph_pos = 0; i < itemLength; ++i, ++glyph_pos) {
const uint engineIdx = initialGlyphs.glyphs[glyph_pos] >> 24;
@@ -1046,35 +1079,29 @@ void QTextEngine::shapeText(int item) const
itemBoundaries.append(0);
}
- bool kerningEnabled;
- bool letterSpacingIsAbsolute;
- QFixed letterSpacing, wordSpacing;
-#ifndef QT_NO_RAWFONT
- if (useRawFont) {
- QTextCharFormat f = format(&si);
- kerningEnabled = f.fontKerning();
- wordSpacing = QFixed::fromReal(f.fontWordSpacing());
- letterSpacing = QFixed::fromReal(f.fontLetterSpacing());
- letterSpacingIsAbsolute = true;
- } else
-#endif
- {
- QFont font = this->font(si);
- kerningEnabled = font.d->kerning;
- letterSpacingIsAbsolute = font.d->letterSpacingIsAbsolute;
- letterSpacing = font.d->letterSpacing;
- wordSpacing = font.d->wordSpacing;
+ if (Q_UNLIKELY(!shapingEnabled)) {
+ ushort *log_clusters = logClusters(&si);
- if (letterSpacingIsAbsolute && letterSpacing.value())
- letterSpacing *= font.d->dpi / qt_defaultDpiY();
- }
+ int glyph_pos = 0;
+ for (int i = 0; i < itemLength; ++i, ++glyph_pos) {
+ log_clusters[i] = glyph_pos;
+ initialGlyphs.attributes[glyph_pos].clusterStart = true;
+ if (QChar::isHighSurrogate(string[i])
+ && i + 1 < itemLength
+ && QChar::isLowSurrogate(string[i + 1])) {
+ ++i;
+ log_clusters[i] = glyph_pos;
+ }
+ }
+ si.num_glyphs = glyph_pos;
#if QT_CONFIG(harfbuzz)
- if (Q_LIKELY(qt_useHarfbuzzNG()))
+ } else if (Q_LIKELY(qt_useHarfbuzzNG())) {
si.num_glyphs = shapeTextWithHarfbuzzNG(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled, letterSpacing != 0);
- else
#endif
- si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled);
+ } else {
+ si.num_glyphs = shapeTextWithHarfbuzz(si, string, itemLength, fontEngine, itemBoundaries, kerningEnabled);
+ }
if (Q_UNLIKELY(si.num_glyphs == 0)) {
Q_UNREACHABLE(); // ### report shaping errors somehow
return;
@@ -3016,7 +3043,7 @@ QFixed QTextEngine::calculateTabWidth(int item, QFixed x) const
}
}
}
- QFixed tab = QFixed::fromReal(option.tabStop());
+ QFixed tab = QFixed::fromReal(option.tabStopDistance());
if (tab <= 0)
tab = 80; // default
tab *= dpiScale;
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index f49e2638f5..89f1328241 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -323,13 +323,9 @@ public:
QFontEngine *fontEngine;
};
-struct Q_AUTOTEST_EXPORT QScriptItem
+struct QScriptItem
{
- inline QScriptItem()
- : position(0),
- num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1),
- glyph_data_offset(0) {}
- inline QScriptItem(int p, const QScriptAnalysis &a)
+ Q_DECL_CONSTEXPR QScriptItem(int p, QScriptAnalysis a) Q_DECL_NOTHROW
: position(p), analysis(a),
num_glyphs(0), descent(-1), ascent(-1), leading(-1), width(-1),
glyph_data_offset(0) {}
@@ -342,11 +338,12 @@ struct Q_AUTOTEST_EXPORT QScriptItem
QFixed leading;
QFixed width;
int glyph_data_offset;
- QFixed height() const { return ascent + descent; }
+ Q_DECL_CONSTEXPR QFixed height() const Q_DECL_NOTHROW { return ascent + descent; }
+private:
+ friend class QVector<QScriptItem>;
+ QScriptItem() {}; // for QVector, don't use
};
-
-
-Q_DECLARE_TYPEINFO(QScriptItem, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QScriptItem, Q_PRIMITIVE_TYPE);
typedef QVector<QScriptItem> QScriptItemArray;
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 36e0a77bd0..1653ac8c33 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -164,24 +164,25 @@ QDataStream &operator>>(QDataStream &stream, QTextLength &length)
}
#endif // QT_NO_DATASTREAM
-class QTextFormatPrivate : public QSharedData
+namespace {
+struct Property
{
-public:
- QTextFormatPrivate() : hashDirty(true), fontDirty(true), hashValue(0) {}
+ inline Property(qint32 k, const QVariant &v) : key(k), value(v) {}
+ inline Property() {}
- struct Property
- {
- inline Property(qint32 k, const QVariant &v) : key(k), value(v) {}
- inline Property() {}
+ qint32 key = -1;
+ QVariant value;
- qint32 key;
- QVariant value;
+ inline bool operator==(const Property &other) const
+ { return key == other.key && value == other.value; }
+};
+}
+Q_DECLARE_TYPEINFO(Property, Q_MOVABLE_TYPE);
- inline bool operator==(const Property &other) const
- { return key == other.key && value == other.value; }
- inline bool operator!=(const Property &other) const
- { return key != other.key || value != other.value; }
- };
+class QTextFormatPrivate : public QSharedData
+{
+public:
+ QTextFormatPrivate() : hashDirty(true), fontDirty(true), hashValue(0) {}
inline uint hash() const
{
@@ -263,7 +264,6 @@ private:
friend QDataStream &operator<<(QDataStream &, const QTextFormat &);
friend QDataStream &operator>>(QDataStream &, QTextFormat &);
};
-Q_DECLARE_TYPEINFO(QTextFormatPrivate::Property, Q_MOVABLE_TYPE);
static inline uint hash(const QColor &color)
{
@@ -845,10 +845,10 @@ void QTextFormat::merge(const QTextFormat &other)
QTextFormatPrivate *d = this->d;
- const QVector<QTextFormatPrivate::Property> &otherProps = other.d->props;
+ const QVector<QT_PREPEND_NAMESPACE(Property)> &otherProps = other.d->props;
d->props.reserve(d->props.size() + otherProps.size());
for (int i = 0; i < otherProps.count(); ++i) {
- const QTextFormatPrivate::Property &p = otherProps.at(i);
+ const QT_PREPEND_NAMESPACE(Property) &p = otherProps.at(i);
d->insertProperty(p.key, p.value);
}
}
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index da4e21728f..be10efad8d 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -493,7 +493,7 @@ static QString quoteNewline(const QString &s)
QTextHtmlParserNode::QTextHtmlParserNode()
: parent(0), id(Html_unknown),
- cssFloat(QTextFrameFormat::InFlow), hasOwnListStyle(false), hasOwnLineHeightType(false),
+ cssFloat(QTextFrameFormat::InFlow), hasOwnListStyle(false), hasOwnLineHeightType(false), hasLineHeightMultiplier(false),
hasCssListIndent(false), isEmptyParagraph(false), isTextFrame(false), isRootFrame(false),
displayMode(QTextHtmlElement::DisplayInline), hasHref(false),
listStyle(QTextListFormat::ListStyleUndefined), imageWidth(-1), imageHeight(-1), tableBorder(0),
@@ -1216,6 +1216,11 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
else
lineHeightType = QTextBlockFormat::SingleHeight;
+ if (hasLineHeightMultiplier) {
+ qreal lineHeight = blockFormat.lineHeight() / 100.0;
+ blockFormat.setProperty(QTextBlockFormat::LineHeight, lineHeight);
+ }
+
blockFormat.setProperty(QTextBlockFormat::LineHeightType, lineHeightType);
hasOwnLineHeightType = true;
}
@@ -1227,9 +1232,14 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
lineHeightType = QTextBlockFormat::MinimumHeight;
} else {
bool ok;
- QString value = decl.d->values.first().toString();
+ QCss::Value cssValue = decl.d->values.first();
+ QString value = cssValue.toString();
lineHeight = value.toDouble(&ok);
if (ok) {
+ if (!hasOwnLineHeightType && cssValue.type == QCss::Value::Number) {
+ lineHeight *= 100.0;
+ hasLineHeightMultiplier = true;
+ }
lineHeightType = QTextBlockFormat::ProportionalHeight;
} else {
lineHeight = 0.0;
diff --git a/src/gui/text/qtexthtmlparser_p.h b/src/gui/text/qtexthtmlparser_p.h
index 77bfa685c0..73dac38b82 100644
--- a/src/gui/text/qtexthtmlparser_p.h
+++ b/src/gui/text/qtexthtmlparser_p.h
@@ -173,6 +173,7 @@ struct QTextHtmlParserNode {
uint cssFloat : 2;
uint hasOwnListStyle : 1;
uint hasOwnLineHeightType : 1;
+ uint hasLineHeightMultiplier : 1;
uint hasCssListIndent : 1;
uint isEmptyParagraph : 1;
uint isTextFrame : 1;
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index cc91c107f9..066f258ea3 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -167,7 +167,7 @@ QRectF QTextInlineObject::rect() const
*/
qreal QTextInlineObject::width() const
{
- return eng->layoutData->items[itm].width.toReal();
+ return eng->layoutData->items.at(itm).width.toReal();
}
/*!
@@ -177,7 +177,7 @@ qreal QTextInlineObject::width() const
*/
qreal QTextInlineObject::ascent() const
{
- return eng->layoutData->items[itm].ascent.toReal();
+ return eng->layoutData->items.at(itm).ascent.toReal();
}
/*!
@@ -187,7 +187,7 @@ qreal QTextInlineObject::ascent() const
*/
qreal QTextInlineObject::descent() const
{
- return eng->layoutData->items[itm].descent.toReal();
+ return eng->layoutData->items.at(itm).descent.toReal();
}
/*!
@@ -198,7 +198,7 @@ qreal QTextInlineObject::descent() const
*/
qreal QTextInlineObject::height() const
{
- return eng->layoutData->items[itm].height().toReal();
+ return eng->layoutData->items.at(itm).height().toReal();
}
/*!
@@ -924,7 +924,7 @@ QRectF QTextLayout::boundingRect() const
QFixed ymin = d->lines.at(0).y;
for (int i = 0; i < d->lines.size(); ++i) {
- const QScriptLine &si = d->lines[i];
+ const QScriptLine &si = d->lines.at(i);
xmin = qMin(xmin, si.x);
ymin = qMin(ymin, si.y);
QFixed lineWidth = si.width < QFIXED_MAX ? qMax(si.width, si.textWidth) : si.textWidth;
@@ -1052,9 +1052,9 @@ QList<QGlyphRun> QTextLayout::glyphRuns(int from, int length) const
QHash<QPair<QFontEngine *, int>, QGlyphRun> glyphRunHash;
for (int i=0; i<d->lines.size(); ++i) {
- if (d->lines[i].from > from + length)
+ if (d->lines.at(i).from > from + length)
break;
- else if (d->lines[i].from + d->lines[i].length >= from) {
+ else if (d->lines.at(i).from + d->lines[i].length >= from) {
QList<QGlyphRun> glyphRuns = QTextLine(i, d).glyphRuns(from, length);
for (int j = 0; j < glyphRuns.size(); j++) {
@@ -1115,7 +1115,7 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang
int lastLine = d->lines.size();
for (int i = 0; i < d->lines.size(); ++i) {
QTextLine l(i, d);
- const QScriptLine &sl = d->lines[i];
+ const QScriptLine &sl = d->lines.at(i);
if (sl.y > clipe) {
lastLine = i;
@@ -1137,7 +1137,7 @@ void QTextLayout::draw(QPainter *p, const QPointF &pos, const QVector<FormatRang
region.setFillRule(Qt::WindingFill);
for (int line = firstLine; line < lastLine; ++line) {
- const QScriptLine &sl = d->lines[line];
+ const QScriptLine &sl = d->lines.at(line);
QTextLine tl(line, d);
QRectF lineRect(tl.naturalTextRect());
@@ -1302,7 +1302,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
return;
QTextLine l(line, d);
- const QScriptLine &sl = d->lines[line];
+ const QScriptLine &sl = d->lines.at(line);
qreal x = position.x() + l.cursorToX(cursorPosition);
@@ -1415,7 +1415,7 @@ void QTextLayout::drawCursor(QPainter *p, const QPointF &pos, int cursorPosition
*/
QRectF QTextLine::rect() const
{
- const QScriptLine& sl = eng->lines[index];
+ const QScriptLine& sl = eng->lines.at(index);
return QRectF(sl.x.toReal(), sl.y.toReal(), sl.width.toReal(), sl.height().toReal());
}
@@ -1424,7 +1424,7 @@ QRectF QTextLine::rect() const
*/
QRectF QTextLine::naturalTextRect() const
{
- const QScriptLine& sl = eng->lines[index];
+ const QScriptLine& sl = eng->lines.at(index);
QFixed x = sl.x + eng->alignLine(sl);
QFixed width = sl.textWidth;
@@ -1441,7 +1441,7 @@ QRectF QTextLine::naturalTextRect() const
*/
qreal QTextLine::x() const
{
- return eng->lines[index].x.toReal();
+ return eng->lines.at(index).x.toReal();
}
/*!
@@ -1451,7 +1451,7 @@ qreal QTextLine::x() const
*/
qreal QTextLine::y() const
{
- return eng->lines[index].y.toReal();
+ return eng->lines.at(index).y.toReal();
}
/*!
@@ -1461,7 +1461,7 @@ qreal QTextLine::y() const
*/
qreal QTextLine::width() const
{
- return eng->lines[index].width.toReal();
+ return eng->lines.at(index).width.toReal();
}
@@ -1472,7 +1472,7 @@ qreal QTextLine::width() const
*/
qreal QTextLine::ascent() const
{
- return eng->lines[index].ascent.toReal();
+ return eng->lines.at(index).ascent.toReal();
}
/*!
@@ -1482,7 +1482,7 @@ qreal QTextLine::ascent() const
*/
qreal QTextLine::descent() const
{
- return eng->lines[index].descent.toReal();
+ return eng->lines.at(index).descent.toReal();
}
/*!
@@ -1494,7 +1494,7 @@ qreal QTextLine::descent() const
*/
qreal QTextLine::height() const
{
- return eng->lines[index].height().ceil().toReal();
+ return eng->lines.at(index).height().ceil().toReal();
}
/*!
@@ -1506,7 +1506,7 @@ qreal QTextLine::height() const
*/
qreal QTextLine::leading() const
{
- return eng->lines[index].leading.toReal();
+ return eng->lines.at(index).leading.toReal();
}
/*!
@@ -1541,7 +1541,7 @@ void QTextLine::setLeadingIncluded(bool included)
*/
bool QTextLine::leadingIncluded() const
{
- return eng->lines[index].leadingIncluded;
+ return eng->lines.at(index).leadingIncluded;
}
/*!
@@ -1551,7 +1551,7 @@ bool QTextLine::leadingIncluded() const
*/
qreal QTextLine::naturalTextWidth() const
{
- return eng->lines[index].textWidth.toReal();
+ return eng->lines.at(index).textWidth.toReal();
}
/*!
@@ -1566,7 +1566,7 @@ qreal QTextLine::naturalTextWidth() const
*/
qreal QTextLine::horizontalAdvance() const
{
- return eng->lines[index].textAdvance.toReal();
+ return eng->lines.at(index).textAdvance.toReal();
}
/*!
@@ -1832,7 +1832,7 @@ void QTextLine::layout_helper(int maxGlyphs)
lbh.softHyphenWidth = 0;
if (newItem != item) {
item = newItem;
- const QScriptItem &current = eng->layoutData->items[item];
+ const QScriptItem &current = eng->layoutData->items.at(item);
if (!current.num_glyphs) {
eng->shape(item);
attributes = eng->attributes();
@@ -1850,7 +1850,7 @@ void QTextLine::layout_helper(int maxGlyphs)
QFixed::fromReal(fontEngine->minRightBearing()));
}
}
- const QScriptItem &current = eng->layoutData->items[item];
+ const QScriptItem &current = eng->layoutData->items.at(item);
lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent,
current.leading + current.ascent) - qMax(lbh.tmpData.ascent,
@@ -2093,7 +2093,7 @@ void QTextLine::setPosition(const QPointF &pos)
*/
QPointF QTextLine::position() const
{
- return QPointF(eng->lines[index].x.toReal(), eng->lines[index].y.toReal());
+ return QPointF(eng->lines.at(index).x.toReal(), eng->lines.at(index).y.toReal());
}
// ### DOC: I have no idea what this means/does.
@@ -2109,7 +2109,7 @@ QPointF QTextLine::position() const
*/
int QTextLine::textStart() const
{
- return eng->lines[index].from;
+ return eng->lines.at(index).from;
}
/*!
@@ -2121,9 +2121,9 @@ int QTextLine::textLength() const
{
if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators
&& eng->block.isValid() && index == eng->lines.count()-1) {
- return eng->lines[index].length - 1;
+ return eng->lines.at(index).length - 1;
}
- return eng->lines[index].length + eng->lines[index].trailingSpaces;
+ return eng->lines.at(index).length + eng->lines.at(index).trailingSpaces;
}
static void setPenAndDrawBackground(QPainter *p, const QPen &defaultPen, const QTextCharFormat &chf, const QRectF &r)
@@ -2247,7 +2247,7 @@ static QGlyphRun glyphRunWithInfo(QFontEngine *fontEngine,
*/
QList<QGlyphRun> QTextLine::glyphRuns(int from, int length) const
{
- const QScriptLine &line = eng->lines[index];
+ const QScriptLine &line = eng->lines.at(index);
if (line.length == 0)
return QList<QGlyphRun>();
diff --git a/src/gui/text/qtextoption.cpp b/src/gui/text/qtextoption.cpp
index 87e31eeb2c..2a16f50f33 100644
--- a/src/gui/text/qtextoption.cpp
+++ b/src/gui/text/qtextoption.cpp
@@ -144,7 +144,7 @@ QTextOption &QTextOption::operator=(const QTextOption &o)
Sets the tab positions for the text layout to those specified by
\a tabStops.
- \sa tabArray(), setTabStop(), setTabs()
+ \sa tabArray(), setTabStopDistance(), setTabs()
*/
void QTextOption::setTabArray(const QList<qreal> &tabStops)
{
@@ -332,22 +332,45 @@ QList<QTextOption::Tab> QTextOption::tabs() const
\sa flags()
*/
+#if QT_DEPRECATED_SINCE(5, 10)
/*!
\fn qreal QTextOption::tabStop() const
+ \deprecated in Qt 5.10. Use tabStopDistance() instead.
Returns the distance in device units between tab stops.
Convenient function for the above method
- \sa setTabStop(), tabArray(), setTabs(), tabs()
+ \sa setTabStopDistance(), tabArray(), setTabs(), tabs()
*/
/*!
\fn void QTextOption::setTabStop(qreal tabStop)
+ \deprecated in Qt 5.10. Use setTabStopDistance() instead.
Sets the default distance in device units between tab stops to the value specified
by \a tabStop.
- \sa tabStop(), setTabArray(), setTabs(), tabs()
+ \sa tabStopDistance(), setTabArray(), setTabs(), tabs()
+*/
+#endif
+
+/*!
+ \fn qreal QTextOption::tabStopDistance() const
+ \since 5.10
+
+ Returns the distance in device units between tab stops.
+
+ \sa setTabStopDistance(), tabArray(), setTabs(), tabs()
+*/
+
+/*!
+ \fn void QTextOption::setTabStopDistance(qreal tabStopDistance)
+ \since 5.10
+
+ Sets the default distance in device units between tab stops to the value specified
+ by \a tabStopDistance.
+
+ \sa tabStopDistance(), setTabArray(), setTabs(), tabs()
*/
/*!
@@ -426,7 +449,7 @@ QList<QTextOption::Tab> QTextOption::tabs() const
\fn void setTabs(const QList<Tab> &tabStops)
Set the Tab properties to \a tabStops.
- \sa tabStop(), tabs()
+ \sa tabStopDistance(), tabs()
*/
/*!
@@ -434,7 +457,7 @@ QList<QTextOption::Tab> QTextOption::tabs() const
\fn QList<QTextOption::Tab> QTextOption::tabs() const
Returns a list of tab positions defined for the text layout.
- \sa tabStop(), setTabs(), setTabStop()
+ \sa tabStopDistance(), setTabs(), setTabStop()
*/
diff --git a/src/gui/text/qtextoption.h b/src/gui/text/qtextoption.h
index 9ef9cee9bb..8b57278633 100644
--- a/src/gui/text/qtextoption.h
+++ b/src/gui/text/qtextoption.h
@@ -117,8 +117,13 @@ public:
inline void setFlags(Flags flags);
inline Flags flags() const { return Flags(f); }
- inline void setTabStop(qreal tabStop);
- inline qreal tabStop() const { return tab; }
+#if QT_DEPRECATED_SINCE(5, 10)
+ QT_DEPRECATED inline void setTabStop(qreal tabStop);
+ QT_DEPRECATED inline qreal tabStop() const { return tabStopDistance(); }
+#endif
+
+ inline void setTabStopDistance(qreal tabStopDistance);
+ inline qreal tabStopDistance() const { return tab; }
void setTabArray(const QList<qreal> &tabStops);
QList<qreal> tabArray() const;
@@ -149,7 +154,12 @@ inline void QTextOption::setAlignment(Qt::Alignment aalignment)
inline void QTextOption::setFlags(Flags aflags)
{ f = aflags; }
+#if QT_DEPRECATED_SINCE(5, 10)
inline void QTextOption::setTabStop(qreal atabStop)
+{ setTabStopDistance(atabStop); }
+#endif
+
+inline void QTextOption::setTabStopDistance(qreal atabStop)
{ tab = atabStop; }
QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderformat.cpp b/src/gui/util/qshaderformat.cpp
new file mode 100644
index 0000000000..373bfb9e7e
--- /dev/null
+++ b/src/gui/util/qshaderformat.cpp
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshaderformat_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QShaderFormat::QShaderFormat() Q_DECL_NOTHROW
+ : m_api(NoApi)
+{
+}
+
+QShaderFormat::Api QShaderFormat::api() const Q_DECL_NOTHROW
+{
+ return m_api;
+}
+
+void QShaderFormat::setApi(QShaderFormat::Api api) Q_DECL_NOTHROW
+{
+ m_api = api;
+}
+
+QVersionNumber QShaderFormat::version() const Q_DECL_NOTHROW
+{
+ return m_version;
+}
+
+void QShaderFormat::setVersion(const QVersionNumber &version) Q_DECL_NOTHROW
+{
+ m_version = version;
+}
+
+QStringList QShaderFormat::extensions() const Q_DECL_NOTHROW
+{
+ return m_extensions;
+}
+
+void QShaderFormat::setExtensions(const QStringList &extensions) Q_DECL_NOTHROW
+{
+ m_extensions = extensions;
+ m_extensions.sort();
+}
+
+QString QShaderFormat::vendor() const Q_DECL_NOTHROW
+{
+ return m_vendor;
+}
+
+void QShaderFormat::setVendor(const QString &vendor) Q_DECL_NOTHROW
+{
+ m_vendor = vendor;
+}
+
+bool QShaderFormat::isValid() const Q_DECL_NOTHROW
+{
+ return m_api != NoApi && m_version.majorVersion() > 0;
+}
+
+bool QShaderFormat::supports(const QShaderFormat &other) const Q_DECL_NOTHROW
+{
+ if (!isValid() || !other.isValid())
+ return false;
+
+ if (m_api == OpenGLES && m_api != other.m_api)
+ return false;
+
+ if (m_api == OpenGLCoreProfile && m_api != other.m_api)
+ return false;
+
+ if (m_version < other.m_version)
+ return false;
+
+ const auto containsAllExtensionsFromOther = std::includes(m_extensions.constBegin(),
+ m_extensions.constEnd(),
+ other.m_extensions.constBegin(),
+ other.m_extensions.constEnd());
+ if (!containsAllExtensionsFromOther)
+ return false;
+
+ if (!other.m_vendor.isEmpty() && m_vendor != other.m_vendor)
+ return false;
+
+ return true;
+}
+
+bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW
+{
+ return lhs.api() == rhs.api()
+ && lhs.version() == rhs.version()
+ && lhs.extensions() == rhs.extensions()
+ && lhs.vendor() == rhs.vendor();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderformat_p.h b/src/gui/util/qshaderformat_p.h
new file mode 100644
index 0000000000..064c2364a7
--- /dev/null
+++ b/src/gui/util/qshaderformat_p.h
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADERFORMAT_P_H
+#define QSHADERFORMAT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qversionnumber.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShaderFormat
+{
+public:
+ enum Api : int {
+ NoApi,
+ OpenGLNoProfile,
+ OpenGLCoreProfile,
+ OpenGLCompatibilityProfile,
+ OpenGLES
+ };
+
+ Q_GUI_EXPORT QShaderFormat() Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT Api api() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setApi(Api api) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QVersionNumber version() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setVersion(const QVersionNumber &version) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QStringList extensions() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setExtensions(const QStringList &extensions) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QString vendor() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setVendor(const QString &vendor) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT bool isValid() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT bool supports(const QShaderFormat &other) const Q_DECL_NOTHROW;
+
+private:
+ Api m_api;
+ QVersionNumber m_version;
+ QStringList m_extensions;
+ QString m_vendor;
+};
+
+Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderFormat &lhs, const QShaderFormat &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_DECLARE_TYPEINFO(QShaderFormat, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderFormat)
+
+#endif // QSHADERFORMAT_P_H
diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp
new file mode 100644
index 0000000000..31c2f74746
--- /dev/null
+++ b/src/gui/util/qshadergenerator.cpp
@@ -0,0 +1,351 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshadergenerator_p.h"
+
+#include "qshaderlanguage_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace
+{
+ QByteArray toGlsl(QShaderLanguage::StorageQualifier qualifier, const QShaderFormat &format)
+ {
+ if (format.version().majorVersion() <= 2) {
+ // Note we're assuming fragment shader only here, it'd be different
+ // values for vertex shader, will need to be fixed properly at some
+ // point but isn't necessary yet (this problem already exists in past
+ // commits anyway)
+ switch (qualifier) {
+ case QShaderLanguage::Const:
+ return "const";
+ case QShaderLanguage::Input:
+ return "varying";
+ case QShaderLanguage::Output:
+ return ""; // Although fragment shaders for <=2 only have fixed outputs
+ case QShaderLanguage::Uniform:
+ return "uniform";
+ }
+ } else {
+ switch (qualifier) {
+ case QShaderLanguage::Const:
+ return "const";
+ case QShaderLanguage::Input:
+ return "in";
+ case QShaderLanguage::Output:
+ return "out";
+ case QShaderLanguage::Uniform:
+ return "uniform";
+ }
+ }
+
+ Q_UNREACHABLE();
+ }
+
+ QByteArray toGlsl(QShaderLanguage::VariableType type)
+ {
+ switch (type) {
+ case QShaderLanguage::Bool:
+ return "bool";
+ case QShaderLanguage::Int:
+ return "int";
+ case QShaderLanguage::Uint:
+ return "uint";
+ case QShaderLanguage::Float:
+ return "float";
+ case QShaderLanguage::Double:
+ return "double";
+ case QShaderLanguage::Vec2:
+ return "vec2";
+ case QShaderLanguage::Vec3:
+ return "vec3";
+ case QShaderLanguage::Vec4:
+ return "vec4";
+ case QShaderLanguage::DVec2:
+ return "dvec2";
+ case QShaderLanguage::DVec3:
+ return "dvec3";
+ case QShaderLanguage::DVec4:
+ return "dvec4";
+ case QShaderLanguage::BVec2:
+ return "bvec2";
+ case QShaderLanguage::BVec3:
+ return "bvec3";
+ case QShaderLanguage::BVec4:
+ return "bvec4";
+ case QShaderLanguage::IVec2:
+ return "ivec2";
+ case QShaderLanguage::IVec3:
+ return "ivec3";
+ case QShaderLanguage::IVec4:
+ return "ivec4";
+ case QShaderLanguage::UVec2:
+ return "uvec2";
+ case QShaderLanguage::UVec3:
+ return "uvec3";
+ case QShaderLanguage::UVec4:
+ return "uvec4";
+ case QShaderLanguage::Mat2:
+ return "mat2";
+ case QShaderLanguage::Mat3:
+ return "mat3";
+ case QShaderLanguage::Mat4:
+ return "mat4";
+ case QShaderLanguage::Mat2x2:
+ return "mat2x2";
+ case QShaderLanguage::Mat2x3:
+ return "mat2x3";
+ case QShaderLanguage::Mat2x4:
+ return "mat2x4";
+ case QShaderLanguage::Mat3x2:
+ return "mat3x2";
+ case QShaderLanguage::Mat3x3:
+ return "mat3x3";
+ case QShaderLanguage::Mat3x4:
+ return "mat3x4";
+ case QShaderLanguage::Mat4x2:
+ return "mat4x2";
+ case QShaderLanguage::Mat4x3:
+ return "mat4x3";
+ case QShaderLanguage::Mat4x4:
+ return "mat4x4";
+ case QShaderLanguage::DMat2:
+ return "dmat2";
+ case QShaderLanguage::DMat3:
+ return "dmat3";
+ case QShaderLanguage::DMat4:
+ return "dmat4";
+ case QShaderLanguage::DMat2x2:
+ return "dmat2x2";
+ case QShaderLanguage::DMat2x3:
+ return "dmat2x3";
+ case QShaderLanguage::DMat2x4:
+ return "dmat2x4";
+ case QShaderLanguage::DMat3x2:
+ return "dmat3x2";
+ case QShaderLanguage::DMat3x3:
+ return "dmat3x3";
+ case QShaderLanguage::DMat3x4:
+ return "dmat3x4";
+ case QShaderLanguage::DMat4x2:
+ return "dmat4x2";
+ case QShaderLanguage::DMat4x3:
+ return "dmat4x3";
+ case QShaderLanguage::DMat4x4:
+ return "dmat4x4";
+ case QShaderLanguage::Sampler1D:
+ return "sampler1D";
+ case QShaderLanguage::Sampler2D:
+ return "sampler2D";
+ case QShaderLanguage::Sampler3D:
+ return "sampler3D";
+ case QShaderLanguage::SamplerCube:
+ return "samplerCube";
+ case QShaderLanguage::Sampler2DRect:
+ return "sampler2DRect";
+ case QShaderLanguage::Sampler2DMs:
+ return "sampler2DMS";
+ case QShaderLanguage::SamplerBuffer:
+ return "samplerBuffer";
+ case QShaderLanguage::Sampler1DArray:
+ return "sampler1DArray";
+ case QShaderLanguage::Sampler2DArray:
+ return "sampler2DArray";
+ case QShaderLanguage::Sampler2DMsArray:
+ return "sampler2DMSArray";
+ case QShaderLanguage::SamplerCubeArray:
+ return "samplerCubeArray";
+ case QShaderLanguage::Sampler1DShadow:
+ return "sampler1DShadow";
+ case QShaderLanguage::Sampler2DShadow:
+ return "sampler2DShadow";
+ case QShaderLanguage::Sampler2DRectShadow:
+ return "sampler2DRectShadow";
+ case QShaderLanguage::Sampler1DArrayShadow:
+ return "sampler1DArrayShadow";
+ case QShaderLanguage::Sampler2DArrayShadow:
+ return "sample2DArrayShadow";
+ case QShaderLanguage::SamplerCubeShadow:
+ return "samplerCubeShadow";
+ case QShaderLanguage::SamplerCubeArrayShadow:
+ return "samplerCubeArrayShadow";
+ case QShaderLanguage::ISampler1D:
+ return "isampler1D";
+ case QShaderLanguage::ISampler2D:
+ return "isampler2D";
+ case QShaderLanguage::ISampler3D:
+ return "isampler3D";
+ case QShaderLanguage::ISamplerCube:
+ return "isamplerCube";
+ case QShaderLanguage::ISampler2DRect:
+ return "isampler2DRect";
+ case QShaderLanguage::ISampler2DMs:
+ return "isampler2DMS";
+ case QShaderLanguage::ISamplerBuffer:
+ return "isamplerBuffer";
+ case QShaderLanguage::ISampler1DArray:
+ return "isampler1DArray";
+ case QShaderLanguage::ISampler2DArray:
+ return "isampler2DArray";
+ case QShaderLanguage::ISampler2DMsArray:
+ return "isampler2DMSArray";
+ case QShaderLanguage::ISamplerCubeArray:
+ return "isamplerCubeArray";
+ case QShaderLanguage::USampler1D:
+ return "usampler1D";
+ case QShaderLanguage::USampler2D:
+ return "usampler2D";
+ case QShaderLanguage::USampler3D:
+ return "usampler3D";
+ case QShaderLanguage::USamplerCube:
+ return "usamplerCube";
+ case QShaderLanguage::USampler2DRect:
+ return "usampler2DRect";
+ case QShaderLanguage::USampler2DMs:
+ return "usampler2DMS";
+ case QShaderLanguage::USamplerBuffer:
+ return "usamplerBuffer";
+ case QShaderLanguage::USampler1DArray:
+ return "usampler1DArray";
+ case QShaderLanguage::USampler2DArray:
+ return "usampler2DArray";
+ case QShaderLanguage::USampler2DMsArray:
+ return "usampler2DMSArray";
+ case QShaderLanguage::USamplerCubeArray:
+ return "usamplerCubeArray";
+ }
+
+ Q_UNREACHABLE();
+ }
+
+ QByteArray replaceParameters(const QByteArray &original, const QShaderNode &node, const QShaderFormat &format)
+ {
+ auto result = original;
+
+ for (const auto &parameterName : node.parameterNames()) {
+ const auto placeholder = QByteArray(QByteArrayLiteral("$") + parameterName.toUtf8());
+ const auto parameter = node.parameter(parameterName);
+ if (parameter.userType() == qMetaTypeId<QShaderLanguage::StorageQualifier>()) {
+ const auto qualifier = parameter.value<QShaderLanguage::StorageQualifier>();
+ const auto value = toGlsl(qualifier, format);
+ result.replace(placeholder, value);
+ } else if (parameter.userType() == qMetaTypeId<QShaderLanguage::VariableType>()) {
+ const auto type = parameter.value<QShaderLanguage::VariableType>();
+ const auto value = toGlsl(type);
+ result.replace(placeholder, value);
+ } else {
+ const auto value = parameter.toString().toUtf8();
+ result.replace(placeholder, value);
+ }
+ }
+
+ return result;
+ }
+}
+
+QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers) const
+{
+ auto code = QByteArrayList();
+
+ if (format.isValid()) {
+ const auto isGLES = format.api() == QShaderFormat::OpenGLES;
+ const auto major = format.version().majorVersion();
+ const auto minor = format.version().minorVersion();
+
+ const auto version = major == 2 && isGLES ? 100
+ : major == 3 && isGLES ? 300
+ : major == 2 ? 100 + 10 * (minor + 1)
+ : major == 3 && minor <= 2 ? 100 + 10 * (minor + 3)
+ : major * 100 + minor * 10;
+
+ const auto profile = isGLES && version > 100 ? QByteArrayLiteral(" es")
+ : version >= 150 && format.api() == QShaderFormat::OpenGLCoreProfile ? QByteArrayLiteral(" core")
+ : version >= 150 && format.api() == QShaderFormat::OpenGLCompatibilityProfile ? QByteArrayLiteral(" compatibility")
+ : QByteArray();
+
+ code << (QByteArrayLiteral("#version ") + QByteArray::number(version) + profile);
+ code << QByteArray();
+ }
+
+ const auto intersectsEnabledLayers = [enabledLayers] (const QStringList &layers) {
+ return layers.isEmpty()
+ || std::any_of(layers.cbegin(), layers.cend(),
+ [enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
+ };
+
+ for (const auto &node : graph.nodes()) {
+ if (intersectsEnabledLayers(node.layers())) {
+ for (const auto &snippet : node.rule(format).headerSnippets) {
+ code << replaceParameters(snippet, node, format);
+ }
+ }
+ }
+
+ code << QByteArray();
+ code << QByteArrayLiteral("void main()");
+ code << QByteArrayLiteral("{");
+
+ for (const auto &statement : graph.createStatements(enabledLayers)) {
+ const auto node = statement.node;
+ auto line = node.rule(format).substitution;
+ for (const auto &port : node.ports()) {
+ const auto portName = port.name;
+ const auto portDirection = port.direction;
+ const auto isInput = port.direction == QShaderNodePort::Input;
+
+ const auto portIndex = statement.portIndex(portDirection, portName);
+ const auto variableIndex = isInput ? statement.inputs.at(portIndex)
+ : statement.outputs.at(portIndex);
+ if (variableIndex < 0)
+ continue;
+
+ const auto placeholder = QByteArray(QByteArrayLiteral("$") + portName.toUtf8());
+ const auto variable = QByteArray(QByteArrayLiteral("v") + QByteArray::number(variableIndex));
+ line.replace(placeholder, variable);
+ }
+
+ code << QByteArrayLiteral(" ") + replaceParameters(line, node, format);
+ }
+
+ code << QByteArrayLiteral("}");
+ code << QByteArray();
+ return code.join('\n');
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadergenerator_p.h b/src/gui/util/qshadergenerator_p.h
new file mode 100644
index 0000000000..7bc8838b52
--- /dev/null
+++ b/src/gui/util/qshadergenerator_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADERGENERATOR_P_H
+#define QSHADERGENERATOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtGui/private/qshadergraph_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShaderGenerator
+{
+public:
+ Q_GUI_EXPORT QByteArray createShaderCode(const QStringList &enabledLayers = QStringList()) const;
+
+ QShaderGraph graph;
+ QShaderFormat format;
+};
+
+Q_DECLARE_TYPEINFO(QShaderGenerator, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderGenerator)
+
+#endif // QSHADERGENERATOR_P_H
diff --git a/src/gui/util/qshadergraph.cpp b/src/gui/util/qshadergraph.cpp
new file mode 100644
index 0000000000..828c709a12
--- /dev/null
+++ b/src/gui/util/qshadergraph.cpp
@@ -0,0 +1,262 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshadergraph_p.h"
+
+QT_BEGIN_NAMESPACE
+
+
+namespace
+{
+ QVector<QShaderNode> copyOutputNodes(const QVector<QShaderNode> &nodes)
+ {
+ auto res = QVector<QShaderNode>();
+ std::copy_if(nodes.cbegin(), nodes.cend(),
+ std::back_inserter(res),
+ [] (const QShaderNode &node) {
+ return node.type() == QShaderNode::Output;
+ });
+ return res;
+ }
+
+ QVector<QShaderGraph::Edge> incomingEdges(const QVector<QShaderGraph::Edge> &edges, const QUuid &uuid)
+ {
+ auto res = QVector<QShaderGraph::Edge>();
+ std::copy_if(edges.cbegin(), edges.cend(),
+ std::back_inserter(res),
+ [uuid] (const QShaderGraph::Edge &edge) {
+ return edge.sourceNodeUuid == uuid;
+ });
+ return res;
+ }
+
+ QVector<QShaderGraph::Edge> outgoingEdges(const QVector<QShaderGraph::Edge> &edges, const QUuid &uuid)
+ {
+ auto res = QVector<QShaderGraph::Edge>();
+ std::copy_if(edges.cbegin(), edges.cend(),
+ std::back_inserter(res),
+ [uuid] (const QShaderGraph::Edge &edge) {
+ return edge.targetNodeUuid == uuid;
+ });
+ return res;
+ }
+
+ QShaderGraph::Statement nodeToStatement(const QShaderNode &node, int &nextVarId)
+ {
+ auto statement = QShaderGraph::Statement();
+ statement.node = node;
+
+ const auto ports = node.ports();
+ for (const auto &port : ports) {
+ if (port.direction == QShaderNodePort::Input) {
+ statement.inputs.append(-1);
+ } else {
+ statement.outputs.append(nextVarId);
+ nextVarId++;
+ }
+ }
+ return statement;
+ }
+
+ QShaderGraph::Statement completeStatement(const QHash<QUuid, QShaderGraph::Statement> &idHash,
+ const QVector<QShaderGraph::Edge> edges,
+ const QUuid &uuid)
+ {
+ auto targetStatement = idHash.value(uuid);
+ for (const auto &edge : edges) {
+ if (edge.targetNodeUuid != uuid)
+ continue;
+
+ const auto sourceStatement = idHash.value(edge.sourceNodeUuid);
+ const auto sourcePortIndex = sourceStatement.portIndex(QShaderNodePort::Output, edge.sourcePortName);
+ const auto targetPortIndex = targetStatement.portIndex(QShaderNodePort::Input, edge.targetPortName);
+
+ if (sourcePortIndex < 0 || targetPortIndex < 0)
+ continue;
+
+ const auto &sourceOutputs = sourceStatement.outputs;
+ auto &targetInputs = targetStatement.inputs;
+ targetInputs[targetPortIndex] = sourceOutputs[sourcePortIndex];
+ }
+ return targetStatement;
+ }
+}
+
+QUuid QShaderGraph::Statement::uuid() const Q_DECL_NOTHROW
+{
+ return node.uuid();
+}
+
+int QShaderGraph::Statement::portIndex(QShaderNodePort::Direction direction, const QString &portName) const Q_DECL_NOTHROW
+{
+ const auto ports = node.ports();
+ int index = 0;
+ for (const auto &port : ports) {
+ if (port.name == portName && port.direction == direction)
+ return index;
+ else if (port.direction == direction)
+ index++;
+ }
+ return -1;
+}
+
+void QShaderGraph::addNode(const QShaderNode &node)
+{
+ removeNode(node);
+ m_nodes.append(node);
+}
+
+void QShaderGraph::removeNode(const QShaderNode &node)
+{
+ const auto it = std::find_if(m_nodes.begin(), m_nodes.end(),
+ [node] (const QShaderNode &n) { return n.uuid() == node.uuid(); });
+ if (it != m_nodes.end())
+ m_nodes.erase(it);
+}
+
+QVector<QShaderNode> QShaderGraph::nodes() const Q_DECL_NOTHROW
+{
+ return m_nodes;
+}
+
+void QShaderGraph::addEdge(const QShaderGraph::Edge &edge)
+{
+ if (m_edges.contains(edge))
+ return;
+ m_edges.append(edge);
+}
+
+void QShaderGraph::removeEdge(const QShaderGraph::Edge &edge)
+{
+ m_edges.removeAll(edge);
+}
+
+QVector<QShaderGraph::Edge> QShaderGraph::edges() const Q_DECL_NOTHROW
+{
+ return m_edges;
+}
+
+QVector<QShaderGraph::Statement> QShaderGraph::createStatements(const QStringList &enabledLayers) const
+{
+ const auto intersectsEnabledLayers = [enabledLayers] (const QStringList &layers) {
+ return layers.isEmpty()
+ || std::any_of(layers.cbegin(), layers.cend(),
+ [enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
+ };
+
+ const auto enabledNodes = [this, intersectsEnabledLayers] {
+ auto res = QVector<QShaderNode>();
+ std::copy_if(m_nodes.cbegin(), m_nodes.cend(),
+ std::back_inserter(res),
+ [intersectsEnabledLayers] (const QShaderNode &node) {
+ return intersectsEnabledLayers(node.layers());
+ });
+ return res;
+ }();
+
+ const auto enabledEdges = [this, intersectsEnabledLayers] {
+ auto res = QVector<Edge>();
+ std::copy_if(m_edges.cbegin(), m_edges.cend(),
+ std::back_inserter(res),
+ [intersectsEnabledLayers] (const Edge &edge) {
+ return intersectsEnabledLayers(edge.layers);
+ });
+ return res;
+ }();
+
+ const auto idHash = [enabledNodes] {
+ auto nextVarId = 0;
+ auto res = QHash<QUuid, Statement>();
+ for (const auto &node : enabledNodes)
+ res.insert(node.uuid(), nodeToStatement(node, nextVarId));
+ return res;
+ }();
+
+ auto result = QVector<Statement>();
+ auto currentEdges = enabledEdges;
+ auto currentUuids = [enabledNodes] {
+ const auto inputs = copyOutputNodes(enabledNodes);
+ auto res = QVector<QUuid>();
+ std::transform(inputs.cbegin(), inputs.cend(),
+ std::back_inserter(res),
+ [](const QShaderNode &node) { return node.uuid(); });
+ return res;
+ }();
+
+ // Implements Kahn's algorithm to flatten the graph
+ // https://en.wikipedia.org/wiki/Topological_sorting#Kahn.27s_algorithm
+ //
+ // We implement it with a small twist though, we follow the edges backward
+ // because we want to track the dependencies from the output nodes and not the
+ // input nodes
+ while (!currentUuids.isEmpty()) {
+ const auto uuid = currentUuids.takeFirst();
+ result.append(completeStatement(idHash, enabledEdges, uuid));
+
+ const auto outgoing = outgoingEdges(currentEdges, uuid);
+ for (const auto &outgoingEdge : outgoing) {
+ currentEdges.removeAll(outgoingEdge);
+ const QUuid nextUuid = outgoingEdge.sourceNodeUuid;
+ const auto incoming = incomingEdges(currentEdges, nextUuid);
+ if (incoming.isEmpty()) {
+ currentUuids.append(nextUuid);
+ }
+ }
+ }
+
+ std::reverse(result.begin(), result.end());
+ return result;
+}
+
+bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) Q_DECL_NOTHROW
+{
+ return lhs.sourceNodeUuid == rhs.sourceNodeUuid
+ && lhs.sourcePortName == rhs.sourcePortName
+ && lhs.targetNodeUuid == rhs.targetNodeUuid
+ && lhs.targetPortName == rhs.targetPortName;
+}
+
+bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) Q_DECL_NOTHROW
+{
+ return lhs.inputs == rhs.inputs
+ && lhs.outputs == rhs.outputs
+ && lhs.node.uuid() == rhs.node.uuid();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadergraph_p.h b/src/gui/util/qshadergraph_p.h
new file mode 100644
index 0000000000..756e1b2da2
--- /dev/null
+++ b/src/gui/util/qshadergraph_p.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADERGRAPH_P_H
+#define QSHADERGRAPH_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtGui/private/qshadernode_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShaderGraph
+{
+public:
+ class Edge
+ {
+ public:
+ QStringList layers;
+ QUuid sourceNodeUuid;
+ QString sourcePortName;
+ QUuid targetNodeUuid;
+ QString targetPortName;
+ };
+
+ class Statement
+ {
+ public:
+ Q_GUI_EXPORT QUuid uuid() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT int portIndex(QShaderNodePort::Direction direction, const QString &portName) const Q_DECL_NOTHROW;
+
+ QShaderNode node;
+ QVector<int> inputs;
+ QVector<int> outputs;
+ };
+
+ Q_GUI_EXPORT void addNode(const QShaderNode &node);
+ Q_GUI_EXPORT void removeNode(const QShaderNode &node);
+ Q_GUI_EXPORT QVector<QShaderNode> nodes() const Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT void addEdge(const Edge &edge);
+ Q_GUI_EXPORT void removeEdge(const Edge &edge);
+ Q_GUI_EXPORT QVector<Edge> edges() const Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QVector<Statement> createStatements(const QStringList &enabledLayers = QStringList()) const;
+
+private:
+ QVector<QShaderNode> m_nodes;
+ QVector<Edge> m_edges;
+};
+
+Q_GUI_EXPORT bool operator==(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderGraph::Edge &lhs, const QShaderGraph::Edge &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_GUI_EXPORT bool operator==(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderGraph::Statement &lhs, const QShaderGraph::Statement &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_DECLARE_TYPEINFO(QShaderGraph, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QShaderGraph::Edge, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QShaderGraph::Statement, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderGraph)
+Q_DECLARE_METATYPE(QShaderGraph::Edge)
+Q_DECLARE_METATYPE(QShaderGraph::Statement)
+
+#endif // QSHADERGRAPH_P_H
diff --git a/src/gui/util/qshadergraphloader.cpp b/src/gui/util/qshadergraphloader.cpp
new file mode 100644
index 0000000000..c7560d9105
--- /dev/null
+++ b/src/gui/util/qshadergraphloader.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshadergraphloader_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+QShaderGraphLoader::QShaderGraphLoader() Q_DECL_NOTHROW
+ : m_status(Null),
+ m_device(nullptr)
+{
+}
+
+QShaderGraphLoader::Status QShaderGraphLoader::status() const Q_DECL_NOTHROW
+{
+ return m_status;
+}
+
+QShaderGraph QShaderGraphLoader::graph() const Q_DECL_NOTHROW
+{
+ return m_graph;
+}
+
+QIODevice *QShaderGraphLoader::device() const Q_DECL_NOTHROW
+{
+ return m_device;
+}
+
+void QShaderGraphLoader::setDevice(QIODevice *device) Q_DECL_NOTHROW
+{
+ m_device = device;
+ m_graph = QShaderGraph();
+ m_status = !m_device ? Null
+ : (m_device->openMode() & QIODevice::ReadOnly) ? Waiting
+ : Error;
+}
+
+QHash<QString, QShaderNode> QShaderGraphLoader::prototypes() const Q_DECL_NOTHROW
+{
+ return m_prototypes;
+}
+
+void QShaderGraphLoader::setPrototypes(const QHash<QString, QShaderNode> &prototypes) Q_DECL_NOTHROW
+{
+ m_prototypes = prototypes;
+}
+
+void QShaderGraphLoader::load()
+{
+ if (m_status == Error)
+ return;
+
+ auto error = QJsonParseError();
+ const auto document = QJsonDocument::fromJson(m_device->readAll(), &error);
+
+ if (error.error != QJsonParseError::NoError) {
+ qWarning() << "Invalid JSON document:" << error.errorString();
+ m_status = Error;
+ return;
+ }
+
+ if (document.isEmpty() || !document.isObject()) {
+ qWarning() << "Invalid JSON document, root should be an object";
+ m_status = Error;
+ return;
+ }
+
+ const auto root = document.object();
+
+ const auto nodesValue = root.value(QStringLiteral("nodes"));
+ if (!nodesValue.isArray()) {
+ qWarning() << "Invalid nodes property, should be an array";
+ m_status = Error;
+ return;
+ }
+
+ const auto edgesValue = root.value(QStringLiteral("edges"));
+ if (!edgesValue.isArray()) {
+ qWarning() << "Invalid edges property, should be an array";
+ m_status = Error;
+ return;
+ }
+
+ bool hasError = false;
+
+ const auto nodes = nodesValue.toArray();
+ for (const auto &nodeValue : nodes) {
+ if (!nodeValue.isObject()) {
+ qWarning() << "Invalid node found";
+ hasError = true;
+ continue;
+ }
+
+ const auto nodeObject = nodeValue.toObject();
+
+ const auto uuidString = nodeObject.value(QStringLiteral("uuid")).toString();
+ const auto uuid = QUuid(uuidString);
+ if (uuid.isNull()) {
+ qWarning() << "Invalid UUID found in node:" << uuidString;
+ hasError = true;
+ continue;
+ }
+
+ const auto type = nodeObject.value(QStringLiteral("type")).toString();
+ if (!m_prototypes.contains(type)) {
+ qWarning() << "Unsupported node type found:" << type;
+ hasError = true;
+ continue;
+ }
+
+ const auto layersArray = nodeObject.value(QStringLiteral("layers")).toArray();
+ auto layers = QStringList();
+ for (const auto &layerValue : layersArray) {
+ layers.append(layerValue.toString());
+ }
+
+ auto node = m_prototypes.value(type);
+ node.setUuid(uuid);
+ node.setLayers(layers);
+
+ const auto parametersValue = nodeObject.value(QStringLiteral("parameters"));
+ if (parametersValue.isObject()) {
+ const auto parametersObject = parametersValue.toObject();
+ for (const auto &parameterName : parametersObject.keys()) {
+ const auto parameterValue = parametersObject.value(parameterName);
+ if (parameterValue.isObject()) {
+ const auto parameterObject = parameterValue.toObject();
+ const auto type = parameterObject.value(QStringLiteral("type")).toString();
+ const auto typeId = QMetaType::type(type.toUtf8());
+
+ const auto value = parameterObject.value(QStringLiteral("value")).toString();
+ auto variant = QVariant(value);
+
+ if (QMetaType::typeFlags(typeId) & QMetaType::IsEnumeration) {
+ const auto metaObject = QMetaType::metaObjectForType(typeId);
+ const auto className = metaObject->className();
+ const auto enumName = type.mid(static_cast<int>(qstrlen(className)) + 2).toUtf8();
+ const auto metaEnum = metaObject->enumerator(metaObject->indexOfEnumerator(enumName));
+ const auto enumValue = metaEnum.keyToValue(value.toUtf8());
+ variant = QVariant(enumValue);
+ variant.convert(typeId);
+ } else {
+ variant.convert(typeId);
+ }
+ node.setParameter(parameterName, variant);
+ } else {
+ node.setParameter(parameterName, parameterValue.toVariant());
+ }
+ }
+ }
+
+ m_graph.addNode(node);
+ }
+
+ const auto edges = edgesValue.toArray();
+ for (const auto &edgeValue : edges) {
+ if (!edgeValue.isObject()) {
+ qWarning() << "Invalid edge found";
+ hasError = true;
+ continue;
+ }
+
+ const auto edgeObject = edgeValue.toObject();
+
+ const auto sourceUuidString = edgeObject.value(QStringLiteral("sourceUuid")).toString();
+ const auto sourceUuid = QUuid(sourceUuidString);
+ if (sourceUuid.isNull()) {
+ qWarning() << "Invalid source UUID found in edge:" << sourceUuidString;
+ hasError = true;
+ continue;
+ }
+
+ const auto sourcePort = edgeObject.value(QStringLiteral("sourcePort")).toString();
+
+ const auto targetUuidString = edgeObject.value(QStringLiteral("targetUuid")).toString();
+ const auto targetUuid = QUuid(targetUuidString);
+ if (targetUuid.isNull()) {
+ qWarning() << "Invalid target UUID found in edge:" << targetUuidString;
+ hasError = true;
+ continue;
+ }
+
+ const auto targetPort = edgeObject.value(QStringLiteral("targetPort")).toString();
+
+ const auto layersArray = edgeObject.value(QStringLiteral("layers")).toArray();
+ auto layers = QStringList();
+ for (const auto &layerValue : layersArray) {
+ layers.append(layerValue.toString());
+ }
+
+ auto edge = QShaderGraph::Edge();
+ edge.sourceNodeUuid = sourceUuid;
+ edge.sourcePortName = sourcePort;
+ edge.targetNodeUuid = targetUuid;
+ edge.targetPortName = targetPort;
+ edge.layers = layers;
+ m_graph.addEdge(edge);
+ }
+
+ if (hasError) {
+ m_status = Error;
+ m_graph = QShaderGraph();
+ } else {
+ m_status = Ready;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadergraphloader_p.h b/src/gui/util/qshadergraphloader_p.h
new file mode 100644
index 0000000000..97cbd8d18c
--- /dev/null
+++ b/src/gui/util/qshadergraphloader_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADERGRAPHLOADER_P_H
+#define QSHADERGRAPHLOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtGui/private/qshadergraph_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+class QShaderGraphLoader
+{
+public:
+ enum Status : char {
+ Null,
+ Waiting,
+ Ready,
+ Error
+ };
+
+ Q_GUI_EXPORT QShaderGraphLoader() Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT Status status() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QShaderGraph graph() const Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QIODevice *device() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setDevice(QIODevice *device) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QHash<QString, QShaderNode> prototypes() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setPrototypes(const QHash<QString, QShaderNode> &prototypes) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT void load();
+
+private:
+ Status m_status;
+ QIODevice *m_device;
+ QHash<QString, QShaderNode> m_prototypes;
+ QShaderGraph m_graph;
+};
+
+Q_DECLARE_TYPEINFO(QShaderGraphLoader, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderGraphLoader)
+Q_DECLARE_METATYPE(QShaderGraphLoader::Status)
+
+#endif // QSHADERGRAPHLOADER_P_H
diff --git a/src/gui/util/qshaderlanguage.cpp b/src/gui/util/qshaderlanguage.cpp
new file mode 100644
index 0000000000..4a0da5bfb5
--- /dev/null
+++ b/src/gui/util/qshaderlanguage.cpp
@@ -0,0 +1,56 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshaderlanguage_p.h"
+
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace {
+ void registerEnums()
+ {
+ qRegisterMetaType<QShaderLanguage::StorageQualifier>();
+ qRegisterMetaType<QShaderLanguage::VariableType>();
+ }
+}
+
+Q_COREAPP_STARTUP_FUNCTION(registerEnums)
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderlanguage_p.h b/src/gui/util/qshaderlanguage_p.h
new file mode 100644
index 0000000000..5c7819a3b8
--- /dev/null
+++ b/src/gui/util/qshaderlanguage_p.h
@@ -0,0 +1,163 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADERLANGUAGE_P_H
+#define QSHADERLANGUAGE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QShaderLanguage
+{
+ Q_GUI_EXPORT Q_NAMESPACE
+
+ enum StorageQualifier : char {
+ Const = 1,
+ Input,
+ Output,
+ Uniform
+ };
+ Q_ENUM_NS(StorageQualifier)
+
+ enum VariableType : int {
+ Bool = 1,
+ Int,
+ Uint,
+ Float,
+ Double,
+ Vec2,
+ Vec3,
+ Vec4,
+ DVec2,
+ DVec3,
+ DVec4,
+ BVec2,
+ BVec3,
+ BVec4,
+ IVec2,
+ IVec3,
+ IVec4,
+ UVec2,
+ UVec3,
+ UVec4,
+ Mat2,
+ Mat3,
+ Mat4,
+ Mat2x2,
+ Mat2x3,
+ Mat2x4,
+ Mat3x2,
+ Mat3x3,
+ Mat3x4,
+ Mat4x2,
+ Mat4x3,
+ Mat4x4,
+ DMat2,
+ DMat3,
+ DMat4,
+ DMat2x2,
+ DMat2x3,
+ DMat2x4,
+ DMat3x2,
+ DMat3x3,
+ DMat3x4,
+ DMat4x2,
+ DMat4x3,
+ DMat4x4,
+ Sampler1D,
+ Sampler2D,
+ Sampler3D,
+ SamplerCube,
+ Sampler2DRect,
+ Sampler2DMs,
+ SamplerBuffer,
+ Sampler1DArray,
+ Sampler2DArray,
+ Sampler2DMsArray,
+ SamplerCubeArray,
+ Sampler1DShadow,
+ Sampler2DShadow,
+ Sampler2DRectShadow,
+ Sampler1DArrayShadow,
+ Sampler2DArrayShadow,
+ SamplerCubeShadow,
+ SamplerCubeArrayShadow,
+ ISampler1D,
+ ISampler2D,
+ ISampler3D,
+ ISamplerCube,
+ ISampler2DRect,
+ ISampler2DMs,
+ ISamplerBuffer,
+ ISampler1DArray,
+ ISampler2DArray,
+ ISampler2DMsArray,
+ ISamplerCubeArray,
+ USampler1D,
+ USampler2D,
+ USampler3D,
+ USamplerCube,
+ USampler2DRect,
+ USampler2DMs,
+ USamplerBuffer,
+ USampler1DArray,
+ USampler2DArray,
+ USampler2DMsArray,
+ USamplerCubeArray
+ };
+ Q_ENUM_NS(VariableType)
+}
+
+QT_END_NAMESPACE
+
+#endif // QSHADERLANGUAGE_P_H
diff --git a/src/gui/util/qshadernode.cpp b/src/gui/util/qshadernode.cpp
new file mode 100644
index 0000000000..676667ddcf
--- /dev/null
+++ b/src/gui/util/qshadernode.cpp
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshadernode_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QShaderNode::Type QShaderNode::type() const Q_DECL_NOTHROW
+{
+ int inputCount = 0;
+ int outputCount = 0;
+ for (const auto &port : qAsConst(m_ports)) {
+ switch (port.direction) {
+ case QShaderNodePort::Input:
+ inputCount++;
+ break;
+ case QShaderNodePort::Output:
+ outputCount++;
+ break;
+ }
+ }
+
+ return (inputCount == 0 && outputCount == 0) ? Invalid
+ : (inputCount > 0 && outputCount == 0) ? Output
+ : (inputCount == 0 && outputCount > 0) ? Input
+ : Function;
+}
+
+QUuid QShaderNode::uuid() const Q_DECL_NOTHROW
+{
+ return m_uuid;
+}
+
+void QShaderNode::setUuid(const QUuid &uuid) Q_DECL_NOTHROW
+{
+ m_uuid = uuid;
+}
+
+QStringList QShaderNode::layers() const Q_DECL_NOTHROW
+{
+ return m_layers;
+}
+
+void QShaderNode::setLayers(const QStringList &layers) Q_DECL_NOTHROW
+{
+ m_layers = layers;
+}
+
+QVector<QShaderNodePort> QShaderNode::ports() const Q_DECL_NOTHROW
+{
+ return m_ports;
+}
+
+void QShaderNode::addPort(const QShaderNodePort &port)
+{
+ removePort(port);
+ m_ports.append(port);
+}
+
+void QShaderNode::removePort(const QShaderNodePort &port)
+{
+ const auto it = std::find_if(m_ports.begin(), m_ports.end(),
+ [port](const QShaderNodePort &p) {
+ return p.name == port.name;
+ });
+ if (it != m_ports.end())
+ m_ports.erase(it);
+}
+
+QStringList QShaderNode::parameterNames() const
+{
+ return m_parameters.keys();
+}
+
+QVariant QShaderNode::parameter(const QString &name) const
+{
+ return m_parameters.value(name);
+}
+
+void QShaderNode::setParameter(const QString &name, const QVariant &value)
+{
+ m_parameters.insert(name, value);
+}
+
+void QShaderNode::clearParameter(const QString &name)
+{
+ m_parameters.remove(name);
+}
+
+void QShaderNode::addRule(const QShaderFormat &format, const QShaderNode::Rule &rule)
+{
+ removeRule(format);
+ m_rules << qMakePair(format, rule);
+}
+
+void QShaderNode::removeRule(const QShaderFormat &format)
+{
+ const auto it = std::find_if(m_rules.begin(), m_rules.end(),
+ [format](const QPair<QShaderFormat, Rule> &entry) {
+ return entry.first == format;
+ });
+ if (it != m_rules.end())
+ m_rules.erase(it);
+}
+
+QVector<QShaderFormat> QShaderNode::availableFormats() const
+{
+ auto res = QVector<QShaderFormat>();
+ std::transform(m_rules.cbegin(), m_rules.cend(),
+ std::back_inserter(res),
+ [](const QPair<QShaderFormat, Rule> &entry) { return entry.first; });
+ return res;
+}
+
+QShaderNode::Rule QShaderNode::rule(const QShaderFormat &format) const
+{
+ const auto it = std::find_if(m_rules.crbegin(), m_rules.crend(),
+ [format](const QPair<QShaderFormat, Rule> &entry) {
+ return format.supports(entry.first);
+ });
+ return it != m_rules.crend() ? it->second : Rule();
+}
+
+QShaderNode::Rule::Rule(const QByteArray &subs, const QByteArrayList &snippets) Q_DECL_NOTHROW
+ : substitution(subs),
+ headerSnippets(snippets)
+{
+}
+
+bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) Q_DECL_NOTHROW
+{
+ return lhs.substitution == rhs.substitution
+ && lhs.headerSnippets == rhs.headerSnippets;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernode_p.h b/src/gui/util/qshadernode_p.h
new file mode 100644
index 0000000000..494c87bc18
--- /dev/null
+++ b/src/gui/util/qshadernode_p.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt Quick Layouts module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADERNODE_P_H
+#define QSHADERNODE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtGui/private/qshaderformat_p.h>
+#include <QtGui/private/qshadernodeport_p.h>
+
+#include <QtCore/quuid.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShaderNode
+{
+public:
+ enum Type : char {
+ Invalid,
+ Input,
+ Output,
+ Function
+ };
+
+ class Rule
+ {
+ public:
+ Q_GUI_EXPORT Rule(const QByteArray &substitution = QByteArray(), const QByteArrayList &headerSnippets = QByteArrayList()) Q_DECL_NOTHROW;
+
+ QByteArray substitution;
+ QByteArrayList headerSnippets;
+ };
+
+ Q_GUI_EXPORT Type type() const Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QUuid uuid() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setUuid(const QUuid &uuid) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QStringList layers() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setLayers(const QStringList &layers) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QVector<QShaderNodePort> ports() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void addPort(const QShaderNodePort &port);
+ Q_GUI_EXPORT void removePort(const QShaderNodePort &port);
+
+ Q_GUI_EXPORT QStringList parameterNames() const;
+ Q_GUI_EXPORT QVariant parameter(const QString &name) const;
+ Q_GUI_EXPORT void setParameter(const QString &name, const QVariant &value);
+ Q_GUI_EXPORT void clearParameter(const QString &name);
+
+ Q_GUI_EXPORT void addRule(const QShaderFormat &format, const Rule &rule);
+ Q_GUI_EXPORT void removeRule(const QShaderFormat &format);
+
+ Q_GUI_EXPORT QVector<QShaderFormat> availableFormats() const;
+ Q_GUI_EXPORT Rule rule(const QShaderFormat &format) const;
+
+private:
+ QUuid m_uuid;
+ QStringList m_layers;
+ QVector<QShaderNodePort> m_ports;
+ QHash<QString, QVariant> m_parameters;
+ QVector<QPair<QShaderFormat, QShaderNode::Rule>> m_rules;
+};
+
+Q_GUI_EXPORT bool operator==(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderNode::Rule &lhs, const QShaderNode::Rule &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_DECLARE_TYPEINFO(QShaderNode, Q_MOVABLE_TYPE);
+Q_DECLARE_TYPEINFO(QShaderNode::Rule, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderNode)
+Q_DECLARE_METATYPE(QShaderNode::Rule)
+
+#endif // QSHADERNODE_P_H
diff --git a/src/gui/util/qshadernodeport.cpp b/src/gui/util/qshadernodeport.cpp
new file mode 100644
index 0000000000..03646a9467
--- /dev/null
+++ b/src/gui/util/qshadernodeport.cpp
@@ -0,0 +1,55 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshadernodeport_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QShaderNodePort::QShaderNodePort() Q_DECL_NOTHROW
+ : direction(Output)
+{
+}
+
+bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) Q_DECL_NOTHROW
+{
+ return lhs.direction == rhs.direction
+ && lhs.name == rhs.name;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernodeport_p.h b/src/gui/util/qshadernodeport_p.h
new file mode 100644
index 0000000000..cfdaf05017
--- /dev/null
+++ b/src/gui/util/qshadernodeport_p.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADERNODEPORT_P_H
+#define QSHADERNODEPORT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtCore/qstring.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+class QShaderNodePort
+{
+public:
+ enum Direction : char {
+ Input,
+ Output
+ };
+
+ Q_GUI_EXPORT QShaderNodePort() Q_DECL_NOTHROW;
+
+ QShaderNodePort::Direction direction;
+ QString name;
+};
+
+Q_GUI_EXPORT bool operator==(const QShaderNodePort &lhs, const QShaderNodePort &rhs) Q_DECL_NOTHROW;
+
+inline bool operator!=(const QShaderNodePort &lhs, const QShaderNodePort &rhs) Q_DECL_NOTHROW
+{
+ return !(lhs == rhs);
+}
+
+Q_DECLARE_TYPEINFO(QShaderNodePort, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderNodePort)
+
+#endif // QSHADERNODEPORT_P_H
diff --git a/src/gui/util/qshadernodesloader.cpp b/src/gui/util/qshadernodesloader.cpp
new file mode 100644
index 0000000000..db34b6d44d
--- /dev/null
+++ b/src/gui/util/qshadernodesloader.cpp
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qshadernodesloader_p.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qjsonarray.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qmetaobject.h>
+
+QT_BEGIN_NAMESPACE
+
+QShaderNodesLoader::QShaderNodesLoader() Q_DECL_NOTHROW
+ : m_status(Null),
+ m_device(nullptr)
+{
+}
+
+QShaderNodesLoader::Status QShaderNodesLoader::status() const Q_DECL_NOTHROW
+{
+ return m_status;
+}
+
+QHash<QString, QShaderNode> QShaderNodesLoader::nodes() const Q_DECL_NOTHROW
+{
+ return m_nodes;
+}
+
+QIODevice *QShaderNodesLoader::device() const Q_DECL_NOTHROW
+{
+ return m_device;
+}
+
+void QShaderNodesLoader::setDevice(QIODevice *device) Q_DECL_NOTHROW
+{
+ m_device = device;
+ m_nodes.clear();
+ m_status = !m_device ? Null
+ : (m_device->openMode() & QIODevice::ReadOnly) ? Waiting
+ : Error;
+}
+
+void QShaderNodesLoader::load()
+{
+ if (m_status == Error)
+ return;
+
+ auto error = QJsonParseError();
+ const auto document = QJsonDocument::fromJson(m_device->readAll(), &error);
+
+ if (error.error != QJsonParseError::NoError) {
+ qWarning() << "Invalid JSON document:" << error.errorString();
+ m_status = Error;
+ return;
+ }
+
+ if (document.isEmpty() || !document.isObject()) {
+ qWarning() << "Invalid JSON document, root should be an object";
+ m_status = Error;
+ return;
+ }
+
+ const auto root = document.object();
+
+ bool hasError = false;
+
+ for (const auto &property : root.keys()) {
+ const auto nodeValue = root.value(property);
+ if (!nodeValue.isObject()) {
+ qWarning() << "Invalid node found";
+ hasError = true;
+ break;
+ }
+
+ const auto nodeObject = nodeValue.toObject();
+
+ auto node = QShaderNode();
+
+ const auto inputsValue = nodeObject.value(QStringLiteral("inputs"));
+ if (inputsValue.isArray()) {
+ const auto inputsArray = inputsValue.toArray();
+ for (const auto &inputValue : inputsArray) {
+ if (!inputValue.isString()) {
+ qWarning() << "Non-string value in inputs";
+ hasError = true;
+ break;
+ }
+
+ auto input = QShaderNodePort();
+ input.direction = QShaderNodePort::Input;
+ input.name = inputValue.toString();
+ node.addPort(input);
+ }
+ }
+
+ const auto outputsValue = nodeObject.value(QStringLiteral("outputs"));
+ if (outputsValue.isArray()) {
+ const auto outputsArray = outputsValue.toArray();
+ for (const auto &outputValue : outputsArray) {
+ if (!outputValue.isString()) {
+ qWarning() << "Non-string value in outputs";
+ hasError = true;
+ break;
+ }
+
+ auto output = QShaderNodePort();
+ output.direction = QShaderNodePort::Output;
+ output.name = outputValue.toString();
+ node.addPort(output);
+ }
+ }
+
+ const auto parametersValue = nodeObject.value(QStringLiteral("parameters"));
+ if (parametersValue.isObject()) {
+ const auto parametersObject = parametersValue.toObject();
+ for (const auto &parameterName : parametersObject.keys()) {
+ const auto parameterValue = parametersObject.value(parameterName);
+ if (parameterValue.isObject()) {
+ const auto parameterObject = parameterValue.toObject();
+ const auto type = parameterObject.value(QStringLiteral("type")).toString();
+ const auto typeId = QMetaType::type(type.toUtf8());
+
+ const auto value = parameterObject.value(QStringLiteral("value")).toString();
+ auto variant = QVariant(value);
+
+ if (QMetaType::typeFlags(typeId) & QMetaType::IsEnumeration) {
+ const auto metaObject = QMetaType::metaObjectForType(typeId);
+ const auto className = metaObject->className();
+ const auto enumName = type.mid(static_cast<int>(qstrlen(className)) + 2).toUtf8();
+ const auto metaEnum = metaObject->enumerator(metaObject->indexOfEnumerator(enumName));
+ const auto enumValue = metaEnum.keyToValue(value.toUtf8());
+ variant = QVariant(enumValue);
+ variant.convert(typeId);
+ } else {
+ variant.convert(typeId);
+ }
+ node.setParameter(parameterName, variant);
+ } else {
+ node.setParameter(parameterName, parameterValue.toVariant());
+ }
+ }
+ }
+
+ const auto rulesValue = nodeObject.value(QStringLiteral("rules"));
+ if (rulesValue.isArray()) {
+ const auto rulesArray = rulesValue.toArray();
+ for (const auto &ruleValue : rulesArray) {
+ if (!ruleValue.isObject()) {
+ qWarning() << "Rules should be objects";
+ hasError = true;
+ break;
+ }
+
+ const auto ruleObject = ruleValue.toObject();
+
+ const auto formatValue = ruleObject.value(QStringLiteral("format"));
+ if (!formatValue.isObject()) {
+ qWarning() << "Format is mandatory in rules and should be an object";
+ hasError = true;
+ break;
+ }
+
+ const auto formatObject = formatValue.toObject();
+ auto format = QShaderFormat();
+
+ const auto apiValue = formatObject.value(QStringLiteral("api"));
+ if (!apiValue.isString()) {
+ qWarning() << "Format API must be a string";
+ hasError = true;
+ break;
+ }
+
+ const auto api = apiValue.toString();
+ format.setApi(api == QStringLiteral("OpenGLES") ? QShaderFormat::OpenGLES
+ : api == QStringLiteral("OpenGLNoProfile") ? QShaderFormat::OpenGLNoProfile
+ : api == QStringLiteral("OpenGLCoreProfile") ? QShaderFormat::OpenGLCoreProfile
+ : api == QStringLiteral("OpenGLCompatibilityProfile") ? QShaderFormat::OpenGLCompatibilityProfile
+ : QShaderFormat::NoApi);
+ if (format.api() == QShaderFormat::NoApi) {
+ qWarning() << "Format API must be one of: OpenGLES, OpenGLNoProfile, OpenGLCoreProfile or OpenGLCompatibilityProfile";
+ hasError = true;
+ break;
+ }
+
+ const auto majorValue = formatObject.value(QStringLiteral("major"));
+ const auto minorValue = formatObject.value(QStringLiteral("minor"));
+ if (!majorValue.isDouble() || !minorValue.isDouble()) {
+ qWarning() << "Format major and minor version must be values";
+ hasError = true;
+ break;
+ }
+ format.setVersion(QVersionNumber(majorValue.toInt(), minorValue.toInt()));
+
+ const auto extensionsValue = formatObject.value(QStringLiteral("extensions"));
+ const auto extensionsArray = extensionsValue.toArray();
+ auto extensions = QStringList();
+ std::transform(extensionsArray.constBegin(), extensionsArray.constEnd(),
+ std::back_inserter(extensions),
+ [] (const QJsonValue &extensionValue) { return extensionValue.toString(); });
+ format.setExtensions(extensions);
+
+ const auto vendor = formatObject.value(QStringLiteral("vendor")).toString();
+ format.setVendor(vendor);
+
+ const auto substitutionValue = ruleObject.value(QStringLiteral("substitution"));
+ if (!substitutionValue.isString()) {
+ qWarning() << "Substitution needs to be a string";
+ hasError = true;
+ break;
+ }
+
+ const auto substitution = substitutionValue.toString().toUtf8();
+
+ const auto snippetsValue = ruleObject.value(QStringLiteral("headerSnippets"));
+ const auto snippetsArray = snippetsValue.toArray();
+ auto snippets = QByteArrayList();
+ std::transform(snippetsArray.constBegin(), snippetsArray.constEnd(),
+ std::back_inserter(snippets),
+ [] (const QJsonValue &snippetValue) { return snippetValue.toString().toUtf8(); });
+
+ node.addRule(format, QShaderNode::Rule(substitution, snippets));
+ }
+ }
+
+ m_nodes.insert(property, node);
+ }
+
+ if (hasError) {
+ m_status = Error;
+ m_nodes.clear();
+ } else {
+ m_status = Ready;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernodesloader_p.h b/src/gui/util/qshadernodesloader_p.h
new file mode 100644
index 0000000000..2696e958b6
--- /dev/null
+++ b/src/gui/util/qshadernodesloader_p.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSHADERNODESLOADER_P_H
+#define QSHADERNODESLOADER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#include <QtGui/private/qshadergraph_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIODevice;
+
+class QShaderNodesLoader
+{
+public:
+ enum Status : char {
+ Null,
+ Waiting,
+ Ready,
+ Error
+ };
+
+ Q_GUI_EXPORT QShaderNodesLoader() Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT Status status() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT QHash<QString, QShaderNode> nodes() const Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT QIODevice *device() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setDevice(QIODevice *device) Q_DECL_NOTHROW;
+
+ Q_GUI_EXPORT void load();
+
+private:
+ Status m_status;
+ QIODevice *m_device;
+ QHash<QString, QShaderNode> m_nodes;
+};
+
+Q_DECLARE_TYPEINFO(QShaderNodesLoader, Q_MOVABLE_TYPE);
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QShaderNodesLoader)
+Q_DECLARE_METATYPE(QShaderNodesLoader::Status)
+
+#endif // QSHADERNODESLOADER_P_H
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index fb9dfc9f69..1709012291 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -420,9 +420,9 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
if (buff.size() == 1 && (buff.at(0) == '+' || buff.at(0) == '-'))
return Intermediate;
- bool ok, overflow;
- qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok, &overflow);
- if (overflow || !ok)
+ bool ok;
+ qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok);
+ if (!ok)
return Invalid;
if (entered >= b && entered <= t) {
@@ -447,9 +447,9 @@ void QIntValidator::fixup(QString &input) const
locale().numberOptions())) {
return;
}
- bool ok, overflow;
- qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok, &overflow);
- if (ok && !overflow)
+ bool ok;
+ qlonglong entered = QLocaleData::bytearrayToLongLong(buff.constData(), 10, &ok);
+ if (ok)
input = locale().toString(entered);
}
diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri
index 79c83599b9..cf3cbee48e 100644
--- a/src/gui/util/util.pri
+++ b/src/gui/util/util.pri
@@ -6,11 +6,27 @@ HEADERS += \
util/qvalidator.h \
util/qgridlayoutengine_p.h \
util/qabstractlayoutstyleinfo_p.h \
- util/qlayoutpolicy_p.h
+ util/qlayoutpolicy_p.h \
+ util/qshaderformat_p.h \
+ util/qshadergenerator_p.h \
+ util/qshadergraph_p.h \
+ util/qshadergraphloader_p.h \
+ util/qshaderlanguage_p.h \
+ util/qshadernode_p.h \
+ util/qshadernodeport_p.h \
+ util/qshadernodesloader_p.h
SOURCES += \
util/qdesktopservices.cpp \
util/qvalidator.cpp \
util/qgridlayoutengine.cpp \
util/qabstractlayoutstyleinfo.cpp \
- util/qlayoutpolicy.cpp
+ util/qlayoutpolicy.cpp \
+ util/qshaderformat.cpp \
+ util/qshadergenerator.cpp \
+ util/qshadergraph.cpp \
+ util/qshadergraphloader.cpp \
+ util/qshaderlanguage.cpp \
+ util/qshadernode.cpp \
+ util/qshadernodeport.cpp \
+ util/qshadernodesloader.cpp
diff --git a/src/gui/vulkan/KHRONOS_LICENSE.txt b/src/gui/vulkan/KHRONOS_LICENSE.txt
new file mode 100644
index 0000000000..7f6672d50e
--- /dev/null
+++ b/src/gui/vulkan/KHRONOS_LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright (c) 2015-2017 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Materials.
+
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
diff --git a/src/gui/vulkan/qplatformvulkaninstance.cpp b/src/gui/vulkan/qplatformvulkaninstance.cpp
new file mode 100644
index 0000000000..6201d3ec11
--- /dev/null
+++ b/src/gui/vulkan/qplatformvulkaninstance.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformvulkaninstance.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QPlatformVulkanInstance
+ \since 5.10
+ \internal
+ \preliminary
+ \ingroup qpa
+
+ \brief The QPlatformVulkanInstance class provides an abstraction for Vulkan instances.
+
+ The platform Vulkan instance is responsible for loading a Vulkan library,
+ resolving the basic entry points for creating instances, providing support
+ for creating new or adopting existing VkInstances, and abstracting some
+ WSI-specifics like checking if a given queue family can be used to present
+ using a given window.
+
+ \note platform plugins will typically subclass not this class, but rather
+ QBasicVulkanPlatformInstance.
+
+ \note Vulkan instance creation is split into two phases: a new
+ QPlatformVulkanInstance is expected to load the Vulkan library and do basic
+ initialization, after which the supported layers and extensions can be
+ queried. Everything else is deferred into createOrAdoptInstance().
+*/
+
+class QPlatformVulkanInstancePrivate
+{
+public:
+ QPlatformVulkanInstancePrivate() { }
+};
+
+QPlatformVulkanInstance::QPlatformVulkanInstance()
+ : d_ptr(new QPlatformVulkanInstancePrivate)
+{
+}
+
+QPlatformVulkanInstance::~QPlatformVulkanInstance()
+{
+}
+
+void QPlatformVulkanInstance::presentQueued(QWindow *window)
+{
+ Q_UNUSED(window);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/vulkan/qplatformvulkaninstance.h b/src/gui/vulkan/qplatformvulkaninstance.h
new file mode 100644
index 0000000000..9470e2d0b4
--- /dev/null
+++ b/src/gui/vulkan/qplatformvulkaninstance.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMVULKANINSTANCE_H
+#define QPLATFORMVULKANINSTANCE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is part of the QPA API and is not meant to be used
+// in applications. Usage of this API may make your code
+// source and binary incompatible with future versions of Qt.
+//
+
+#include <QtGui/qtguiglobal.h>
+
+#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+
+#include <qvulkaninstance.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPlatformVulkanInstancePrivate;
+
+class Q_GUI_EXPORT QPlatformVulkanInstance
+{
+ Q_DECLARE_PRIVATE(QPlatformVulkanInstance)
+
+public:
+ QPlatformVulkanInstance();
+ virtual ~QPlatformVulkanInstance();
+
+ virtual QVulkanInfoVector<QVulkanLayer> supportedLayers() const = 0;
+ virtual QVulkanInfoVector<QVulkanExtension> supportedExtensions() const = 0;
+ virtual void createOrAdoptInstance() = 0;
+ virtual bool isValid() const = 0;
+ virtual VkResult errorCode() const = 0;
+ virtual VkInstance vkInstance() const = 0;
+ virtual QByteArrayList enabledLayers() const = 0;
+ virtual QByteArrayList enabledExtensions() const = 0;
+ virtual PFN_vkVoidFunction getInstanceProcAddr(const char *name) = 0;
+ virtual bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) = 0;
+ virtual void presentQueued(QWindow *window);
+
+private:
+ QScopedPointer<QPlatformVulkanInstancePrivate> d_ptr;
+ Q_DISABLE_COPY(QPlatformVulkanInstance)
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(vulkan)
+
+#endif // QPLATFORMVULKANINSTANCE_H
diff --git a/src/gui/vulkan/qt_attribution.json b/src/gui/vulkan/qt_attribution.json
new file mode 100644
index 0000000000..3c09e9f498
--- /dev/null
+++ b/src/gui/vulkan/qt_attribution.json
@@ -0,0 +1,17 @@
+[
+ {
+ "Id": "vulkan-xml-spec",
+ "Name": "Vulkan API Registry",
+ "QDocModule": "qtgui",
+ "Description": "Vulkan XML API Registry.",
+ "QtUsage": "Used to dynamically generate the sources for the QVulkan(Device)Functions classes.",
+ "Path": "vk.xml",
+
+ "Homepage": "https://www.khronos.org/",
+ "Version": "1.0.39",
+ "License": "MIT License",
+ "LicenseId": "MIT",
+ "LicenseFile": "KHRONOS_LICENSE.txt",
+ "Copyright": "Copyright (c) 2015-2017 The Khronos Group Inc."
+ }
+]
diff --git a/src/gui/vulkan/qvulkanfunctions.cpp b/src/gui/vulkan/qvulkanfunctions.cpp
new file mode 100644
index 0000000000..c5f9616d20
--- /dev/null
+++ b/src/gui/vulkan/qvulkanfunctions.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qvulkanfunctions_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVulkanFunctions
+ \since 5.10
+ \ingroup painting-3D
+ \inmodule QtGui
+ \wrapper
+
+ \brief The QVulkanFunctions class provides cross-platform access to the
+ instance level core Vulkan 1.0 API.
+
+ Qt and Qt applications do not link to any Vulkan libraries by default.
+ Instead, all functions are resolved dynamically at run time. Each
+ QVulkanInstance provides a QVulkanFunctions object retrievable via
+ QVulkanInstance::functions(). This does not contain device level functions
+ in order to avoid the potential overhead of an internal dispatching.
+ Instead, functions that rely on a device, or a dispatchable child object of
+ a device, are exposed via QVulkanDeviceFunctions and
+ QVulkanInstance::deviceFunctions(). QVulkanFunctions and
+ QVulkanDeviceFunctions together provides access to the full core Vulkan
+ API, excluding any extensions.
+
+ \note QVulkanFunctions instances cannot be constructed directly.
+
+ The typical usage is the following:
+
+ \code
+ void Window::render()
+ {
+ QVulkanInstance *inst = vulkanInstance();
+ QVulkanFunctions *f = inst->functions();
+ ...
+ VkResult err = f->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf);
+ ...
+ }
+ \endcode
+
+ \note Windowing system interface (WSI) specifics and extensions are
+ excluded. This class only covers core Vulkan commands, with the exception
+ of instance creation, destruction, and function resolving, since such
+ functionality is covered by QVulkanInstance itself.
+
+ To access additional functions, applications can use
+ QVulkanInstance::getInstanceProcAddr() and vkGetDeviceProcAddr().
+ Applications can also decide to link to a Vulkan library directly, as
+ platforms with an appropriate loader will typically export function symbols
+ for the core commands. See
+ \l{https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkGetInstanceProcAddr.html}{the
+ man page for vkGetInstanceProcAddr} for more information.
+
+ \sa QVulkanInstance, QVulkanDeviceFunctions, QWindow::setVulkanInstance(), QWindow::setSurfaceType()
+*/
+
+/*!
+ \class QVulkanDeviceFunctions
+ \since 5.10
+ \ingroup painting-3D
+ \inmodule QtGui
+ \wrapper
+
+ \brief The QVulkanDeviceFunctions class provides cross-platform access to
+ the device level core Vulkan 1.0 API.
+
+ Qt and Qt applications do not link to any Vulkan libraries by default.
+ Instead, all functions are resolved dynamically at run time. Each
+ QVulkanInstance provides a QVulkanFunctions object retrievable via
+ QVulkanInstance::functions(). This does not contain device level functions
+ in order to avoid the potential overhead of an internal dispatching.
+ Instead, functions that rely on a device, or a dispatchable child object of
+ a device, are exposed via QVulkanDeviceFunctions and
+ QVulkanInstance::deviceFunctions(). QVulkanFunctions and
+ QVulkanDeviceFunctions together provides access to the full core Vulkan
+ API, excluding any extensions.
+
+ \note QVulkanDeviceFunctions instances cannot be constructed directly.
+
+ The typical usage is the following:
+
+ \code
+ void Window::render()
+ {
+ QVulkanInstance *inst = vulkanInstance();
+ QVulkanDeviceFunctions *df = inst->deviceFunctions(device);
+ VkResult err = df->vkAllocateCommandBuffers(device, &cmdBufInfo, &cmdBuf);
+ ...
+ }
+ \endcode
+
+ The QVulkanDeviceFunctions object specific to the provided VkDevice is
+ created when QVulkanInstance::deviceFunctions() is first called with the
+ device in question. The object is then cached internally.
+
+ To access additional functions, applications can use
+ QVulkanInstance::getInstanceProcAddr() and vkGetDeviceProcAddr().
+ Applications can also decide to link to a Vulkan library directly, as many
+ implementations export function symbols for the core commands. See
+ \l{https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkGetInstanceProcAddr.html}{the
+ man page for vkGetInstanceProcAddr} for more information.
+
+ \sa QVulkanInstance, QVulkanFunctions, QWindow::setVulkanInstance(), QWindow::setSurfaceType()
+*/
+
+/*
+ Constructs a new QVulkanFunctions for \a inst.
+ \internal
+ */
+QVulkanFunctions::QVulkanFunctions(QVulkanInstance *inst)
+ : d_ptr(new QVulkanFunctionsPrivate(inst))
+{
+}
+
+/*
+ Destructor.
+ */
+QVulkanFunctions::~QVulkanFunctions()
+{
+}
+
+/*
+ Constructs a new QVulkanDeviceFunctions for \a inst and the given \a device.
+ \internal
+ */
+QVulkanDeviceFunctions::QVulkanDeviceFunctions(QVulkanInstance *inst, VkDevice device)
+ : d_ptr(new QVulkanDeviceFunctionsPrivate(inst, device))
+{
+}
+
+/*
+ Destructor.
+ */
+QVulkanDeviceFunctions::~QVulkanDeviceFunctions()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/vulkan/qvulkaninstance.cpp b/src/gui/vulkan/qvulkaninstance.cpp
new file mode 100644
index 0000000000..8f364328d6
--- /dev/null
+++ b/src/gui/vulkan/qvulkaninstance.cpp
@@ -0,0 +1,894 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvulkaninstance.h"
+#include <private/qvulkanfunctions_p.h>
+#include <qpa/qplatformvulkaninstance.h>
+#include <qpa/qplatformintegration.h>
+#include <qpa/qplatformnativeinterface.h>
+#include <QtGui/private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVulkanInstance
+ \since 5.10
+ \inmodule QtGui
+
+ \brief The QVulkanInstance class represents a native Vulkan instance, enabling
+ Vulkan rendering onto a QSurface.
+
+ \l{https://www.khronos.org/vulkan/}{Vulkan} is a cross-platform, explicit
+ graphics and compute API. This class provides support for loading a Vulkan
+ library and creating an \c instance in a cross-platform manner. For an
+ introduction on Vulkan instances, refer
+ \l{https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html#initialization-instances}{to
+ section 3.2 of the specification}.
+
+ \note Platform-specific support for Vulkan instances and windows with
+ Vulkan-capable surfaces is provided by the various platform plugins. Not
+ all of them will support Vulkan, however. When running on such a platform,
+ create() will fail and always return \c false.
+
+ \note Vulkan support may get automatically disabled for a given Qt build due
+ to not having the necessary Vulkan headers available at build time. When
+ this is the case, and the output of \c configure indicates Vulkan support is
+ disabled, the QVulkan* classes will be unavailable.
+
+ \note Some functions changed their signature between the various Vulkan
+ header revisions. When building Qt and only headers with the old,
+ conflicting signatures are present in a system, Vulkan support will get
+ disabled. It is recommended to use headers from Vulkan 1.0.39 or newer.
+
+ \section1 Initialization
+
+ Similarly to QOpenGLContext, any actual Vulkan instance creation happens
+ only when calling create(). This allows using QVulkanInstance as a plain
+ member variable while retaining control over when to perform
+ initialization.
+
+ Querying the supported instance-level layers and extensions is possible by
+ calling supportedLayers() and supportedExtensions(). These ensure the
+ Vulkan library is loaded, and can therefore be called safely before
+ create() as well.
+
+ Instances store per-application Vulkan state and creating a \c VkInstance
+ object initializes the Vulkan library. In practice there will typically be
+ a single instance constructed early on in main(). The object then stays
+ alive until exiting the application.
+
+ Every Vulkan-based QWindow must be associated with a QVulkanInstance by
+ calling QWindow::setVulkanInstance(). Thus a typical application pattern is
+ the following:
+
+ \code
+ int main(int argc, char **argv)
+ {
+ QGuiApplication app(argc, argv);
+
+ QVulkanInstance inst;
+ if (!inst.create())
+ return 1;
+
+ ...
+ window->setVulkanInstance(&inst);
+ window->show();
+
+ return app.exec();
+ }
+ \endcode
+
+ \section1 Configuration
+
+ QVulkanInstance automatically enables the minimum set of extensions it
+ needs on the newly created instance. In practice this means the
+ \c{VK_KHR_*_surface} family of extensions.
+
+ By default Vulkan debug output, for example messages from the validation
+ layers, is routed to qDebug(). This can be disabled by passing the flag
+ \c NoDebugOutputRedirect to setFlags() \e before invoking create().
+
+ To enable additional layers and extensions, provide the list via
+ setLayers() and setExtensions() \e before invoking create(). When a
+ given layer or extension is not reported as available from the instance,
+ the request is ignored. After a successful call to create(), the values
+ returned from functions like layers() and extensions() reflect the actual
+ enabled layers and extensions. When necessary, for example to avoid
+ requesting extensions that conflict and thus would fail the Vulkan instance
+ creation, the list of actually supported layers and extensions can be
+ examined via supportedLayers() and supportedExtensions() before calling
+ create().
+
+ For example, to enable the standard validation layers, one could do the
+ following:
+
+ \code
+ QVulkanInstance inst;
+
+ // Enable validation layer, if supported. Messages go to qDebug by default.
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+
+ bool ok = inst.create();
+ if (!ok)
+ ... // Vulkan not available
+ if (!inst.layers().contains("VK_LAYER_LUNARG_standard_validation"))
+ ... // validation layer not available
+ \endcode
+
+ Or, alternatively, to make decisions before attempting to create a Vulkan
+ instance:
+
+ \code
+ QVulkanInstance inst;
+
+ if (inst.supportedLayers().contains("VK_LAYER_LUNARG_standard_validation"))
+ ...
+
+ bool ok = inst.create();
+ ...
+ \endcode
+
+ \section1 Adopting an Existing Instance
+
+ By default QVulkanInstance creates a new Vulkan instance. When working with
+ external engines and renderers, this may sometimes not be desirable. When
+ there is a \c VkInstance handle already available, call setVkInstance()
+ before invoking create(). This way no additional instances will get
+ created, and QVulkanInstance will not own the handle.
+
+ \note It is up to the component creating the external instance to ensure
+ the necessary extensions are enabled on it. These are: \c{VK_KHR_surface},
+ the WSI-specific \c{VK_KHR_*_surface} that is appropriate for the platform
+ in question, and \c{VK_EXT_debug_report} in case QVulkanInstance's debug
+ output redirection is desired.
+
+ \section1 Accessing Core Vulkan Commands
+
+ To access the \c VkInstance handle the QVulkanInstance wraps, call
+ vkInstance(). To resolve Vulkan functions, call getInstanceProcAddr(). For
+ core Vulkan commands manual resolving is not necessary as they are provided
+ via the QVulkanFunctions and QVulkanDeviceFunctions objects accessible via
+ functions() and deviceFunctions().
+
+ \note QVulkanFunctions and QVulkanDeviceFunctions are generated from the
+ Vulkan API XML specifications when building the Qt libraries. Therefore no
+ documentation is provided for them. They contain the Vulkan 1.0 functions
+ with the same signatures as described in the
+ \l{https://www.khronos.org/registry/vulkan/specs/1.0/html/}{Vulkan API
+ documentation}.
+
+ \section1 Getting a Native Vulkan Surface for a Window
+
+ The two common windowing system specific operations are getting a surface
+ (a \c{VkSurfaceKHR} handle) for a window, and querying if a given queue
+ family supports presenting to a given surface. To avoid WSI-specific bits
+ in the applications, these are abstracted by QVulkanInstance and the
+ underlying QPA layers.
+
+ To create a Vulkan surface for a window, or retrieve an existing one,
+ call surfaceForWindow(). Most platforms will only create the surface via
+ \c{VK_KHR_*_surface} when first calling surfaceForWindow(), but there may be
+ platform-specific variations in the internal behavior. Once created,
+ subsequent calls to surfaceForWindow() just return the same handle. This
+ fits the structure of typical Vulkan-enabled QWindow subclasses well.
+
+ To query if a given queue family within a physical device can be used to
+ perform presentation to a given surface, call supportsPresent(). This
+ encapsulates both the generic \c vkGetPhysicalDeviceSurfaceSupportKHR and
+ the WSI-specific \c{vkGetPhysicalDevice*PresentationSupportKHR} checks.
+
+ \section1 Troubleshooting
+
+ Besides returning \c false from create() or \c 0 from surfaceForWindow(),
+ critical errors will also get printed to the debug output via qWarning().
+ Additional logging can be requested by enabling debug output for the
+ logging category \c{qt.vulkan}. The actual Vulkan error code from instance
+ creation can be retrieved by calling errorCode() after a failing create().
+
+ In some special cases it may be necessary to override the Vulkan
+ library name. This can be achieved by setting the \c{QT_VULKAN_LIB}
+ environment variable.
+
+ \section1 Example
+
+ The following is the basic outline of creating a Vulkan-capable QWindow:
+
+ \code
+ class VulkanWindow : public QWindow
+ {
+ public:
+ VulkanWindow() {
+ setSurfaceType(VulkanSurface);
+ }
+
+ void exposeEvent(QExposeEvent *) {
+ if (isExposed()) {
+ if (!m_initialized) {
+ m_initialized = true;
+ // initialize device, swapchain, etc.
+ QVulkanInstance *inst = vulkanInstance();
+ QVulkanFunctions *f = inst->functions();
+ uint32_t devCount = 0;
+ f->vkEnumeratePhysicalDevices(inst->vkInstance(), &devCount, nullptr);
+ ...
+ // build the first frame
+ render();
+ }
+ }
+ }
+
+ bool event(QEvent *e) {
+ if (e->type == QEvent::UpdateRequest)
+ render();
+ return QWindow::event(e);
+ }
+
+ void render() {
+ ...
+ requestUpdate(); // render continuously
+ }
+
+ private:
+ bool m_initialized = false;
+ };
+
+ int main(int argc, char **argv)
+ {
+ QGuiApplication app(argc, argv);
+
+ QVulkanInstance inst;
+ if (!inst.create()) {
+ qWarning("Vulkan not available");
+ return 1;
+ }
+
+ VulkanWindow window;
+ window.showMaximized();
+
+ return app.exec();
+
+ }
+ \endcode
+
+ \note In addition to expose, a well-behaving window implementation will
+ also have to take care of additional events like resize and
+ QPlatformSurfaceEvent in order to ensure proper management of the
+ swap chain. Additionally, some platforms may require releasing resources
+ when not being exposed anymore.
+
+ \section1 Using C++ Bindings for Vulkan
+
+ Combining Qt's Vulkan enablers with a C++ Vulkan wrapper, for example
+ \l{https://github.com/KhronosGroup/Vulkan-Hpp}{Vulkan-Hpp}, is possible as
+ well. The pre-requisite here is that the C++ layer must be able to adopt
+ native handles (VkInstance, VkSurfaceKHR) in its classes without taking
+ ownership (since the ownership stays with QVulkanInstance and QWindow).
+ Consider also the following:
+
+ \list
+
+ \li Some wrappers require exception support to be enabled. Qt does not use
+ exceptions. To enable exceptions for the application, add \c{CONFIG += exceptions}
+ to the \c{.pro} file.
+
+ \li Some wrappers call Vulkan functions directly, assuming \c{vulkan.h}
+ provides prototypes and the application links to a Vulkan library exporting
+ all necessary symbols. Qt may not directly link to a Vulkan library.
+ Therefore, on some platforms it may be necessary to add
+ \c{LIBS += -lvulkan} or similar in the application's \c{.pro} file.
+
+ \li The headers for the QVulkan classes may include \c{vulkan.h} with
+ \c{VK_NO_PROTOTYPES} enabled. This can cause issues in C++ wrapper headers
+ that rely on the prototypes. Hence in application code it may be
+ necessary to include \c{vulkan.hpp} or similar before any of the QVulkan
+ headers.
+
+ \endlist
+
+ \sa QVulkanFunctions, QSurface::SurfaceType
+*/
+
+/*!
+ \enum QVulkanInstance::Flag
+ \since 5.10
+
+ This enum describes the flags that can be passed to setFlags(). These control
+ the behavior of create().
+
+ \value NoDebugOutputRedirect Disables Vulkan debug output (\c{VK_EXT_debug_report}) redirection to qDebug.
+*/
+
+class QVulkanInstancePrivate
+{
+public:
+ QVulkanInstancePrivate(QVulkanInstance *q)
+ : q_ptr(q),
+ vkInst(VK_NULL_HANDLE),
+ flags(0),
+ errorCode(VK_SUCCESS)
+ { }
+ ~QVulkanInstancePrivate() { reset(); }
+
+ bool ensureVulkan();
+ void reset();
+
+ QVulkanInstance *q_ptr;
+ QScopedPointer<QPlatformVulkanInstance> platformInst;
+ VkInstance vkInst;
+ QVulkanInstance::Flags flags;
+ QByteArrayList layers;
+ QByteArrayList extensions;
+ QVersionNumber apiVersion;
+ VkResult errorCode;
+ QScopedPointer<QVulkanFunctions> funcs;
+ QHash<VkDevice, QVulkanDeviceFunctions *> deviceFuncs;
+};
+
+bool QVulkanInstancePrivate::ensureVulkan()
+{
+ if (!platformInst) {
+ platformInst.reset(QGuiApplicationPrivate::platformIntegration()->createPlatformVulkanInstance(q_ptr));
+ if (!platformInst) {
+ qWarning("QVulkanInstance: Failed to initialize Vulkan");
+ return false;
+ }
+ }
+ return true;
+}
+
+void QVulkanInstancePrivate::reset()
+{
+ qDeleteAll(deviceFuncs);
+ deviceFuncs.clear();
+ funcs.reset();
+ platformInst.reset();
+ vkInst = VK_NULL_HANDLE;
+ errorCode = VK_SUCCESS;
+}
+
+/*!
+ Constructs a new instance.
+
+ \note No Vulkan initialization is performed in the constructor.
+ */
+QVulkanInstance::QVulkanInstance()
+ : d_ptr(new QVulkanInstancePrivate(this))
+{
+}
+
+/*!
+ Destructor.
+
+ \note current() will return \c nullptr once the instance is destroyed.
+ */
+QVulkanInstance::~QVulkanInstance()
+{
+ destroy();
+}
+
+/*!
+ \class QVulkanLayer
+ \brief Represents information about a Vulkan layer.
+ */
+
+/*!
+ \variable QVulkanLayer::name
+ \brief The name of the layer.
+ */
+
+/*!
+ \variable QVulkanLayer::version
+ \brief The version of the layer. This is an integer, increasing with each backward
+ compatible change.
+ */
+
+/*!
+ \variable QVulkanLayer::specVersion
+ \brief The Vulkan version the layer was written against.
+ */
+
+/*!
+ \variable QVulkanLayer::description
+ \brief The description of the layer.
+ */
+
+/*!
+ \fn bool operator==(const QVulkanLayer &lhs, const QVulkanLayer &rhs)
+ \since 5.10
+ \relates QVulkanLayer
+
+ Returns \c true if Vulkan layers \a lhs and \a rhs have
+ the same name, version, and spec version.
+*/
+
+/*!
+ \fn bool operator!=(const QVulkanLayer &lhs, const QVulkanLayer &rhs)
+ \since 5.10
+ \relates QVulkanLayer
+
+ Returns \c true if Vulkan layers \a lhs and \a rhs have
+ different name, version, or spec version.
+*/
+
+/*!
+ \fn uint qHash(const QVulkanLayer &key, uint seed)
+ \since 5.10
+ \relates QVulkanLayer
+
+ Returns the hash value for the \a key, using \a seed to seed the
+ calculation.
+*/
+
+/*!
+ \class QVulkanExtension
+ \brief Represents information about a Vulkan extension.
+ */
+
+/*!
+ \variable QVulkanExtension::name
+ \brief The name of the extension.
+ */
+
+/*!
+ \variable QVulkanExtension::version
+ \brief The version of the extension. This is an integer, increasing with each backward
+ compatible change.
+ */
+
+/*!
+ \fn bool operator==(const QVulkanExtension &lhs, const QVulkanExtension &rhs)
+ \since 5.10
+ \relates QVulkanExtension
+
+ Returns \c true if Vulkan extensions \a lhs and \a rhs are have the
+ same name and version.
+*/
+
+/*!
+ \fn bool operator!=(const QVulkanExtension &lhs, const QVulkanExtension &rhs)
+ \since 5.10
+ \relates QVulkanExtension
+
+ Returns \c true if Vulkan extensions \a lhs and \a rhs are have different
+ name or version.
+*/
+
+/*!
+ \fn uint qHash(const QVulkanExtension &key, uint seed)
+ \since 5.10
+ \relates QVulkanExtension
+
+ Returns the hash value for the \a key, using \a seed to seed the
+ calculation.
+*/
+
+/*!
+ \class QVulkanInfoVector
+ \brief A specialized QVector for QVulkanLayer and QVulkanExtension.
+ */
+
+/*!
+ \fn bool QVulkanInfoVector::contains(const QByteArray &name) const
+
+ \return true if the vector contains a layer or extension with the given \a name.
+ */
+
+/*!
+ \fn bool QVulkanInfoVector::contains(const QByteArray &name, int minVersion) const
+
+ \return true if the vector contains a layer or extension with the given
+ \a name and a version same as or newer than \a minVersion.
+ */
+
+/*!
+ \return the list of supported instance-level layers.
+
+ \note This function can be called before create().
+ */
+QVulkanInfoVector<QVulkanLayer> QVulkanInstance::supportedLayers()
+{
+ return d_ptr->ensureVulkan() ? d_ptr->platformInst->supportedLayers() : QVulkanInfoVector<QVulkanLayer>();
+}
+
+/*!
+ \return the list of supported instance-level extensions.
+
+ \note This function can be called before create().
+ */
+QVulkanInfoVector<QVulkanExtension> QVulkanInstance::supportedExtensions()
+{
+ return d_ptr->ensureVulkan() ? d_ptr->platformInst->supportedExtensions() : QVulkanInfoVector<QVulkanExtension>();
+}
+
+/*!
+ Makes QVulkanInstance adopt an existing VkInstance handle instead of
+ creating a new one.
+
+ \note \a existingVkInstance must have at least \c{VK_KHR_surface} and the
+ appropriate WSI-specific \c{VK_KHR_*_surface} extensions enabled. To ensure
+ debug output redirection is functional, \c{VK_EXT_debug_report} is needed as
+ well.
+
+ \note This function can only be called before create() and has no effect if
+ called afterwards.
+ */
+void QVulkanInstance::setVkInstance(VkInstance existingVkInstance)
+{
+ if (isValid()) {
+ qWarning("QVulkanInstance already created; setVkInstance() has no effect");
+ return;
+ }
+
+ d_ptr->vkInst = existingVkInstance;
+}
+
+/*!
+ Configures the behavior of create() based on the provided \a flags.
+
+ \note This function can only be called before create() and has no effect if
+ called afterwards.
+ */
+void QVulkanInstance::setFlags(Flags flags)
+{
+ if (isValid()) {
+ qWarning("QVulkanInstance already created; setFlags() has no effect");
+ return;
+ }
+
+ d_ptr->flags = flags;
+}
+
+/*!
+ Specifies the list of instance \a layers to enable. It is safe to specify
+ unsupported layers as well because these get ignored when not supported at
+ run time.
+
+ \note This function can only be called before create() and has no effect if
+ called afterwards.
+ */
+void QVulkanInstance::setLayers(const QByteArrayList &layers)
+{
+ if (isValid()) {
+ qWarning("QVulkanInstance already created; setLayers() has no effect");
+ return;
+ }
+
+ d_ptr->layers = layers;
+}
+
+/*!
+ Specifies the list of additional instance \a extensions to enable. It is
+ safe to specify unsupported extensions as well because these get ignored
+ when not supported at run time. The surface-related extensions required by
+ Qt will always be added automatically, no need to include them in this
+ list.
+
+ \note This function can only be called before create() and has no effect if
+ called afterwards.
+ */
+void QVulkanInstance::setExtensions(const QByteArrayList &extensions)
+{
+ if (isValid()) {
+ qWarning("QVulkanInstance already created; setExtensions() has no effect");
+ return;
+ }
+
+ d_ptr->extensions = extensions;
+}
+
+/*!
+ Specifies the Vulkan API against which the application expects to run.
+
+ By default no \a vulkanVersion is specified, and so no version check is performed
+ during Vulkan instance creation.
+
+ \note This function can only be called before create() and has no effect if
+ called afterwards.
+ */
+void QVulkanInstance::setApiVersion(const QVersionNumber &vulkanVersion)
+{
+ if (isValid()) {
+ qWarning("QVulkanInstance already created; setApiVersion() has no effect");
+ return;
+ }
+
+ d_ptr->apiVersion = vulkanVersion;
+}
+
+/*!
+ Initializes the Vulkan library and creates a new or adopts and existing
+ Vulkan instance.
+
+ \return true if successful, false on error or when Vulkan is not supported.
+
+ When successful, the pointer to this QVulkanInstance is retrievable via the
+ static function current().
+
+ The Vulkan instance and library is available as long as this
+ QVulkanInstance exists, or until destroy() is called.
+ */
+bool QVulkanInstance::create()
+{
+ if (isValid())
+ destroy();
+
+ if (!d_ptr->ensureVulkan())
+ return false;
+
+ d_ptr->platformInst->createOrAdoptInstance();
+
+ if (d_ptr->platformInst->isValid()) {
+ d_ptr->vkInst = d_ptr->platformInst->vkInstance();
+ d_ptr->layers = d_ptr->platformInst->enabledLayers();
+ d_ptr->extensions = d_ptr->platformInst->enabledExtensions();
+ d_ptr->errorCode = VK_SUCCESS;
+ d_ptr->funcs.reset(new QVulkanFunctions(this));
+ return true;
+ }
+
+ qWarning("Failed to create platform Vulkan instance");
+ if (d_ptr->platformInst) {
+ d_ptr->errorCode = d_ptr->platformInst->errorCode();
+ d_ptr->platformInst.reset();
+ } else {
+ d_ptr->errorCode = VK_NOT_READY;
+ }
+ return false;
+}
+
+/*!
+ Destroys the underlying platform instance, thus destroying the VkInstance
+ (when owned). The QVulkanInstance object is still reusable by calling
+ create() again.
+ */
+void QVulkanInstance::destroy()
+{
+ d_ptr->reset();
+}
+
+/*!
+ \return true if create() was successful and the instance is valid.
+ */
+bool QVulkanInstance::isValid() const
+{
+ return d_ptr->platformInst && d_ptr->platformInst->isValid();
+}
+
+/*!
+ \return the Vulkan error code after an unsuccessful create(), \c VK_SUCCESS otherwise.
+
+ The value is typically the return value from vkCreateInstance() (when
+ creating a new Vulkan instance instead of adopting an existing one), but
+ may also be \c VK_NOT_READY if the platform plugin does not support Vulkan.
+ */
+VkResult QVulkanInstance::errorCode() const
+{
+ return d_ptr->errorCode;
+}
+
+/*!
+ \return the VkInstance handle this QVulkanInstance wraps, or \c null if
+ create() has not yet been successfully called and no existing instance has
+ been provided via setVkInstance().
+ */
+VkInstance QVulkanInstance::vkInstance() const
+{
+ return d_ptr->vkInst;
+}
+
+/*!
+ \return the requested flags.
+ */
+QVulkanInstance::Flags QVulkanInstance::flags() const
+{
+ return d_ptr->flags;
+}
+
+/*!
+ \return the enabled instance layers, if create() was called and was successful. The
+ requested layers otherwise.
+ */
+QByteArrayList QVulkanInstance::layers() const
+{
+ return d_ptr->layers;
+}
+
+/*!
+ \return the enabled instance extensions, if create() was called and was
+ successful. The requested extensions otherwise.
+ */
+QByteArrayList QVulkanInstance::extensions() const
+{
+ return d_ptr->extensions;
+}
+
+/*!
+ \return the requested Vulkan API version against which the application
+ expects to run, or a null version number if setApiVersion() was not called
+ before create().
+ */
+QVersionNumber QVulkanInstance::apiVersion() const
+{
+ return d_ptr->apiVersion;
+}
+
+/*!
+ Resolves the Vulkan function with the given \a name.
+
+ For core Vulkan commands prefer using the function wrappers retrievable from
+ functions() and deviceFunctions() instead.
+ */
+PFN_vkVoidFunction QVulkanInstance::getInstanceProcAddr(const char *name)
+{
+ // The return value is PFN_vkVoidFunction instead of QFunctionPointer or
+ // similar because on some platforms honoring VKAPI_PTR is important.
+ return d_ptr->platformInst->getInstanceProcAddr(name);
+}
+
+/*!
+ \return the platform Vulkan instance corresponding to this QVulkanInstance.
+
+ \internal
+ */
+QPlatformVulkanInstance *QVulkanInstance::handle() const
+{
+ return d_ptr->platformInst.data();
+}
+
+/*!
+ \return the corresponding QVulkanFunctions object that exposes the core
+ Vulkan command set, excluding device level functions, and is guaranteed to
+ be functional cross-platform.
+
+ \note The returned object is owned and managed by the QVulkanInstance. Do
+ not destroy or alter it.
+
+ \sa deviceFunctions()
+ */
+QVulkanFunctions *QVulkanInstance::functions() const
+{
+ return d_ptr->funcs.data();
+}
+
+/*!
+ \return the QVulkanDeviceFunctions object that exposes the device level
+ core Vulkan command set and is guaranteed to be functional cross-platform.
+
+ \note The Vulkan functions in the returned object must only be called with
+ \a device or a child object (VkQueue, VkCommandBuffer) of \a device as
+ their first parameter. This is because these functions are resolved via
+ \l{https://www.khronos.org/registry/vulkan/specs/1.0/man/html/vkGetDeviceProcAddr.html}{vkGetDeviceProcAddr}
+ in order to avoid the potential overhead of internal dispatching.
+
+ \note The returned object is owned and managed by the QVulkanInstance. Do
+ not destroy or alter it.
+
+ \note The object is cached so calling this function with the same \a device
+ again is a cheap operation. However, when the device gets destroyed, it is up
+ to the application to notify the QVulkanInstance by calling
+ resetDeviceFunctions().
+
+ \sa functions(), resetDeviceFunctions()
+ */
+QVulkanDeviceFunctions *QVulkanInstance::deviceFunctions(VkDevice device)
+{
+ QVulkanDeviceFunctions *&f(d_ptr->deviceFuncs[device]);
+ if (!f)
+ f = new QVulkanDeviceFunctions(this, device);
+ return f;
+}
+
+/*!
+ Invalidates and destroys the QVulkanDeviceFunctions object for the given
+ \a device.
+
+ This function must be called when a VkDevice, for which deviceFunctions()
+ was called, gets destroyed while the application intends to continue
+ running, possibly creating a new logical Vulkan device later on.
+
+ There is no need to call this before destroying the QVulkanInstance since
+ clean up is then performed automatically.
+
+ \sa deviceFunctions()
+ */
+void QVulkanInstance::resetDeviceFunctions(VkDevice device)
+{
+ QVulkanDeviceFunctions *&f(d_ptr->deviceFuncs[device]);
+ delete f;
+ f = nullptr;
+}
+
+/*!
+ Creates or retrieves the already existing \c{VkSurfaceKHR} handle for the
+ given \a window.
+
+ \return the Vulkan surface handle or 0 when failed.
+ */
+VkSurfaceKHR QVulkanInstance::surfaceForWindow(QWindow *window)
+{
+ QPlatformNativeInterface *nativeInterface = qGuiApp->platformNativeInterface();
+ // VkSurfaceKHR is non-dispatchable and maps to a pointer on x64 and a uint64 on x86.
+ // Therefore a pointer is returned from the platform plugin, not the value itself.
+ void *p = nativeInterface->nativeResourceForWindow(QByteArrayLiteral("vkSurface"), window);
+ return p ? *static_cast<VkSurfaceKHR *>(p) : 0;
+}
+
+/*!
+ \return true if the queue family with \a queueFamilyIndex within the
+ \a physicalDevice supports presenting to \a window.
+
+ Call this function when examining the queues of a given Vulkan device, in
+ order to decide which queue can be used for performing presentation.
+ */
+bool QVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window)
+{
+ return d_ptr->platformInst->supportsPresent(physicalDevice, queueFamilyIndex, window);
+}
+
+/*!
+ This function should be called by the application's renderer after queuing
+ a present operation for \a window.
+
+ While on some platforms this will be a no-op, some may perform windowing
+ system dependent synchronization. For example, on X11 this will update
+ \c{_NET_WM_SYNC_REQUEST_COUNTER}.
+ */
+void QVulkanInstance::presentQueued(QWindow *window)
+{
+ d_ptr->platformInst->presentQueued(window);
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug dbg, const QVulkanLayer &layer)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QVulkanLayer(" << layer.name << " " << layer.version
+ << " " << layer.specVersion << " " << layer.description << ")";
+ return dbg;
+}
+
+QDebug operator<<(QDebug dbg, const QVulkanExtension &extension)
+{
+ QDebugStateSaver saver(dbg);
+ dbg.nospace() << "QVulkanExtension(" << extension.name << " " << extension.version << ")";
+ return dbg;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/vulkan/qvulkaninstance.h b/src/gui/vulkan/qvulkaninstance.h
new file mode 100644
index 0000000000..ada297be43
--- /dev/null
+++ b/src/gui/vulkan/qvulkaninstance.h
@@ -0,0 +1,198 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVULKANINSTANCE_H
+#define QVULKANINSTANCE_H
+
+#include <QtGui/qtguiglobal.h>
+
+#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+
+#ifndef VK_NO_PROTOTYPES
+#define VK_NO_PROTOTYPES
+#endif
+#ifndef Q_CLANG_QDOC
+#include <vulkan/vulkan.h>
+#else
+typedef void* PFN_vkVoidFunction;
+typedef unsigned long VkSurfaceKHR;
+typedef unsigned long VkImage;
+typedef unsigned long VkImageView;
+#endif
+
+#include <QtCore/qhashfunctions.h>
+#include <QtCore/qscopedpointer.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qbytearraylist.h>
+#include <QtCore/qversionnumber.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVulkanInstancePrivate;
+class QPlatformVulkanInstance;
+class QVulkanFunctions;
+class QVulkanDeviceFunctions;
+class QWindow;
+
+struct QVulkanLayer
+{
+ QByteArray name;
+ uint32_t version;
+ QVersionNumber specVersion;
+ QByteArray description;
+};
+Q_DECLARE_TYPEINFO(QVulkanLayer, Q_MOVABLE_TYPE);
+
+inline bool operator==(const QVulkanLayer &lhs, const QVulkanLayer &rhs) Q_DECL_NOTHROW
+{
+ return lhs.name == rhs.name && lhs.version == rhs.version && lhs.specVersion == rhs.specVersion;
+}
+inline bool operator!=(const QVulkanLayer &lhs, const QVulkanLayer &rhs) Q_DECL_NOTHROW
+{ return !(lhs == rhs); }
+
+inline uint qHash(const QVulkanLayer &key, uint seed = 0) Q_DECL_NOTHROW
+{
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, key.name);
+ seed = hash(seed, key.version);
+ seed = hash(seed, key.specVersion);
+ return seed;
+}
+
+struct QVulkanExtension
+{
+ QByteArray name;
+ uint32_t version;
+};
+Q_DECLARE_TYPEINFO(QVulkanExtension, Q_MOVABLE_TYPE);
+
+inline bool operator==(const QVulkanExtension &lhs, const QVulkanExtension &rhs) Q_DECL_NOTHROW
+{
+ return lhs.name == rhs.name && lhs.version == rhs.version;
+}
+inline bool operator!=(const QVulkanExtension &lhs, const QVulkanExtension &rhs) Q_DECL_NOTHROW
+{ return !(lhs == rhs); }
+
+inline uint qHash(const QVulkanExtension &key, uint seed = 0) Q_DECL_NOTHROW
+{
+ QtPrivate::QHashCombine hash;
+ seed = hash(seed, key.name);
+ seed = hash(seed, key.version);
+ return seed;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QVulkanLayer &);
+Q_GUI_EXPORT QDebug operator<<(QDebug, const QVulkanExtension &);
+#endif
+
+template<typename T>
+class QVulkanInfoVector : public QVector<T>
+{
+public:
+ bool contains(const QByteArray &name) const {
+ return std::any_of(this->cbegin(), this->cend(), [&](const T &entry) {
+ return entry.name == name; });
+ }
+ bool contains(const QByteArray &name, int minVersion) const {
+ return std::any_of(this->cbegin(), this->cend(), [&](const T &entry) {
+ return entry.name == name && entry.version >= minVersion; });
+ }
+};
+
+class Q_GUI_EXPORT QVulkanInstance
+{
+public:
+ QVulkanInstance();
+ ~QVulkanInstance();
+
+ enum Flag {
+ NoDebugOutputRedirect = 0x01
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ QVulkanInfoVector<QVulkanLayer> supportedLayers();
+ QVulkanInfoVector<QVulkanExtension> supportedExtensions();
+
+ void setVkInstance(VkInstance existingVkInstance);
+
+ void setFlags(Flags flags);
+ void setLayers(const QByteArrayList &layers);
+ void setExtensions(const QByteArrayList &extensions);
+ void setApiVersion(const QVersionNumber &vulkanVersion);
+
+ bool create();
+ void destroy();
+ bool isValid() const;
+ VkResult errorCode() const;
+
+ VkInstance vkInstance() const;
+
+ Flags flags() const;
+ QByteArrayList layers() const;
+ QByteArrayList extensions() const;
+ QVersionNumber apiVersion() const;
+
+ PFN_vkVoidFunction getInstanceProcAddr(const char *name);
+
+ QPlatformVulkanInstance *handle() const;
+
+ QVulkanFunctions *functions() const;
+ QVulkanDeviceFunctions *deviceFunctions(VkDevice device);
+ void resetDeviceFunctions(VkDevice device);
+
+ static VkSurfaceKHR surfaceForWindow(QWindow *window);
+
+ bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window);
+
+ void presentQueued(QWindow *window);
+
+private:
+ QScopedPointer<QVulkanInstancePrivate> d_ptr;
+ Q_DISABLE_COPY(QVulkanInstance)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QVulkanInstance::Flags)
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(vulkan)
+
+#endif // QVULKANINSTANCE_H
diff --git a/src/gui/vulkan/qvulkanwindow.cpp b/src/gui/vulkan/qvulkanwindow.cpp
new file mode 100644
index 0000000000..bc82f5df08
--- /dev/null
+++ b/src/gui/vulkan/qvulkanwindow.cpp
@@ -0,0 +1,2720 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvulkanwindow_p.h"
+#include "qvulkanfunctions.h"
+#include <QLoggingCategory>
+#include <QTimer>
+#include <QThread>
+#include <QCoreApplication>
+#include <qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+/*!
+ \class QVulkanWindow
+ \inmodule QtGui
+ \since 5.10
+ \brief The QVulkanWindow class is a convenience subclass of QWindow to perform Vulkan rendering.
+
+ QVulkanWindow is a Vulkan-capable QWindow that manages a Vulkan device, a
+ graphics queue, a command pool and buffer, a depth-stencil image and a
+ double-buffered FIFO swapchain, while taking care of correct behavior when it
+ comes to events like resize, special situations like not having a device
+ queue supporting both graphics and presentation, device lost scenarios, and
+ additional functionality like reading the rendered content back. Conceptually
+ it is the counterpart of QOpenGLWindow in the Vulkan world.
+
+ \note QVulkanWindow does not always eliminate the need to implement a fully
+ custom QWindow subclass as it will not necessarily be sufficient in advanced
+ use cases.
+
+ QVulkanWindow can be embedded into QWidget-based user interfaces via
+ QWidget::createWindowContainer(). This approach has a number of limitations,
+ however. Make sure to study the
+ \l{QWidget::createWindowContainer()}{documentation} first.
+
+ A typical application using QVulkanWindow may look like the following:
+
+ \code
+ class VulkanRenderer : public QVulkanWindowRenderer
+ {
+ public:
+ VulkanRenderer(QVulkanWindow *w) : m_window(w) { }
+
+ void initResources() override
+ {
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(m_window->device());
+ ...
+ }
+ void initSwapChainResources() override { ... }
+ void releaseSwapChainResources() override { ... }
+ void releaseResources() override { ... }
+
+ void startNextFrame() override
+ {
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ ...
+ m_devFuncs->vkCmdBeginRenderPass(...);
+ ...
+ m_window->frameReady();
+ }
+
+ private:
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+ };
+
+ class VulkanWindow : public QVulkanWindow
+ {
+ public:
+ QVulkanWindowRenderer *createRenderer() override {
+ return new VulkanRenderer(this);
+ }
+ };
+
+ int main(int argc, char *argv[])
+ {
+ QGuiApplication app(argc, argv);
+
+ QVulkanInstance inst;
+ // enable the standard validation layers, when available
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+ if (!inst.create())
+ qFatal("Failed to create Vulkan instance: %d", inst.errorCode());
+
+ VulkanWindow w;
+ w.setVulkanInstance(&inst);
+ w.showMaximized();
+
+ return app.exec();
+ }
+ \endcode
+
+ As it can be seen in the example, the main patterns in QVulkanWindow usage are:
+
+ \list
+
+ \li The QVulkanInstance is associated via QWindow::setVulkanInstance(). It is
+ then retrievable via QWindow::vulkanInstance() from everywhere, on any
+ thread.
+
+ \li Similarly to QVulkanInstance, device extensions can be queried via
+ supportedDeviceExtensions() before the actual initialization. Requesting an
+ extension to be enabled is done via setDeviceExtensions(). Such calls must be
+ made before the window becomes visible, that is, before calling show() or
+ similar functions. Unsupported extension requests are gracefully ignored.
+
+ \li The renderer is implemented in a QVulkanWindowRenderer subclass, an
+ instance of which is created in the createRenderer() factory function.
+
+ \li The core Vulkan commands are exposed via the QVulkanFunctions object,
+ retrievable by calling QVulkanInstance::functions(). Device level functions
+ are available after creating a VkDevice by calling
+ QVulkanInstance::deviceFunctions().
+
+ \li The building of the draw calls for the next frame happens in
+ QVulkanWindowRenderer::startNextFrame(). The implementation is expected to
+ add commands to the command buffer returned from currentCommandBuffer().
+ Returning from the function does not indicate that the commands are ready for
+ submission. Rather, an explicit call to frameReady() is required. This allows
+ asynchronous generation of commands, possibly on multiple threads. Simple
+ implementations will simply call frameReady() at the end of their
+ QVulkanWindowRenderer::startNextFrame().
+
+ \li The basic Vulkan resources (physical device, graphics queue, a command
+ pool, the window's main command buffer, image formats, etc.) are exposed on
+ the QVulkanWindow via lightweight getter functions. Some of these are for
+ convenience only, and applications are always free to query, create and
+ manage additional resources directly via the Vulkan API.
+
+ \li The renderer lives in the gui/main thread, like the window itself. This
+ thread is then throttled to the presentation rate, similarly to how OpenGL
+ with a swap interval of 1 would behave. However, the renderer implementation
+ is free to utilize multiple threads in any way it sees fit. The accessors
+ like vulkanInstance(), currentCommandBuffer(), etc. can be called from any
+ thread. The submission of the main command buffer, the queueing of present,
+ and the building of the next frame do not start until frameReady() is
+ invoked on the gui/main thread.
+
+ \li When the window is made visible, the content is updated automatically.
+ Further updates can be requested by calling QWindow::requestUpdate(). To
+ render continuously, call requestUpdate() after frameReady().
+
+ \endlist
+
+ For troubleshooting, enable the logging category \c{qt.vulkan}. Critical
+ errors are printed via qWarning() automatically.
+
+ \section1 Coordinate system differences between OpenGL and Vulkan
+
+ There are two notable differences to be aware of: First, with Vulkan Y points
+ down the screen in clip space, while OpenGL uses an upwards pointing Y axis.
+ Second, the standard OpenGL projection matrix assume a near and far plane
+ values of -1 and 1, while Vulkan prefers 0 and 1.
+
+ In order to help applications migrate from OpenGL-based code without having
+ to flip Y coordinates in the vertex data, and to allow using QMatrix4x4
+ functions like QMatrix4x4::perspective() while keeping the Vulkan viewport's
+ minDepth and maxDepth set to 0 and 1, QVulkanWindow provides a correction
+ matrix retrievable by calling clipCorrectionMatrix().
+
+ \section1 Multisampling
+
+ While disabled by default, multisample antialiasing is fully supported by
+ QVulkanWindow. Additional color buffers and resolving into the swapchain's
+ non-multisample buffers are all managed automatically.
+
+ To query the supported sample counts, call supportedSampleCounts(). When the
+ returned set contains 4, 8, ..., passing one of those values to setSampleCount()
+ requests multisample rendering.
+
+ \note unlike QSurfaceFormat::setSamples(), the list of supported sample
+ counts are exposed to the applications in advance and there is no automatic
+ falling back to lower sample counts in setSampleCount(). If the requested value
+ is not supported, a warning is shown and a no multisampling will be used.
+
+ \section1 Reading images back
+
+ When supportsGrab() returns true, QVulkanWindow can perform readbacks from
+ the color buffer into a QImage. grab() is a slow and inefficient operation,
+ so frequent usage should be avoided. It is nonetheless valuable since it
+ allows applications to take screenshots, or tools and tests to process and
+ verify the output of the GPU rendering.
+
+ \section1 sRGB support
+
+ While many applications will be fine with the default behavior of
+ QVulkanWindow when it comes to swapchain image formats,
+ setPreferredColorFormats() allows requesting a pre-defined format. This is
+ useful most notably when working in the sRGB color space. Passing a format
+ like \c{VK_FORMAT_B8G8R8A8_SRGB} results in choosing an sRGB format, when
+ available.
+
+ \section1 Validation layers
+
+ During application development it can be extremely valuable to have the
+ Vulkan validation layers enabled. As shown in the example code above, calling
+ QVulkanInstance::setLayers() on the QVulkanInstance before
+ QVulkanInstance::create() enables validation, assuming the Vulkan driver
+ stack in the system contains the necessary layers.
+
+ \note Be aware of platform-specific differences. On desktop platforms
+ installing the \l{https://www.lunarg.com/vulkan-sdk/}{Vulkan SDK} is
+ typically sufficient. However, Android for example requires deploying
+ additional shared libraries together with the application, and also mandates
+ a different list of validation layer names. See
+ \l{https://developer.android.com/ndk/guides/graphics/validation-layer.html}{the
+ Android Vulkan development pages} for more information.
+
+ \note QVulkanWindow does not expose device layers since this functionality
+ has been deprecated since version 1.0.13 of the Vulkan API.
+
+ \sa QVulkanInstance, QWindow
+ */
+
+/*!
+ \class QVulkanWindowRenderer
+ \inmodule QtGui
+ \since 5.10
+
+ \brief The QVulkanWindowRenderer class is used to implement the
+ application-specific rendering logic for a QVulkanWindow.
+
+ Applications typically subclass both QVulkanWindow and QVulkanWindowRenderer.
+ The former allows handling events, for example, input, while the latter allows
+ implementing the Vulkan resource management and command buffer building that
+ make up the application's rendering.
+
+ In addition to event handling, the QVulkanWindow subclass is responsible for
+ providing an implementation for QVulkanWindow::createRenderer() as well. This
+ is where the window and renderer get connected. A typical implementation will
+ simply create a new instance of a subclass of QVulkanWindowRenderer.
+ */
+
+/*!
+ Constructs a new QVulkanWindow with the given \a parent.
+
+ The surface type is set to QSurface::VulkanSurface.
+ */
+QVulkanWindow::QVulkanWindow(QWindow *parent)
+ : QWindow(*(new QVulkanWindowPrivate), parent)
+{
+ setSurfaceType(QSurface::VulkanSurface);
+}
+
+/*!
+ Destructor.
+*/
+QVulkanWindow::~QVulkanWindow()
+{
+}
+
+QVulkanWindowPrivate::~QVulkanWindowPrivate()
+{
+ // graphics resource cleanup is already done at this point due to
+ // QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed
+
+ delete renderer;
+}
+
+/*!
+ \enum QVulkanWindow::Flag
+
+ This enum describes the flags that can be passed to setFlags().
+
+ \value PersistentResources Ensures no graphics resources are released when
+ the window becomes unexposed. The default behavior is to release
+ everything, and reinitialize later when becoming visible again.
+ */
+
+/*!
+ Configures the behavior based on the provided \a flags.
+
+ \note This function must be called before the window is made visible or at
+ latest in QVulkanWindowRenderer::preInitResources(), and has no effect if
+ called afterwards.
+ */
+void QVulkanWindow::setFlags(Flags flags)
+{
+ Q_D(QVulkanWindow);
+ if (d->status != QVulkanWindowPrivate::StatusUninitialized) {
+ qWarning("QVulkanWindow: Attempted to set flags when already initialized");
+ return;
+ }
+ d->flags = flags;
+}
+
+/*!
+ Return the requested flags.
+ */
+QVulkanWindow::Flags QVulkanWindow::flags() const
+{
+ Q_D(const QVulkanWindow);
+ return d->flags;
+}
+
+/*!
+ Returns the list of properties for the supported physical devices in the system.
+
+ \note This function can be called before making the window visible.
+ */
+QVector<VkPhysicalDeviceProperties> QVulkanWindow::availablePhysicalDevices()
+{
+ Q_D(QVulkanWindow);
+ if (!d->physDevs.isEmpty() && !d->physDevProps.isEmpty())
+ return d->physDevProps;
+
+ QVulkanInstance *inst = vulkanInstance();
+ if (!inst) {
+ qWarning("QVulkanWindow: Attempted to call availablePhysicalDevices() without a QVulkanInstance");
+ return d->physDevProps;
+ }
+
+ QVulkanFunctions *f = inst->functions();
+ uint32_t count = 1;
+ VkResult err = f->vkEnumeratePhysicalDevices(inst->vkInstance(), &count, nullptr);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to get physical device count: %d", err);
+ return d->physDevProps;
+ }
+
+ qCDebug(lcVk, "%d physical devices", count);
+ if (!count)
+ return d->physDevProps;
+
+ QVector<VkPhysicalDevice> devs(count);
+ err = f->vkEnumeratePhysicalDevices(inst->vkInstance(), &count, devs.data());
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to enumerate physical devices: %d", err);
+ return d->physDevProps;
+ }
+
+ d->physDevs = devs;
+ d->physDevProps.resize(count);
+ for (uint32_t i = 0; i < count; ++i) {
+ VkPhysicalDeviceProperties *p = &d->physDevProps[i];
+ f->vkGetPhysicalDeviceProperties(d->physDevs.at(i), p);
+ qCDebug(lcVk, "Physical device [%d]: name '%s' version %d.%d.%d", i, p->deviceName,
+ VK_VERSION_MAJOR(p->driverVersion), VK_VERSION_MINOR(p->driverVersion),
+ VK_VERSION_PATCH(p->driverVersion));
+ }
+
+ return d->physDevProps;
+}
+
+/*!
+ Requests the usage of the physical device with index \a idx. The index
+ corresponds to the list returned from availablePhysicalDevices().
+
+ By default the first physical device is used.
+
+ \note This function must be called before the window is made visible or at
+ latest in QVulkanWindowRenderer::preInitResources(), and has no effect if
+ called afterwards.
+ */
+void QVulkanWindow::setPhysicalDeviceIndex(int idx)
+{
+ Q_D(QVulkanWindow);
+ if (d->status != QVulkanWindowPrivate::StatusUninitialized) {
+ qWarning("QVulkanWindow: Attempted to set physical device when already initialized");
+ return;
+ }
+ const int count = availablePhysicalDevices().count();
+ if (idx < 0 || idx >= count) {
+ qWarning("QVulkanWindow: Invalid physical device index %d (total physical devices: %d)", idx, count);
+ return;
+ }
+ d->physDevIndex = idx;
+}
+
+/*!
+ Returns the list of the extensions that are supported by logical devices
+ created from the physical device selected by setPhysicalDeviceIndex().
+
+ \note This function can be called before making the window visible.
+ */
+QVulkanInfoVector<QVulkanExtension> QVulkanWindow::supportedDeviceExtensions()
+{
+ Q_D(QVulkanWindow);
+
+ availablePhysicalDevices();
+
+ if (d->physDevs.isEmpty()) {
+ qWarning("QVulkanWindow: No physical devices found");
+ return QVulkanInfoVector<QVulkanExtension>();
+ }
+
+ VkPhysicalDevice physDev = d->physDevs.at(d->physDevIndex);
+ if (d->supportedDevExtensions.contains(physDev))
+ return d->supportedDevExtensions.value(physDev);
+
+ QVulkanFunctions *f = vulkanInstance()->functions();
+ uint32_t count = 0;
+ VkResult err = f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &count, nullptr);
+ if (err == VK_SUCCESS) {
+ QVector<VkExtensionProperties> extProps(count);
+ err = f->vkEnumerateDeviceExtensionProperties(physDev, nullptr, &count, extProps.data());
+ if (err == VK_SUCCESS) {
+ QVulkanInfoVector<QVulkanExtension> exts;
+ for (const VkExtensionProperties &prop : extProps) {
+ QVulkanExtension ext;
+ ext.name = prop.extensionName;
+ ext.version = prop.specVersion;
+ exts.append(ext);
+ }
+ d->supportedDevExtensions.insert(physDev, exts);
+ qDebug(lcVk) << "Supported device extensions:" << exts;
+ return exts;
+ }
+ }
+
+ qWarning("QVulkanWindow: Failed to query device extension count: %d", err);
+ return QVulkanInfoVector<QVulkanExtension>();
+}
+
+/*!
+ Sets the list of device \a extensions to be enabled.
+
+ Unsupported extensions are ignored.
+
+ The swapchain extension will always be added automatically, no need to
+ include it in this list.
+
+ \note This function must be called before the window is made visible or at
+ latest in QVulkanWindowRenderer::preInitResources(), and has no effect if
+ called afterwards.
+ */
+void QVulkanWindow::setDeviceExtensions(const QByteArrayList &extensions)
+{
+ Q_D(QVulkanWindow);
+ if (d->status != QVulkanWindowPrivate::StatusUninitialized) {
+ qWarning("QVulkanWindow: Attempted to set device extensions when already initialized");
+ return;
+ }
+ d->requestedDevExtensions = extensions;
+}
+
+/*!
+ Sets the preferred \a formats of the swapchain.
+
+ By default no application-preferred format is set. In this case the
+ surface's preferred format will be used or, in absence of that,
+ \c{VK_FORMAT_B8G8R8A8_UNORM}.
+
+ The list in \a formats is ordered. If the first format is not supported,
+ the second will be considered, and so on. When no formats in the list are
+ supported, the behavior is the same as in the default case.
+
+ To query the actual format after initialization, call colorFormat().
+
+ \note This function must be called before the window is made visible or at
+ latest in QVulkanWindowRenderer::preInitResources(), and has no effect if
+ called afterwards.
+
+ \note Reimplementing QVulkanWindowRenderer::preInitResources() allows
+ dynamically examining the list of supported formats, should that be
+ desired. There the surface is retrievable via
+ QVulkanInstace::surfaceForWindow(), while this function can still safely be
+ called to affect the later stages of initialization.
+
+ \sa colorFormat()
+ */
+void QVulkanWindow::setPreferredColorFormats(const QVector<VkFormat> &formats)
+{
+ Q_D(QVulkanWindow);
+ if (d->status != QVulkanWindowPrivate::StatusUninitialized) {
+ qWarning("QVulkanWindow: Attempted to set preferred color format when already initialized");
+ return;
+ }
+ d->requestedColorFormats = formats;
+}
+
+static struct {
+ VkSampleCountFlagBits mask;
+ int count;
+} qvk_sampleCounts[] = {
+ // keep this sorted by 'count'
+ { VK_SAMPLE_COUNT_1_BIT, 1 },
+ { VK_SAMPLE_COUNT_2_BIT, 2 },
+ { VK_SAMPLE_COUNT_4_BIT, 4 },
+ { VK_SAMPLE_COUNT_8_BIT, 8 },
+ { VK_SAMPLE_COUNT_16_BIT, 16 },
+ { VK_SAMPLE_COUNT_32_BIT, 32 },
+ { VK_SAMPLE_COUNT_64_BIT, 64 }
+};
+
+/*!
+ Returns the set of supported sample counts when using the physical device
+ selected by setPhysicalDeviceIndex(), as a sorted vector.
+
+ By default QVulkanWindow uses a sample count of 1. By calling setSampleCount()
+ with a different value (2, 4, 8, ...) from the set returned by this
+ function, multisample anti-aliasing can be requested.
+
+ \note This function can be called before making the window visible.
+
+ \sa setSampleCount()
+ */
+QVector<int> QVulkanWindow::supportedSampleCounts()
+{
+ Q_D(const QVulkanWindow);
+ QVector<int> result;
+
+ availablePhysicalDevices();
+
+ if (d->physDevs.isEmpty()) {
+ qWarning("QVulkanWindow: No physical devices found");
+ return result;
+ }
+
+ const VkPhysicalDeviceLimits *limits = &d->physDevProps[d->physDevIndex].limits;
+ VkSampleCountFlags color = limits->framebufferColorSampleCounts;
+ VkSampleCountFlags depth = limits->framebufferDepthSampleCounts;
+ VkSampleCountFlags stencil = limits->framebufferStencilSampleCounts;
+
+ for (size_t i = 0; i < sizeof(qvk_sampleCounts) / sizeof(qvk_sampleCounts[0]); ++i) {
+ if ((color & qvk_sampleCounts[i].mask)
+ && (depth & qvk_sampleCounts[i].mask)
+ && (stencil & qvk_sampleCounts[i].mask))
+ {
+ result.append(qvk_sampleCounts[i].count);
+ }
+ }
+
+ return result;
+}
+
+/*!
+ Requests multisample antialiasing with the given \a sampleCount. The valid
+ values are 1, 2, 4, 8, ... up until the maximum value supported by the
+ physical device.
+
+ When the sample count is greater than 1, QVulkanWindow will create a
+ multisample color buffer instead of simply targeting the swapchain's
+ images. The rendering in the multisample buffer will get resolved into the
+ non-multisample buffers at the end of each frame.
+
+ To examine the list of supported sample counts, call supportedSampleCounts().
+
+ When setting up the rendering pipeline, call sampleCountFlagBits() to query the
+ active sample count as a \c VkSampleCountFlagBits value.
+
+ \note This function must be called before the window is made visible or at
+ latest in QVulkanWindowRenderer::preInitResources(), and has no effect if
+ called afterwards.
+
+ \sa supportedSampleCounts(), sampleCountFlagBits()
+ */
+void QVulkanWindow::setSampleCount(int sampleCount)
+{
+ Q_D(QVulkanWindow);
+ if (d->status != QVulkanWindowPrivate::StatusUninitialized) {
+ qWarning("QVulkanWindow: Attempted to set sample count when already initialized");
+ return;
+ }
+
+ // Stay compatible with QSurfaceFormat and friends where samples == 0 means the same as 1.
+ sampleCount = qBound(1, sampleCount, 64);
+
+ if (!supportedSampleCounts().contains(sampleCount)) {
+ qWarning("QVulkanWindow: Attempted to set unsupported sample count %d", sampleCount);
+ return;
+ }
+
+ for (size_t i = 0; i < sizeof(qvk_sampleCounts) / sizeof(qvk_sampleCounts[0]); ++i) {
+ if (qvk_sampleCounts[i].count == sampleCount) {
+ d->sampleCount = qvk_sampleCounts[i].mask;
+ return;
+ }
+ }
+
+ Q_UNREACHABLE();
+}
+
+void QVulkanWindowPrivate::init()
+{
+ Q_Q(QVulkanWindow);
+ Q_ASSERT(status == StatusUninitialized);
+
+ qCDebug(lcVk, "QVulkanWindow init");
+
+ inst = q->vulkanInstance();
+ if (!inst) {
+ qWarning("QVulkanWindow: Attempted to initialize without a QVulkanInstance");
+ // This is a simple user error, recheck on the next expose instead of
+ // going into the permanent failure state.
+ status = StatusFailRetry;
+ return;
+ }
+
+ if (!renderer)
+ renderer = q->createRenderer();
+
+ surface = QVulkanInstance::surfaceForWindow(q);
+ if (surface == VK_NULL_HANDLE) {
+ qWarning("QVulkanWindow: Failed to retrieve Vulkan surface for window");
+ status = StatusFailRetry;
+ return;
+ }
+
+ q->availablePhysicalDevices();
+
+ if (physDevs.isEmpty()) {
+ qWarning("QVulkanWindow: No physical devices found");
+ status = StatusFail;
+ return;
+ }
+
+ if (physDevIndex < 0 || physDevIndex >= physDevs.count()) {
+ qWarning("QVulkanWindow: Invalid physical device index; defaulting to 0");
+ physDevIndex = 0;
+ }
+ qCDebug(lcVk, "Using physical device [%d]", physDevIndex);
+
+ // Give a last chance to do decisions based on the physical device and the surface.
+ if (renderer)
+ renderer->preInitResources();
+
+ VkPhysicalDevice physDev = physDevs.at(physDevIndex);
+ QVulkanFunctions *f = inst->functions();
+
+ uint32_t queueCount = 0;
+ f->vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, nullptr);
+ QVector<VkQueueFamilyProperties> queueFamilyProps(queueCount);
+ f->vkGetPhysicalDeviceQueueFamilyProperties(physDev, &queueCount, queueFamilyProps.data());
+ gfxQueueFamilyIdx = uint32_t(-1);
+ presQueueFamilyIdx = uint32_t(-1);
+ for (int i = 0; i < queueFamilyProps.count(); ++i) {
+ const bool supportsPresent = inst->supportsPresent(physDev, i, q);
+ qCDebug(lcVk, "queue family %d: flags=0x%x count=%d supportsPresent=%d", i,
+ queueFamilyProps[i].queueFlags, queueFamilyProps[i].queueCount, supportsPresent);
+ if (gfxQueueFamilyIdx == uint32_t(-1)
+ && (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
+ && supportsPresent)
+ gfxQueueFamilyIdx = i;
+ }
+ if (gfxQueueFamilyIdx != uint32_t(-1)) {
+ presQueueFamilyIdx = gfxQueueFamilyIdx;
+ } else {
+ qCDebug(lcVk, "No queue with graphics+present; trying separate queues");
+ for (int i = 0; i < queueFamilyProps.count(); ++i) {
+ if (gfxQueueFamilyIdx == uint32_t(-1) && (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
+ gfxQueueFamilyIdx = i;
+ if (presQueueFamilyIdx == uint32_t(-1) && inst->supportsPresent(physDev, i, q))
+ presQueueFamilyIdx = i;
+ }
+ }
+ if (gfxQueueFamilyIdx == uint32_t(-1)) {
+ qWarning("QVulkanWindow: No graphics queue family found");
+ status = StatusFail;
+ return;
+ }
+ if (presQueueFamilyIdx == uint32_t(-1)) {
+ qWarning("QVulkanWindow: No present queue family found");
+ status = StatusFail;
+ return;
+ }
+#ifdef QT_DEBUG
+ // allow testing the separate present queue case in debug builds on AMD cards
+ if (qEnvironmentVariableIsSet("QT_VK_PRESENT_QUEUE_INDEX"))
+ presQueueFamilyIdx = qEnvironmentVariableIntValue("QT_VK_PRESENT_QUEUE_INDEX");
+#endif
+ qCDebug(lcVk, "Using queue families: graphics = %u present = %u", gfxQueueFamilyIdx, presQueueFamilyIdx);
+
+ VkDeviceQueueCreateInfo queueInfo[2];
+ const float prio[] = { 0 };
+ memset(queueInfo, 0, sizeof(queueInfo));
+ queueInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueInfo[0].queueFamilyIndex = gfxQueueFamilyIdx;
+ queueInfo[0].queueCount = 1;
+ queueInfo[0].pQueuePriorities = prio;
+ if (gfxQueueFamilyIdx != presQueueFamilyIdx) {
+ queueInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueInfo[1].queueFamilyIndex = presQueueFamilyIdx;
+ queueInfo[1].queueCount = 1;
+ queueInfo[1].pQueuePriorities = prio;
+ }
+
+ // Filter out unsupported extensions in order to keep symmetry
+ // with how QVulkanInstance behaves. Add the swapchain extension.
+ QVector<const char *> devExts;
+ QVulkanInfoVector<QVulkanExtension> supportedExtensions = q->supportedDeviceExtensions();
+ QByteArrayList reqExts = requestedDevExtensions;
+ reqExts.append("VK_KHR_swapchain");
+ for (const QByteArray &ext : reqExts) {
+ if (supportedExtensions.contains(ext))
+ devExts.append(ext.constData());
+ }
+ qCDebug(lcVk) << "Enabling device extensions:" << devExts;
+
+ VkDeviceCreateInfo devInfo;
+ memset(&devInfo, 0, sizeof(devInfo));
+ devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ devInfo.queueCreateInfoCount = gfxQueueFamilyIdx == presQueueFamilyIdx ? 1 : 2;
+ devInfo.pQueueCreateInfos = queueInfo;
+ devInfo.enabledExtensionCount = devExts.count();
+ devInfo.ppEnabledExtensionNames = devExts.constData();
+
+ // Device layers are not supported by QVulkanWindow since that's an already deprecated
+ // API. However, have a workaround for systems with older API and layers (f.ex. L4T
+ // 24.2 for the Jetson TX1 provides API 1.0.13 and crashes when the validation layer
+ // is enabled for the instance but not the device).
+ uint32_t apiVersion = physDevProps[physDevIndex].apiVersion;
+ if (VK_VERSION_MAJOR(apiVersion) == 1
+ && VK_VERSION_MINOR(apiVersion) == 0
+ && VK_VERSION_PATCH(apiVersion) <= 13)
+ {
+ // Make standard validation work at least.
+ const QByteArray stdValName = QByteArrayLiteral("VK_LAYER_LUNARG_standard_validation");
+ const char *stdValNamePtr = stdValName.constData();
+ if (inst->layers().contains(stdValName)) {
+ uint32_t count = 0;
+ VkResult err = f->vkEnumerateDeviceLayerProperties(physDev, &count, nullptr);
+ if (err == VK_SUCCESS) {
+ QVector<VkLayerProperties> layerProps(count);
+ err = f->vkEnumerateDeviceLayerProperties(physDev, &count, layerProps.data());
+ if (err == VK_SUCCESS) {
+ for (const VkLayerProperties &prop : layerProps) {
+ if (!strncmp(prop.layerName, stdValNamePtr, stdValName.count())) {
+ devInfo.enabledLayerCount = 1;
+ devInfo.ppEnabledLayerNames = &stdValNamePtr;
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ VkResult err = f->vkCreateDevice(physDev, &devInfo, nullptr, &dev);
+ if (err == VK_ERROR_DEVICE_LOST) {
+ qWarning("QVulkanWindow: Physical device lost");
+ if (renderer)
+ renderer->physicalDeviceLost();
+ // clear the caches so the list of physical devices is re-queried
+ physDevs.clear();
+ physDevProps.clear();
+ status = StatusUninitialized;
+ qCDebug(lcVk, "Attempting to restart in 2 seconds");
+ QTimer::singleShot(2000, q, [this]() { ensureStarted(); });
+ return;
+ }
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create device: %d", err);
+ status = StatusFail;
+ return;
+ }
+
+ devFuncs = inst->deviceFunctions(dev);
+ Q_ASSERT(devFuncs);
+
+ devFuncs->vkGetDeviceQueue(dev, gfxQueueFamilyIdx, 0, &gfxQueue);
+ if (gfxQueueFamilyIdx == presQueueFamilyIdx)
+ presQueue = gfxQueue;
+ else
+ devFuncs->vkGetDeviceQueue(dev, presQueueFamilyIdx, 0, &presQueue);
+
+ VkCommandPoolCreateInfo poolInfo;
+ memset(&poolInfo, 0, sizeof(poolInfo));
+ poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ poolInfo.queueFamilyIndex = gfxQueueFamilyIdx;
+ err = devFuncs->vkCreateCommandPool(dev, &poolInfo, nullptr, &cmdPool);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create command pool: %d", err);
+ status = StatusFail;
+ return;
+ }
+ if (gfxQueueFamilyIdx != presQueueFamilyIdx) {
+ poolInfo.queueFamilyIndex = presQueueFamilyIdx;
+ err = devFuncs->vkCreateCommandPool(dev, &poolInfo, nullptr, &presCmdPool);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create command pool for present queue: %d", err);
+ status = StatusFail;
+ return;
+ }
+ }
+
+ hostVisibleMemIndex = 0;
+ VkPhysicalDeviceMemoryProperties physDevMemProps;
+ bool hostVisibleMemIndexSet = false;
+ f->vkGetPhysicalDeviceMemoryProperties(physDev, &physDevMemProps);
+ for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) {
+ const VkMemoryType *memType = physDevMemProps.memoryTypes;
+ qCDebug(lcVk, "memtype %d: flags=0x%x", i, memType[i].propertyFlags);
+ // Find a host visible, host coherent memtype. If there is one that is
+ // cached as well (in addition to being coherent), prefer that.
+ const int hostVisibleAndCoherent = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
+ if ((memType[i].propertyFlags & hostVisibleAndCoherent) == hostVisibleAndCoherent) {
+ if (!hostVisibleMemIndexSet
+ || (memType[i].propertyFlags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT)) {
+ hostVisibleMemIndexSet = true;
+ hostVisibleMemIndex = i;
+ }
+ }
+ }
+ qCDebug(lcVk, "Picked memtype %d for host visible memory", hostVisibleMemIndex);
+ deviceLocalMemIndex = 0;
+ for (uint32_t i = 0; i < physDevMemProps.memoryTypeCount; ++i) {
+ const VkMemoryType *memType = physDevMemProps.memoryTypes;
+ // Just pick the first device local memtype.
+ if (memType[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
+ deviceLocalMemIndex = i;
+ break;
+ }
+ }
+ qCDebug(lcVk, "Picked memtype %d for device local memory", deviceLocalMemIndex);
+
+ if (!vkGetPhysicalDeviceSurfaceCapabilitiesKHR || !vkGetPhysicalDeviceSurfaceFormatsKHR) {
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
+ inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
+ vkGetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
+ inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfaceFormatsKHR"));
+ if (!vkGetPhysicalDeviceSurfaceCapabilitiesKHR || !vkGetPhysicalDeviceSurfaceFormatsKHR) {
+ qWarning("QVulkanWindow: Physical device surface queries not available");
+ status = StatusFail;
+ return;
+ }
+ }
+
+ // Figure out the color format here. Must not wait until recreateSwapChain()
+ // because the renderpass should be available already from initResources (so
+ // that apps do not have to defer pipeline creation to
+ // initSwapChainResources), but the renderpass needs the final color format.
+
+ uint32_t formatCount = 0;
+ vkGetPhysicalDeviceSurfaceFormatsKHR(physDev, surface, &formatCount, nullptr);
+ QVector<VkSurfaceFormatKHR> formats(formatCount);
+ if (formatCount)
+ vkGetPhysicalDeviceSurfaceFormatsKHR(physDev, surface, &formatCount, formats.data());
+
+ colorFormat = VK_FORMAT_B8G8R8A8_UNORM; // our documented default if all else fails
+ colorSpace = VkColorSpaceKHR(0); // this is in fact VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
+
+ // Pick the preferred format, if there is one.
+ if (!formats.isEmpty() && formats[0].format != VK_FORMAT_UNDEFINED) {
+ colorFormat = formats[0].format;
+ colorSpace = formats[0].colorSpace;
+ }
+
+ // Try to honor the user request.
+ if (!formats.isEmpty() && !requestedColorFormats.isEmpty()) {
+ for (VkFormat reqFmt : qAsConst(requestedColorFormats)) {
+ auto r = std::find_if(formats.cbegin(), formats.cend(),
+ [reqFmt](const VkSurfaceFormatKHR &sfmt) { return sfmt.format == reqFmt; });
+ if (r != formats.cend()) {
+ colorFormat = r->format;
+ colorSpace = r->colorSpace;
+ break;
+ }
+ }
+ }
+
+ const VkFormat dsFormatCandidates[] = {
+ VK_FORMAT_D24_UNORM_S8_UINT,
+ VK_FORMAT_D32_SFLOAT_S8_UINT,
+ VK_FORMAT_D16_UNORM_S8_UINT
+ };
+ const int dsFormatCandidateCount = sizeof(dsFormatCandidates) / sizeof(VkFormat);
+ int dsFormatIdx = 0;
+ while (dsFormatIdx < dsFormatCandidateCount) {
+ dsFormat = dsFormatCandidates[dsFormatIdx];
+ VkFormatProperties fmtProp;
+ f->vkGetPhysicalDeviceFormatProperties(physDev, dsFormat, &fmtProp);
+ if (fmtProp.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
+ break;
+ ++dsFormatIdx;
+ }
+ if (dsFormatIdx == dsFormatCandidateCount)
+ qWarning("QVulkanWindow: Failed to find an optimal depth-stencil format");
+
+ qCDebug(lcVk, "Color format: %d Depth-stencil format: %d", colorFormat, dsFormat);
+
+ if (!createDefaultRenderPass())
+ return;
+
+ if (renderer)
+ renderer->initResources();
+
+ status = StatusDeviceReady;
+}
+
+void QVulkanWindowPrivate::reset()
+{
+ if (!dev) // do not rely on 'status', a half done init must be cleaned properly too
+ return;
+
+ qCDebug(lcVk, "QVulkanWindow reset");
+
+ devFuncs->vkDeviceWaitIdle(dev);
+
+ if (renderer) {
+ renderer->releaseResources();
+ devFuncs->vkDeviceWaitIdle(dev);
+ }
+
+ if (defaultRenderPass) {
+ devFuncs->vkDestroyRenderPass(dev, defaultRenderPass, nullptr);
+ defaultRenderPass = VK_NULL_HANDLE;
+ }
+
+ if (cmdPool) {
+ devFuncs->vkDestroyCommandPool(dev, cmdPool, nullptr);
+ cmdPool = VK_NULL_HANDLE;
+ }
+
+ if (presCmdPool) {
+ devFuncs->vkDestroyCommandPool(dev, presCmdPool, nullptr);
+ presCmdPool = VK_NULL_HANDLE;
+ }
+
+ if (frameGrabImage) {
+ devFuncs->vkDestroyImage(dev, frameGrabImage, nullptr);
+ frameGrabImage = VK_NULL_HANDLE;
+ }
+
+ if (frameGrabImageMem) {
+ devFuncs->vkFreeMemory(dev, frameGrabImageMem, nullptr);
+ frameGrabImageMem = VK_NULL_HANDLE;
+ }
+
+ if (dev) {
+ devFuncs->vkDestroyDevice(dev, nullptr);
+ inst->resetDeviceFunctions(dev);
+ dev = VK_NULL_HANDLE;
+ vkCreateSwapchainKHR = nullptr; // re-resolve swapchain funcs later on since some come via the device
+ }
+
+ surface = VK_NULL_HANDLE;
+
+ status = StatusUninitialized;
+}
+
+bool QVulkanWindowPrivate::createDefaultRenderPass()
+{
+ VkAttachmentDescription attDesc[3];
+ memset(attDesc, 0, sizeof(attDesc));
+
+ const bool msaa = sampleCount > VK_SAMPLE_COUNT_1_BIT;
+
+ // This is either the non-msaa render target or the resolve target.
+ attDesc[0].format = colorFormat;
+ attDesc[0].samples = VK_SAMPLE_COUNT_1_BIT;
+ attDesc[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; // ignored when msaa
+ attDesc[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attDesc[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attDesc[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+ attDesc[1].format = dsFormat;
+ attDesc[1].samples = sampleCount;
+ attDesc[1].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attDesc[1].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc[1].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attDesc[1].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc[1].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc[1].finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
+
+ if (msaa) {
+ // msaa render target
+ attDesc[2].format = colorFormat;
+ attDesc[2].samples = sampleCount;
+ attDesc[2].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attDesc[2].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc[2].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ attDesc[2].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ attDesc[2].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc[2].finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ }
+
+ VkAttachmentReference colorRef = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
+ VkAttachmentReference resolveRef = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
+ VkAttachmentReference dsRef = { 1, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
+
+ VkSubpassDescription subPassDesc;
+ memset(&subPassDesc, 0, sizeof(subPassDesc));
+ subPassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subPassDesc.colorAttachmentCount = 1;
+ subPassDesc.pColorAttachments = &colorRef;
+ subPassDesc.pDepthStencilAttachment = &dsRef;
+
+ VkRenderPassCreateInfo rpInfo;
+ memset(&rpInfo, 0, sizeof(rpInfo));
+ rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ rpInfo.attachmentCount = 2;
+ rpInfo.pAttachments = attDesc;
+ rpInfo.subpassCount = 1;
+ rpInfo.pSubpasses = &subPassDesc;
+
+ if (msaa) {
+ colorRef.attachment = 2;
+ subPassDesc.pResolveAttachments = &resolveRef;
+ rpInfo.attachmentCount = 3;
+ }
+
+ VkResult err = devFuncs->vkCreateRenderPass(dev, &rpInfo, nullptr, &defaultRenderPass);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create renderpass: %d", err);
+ return false;
+ }
+
+ return true;
+}
+
+void QVulkanWindowPrivate::recreateSwapChain()
+{
+ Q_Q(QVulkanWindow);
+ Q_ASSERT(status >= StatusDeviceReady);
+
+ swapChainImageSize = q->size() * q->devicePixelRatio(); // note: may change below due to surfaceCaps
+
+ if (swapChainImageSize.isEmpty()) // handle null window size gracefully
+ return;
+
+ QVulkanInstance *inst = q->vulkanInstance();
+ QVulkanFunctions *f = inst->functions();
+ devFuncs->vkDeviceWaitIdle(dev);
+
+ if (!vkCreateSwapchainKHR) {
+ vkCreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(f->vkGetDeviceProcAddr(dev, "vkCreateSwapchainKHR"));
+ vkDestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(f->vkGetDeviceProcAddr(dev, "vkDestroySwapchainKHR"));
+ vkGetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(f->vkGetDeviceProcAddr(dev, "vkGetSwapchainImagesKHR"));
+ vkAcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(f->vkGetDeviceProcAddr(dev, "vkAcquireNextImageKHR"));
+ vkQueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(f->vkGetDeviceProcAddr(dev, "vkQueuePresentKHR"));
+ }
+
+ VkPhysicalDevice physDev = physDevs.at(physDevIndex);
+ VkSurfaceCapabilitiesKHR surfaceCaps;
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR(physDev, surface, &surfaceCaps);
+ uint32_t reqBufferCount = swapChainBufferCount;
+ if (surfaceCaps.maxImageCount)
+ reqBufferCount = qBound(surfaceCaps.minImageCount, reqBufferCount, surfaceCaps.maxImageCount);
+
+ VkExtent2D bufferSize = surfaceCaps.currentExtent;
+ if (bufferSize.width == uint32_t(-1)) {
+ Q_ASSERT(bufferSize.height == uint32_t(-1));
+ bufferSize.width = swapChainImageSize.width();
+ bufferSize.height = swapChainImageSize.height();
+ } else {
+ swapChainImageSize = QSize(bufferSize.width, bufferSize.height);
+ }
+
+ VkSurfaceTransformFlagBitsKHR preTransform =
+ (surfaceCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
+ ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
+ : surfaceCaps.currentTransform;
+
+ VkCompositeAlphaFlagBitsKHR compositeAlpha =
+ (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
+ ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
+ : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+
+ if (q->requestedFormat().hasAlpha()) {
+ if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)
+ compositeAlpha = VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
+ else if (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR)
+ compositeAlpha = VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR;
+ }
+
+ VkImageUsageFlags usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ swapChainSupportsReadBack = (surfaceCaps.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
+ if (swapChainSupportsReadBack)
+ usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
+
+ VkSwapchainKHR oldSwapChain = swapChain;
+ VkSwapchainCreateInfoKHR swapChainInfo;
+ memset(&swapChainInfo, 0, sizeof(swapChainInfo));
+ swapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapChainInfo.surface = surface;
+ swapChainInfo.minImageCount = reqBufferCount;
+ swapChainInfo.imageFormat = colorFormat;
+ swapChainInfo.imageColorSpace = colorSpace;
+ swapChainInfo.imageExtent = bufferSize;
+ swapChainInfo.imageArrayLayers = 1;
+ swapChainInfo.imageUsage = usage;
+ swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapChainInfo.preTransform = preTransform;
+ swapChainInfo.compositeAlpha = compositeAlpha;
+ swapChainInfo.presentMode = presentMode;
+ swapChainInfo.clipped = true;
+ swapChainInfo.oldSwapchain = oldSwapChain;
+
+ qCDebug(lcVk, "Creating new swap chain of %d buffers, size %dx%d", reqBufferCount, bufferSize.width, bufferSize.height);
+
+ VkSwapchainKHR newSwapChain;
+ VkResult err = vkCreateSwapchainKHR(dev, &swapChainInfo, nullptr, &newSwapChain);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create swap chain: %d", err);
+ return;
+ }
+
+ if (oldSwapChain)
+ releaseSwapChain();
+
+ swapChain = newSwapChain;
+
+ uint32_t actualSwapChainBufferCount = 0;
+ err = vkGetSwapchainImagesKHR(dev, swapChain, &actualSwapChainBufferCount, nullptr);
+ if (err != VK_SUCCESS || actualSwapChainBufferCount < 2) {
+ qWarning("QVulkanWindow: Failed to get swapchain images: %d (count=%d)", err, actualSwapChainBufferCount);
+ return;
+ }
+
+ qCDebug(lcVk, "Actual swap chain buffer count: %d (supportsReadback=%d)",
+ actualSwapChainBufferCount, swapChainSupportsReadBack);
+ if (actualSwapChainBufferCount > MAX_SWAPCHAIN_BUFFER_COUNT) {
+ qWarning("QVulkanWindow: Too many swapchain buffers (%d)", actualSwapChainBufferCount);
+ return;
+ }
+ swapChainBufferCount = actualSwapChainBufferCount;
+
+ VkImage swapChainImages[MAX_SWAPCHAIN_BUFFER_COUNT];
+ err = vkGetSwapchainImagesKHR(dev, swapChain, &actualSwapChainBufferCount, swapChainImages);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to get swapchain images: %d", err);
+ return;
+ }
+
+ if (!createTransientImage(dsFormat,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,
+ VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT,
+ &dsImage,
+ &dsMem,
+ &dsView,
+ 1))
+ {
+ return;
+ }
+
+ const bool msaa = sampleCount > VK_SAMPLE_COUNT_1_BIT;
+ VkImage msaaImages[MAX_SWAPCHAIN_BUFFER_COUNT];
+ VkImageView msaaViews[MAX_SWAPCHAIN_BUFFER_COUNT];
+
+ if (msaa) {
+ if (!createTransientImage(colorFormat,
+ VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ VK_IMAGE_ASPECT_COLOR_BIT,
+ msaaImages,
+ &msaaImageMem,
+ msaaViews,
+ swapChainBufferCount))
+ {
+ return;
+ }
+ }
+
+ VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, VK_FENCE_CREATE_SIGNALED_BIT };
+
+ for (int i = 0; i < swapChainBufferCount; ++i) {
+ ImageResources &image(imageRes[i]);
+ image.image = swapChainImages[i];
+
+ if (msaa) {
+ image.msaaImage = msaaImages[i];
+ image.msaaImageView = msaaViews[i];
+ }
+
+ VkImageViewCreateInfo imgViewInfo;
+ memset(&imgViewInfo, 0, sizeof(imgViewInfo));
+ imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ imgViewInfo.image = swapChainImages[i];
+ imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ imgViewInfo.format = colorFormat;
+ imgViewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ imgViewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ imgViewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ imgViewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ imgViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ imgViewInfo.subresourceRange.levelCount = imgViewInfo.subresourceRange.layerCount = 1;
+ err = devFuncs->vkCreateImageView(dev, &imgViewInfo, nullptr, &image.imageView);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create swapchain image view %d: %d", i, err);
+ return;
+ }
+
+ err = devFuncs->vkCreateFence(dev, &fenceInfo, nullptr, &image.cmdFence);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create command buffer fence: %d", err);
+ return;
+ }
+ image.cmdFenceWaitable = true; // fence was created in signaled state
+
+ VkImageView views[3] = { image.imageView,
+ dsView,
+ msaa ? image.msaaImageView : VK_NULL_HANDLE };
+ VkFramebufferCreateInfo fbInfo;
+ memset(&fbInfo, 0, sizeof(fbInfo));
+ fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fbInfo.renderPass = defaultRenderPass;
+ fbInfo.attachmentCount = msaa ? 3 : 2;
+ fbInfo.pAttachments = views;
+ fbInfo.width = swapChainImageSize.width();
+ fbInfo.height = swapChainImageSize.height();
+ fbInfo.layers = 1;
+ VkResult err = devFuncs->vkCreateFramebuffer(dev, &fbInfo, nullptr, &image.fb);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create framebuffer: %d", err);
+ return;
+ }
+
+ if (gfxQueueFamilyIdx != presQueueFamilyIdx) {
+ // pre-build the static image-acquire-on-present-queue command buffer
+ VkCommandBufferAllocateInfo cmdBufInfo = {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, presCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1 };
+ err = devFuncs->vkAllocateCommandBuffers(dev, &cmdBufInfo, &image.presTransCmdBuf);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to allocate acquire-on-present-queue command buffer: %d", err);
+ return;
+ }
+ VkCommandBufferBeginInfo cmdBufBeginInfo = {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr,
+ VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, nullptr };
+ err = devFuncs->vkBeginCommandBuffer(image.presTransCmdBuf, &cmdBufBeginInfo);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to begin acquire-on-present-queue command buffer: %d", err);
+ return;
+ }
+ VkImageMemoryBarrier presTrans;
+ memset(&presTrans, 0, sizeof(presTrans));
+ presTrans.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ presTrans.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ presTrans.oldLayout = presTrans.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ presTrans.srcQueueFamilyIndex = gfxQueueFamilyIdx;
+ presTrans.dstQueueFamilyIndex = presQueueFamilyIdx;
+ presTrans.image = image.image;
+ presTrans.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ presTrans.subresourceRange.levelCount = presTrans.subresourceRange.layerCount = 1;
+ devFuncs->vkCmdPipelineBarrier(image.presTransCmdBuf,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &presTrans);
+ err = devFuncs->vkEndCommandBuffer(image.presTransCmdBuf);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to end acquire-on-present-queue command buffer: %d", err);
+ return;
+ }
+ }
+ }
+
+ currentImage = 0;
+
+ VkSemaphoreCreateInfo semInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, 0 };
+ for (int i = 0; i < frameLag; ++i) {
+ FrameResources &frame(frameRes[i]);
+
+ frame.imageAcquired = false;
+ frame.imageSemWaitable = false;
+
+ devFuncs->vkCreateFence(dev, &fenceInfo, nullptr, &frame.fence);
+ frame.fenceWaitable = true; // fence was created in signaled state
+
+ devFuncs->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.imageSem);
+ devFuncs->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.drawSem);
+ if (gfxQueueFamilyIdx != presQueueFamilyIdx)
+ devFuncs->vkCreateSemaphore(dev, &semInfo, nullptr, &frame.presTransSem);
+ }
+
+ currentFrame = 0;
+
+ if (renderer)
+ renderer->initSwapChainResources();
+
+ status = StatusReady;
+}
+
+uint32_t QVulkanWindowPrivate::chooseTransientImageMemType(VkImage img, uint32_t startIndex)
+{
+ VkPhysicalDeviceMemoryProperties physDevMemProps;
+ inst->functions()->vkGetPhysicalDeviceMemoryProperties(physDevs[physDevIndex], &physDevMemProps);
+
+ VkMemoryRequirements memReq;
+ devFuncs->vkGetImageMemoryRequirements(dev, img, &memReq);
+ uint32_t memTypeIndex = uint32_t(-1);
+
+ if (memReq.memoryTypeBits) {
+ // Find a device local + lazily allocated, or at least device local memtype.
+ const VkMemoryType *memType = physDevMemProps.memoryTypes;
+ bool foundDevLocal = false;
+ for (uint32_t i = startIndex; i < physDevMemProps.memoryTypeCount; ++i) {
+ if (memReq.memoryTypeBits & (1 << i)) {
+ if (memType[i].propertyFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
+ if (!foundDevLocal) {
+ foundDevLocal = true;
+ memTypeIndex = i;
+ }
+ if (memType[i].propertyFlags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
+ memTypeIndex = i;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ return memTypeIndex;
+}
+
+static inline VkDeviceSize aligned(VkDeviceSize v, VkDeviceSize byteAlign)
+{
+ return (v + byteAlign - 1) & ~(byteAlign - 1);
+}
+
+bool QVulkanWindowPrivate::createTransientImage(VkFormat format,
+ VkImageUsageFlags usage,
+ VkImageAspectFlags aspectMask,
+ VkImage *images,
+ VkDeviceMemory *mem,
+ VkImageView *views,
+ int count)
+{
+ VkMemoryRequirements memReq;
+ VkResult err;
+
+ for (int i = 0; i < count; ++i) {
+ VkImageCreateInfo imgInfo;
+ memset(&imgInfo, 0, sizeof(imgInfo));
+ imgInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imgInfo.imageType = VK_IMAGE_TYPE_2D;
+ imgInfo.format = format;
+ imgInfo.extent.width = swapChainImageSize.width();
+ imgInfo.extent.height = swapChainImageSize.height();
+ imgInfo.extent.depth = 1;
+ imgInfo.mipLevels = imgInfo.arrayLayers = 1;
+ imgInfo.samples = sampleCount;
+ imgInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
+ imgInfo.usage = usage | VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
+
+ err = devFuncs->vkCreateImage(dev, &imgInfo, nullptr, images + i);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create image: %d", err);
+ return false;
+ }
+
+ // Assume the reqs are the same since the images are same in every way.
+ // Still, call GetImageMemReq for every image, in order to prevent the
+ // validation layer from complaining.
+ devFuncs->vkGetImageMemoryRequirements(dev, images[i], &memReq);
+ }
+
+ VkMemoryAllocateInfo memInfo;
+ memset(&memInfo, 0, sizeof(memInfo));
+ memInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
+ memInfo.allocationSize = aligned(memReq.size, memReq.alignment) * count;
+
+ uint32_t startIndex = 0;
+ do {
+ memInfo.memoryTypeIndex = chooseTransientImageMemType(images[0], startIndex);
+ if (memInfo.memoryTypeIndex == uint32_t(-1)) {
+ qWarning("QVulkanWindow: No suitable memory type found");
+ return false;
+ }
+ startIndex = memInfo.memoryTypeIndex + 1;
+ qCDebug(lcVk, "Allocating %u bytes for transient image (memtype %u)",
+ uint32_t(memInfo.allocationSize), memInfo.memoryTypeIndex);
+ err = devFuncs->vkAllocateMemory(dev, &memInfo, nullptr, mem);
+ if (err != VK_SUCCESS && err != VK_ERROR_OUT_OF_DEVICE_MEMORY) {
+ qWarning("QVulkanWindow: Failed to allocate image memory: %d", err);
+ return false;
+ }
+ } while (err != VK_SUCCESS);
+
+ VkDeviceSize ofs = 0;
+ for (int i = 0; i < count; ++i) {
+ err = devFuncs->vkBindImageMemory(dev, images[i], *mem, ofs);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to bind image memory: %d", err);
+ return false;
+ }
+ ofs += aligned(memReq.size, memReq.alignment);
+
+ VkImageViewCreateInfo imgViewInfo;
+ memset(&imgViewInfo, 0, sizeof(imgViewInfo));
+ imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ imgViewInfo.image = images[i];
+ imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ imgViewInfo.format = format;
+ imgViewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ imgViewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ imgViewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ imgViewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ imgViewInfo.subresourceRange.aspectMask = aspectMask;
+ imgViewInfo.subresourceRange.levelCount = imgViewInfo.subresourceRange.layerCount = 1;
+
+ err = devFuncs->vkCreateImageView(dev, &imgViewInfo, nullptr, views + i);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create image view: %d", err);
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void QVulkanWindowPrivate::releaseSwapChain()
+{
+ if (!dev || !swapChain) // do not rely on 'status', a half done init must be cleaned properly too
+ return;
+
+ qCDebug(lcVk, "Releasing swapchain");
+
+ devFuncs->vkDeviceWaitIdle(dev);
+
+ if (renderer) {
+ renderer->releaseSwapChainResources();
+ devFuncs->vkDeviceWaitIdle(dev);
+ }
+
+ for (int i = 0; i < frameLag; ++i) {
+ FrameResources &frame(frameRes[i]);
+ if (frame.fence) {
+ if (frame.fenceWaitable)
+ devFuncs->vkWaitForFences(dev, 1, &frame.fence, VK_TRUE, UINT64_MAX);
+ devFuncs->vkDestroyFence(dev, frame.fence, nullptr);
+ frame.fence = VK_NULL_HANDLE;
+ frame.fenceWaitable = false;
+ }
+ if (frame.imageSem) {
+ devFuncs->vkDestroySemaphore(dev, frame.imageSem, nullptr);
+ frame.imageSem = VK_NULL_HANDLE;
+ }
+ if (frame.drawSem) {
+ devFuncs->vkDestroySemaphore(dev, frame.drawSem, nullptr);
+ frame.drawSem = VK_NULL_HANDLE;
+ }
+ if (frame.presTransSem) {
+ devFuncs->vkDestroySemaphore(dev, frame.presTransSem, nullptr);
+ frame.presTransSem = VK_NULL_HANDLE;
+ }
+ }
+
+ for (int i = 0; i < swapChainBufferCount; ++i) {
+ ImageResources &image(imageRes[i]);
+ if (image.cmdFence) {
+ if (image.cmdFenceWaitable)
+ devFuncs->vkWaitForFences(dev, 1, &image.cmdFence, VK_TRUE, UINT64_MAX);
+ devFuncs->vkDestroyFence(dev, image.cmdFence, nullptr);
+ image.cmdFence = VK_NULL_HANDLE;
+ image.cmdFenceWaitable = false;
+ }
+ if (image.fb) {
+ devFuncs->vkDestroyFramebuffer(dev, image.fb, nullptr);
+ image.fb = VK_NULL_HANDLE;
+ }
+ if (image.imageView) {
+ devFuncs->vkDestroyImageView(dev, image.imageView, nullptr);
+ image.imageView = VK_NULL_HANDLE;
+ }
+ if (image.cmdBuf) {
+ devFuncs->vkFreeCommandBuffers(dev, cmdPool, 1, &image.cmdBuf);
+ image.cmdBuf = VK_NULL_HANDLE;
+ }
+ if (image.presTransCmdBuf) {
+ devFuncs->vkFreeCommandBuffers(dev, presCmdPool, 1, &image.presTransCmdBuf);
+ image.presTransCmdBuf = VK_NULL_HANDLE;
+ }
+ if (image.msaaImageView) {
+ devFuncs->vkDestroyImageView(dev, image.msaaImageView, nullptr);
+ image.msaaImageView = VK_NULL_HANDLE;
+ }
+ if (image.msaaImage) {
+ devFuncs->vkDestroyImage(dev, image.msaaImage, nullptr);
+ image.msaaImage = VK_NULL_HANDLE;
+ }
+ }
+
+ if (msaaImageMem) {
+ devFuncs->vkFreeMemory(dev, msaaImageMem, nullptr);
+ msaaImageMem = VK_NULL_HANDLE;
+ }
+
+ if (dsView) {
+ devFuncs->vkDestroyImageView(dev, dsView, nullptr);
+ dsView = VK_NULL_HANDLE;
+ }
+ if (dsImage) {
+ devFuncs->vkDestroyImage(dev, dsImage, nullptr);
+ dsImage = VK_NULL_HANDLE;
+ }
+ if (dsMem) {
+ devFuncs->vkFreeMemory(dev, dsMem, nullptr);
+ dsMem = VK_NULL_HANDLE;
+ }
+
+ if (swapChain) {
+ vkDestroySwapchainKHR(dev, swapChain, nullptr);
+ swapChain = VK_NULL_HANDLE;
+ }
+
+ if (status == StatusReady)
+ status = StatusDeviceReady;
+}
+
+/*!
+ \internal
+ */
+void QVulkanWindow::exposeEvent(QExposeEvent *)
+{
+ Q_D(QVulkanWindow);
+
+ if (isExposed()) {
+ d->ensureStarted();
+ } else {
+ if (!d->flags.testFlag(PersistentResources)) {
+ d->releaseSwapChain();
+ d->reset();
+ }
+ }
+}
+
+void QVulkanWindowPrivate::ensureStarted()
+{
+ Q_Q(QVulkanWindow);
+ if (status == QVulkanWindowPrivate::StatusFailRetry)
+ status = QVulkanWindowPrivate::StatusUninitialized;
+ if (status == QVulkanWindowPrivate::StatusUninitialized) {
+ init();
+ if (status == QVulkanWindowPrivate::StatusDeviceReady)
+ recreateSwapChain();
+ }
+ if (status == QVulkanWindowPrivate::StatusReady)
+ q->requestUpdate();
+}
+
+/*!
+ \internal
+ */
+void QVulkanWindow::resizeEvent(QResizeEvent *)
+{
+ // Nothing to do here - recreating the swapchain is handled when building the next frame.
+}
+
+/*!
+ \internal
+ */
+bool QVulkanWindow::event(QEvent *e)
+{
+ Q_D(QVulkanWindow);
+
+ switch (e->type()) {
+ case QEvent::UpdateRequest:
+ d->beginFrame();
+ break;
+
+ // The swapchain must be destroyed before the surface as per spec. This is
+ // not ideal for us because the surface is managed by the QPlatformWindow
+ // which may be gone already when the unexpose comes, making the validation
+ // layer scream. The solution is to listen to the PlatformSurface events.
+ case QEvent::PlatformSurface:
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed) {
+ d->releaseSwapChain();
+ d->reset();
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
+
+/*!
+ Returns true if this window has successfully initialized all Vulkan
+ resources, including the swapchain.
+
+ \note Initialization happens on the first expose event after the window is
+ made visible.
+ */
+bool QVulkanWindow::isValid() const
+{
+ Q_D(const QVulkanWindow);
+ return d->status == QVulkanWindowPrivate::StatusReady;
+}
+
+/*!
+ Returns a new instance of QVulkanWindowRenderer.
+
+ This virtual function is called once during the lifetime of the window, at
+ some point after making it visible for the first time.
+
+ The default implementation returns null and so no rendering will be
+ performed apart from clearing the buffers.
+
+ The window takes ownership of the returned renderer object.
+ */
+QVulkanWindowRenderer *QVulkanWindow::createRenderer()
+{
+ return nullptr;
+}
+
+/*!
+ Virtual destructor.
+ */
+QVulkanWindowRenderer::~QVulkanWindowRenderer()
+{
+}
+
+/*!
+ This virtual function is called right before graphics initialization, that
+ ends up in calling initResources(), is about to begin.
+
+ Normally there is no need to reimplement this function. However, there are
+ cases that involve decisions based on both the physical device and the
+ surface. These cannot normally be performed before making the QVulkanWindow
+ visible since the Vulkan surface is not retrievable at that stage.
+
+ Instead, applications can reimplement this function. Here both
+ QVulkanWindow::physicalDevice() and QVulkanInstance::surfaceForWindow() are
+ functional, but no further logical device initialization has taken place
+ yet.
+
+ The default implementation is empty.
+ */
+void QVulkanWindowRenderer::preInitResources()
+{
+}
+
+/*!
+ This virtual function is called when it is time to create the renderer's
+ graphics resources.
+
+ Depending on the QVulkanWindow::PersistentResources flag, device lost
+ situations, etc. this function may be called more than once during the
+ lifetime of a QVulkanWindow. However, subsequent invocations are always
+ preceded by a call to releaseResources().
+
+ Accessors like device(), graphicsQueue() and graphicsCommandPool() are only
+ guaranteed to return valid values inside this function and afterwards, up
+ until releaseResources() is called.
+
+ The default implementation is empty.
+ */
+void QVulkanWindowRenderer::initResources()
+{
+}
+
+/*!
+ This virtual function is called when swapchain, framebuffer or renderpass
+ related initialization can be performed. Swapchain and related resources
+ are reset and then recreated in response to window resize events, and
+ therefore a pair of calls to initResources() and releaseResources() can
+ have multiple calls to initSwapChainResources() and
+ releaseSwapChainResources() calls in-between.
+
+ Accessors like QVulkanWindow::swapChainImageSize() are only guaranteed to
+ return valid values inside this function and afterwards, up until
+ releaseSwapChainResources() is called.
+
+ This is also the place where size-dependent calculations (for example, the
+ projection matrix) should be made since this function is called effectively
+ on every resize.
+
+ The default implementation is empty.
+ */
+void QVulkanWindowRenderer::initSwapChainResources()
+{
+}
+
+/*!
+ This virtual function is called when swapchain, framebuffer or renderpass
+ related resources must be released.
+
+ The implementation must be prepared that a call to this function may be
+ followed by a new call to initSwapChainResources() at a later point.
+
+ QVulkanWindow takes care of waiting for the device to become idle before
+ and after invoking this function.
+
+ The default implementation is empty.
+
+ \note This is the last place to act with all graphics resources intact
+ before QVulkanWindow starts releasing them. It is therefore essential that
+ implementations with an asynchronous, potentially multi-threaded
+ startNextFrame() perform a blocking wait and call
+ QVulkanWindow::frameReady() before returning from this function in case
+ there is a pending frame submission.
+ */
+void QVulkanWindowRenderer::releaseSwapChainResources()
+{
+}
+
+/*!
+ This virtual function is called when the renderer's graphics resources must be
+ released.
+
+ The implementation must be prepared that a call to this function may be
+ followed by an initResources() at a later point.
+
+ QVulkanWindow takes care of waiting for the device to become idle before
+ and after invoking this function.
+
+ The default implementation is empty.
+ */
+void QVulkanWindowRenderer::releaseResources()
+{
+}
+
+/*!
+ \fn QVulkanWindowRenderer::startNextFrame()
+
+ This virtual function is called when the draw calls for the next frame are
+ to be added to the command buffer.
+
+ Each call to this function must be followed by a call to
+ QVulkanWindow::frameReady(). Failing to do so will stall the rendering
+ loop. The call can also be made at a later time, after returning from this
+ function. This means that it is possible to kick off asynchronous work, and
+ only update the command buffer and notify QVulkanWindow when that work has
+ finished.
+
+ All Vulkan resources are initialized and ready when this function is
+ invoked. The current framebuffer and main command buffer can be retrieved
+ via QVulkanWindow::currentFramebuffer() and
+ QVulkanWindow::currentCommandBuffer(). The logical device and the active
+ graphics queue are available via QVulkanWindow::device() and
+ QVulkanWindow::graphicsQueue(). Implementations can create additional
+ command buffers from the pool returned by
+ QVulkanWindow::graphicsCommandPool(). For convenience, the index of a host
+ visible and device local memory type index are exposed via
+ QVulkanWindow::hostVisibleMemoryIndex() and
+ QVulkanWindow::deviceLocalMemoryIndex(). All these accessors are safe to be
+ called from any thread.
+
+ \sa QVulkanWindow::frameReady(), QVulkanWindow
+ */
+
+/*!
+ This virtual function is called when the physical device is lost, meaning
+ the creation of the logical device fails with \c{VK_ERROR_DEVICE_LOST}.
+
+ The default implementation is empty.
+
+ There is typically no need to perform anything special in this function
+ because QVulkanWindow will automatically retry to initialize itself after a
+ certain amount of time.
+
+ \sa logicalDeviceLost()
+ */
+void QVulkanWindowRenderer::physicalDeviceLost()
+{
+}
+
+/*!
+ This virtual function is called when the logical device (VkDevice) is lost,
+ meaning some operation failed with \c{VK_ERROR_DEVICE_LOST}.
+
+ The default implementation is empty.
+
+ There is typically no need to perform anything special in this function.
+ QVulkanWindow will automatically release all resources (invoking
+ releaseSwapChainResources() and releaseResources() as necessary) and will
+ attempt to reinitialize, acquiring a new device. When the physical device
+ was also lost, this reinitialization attempt may then result in
+ physicalDeviceLost().
+
+ \sa physicalDeviceLost()
+ */
+void QVulkanWindowRenderer::logicalDeviceLost()
+{
+}
+
+void QVulkanWindowPrivate::beginFrame()
+{
+ if (!swapChain || framePending)
+ return;
+
+ Q_Q(QVulkanWindow);
+ if (q->size() * q->devicePixelRatio() != swapChainImageSize) {
+ recreateSwapChain();
+ if (!swapChain)
+ return;
+ }
+
+ FrameResources &frame(frameRes[currentFrame]);
+
+ if (!frame.imageAcquired) {
+ // Wait if we are too far ahead, i.e. the thread gets throttled based on the presentation rate
+ // (note that we are using FIFO mode -> vsync)
+ if (frame.fenceWaitable) {
+ devFuncs->vkWaitForFences(dev, 1, &frame.fence, VK_TRUE, UINT64_MAX);
+ devFuncs->vkResetFences(dev, 1, &frame.fence);
+ frame.fenceWaitable = false;
+ }
+
+ // move on to next swapchain image
+ VkResult err = vkAcquireNextImageKHR(dev, swapChain, UINT64_MAX,
+ frame.imageSem, frame.fence, &currentImage);
+ if (err == VK_SUCCESS || err == VK_SUBOPTIMAL_KHR) {
+ frame.imageSemWaitable = true;
+ frame.imageAcquired = true;
+ frame.fenceWaitable = true;
+ } else if (err == VK_ERROR_OUT_OF_DATE_KHR) {
+ recreateSwapChain();
+ q->requestUpdate();
+ return;
+ } else {
+ if (!checkDeviceLost(err))
+ qWarning("QVulkanWindow: Failed to acquire next swapchain image: %d", err);
+ q->requestUpdate();
+ return;
+ }
+ }
+
+ // make sure the previous draw for the same image has finished
+ ImageResources &image(imageRes[currentImage]);
+ if (image.cmdFenceWaitable) {
+ devFuncs->vkWaitForFences(dev, 1, &image.cmdFence, VK_TRUE, UINT64_MAX);
+ devFuncs->vkResetFences(dev, 1, &image.cmdFence);
+ image.cmdFenceWaitable = false;
+ }
+
+ // build new draw command buffer
+ if (image.cmdBuf) {
+ devFuncs->vkFreeCommandBuffers(dev, cmdPool, 1, &image.cmdBuf);
+ image.cmdBuf = 0;
+ }
+
+ VkCommandBufferAllocateInfo cmdBufInfo = {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1 };
+ VkResult err = devFuncs->vkAllocateCommandBuffers(dev, &cmdBufInfo, &image.cmdBuf);
+ if (err != VK_SUCCESS) {
+ if (!checkDeviceLost(err))
+ qWarning("QVulkanWindow: Failed to allocate frame command buffer: %d", err);
+ return;
+ }
+
+ VkCommandBufferBeginInfo cmdBufBeginInfo = {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, 0, nullptr };
+ err = devFuncs->vkBeginCommandBuffer(image.cmdBuf, &cmdBufBeginInfo);
+ if (err != VK_SUCCESS) {
+ if (!checkDeviceLost(err))
+ qWarning("QVulkanWindow: Failed to begin frame command buffer: %d", err);
+ return;
+ }
+
+ if (frameGrabbing)
+ frameGrabTargetImage = QImage(swapChainImageSize, QImage::Format_RGBA8888);
+
+ if (renderer) {
+ framePending = true;
+ renderer->startNextFrame();
+ // done for now - endFrame() will get invoked when frameReady() is called back
+ } else {
+ VkClearColorValue clearColor = { { 0.0f, 0.0f, 0.0f, 1.0f } };
+ VkClearDepthStencilValue clearDS = { 1.0f, 0 };
+ VkClearValue clearValues[3];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearValues[2].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = defaultRenderPass;
+ rpBeginInfo.framebuffer = image.fb;
+ rpBeginInfo.renderArea.extent.width = swapChainImageSize.width();
+ rpBeginInfo.renderArea.extent.height = swapChainImageSize.height();
+ rpBeginInfo.clearValueCount = sampleCount > VK_SAMPLE_COUNT_1_BIT ? 3 : 2;
+ rpBeginInfo.pClearValues = clearValues;
+ devFuncs->vkCmdBeginRenderPass(image.cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+ devFuncs->vkCmdEndRenderPass(image.cmdBuf);
+
+ endFrame();
+ }
+}
+
+void QVulkanWindowPrivate::endFrame()
+{
+ Q_Q(QVulkanWindow);
+
+ FrameResources &frame(frameRes[currentFrame]);
+ ImageResources &image(imageRes[currentImage]);
+
+ if (gfxQueueFamilyIdx != presQueueFamilyIdx && !frameGrabbing) {
+ // Add the swapchain image release to the command buffer that will be
+ // submitted to the graphics queue.
+ VkImageMemoryBarrier presTrans;
+ memset(&presTrans, 0, sizeof(presTrans));
+ presTrans.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ presTrans.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ presTrans.oldLayout = presTrans.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ presTrans.srcQueueFamilyIndex = gfxQueueFamilyIdx;
+ presTrans.dstQueueFamilyIndex = presQueueFamilyIdx;
+ presTrans.image = image.image;
+ presTrans.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ presTrans.subresourceRange.levelCount = presTrans.subresourceRange.layerCount = 1;
+ devFuncs->vkCmdPipelineBarrier(image.cmdBuf,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &presTrans);
+ }
+
+ // When grabbing a frame, add a readback at the end and skip presenting.
+ if (frameGrabbing)
+ addReadback();
+
+ VkResult err = devFuncs->vkEndCommandBuffer(image.cmdBuf);
+ if (err != VK_SUCCESS) {
+ if (!checkDeviceLost(err))
+ qWarning("QVulkanWindow: Failed to end frame command buffer: %d", err);
+ return;
+ }
+
+ // submit draw calls
+ VkSubmitInfo submitInfo;
+ memset(&submitInfo, 0, sizeof(submitInfo));
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &image.cmdBuf;
+ if (frame.imageSemWaitable) {
+ submitInfo.waitSemaphoreCount = 1;
+ submitInfo.pWaitSemaphores = &frame.imageSem;
+ }
+ if (!frameGrabbing) {
+ submitInfo.signalSemaphoreCount = 1;
+ submitInfo.pSignalSemaphores = &frame.drawSem;
+ }
+ VkPipelineStageFlags psf = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ submitInfo.pWaitDstStageMask = &psf;
+
+ Q_ASSERT(!image.cmdFenceWaitable);
+
+ err = devFuncs->vkQueueSubmit(gfxQueue, 1, &submitInfo, image.cmdFence);
+ if (err == VK_SUCCESS) {
+ frame.imageSemWaitable = false;
+ image.cmdFenceWaitable = true;
+ } else {
+ if (!checkDeviceLost(err))
+ qWarning("QVulkanWindow: Failed to submit to graphics queue: %d", err);
+ return;
+ }
+
+ // block and then bail out when grabbing
+ if (frameGrabbing) {
+ finishBlockingReadback();
+ frameGrabbing = false;
+ // Leave frame.imageAcquired set to true.
+ // Do not change currentFrame.
+ emit q->frameGrabbed(frameGrabTargetImage);
+ return;
+ }
+
+ if (gfxQueueFamilyIdx != presQueueFamilyIdx) {
+ // Submit the swapchain image acquire to the present queue.
+ submitInfo.pWaitSemaphores = &frame.drawSem;
+ submitInfo.pSignalSemaphores = &frame.presTransSem;
+ submitInfo.pCommandBuffers = &image.presTransCmdBuf; // must be USAGE_SIMULTANEOUS
+ err = devFuncs->vkQueueSubmit(presQueue, 1, &submitInfo, VK_NULL_HANDLE);
+ if (err != VK_SUCCESS) {
+ if (!checkDeviceLost(err))
+ qWarning("QVulkanWindow: Failed to submit to present queue: %d", err);
+ return;
+ }
+ }
+
+ // queue present
+ VkPresentInfoKHR presInfo;
+ memset(&presInfo, 0, sizeof(presInfo));
+ presInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ presInfo.swapchainCount = 1;
+ presInfo.pSwapchains = &swapChain;
+ presInfo.pImageIndices = &currentImage;
+ presInfo.waitSemaphoreCount = 1;
+ presInfo.pWaitSemaphores = gfxQueueFamilyIdx == presQueueFamilyIdx ? &frame.drawSem : &frame.presTransSem;
+
+ err = vkQueuePresentKHR(gfxQueue, &presInfo);
+ if (err != VK_SUCCESS) {
+ if (err == VK_ERROR_OUT_OF_DATE_KHR) {
+ recreateSwapChain();
+ q->requestUpdate();
+ return;
+ } else if (err != VK_SUBOPTIMAL_KHR) {
+ if (!checkDeviceLost(err))
+ qWarning("QVulkanWindow: Failed to present: %d", err);
+ return;
+ }
+ }
+
+ frame.imageAcquired = false;
+
+ inst->presentQueued(q);
+
+ currentFrame = (currentFrame + 1) % frameLag;
+}
+
+/*!
+ This function must be called exactly once in response to each invocation of
+ the QVulkanWindowRenderer::startNextFrame() implementation. At the time of
+ this call, the main command buffer, exposed via currentCommandBuffer(),
+ must have all necessary rendering commands added to it since this function
+ will trigger submitting the commands and queuing the present command.
+
+ \note This function must only be called from the gui/main thread, which is
+ where QVulkanWindowRenderer's functions are invoked and where the
+ QVulkanWindow instance lives.
+
+ \sa QVulkanWindowRenderer::startNextFrame()
+ */
+void QVulkanWindow::frameReady()
+{
+ Q_ASSERT_X(QThread::currentThread() == QCoreApplication::instance()->thread(),
+ "QVulkanWindow", "frameReady() can only be called from the GUI (main) thread");
+
+ Q_D(QVulkanWindow);
+
+ if (!d->framePending) {
+ qWarning("QVulkanWindow: frameReady() called without a corresponding startNextFrame()");
+ return;
+ }
+
+ d->framePending = false;
+
+ d->endFrame();
+}
+
+bool QVulkanWindowPrivate::checkDeviceLost(VkResult err)
+{
+ if (err == VK_ERROR_DEVICE_LOST) {
+ qWarning("QVulkanWindow: Device lost");
+ if (renderer)
+ renderer->logicalDeviceLost();
+ qCDebug(lcVk, "Releasing all resources due to device lost");
+ releaseSwapChain();
+ reset();
+ qCDebug(lcVk, "Restarting");
+ ensureStarted();
+ return true;
+ }
+ return false;
+}
+
+void QVulkanWindowPrivate::addReadback()
+{
+ VkImageCreateInfo imageInfo;
+ memset(&imageInfo, 0, sizeof(imageInfo));
+ imageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
+ imageInfo.imageType = VK_IMAGE_TYPE_2D;
+ imageInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
+ imageInfo.extent.width = frameGrabTargetImage.width();
+ imageInfo.extent.height = frameGrabTargetImage.height();
+ imageInfo.extent.depth = 1;
+ imageInfo.mipLevels = 1;
+ imageInfo.arrayLayers = 1;
+ imageInfo.samples = VK_SAMPLE_COUNT_1_BIT;
+ imageInfo.tiling = VK_IMAGE_TILING_LINEAR;
+ imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
+ imageInfo.initialLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+
+ VkResult err = devFuncs->vkCreateImage(dev, &imageInfo, nullptr, &frameGrabImage);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to create image for readback: %d", err);
+ return;
+ }
+
+ VkMemoryRequirements memReq;
+ devFuncs->vkGetImageMemoryRequirements(dev, frameGrabImage, &memReq);
+
+ VkMemoryAllocateInfo allocInfo = {
+ VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ nullptr,
+ memReq.size,
+ hostVisibleMemIndex
+ };
+
+ err = devFuncs->vkAllocateMemory(dev, &allocInfo, nullptr, &frameGrabImageMem);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to allocate memory for readback image: %d", err);
+ return;
+ }
+
+ err = devFuncs->vkBindImageMemory(dev, frameGrabImage, frameGrabImageMem, 0);
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to bind readback image memory: %d", err);
+ return;
+ }
+
+ ImageResources &image(imageRes[currentImage]);
+
+ VkImageMemoryBarrier barrier;
+ memset(&barrier, 0, sizeof(barrier));
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ barrier.subresourceRange.levelCount = barrier.subresourceRange.layerCount = 1;
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
+ barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
+ barrier.image = image.image;
+
+ devFuncs->vkCmdPipelineBarrier(image.cmdBuf,
+ VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_PREINITIALIZED;
+ barrier.newLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.srcAccessMask = 0;
+ barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.image = frameGrabImage;
+
+ devFuncs->vkCmdPipelineBarrier(image.cmdBuf,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+
+ VkImageCopy copyInfo;
+ memset(&copyInfo, 0, sizeof(copyInfo));
+ copyInfo.srcSubresource.aspectMask = copyInfo.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ copyInfo.srcSubresource.layerCount = copyInfo.dstSubresource.layerCount = 1;
+ copyInfo.extent.width = frameGrabTargetImage.width();
+ copyInfo.extent.height = frameGrabTargetImage.height();
+ copyInfo.extent.depth = 1;
+
+ devFuncs->vkCmdCopyImage(image.cmdBuf, image.image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
+ frameGrabImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, &copyInfo);
+
+ barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
+ barrier.newLayout = VK_IMAGE_LAYOUT_GENERAL;
+ barrier.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
+ barrier.dstAccessMask = VK_ACCESS_HOST_READ_BIT;
+ barrier.image = frameGrabImage;
+
+ devFuncs->vkCmdPipelineBarrier(image.cmdBuf,
+ VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
+ VK_PIPELINE_STAGE_TRANSFER_BIT,
+ 0, 0, nullptr, 0, nullptr,
+ 1, &barrier);
+}
+
+void QVulkanWindowPrivate::finishBlockingReadback()
+{
+ ImageResources &image(imageRes[currentImage]);
+
+ // Block until the current frame is done. Normally this wait would only be
+ // done in current + concurrentFrameCount().
+ devFuncs->vkWaitForFences(dev, 1, &image.cmdFence, VK_TRUE, UINT64_MAX);
+ devFuncs->vkResetFences(dev, 1, &image.cmdFence);
+ // will reuse the same image for the next "real" frame, do not wait then
+ image.cmdFenceWaitable = false;
+
+ VkImageSubresource subres = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0 };
+ VkSubresourceLayout layout;
+ devFuncs->vkGetImageSubresourceLayout(dev, frameGrabImage, &subres, &layout);
+
+ uchar *p;
+ VkResult err = devFuncs->vkMapMemory(dev, frameGrabImageMem, layout.offset, layout.size, 0, reinterpret_cast<void **>(&p));
+ if (err != VK_SUCCESS) {
+ qWarning("QVulkanWindow: Failed to map readback image memory after transfer: %d", err);
+ return;
+ }
+
+ for (int y = 0; y < frameGrabTargetImage.height(); ++y) {
+ memcpy(frameGrabTargetImage.scanLine(y), p, frameGrabTargetImage.width() * 4);
+ p += layout.rowPitch;
+ }
+
+ devFuncs->vkUnmapMemory(dev, frameGrabImageMem);
+
+ devFuncs->vkDestroyImage(dev, frameGrabImage, nullptr);
+ frameGrabImage = VK_NULL_HANDLE;
+ devFuncs->vkFreeMemory(dev, frameGrabImageMem, nullptr);
+ frameGrabImageMem = VK_NULL_HANDLE;
+}
+
+/*!
+ Returns the active physical device.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::preInitResources() up until
+ QVulkanWindowRenderer::releaseResources().
+ */
+VkPhysicalDevice QVulkanWindow::physicalDevice() const
+{
+ Q_D(const QVulkanWindow);
+ if (d->physDevIndex < d->physDevs.count())
+ return d->physDevs[d->physDevIndex];
+ qWarning("QVulkanWindow: Physical device not available");
+ return VK_NULL_HANDLE;
+}
+
+/*!
+ Returns a pointer to the properties for the active physical device.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::preInitResources() up until
+ QVulkanWindowRenderer::releaseResources().
+ */
+const VkPhysicalDeviceProperties *QVulkanWindow::physicalDeviceProperties() const
+{
+ Q_D(const QVulkanWindow);
+ if (d->physDevIndex < d->physDevProps.count())
+ return &d->physDevProps[d->physDevIndex];
+ qWarning("QVulkanWindow: Physical device properties not available");
+ return nullptr;
+}
+
+/*!
+ Returns the active logical device.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initResources() up until
+ QVulkanWindowRenderer::releaseResources().
+ */
+VkDevice QVulkanWindow::device() const
+{
+ Q_D(const QVulkanWindow);
+ return d->dev;
+}
+
+/*!
+ Returns the active graphics queue.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initResources() up until
+ QVulkanWindowRenderer::releaseResources().
+ */
+VkQueue QVulkanWindow::graphicsQueue() const
+{
+ Q_D(const QVulkanWindow);
+ return d->gfxQueue;
+}
+
+/*!
+ Returns the active graphics command pool.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initResources() up until
+ QVulkanWindowRenderer::releaseResources().
+ */
+VkCommandPool QVulkanWindow::graphicsCommandPool() const
+{
+ Q_D(const QVulkanWindow);
+ return d->cmdPool;
+}
+
+/*!
+ Returns a host visible memory type index suitable for general use.
+
+ The returned memory type will be both host visible and coherent. In
+ addition, it will also be cached, if possible.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initResources() up until
+ QVulkanWindowRenderer::releaseResources().
+ */
+uint32_t QVulkanWindow::hostVisibleMemoryIndex() const
+{
+ Q_D(const QVulkanWindow);
+ return d->hostVisibleMemIndex;
+}
+
+/*!
+ Returns a device local memory type index suitable for general use.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initResources() up until
+ QVulkanWindowRenderer::releaseResources().
+ */
+uint32_t QVulkanWindow::deviceLocalMemoryIndex() const
+{
+ Q_D(const QVulkanWindow);
+ return d->deviceLocalMemIndex;
+}
+
+/*!
+ Returns a typical render pass with one sub-pass.
+
+ \note Applications are not required to use this render pass. However, they
+ are then responsible for ensuring the current swap chain and depth-stencil
+ images get transitioned from \c{VK_IMAGE_LAYOUT_UNDEFINED} to
+ \c{VK_IMAGE_LAYOUT_PRESENT_SRC_KHR} and
+ \c{VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL} either via the
+ application's custom render pass or by other means.
+
+ \note Stencil read/write is not enabled in this render pass.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initResources() up until
+ QVulkanWindowRenderer::releaseResources().
+
+ \sa currentFramebuffer()
+ */
+VkRenderPass QVulkanWindow::defaultRenderPass() const
+{
+ Q_D(const QVulkanWindow);
+ return d->defaultRenderPass;
+}
+
+/*!
+ Returns the color buffer format used by the swapchain.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initResources() up until
+ QVulkanWindowRenderer::releaseResources().
+
+ \sa setPreferredColorFormats()
+ */
+VkFormat QVulkanWindow::colorFormat() const
+{
+ Q_D(const QVulkanWindow);
+ return d->colorFormat;
+}
+
+/*!
+ Returns the format used by the depth-stencil buffer(s).
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initResources() up until
+ QVulkanWindowRenderer::releaseResources().
+ */
+VkFormat QVulkanWindow::depthStencilFormat() const
+{
+ Q_D(const QVulkanWindow);
+ return d->dsFormat;
+}
+
+/*!
+ Returns the image size of the swapchain.
+
+ This usually matches the size of the window, but may also differ in case
+ \c vkGetPhysicalDeviceSurfaceCapabilitiesKHR reports a fixed size.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initSwapChainResources() up until
+ QVulkanWindowRenderer::releaseSwapChainResources().
+ */
+QSize QVulkanWindow::swapChainImageSize() const
+{
+ Q_D(const QVulkanWindow);
+ return d->swapChainImageSize;
+}
+
+/*!
+ Returns The active command buffer for the current swap chain image.
+ Implementations of QVulkanWindowRenderer::startNextFrame() are expected to
+ add commands to this command buffer.
+
+ \note This function must only be called from within startNextFrame() and, in
+ case of asynchronous command generation, up until the call to frameReady().
+ */
+VkCommandBuffer QVulkanWindow::currentCommandBuffer() const
+{
+ Q_D(const QVulkanWindow);
+ if (!d->framePending) {
+ qWarning("QVulkanWindow: Attempted to call currentCommandBuffer() without an active frame");
+ return VK_NULL_HANDLE;
+ }
+ return d->imageRes[d->currentImage].cmdBuf;
+}
+
+/*!
+ Returns a VkFramebuffer for the current swapchain image using the default
+ render pass.
+
+ The framebuffer has two attachments (color, depth-stencil) when
+ multisampling is not in use, and three (color resolve, depth-stencil,
+ multisample color) when sampleCountFlagBits() is greater than
+ \c{VK_SAMPLE_COUNT_1_BIT}. Renderers must take this into account, for
+ example when providing clear values.
+
+ \note Applications are not required to use this framebuffer in case they
+ provide their own render pass instead of using the one returned from
+ defaultRenderPass().
+
+ \note This function must only be called from within startNextFrame() and, in
+ case of asynchronous command generation, up until the call to frameReady().
+
+ \sa defaultRenderPass()
+ */
+VkFramebuffer QVulkanWindow::currentFramebuffer() const
+{
+ Q_D(const QVulkanWindow);
+ if (!d->framePending) {
+ qWarning("QVulkanWindow: Attempted to call currentFramebuffer() without an active frame");
+ return VK_NULL_HANDLE;
+ }
+ return d->imageRes[d->currentImage].fb;
+}
+
+/*!
+ Returns the current frame index in the range [0, concurrentFrameCount() - 1].
+
+ Renderer implementations will have to ensure that uniform data and other
+ dynamic resources exist in multiple copies, in order to prevent frame N
+ altering the data used by the still-active frames N - 1, N - 2, ... N -
+ concurrentFrameCount() + 1.
+
+ To avoid relying on dynamic array sizes, applications can use
+ MAX_CONCURRENT_FRAME_COUNT when declaring arrays. This is guaranteed to be
+ always equal to or greater than the value returned from
+ concurrentFrameCount(). Such arrays can then be indexed by the value
+ returned from this function.
+
+ \code
+ class Renderer {
+ ...
+ VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+ };
+
+ void Renderer::startNextFrame()
+ {
+ VkDescriptorBufferInfo &uniformBufInfo(m_uniformBufInfo[m_window->currentFrame()]);
+ ...
+ }
+ \endcode
+
+ \note This function must only be called from within startNextFrame() and, in
+ case of asynchronous command generation, up until the call to frameReady().
+
+ \sa concurrentFrameCount()
+ */
+int QVulkanWindow::currentFrame() const
+{
+ Q_D(const QVulkanWindow);
+ if (!d->framePending)
+ qWarning("QVulkanWindow: Attempted to call currentFrame() without an active frame");
+ return d->currentFrame;
+}
+
+/*!
+ \variable QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT
+
+ \brief A constant value that is always equal to or greater than the maximum value
+ of concurrentFrameCount().
+ */
+
+/*!
+ Returns the number of frames that can be potentially active at the same time.
+
+ \note The value is constant for the entire lifetime of the QVulkanWindow.
+
+ \code
+ class Renderer {
+ ...
+ VkDescriptorBufferInfo m_uniformBufInfo[QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT];
+ };
+
+ void Renderer::startNextFrame()
+ {
+ const int count = m_window->concurrentFrameCount();
+ for (int i = 0; i < count; ++i)
+ m_uniformBufInfo[i] = ...
+ ...
+ }
+ \endcode
+
+ \sa currentFrame()
+ */
+int QVulkanWindow::concurrentFrameCount() const
+{
+ Q_D(const QVulkanWindow);
+ return d->frameLag;
+}
+
+/*!
+ Returns the number of images in the swap chain.
+
+ \note Accessing this is necessary when providing a custom render pass and
+ framebuffer. The framebuffer is specific to the current swapchain image and
+ hence the application must provide multiple framebuffers.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initSwapChainResources() up until
+ QVulkanWindowRenderer::releaseSwapChainResources().
+ */
+int QVulkanWindow::swapChainImageCount() const
+{
+ Q_D(const QVulkanWindow);
+ return d->swapChainBufferCount;
+}
+
+/*!
+ Returns the current swap chain image index in the range [0, swapChainImageCount() - 1].
+
+ \note This function must only be called from within startNextFrame() and, in
+ case of asynchronous command generation, up until the call to frameReady().
+ */
+int QVulkanWindow::currentSwapChainImageIndex() const
+{
+ Q_D(const QVulkanWindow);
+ if (!d->framePending)
+ qWarning("QVulkanWindow: Attempted to call currentSwapChainImageIndex() without an active frame");
+ return d->currentImage;
+}
+
+/*!
+ Returns the specified swap chain image.
+
+ \a idx must be in the range [0, swapChainImageCount() - 1].
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initSwapChainResources() up until
+ QVulkanWindowRenderer::releaseSwapChainResources().
+ */
+VkImage QVulkanWindow::swapChainImage(int idx) const
+{
+ Q_D(const QVulkanWindow);
+ return idx >= 0 && idx < d->swapChainBufferCount ? d->imageRes[idx].image : VK_NULL_HANDLE;
+}
+
+/*!
+ Returns the specified swap chain image view.
+
+ \a idx must be in the range [0, swapChainImageCount() - 1].
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initSwapChainResources() up until
+ QVulkanWindowRenderer::releaseSwapChainResources().
+ */
+VkImageView QVulkanWindow::swapChainImageView(int idx) const
+{
+ Q_D(const QVulkanWindow);
+ return idx >= 0 && idx < d->swapChainBufferCount ? d->imageRes[idx].imageView : VK_NULL_HANDLE;
+}
+
+/*!
+ Returns the depth-stencil image.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initSwapChainResources() up until
+ QVulkanWindowRenderer::releaseSwapChainResources().
+ */
+VkImage QVulkanWindow::depthStencilImage() const
+{
+ Q_D(const QVulkanWindow);
+ return d->dsImage;
+}
+
+/*!
+ Returns the depth-stencil image view.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initSwapChainResources() up until
+ QVulkanWindowRenderer::releaseSwapChainResources().
+ */
+VkImageView QVulkanWindow::depthStencilImageView() const
+{
+ Q_D(const QVulkanWindow);
+ return d->dsView;
+}
+
+/*!
+ Returns the current sample count as a \c VkSampleCountFlagBits value.
+
+ When targeting the default render target, the \c rasterizationSamples field
+ of \c VkPipelineMultisampleStateCreateInfo must be set to this value.
+
+ \sa setSampleCount(), supportedSampleCounts()
+ */
+VkSampleCountFlagBits QVulkanWindow::sampleCountFlagBits() const
+{
+ Q_D(const QVulkanWindow);
+ return d->sampleCount;
+}
+
+/*!
+ Returns the specified multisample color image, or \c{VK_NULL_HANDLE} if
+ multisampling is not in use.
+
+ \a idx must be in the range [0, swapChainImageCount() - 1].
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initSwapChainResources() up until
+ QVulkanWindowRenderer::releaseSwapChainResources().
+ */
+VkImage QVulkanWindow::msaaColorImage(int idx) const
+{
+ Q_D(const QVulkanWindow);
+ return idx >= 0 && idx < d->swapChainBufferCount ? d->imageRes[idx].msaaImage : VK_NULL_HANDLE;
+}
+
+/*!
+ Returns the specified multisample color image view, or \c{VK_NULL_HANDLE} if
+ multisampling is not in use.
+
+ \a idx must be in the range [0, swapChainImageCount() - 1].
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initSwapChainResources() up until
+ QVulkanWindowRenderer::releaseSwapChainResources().
+ */
+VkImageView QVulkanWindow::msaaColorImageView(int idx) const
+{
+ Q_D(const QVulkanWindow);
+ return idx >= 0 && idx < d->swapChainBufferCount ? d->imageRes[idx].msaaImageView : VK_NULL_HANDLE;
+}
+
+/*!
+ Returns true if the swapchain supports usage as transfer source, meaning
+ grab() is functional.
+
+ \note Calling this function is only valid from the invocation of
+ QVulkanWindowRenderer::initSwapChainResources() up until
+ QVulkanWindowRenderer::releaseSwapChainResources().
+ */
+bool QVulkanWindow::supportsGrab() const
+{
+ Q_D(const QVulkanWindow);
+ return d->swapChainSupportsReadBack;
+}
+
+/*!
+ \fn void QVulkanWindow::frameGrabbed(const QImage &image)
+
+ This signal is emitted when the \a image is ready.
+*/
+
+/*!
+ Builds and renders the next frame without presenting it, then performs a
+ blocking readback of the image content.
+
+ Returns the image if the renderer's
+ \l{QVulkanWindowRenderer::startNextFrame()}{startNextFrame()}
+ implementation calls back frameReady() directly. Otherwise, returns an
+ incomplete image, that has the correct size but not the content yet. The
+ content will be delivered via the frameGrabbed() signal in the latter case.
+
+ \note This function should not be called when a frame is in progress
+ (that is, frameReady() has not yet been called back by the application).
+
+ \note This function is potentially expensive due to the additional,
+ blocking readback.
+
+ \note This function currently requires that the swapchain supports usage as
+ a transfer source (\c{VK_IMAGE_USAGE_TRANSFER_SRC_BIT}), and will fail otherwise.
+ */
+QImage QVulkanWindow::grab()
+{
+ Q_D(QVulkanWindow);
+ if (!d->swapChain) {
+ qWarning("QVulkanWindow: Attempted to call grab() without a swapchain");
+ return QImage();
+ }
+ if (d->framePending) {
+ qWarning("QVulkanWindow: Attempted to call grab() while a frame is still pending");
+ return QImage();
+ }
+ if (!d->swapChainSupportsReadBack) {
+ qWarning("QVulkanWindow: Attempted to call grab() with a swapchain that does not support usage as transfer source");
+ return QImage();
+ }
+
+ d->frameGrabbing = true;
+ d->beginFrame();
+
+ return d->frameGrabTargetImage;
+}
+
+/*!
+ Returns a QMatrix4x4 that can be used to correct for coordinate
+ system differences between OpenGL and Vulkan.
+
+ By pre-multiplying the projection matrix with this matrix, applications can
+ continue to assume OpenGL-style Y coordinates in clip space (i.e. Y pointing
+ upwards), and can set minDepth and maxDepth to 0 and 1, respectively,
+ without any further corrections to the vertex Z positions, while using the
+ projection matrices retrieved from the QMatrix4x4 functions, such as
+ QMatrix4x4::perspective(), as-is.
+
+ \note With vertex data following the default OpenGL rules (that is, the
+ front face being CCW), the correct winding order in the rasterization state
+ after applying this matrix is clockwise (\c{VK_FRONT_FACE_CLOCKWISE}).
+ */
+QMatrix4x4 QVulkanWindow::clipCorrectionMatrix()
+{
+ Q_D(QVulkanWindow);
+ if (d->m_clipCorrect.isIdentity()) {
+ // NB the ctor takes row-major
+ d->m_clipCorrect = QMatrix4x4(1.0f, 0.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 0.5f, 0.5f,
+ 0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ return d->m_clipCorrect;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/vulkan/qvulkanwindow.h b/src/gui/vulkan/qvulkanwindow.h
new file mode 100644
index 0000000000..65249ecbfc
--- /dev/null
+++ b/src/gui/vulkan/qvulkanwindow.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVULKANWINDOW_H
+#define QVULKANWINDOW_H
+
+#include <QtGui/qtguiglobal.h>
+
+#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+
+#include <QtGui/qvulkaninstance.h>
+#include <QtGui/qwindow.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qmatrix4x4.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVulkanWindowPrivate;
+
+class Q_GUI_EXPORT QVulkanWindowRenderer
+{
+public:
+ virtual ~QVulkanWindowRenderer();
+
+ virtual void preInitResources();
+ virtual void initResources();
+ virtual void initSwapChainResources();
+ virtual void releaseSwapChainResources();
+ virtual void releaseResources();
+
+ virtual void startNextFrame() = 0;
+
+ virtual void physicalDeviceLost();
+ virtual void logicalDeviceLost();
+};
+
+class Q_GUI_EXPORT QVulkanWindow : public QWindow
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QVulkanWindow)
+
+public:
+ enum Flag {
+ PersistentResources = 0x01
+ };
+ Q_DECLARE_FLAGS(Flags, Flag)
+
+ explicit QVulkanWindow(QWindow *parent = nullptr);
+ ~QVulkanWindow();
+
+ void setFlags(Flags flags);
+ Flags flags() const;
+
+ QVector<VkPhysicalDeviceProperties> availablePhysicalDevices();
+ void setPhysicalDeviceIndex(int idx);
+
+ QVulkanInfoVector<QVulkanExtension> supportedDeviceExtensions();
+ void setDeviceExtensions(const QByteArrayList &extensions);
+
+ void setPreferredColorFormats(const QVector<VkFormat> &formats);
+
+ QVector<int> supportedSampleCounts();
+ void setSampleCount(int sampleCount);
+
+ bool isValid() const;
+
+ virtual QVulkanWindowRenderer *createRenderer();
+ void frameReady();
+
+ VkPhysicalDevice physicalDevice() const;
+ const VkPhysicalDeviceProperties *physicalDeviceProperties() const;
+ VkDevice device() const;
+ VkQueue graphicsQueue() const;
+ VkCommandPool graphicsCommandPool() const;
+ uint32_t hostVisibleMemoryIndex() const;
+ uint32_t deviceLocalMemoryIndex() const;
+ VkRenderPass defaultRenderPass() const;
+
+ VkFormat colorFormat() const;
+ VkFormat depthStencilFormat() const;
+ QSize swapChainImageSize() const;
+
+ VkCommandBuffer currentCommandBuffer() const;
+ VkFramebuffer currentFramebuffer() const;
+ int currentFrame() const;
+
+ static const int MAX_CONCURRENT_FRAME_COUNT = 3;
+ int concurrentFrameCount() const;
+
+ int swapChainImageCount() const;
+ int currentSwapChainImageIndex() const;
+ VkImage swapChainImage(int idx) const;
+ VkImageView swapChainImageView(int idx) const;
+ VkImage depthStencilImage() const;
+ VkImageView depthStencilImageView() const;
+
+ VkSampleCountFlagBits sampleCountFlagBits() const;
+ VkImage msaaColorImage(int idx) const;
+ VkImageView msaaColorImageView(int idx) const;
+
+ bool supportsGrab() const;
+ QImage grab();
+
+ QMatrix4x4 clipCorrectionMatrix();
+
+Q_SIGNALS:
+ void frameGrabbed(const QImage &image);
+
+protected:
+ void exposeEvent(QExposeEvent *) override;
+ void resizeEvent(QResizeEvent *) override;
+ bool event(QEvent *) override;
+
+private:
+ Q_DISABLE_COPY(QVulkanWindow)
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QVulkanWindow::Flags)
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(vulkan)
+
+#endif
diff --git a/src/gui/vulkan/qvulkanwindow_p.h b/src/gui/vulkan/qvulkanwindow_p.h
new file mode 100644
index 0000000000..c6a772bc31
--- /dev/null
+++ b/src/gui/vulkan/qvulkanwindow_p.h
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVULKANWINDOW_P_H
+#define QVULKANWINDOW_P_H
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
+
+#include "qvulkanwindow.h"
+#include <QtCore/QHash>
+#include <private/qwindow_p.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QVulkanWindowPrivate : public QWindowPrivate
+{
+ Q_DECLARE_PUBLIC(QVulkanWindow)
+
+public:
+ ~QVulkanWindowPrivate();
+
+ void ensureStarted();
+ void init();
+ void reset();
+ bool createDefaultRenderPass();
+ void recreateSwapChain();
+ uint32_t chooseTransientImageMemType(VkImage img, uint32_t startIndex);
+ bool createTransientImage(VkFormat format, VkImageUsageFlags usage, VkImageAspectFlags aspectMask,
+ VkImage *images, VkDeviceMemory *mem, VkImageView *views, int count);
+ void releaseSwapChain();
+ void beginFrame();
+ void endFrame();
+ bool checkDeviceLost(VkResult err);
+ void addReadback();
+ void finishBlockingReadback();
+
+ enum Status {
+ StatusUninitialized,
+ StatusFail,
+ StatusFailRetry,
+ StatusDeviceReady,
+ StatusReady
+ };
+ Status status = StatusUninitialized;
+ QVulkanWindowRenderer *renderer = nullptr;
+ QVulkanInstance *inst = nullptr;
+ VkSurfaceKHR surface = VK_NULL_HANDLE;
+ int physDevIndex = 0;
+ QVector<VkPhysicalDevice> physDevs;
+ QVector<VkPhysicalDeviceProperties> physDevProps;
+ QVulkanWindow::Flags flags = 0;
+ QByteArrayList requestedDevExtensions;
+ QHash<VkPhysicalDevice, QVulkanInfoVector<QVulkanExtension> > supportedDevExtensions;
+ QVector<VkFormat> requestedColorFormats;
+ VkSampleCountFlagBits sampleCount = VK_SAMPLE_COUNT_1_BIT;
+
+ VkDevice dev = VK_NULL_HANDLE;
+ QVulkanDeviceFunctions *devFuncs;
+ uint32_t gfxQueueFamilyIdx;
+ uint32_t presQueueFamilyIdx;
+ VkQueue gfxQueue;
+ VkQueue presQueue;
+ VkCommandPool cmdPool = VK_NULL_HANDLE;
+ VkCommandPool presCmdPool = VK_NULL_HANDLE;
+ uint32_t hostVisibleMemIndex;
+ uint32_t deviceLocalMemIndex;
+ VkFormat colorFormat;
+ VkColorSpaceKHR colorSpace;
+ VkFormat dsFormat = VK_FORMAT_D24_UNORM_S8_UINT;
+
+ PFN_vkCreateSwapchainKHR vkCreateSwapchainKHR = nullptr;
+ PFN_vkDestroySwapchainKHR vkDestroySwapchainKHR;
+ PFN_vkGetSwapchainImagesKHR vkGetSwapchainImagesKHR;
+ PFN_vkAcquireNextImageKHR vkAcquireNextImageKHR;
+ PFN_vkQueuePresentKHR vkQueuePresentKHR;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR vkGetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr;
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR vkGetPhysicalDeviceSurfaceFormatsKHR;
+
+ static const int MAX_SWAPCHAIN_BUFFER_COUNT = 3;
+ static const int MAX_FRAME_LAG = QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT;
+ // QVulkanWindow only supports the always available FIFO mode. The
+ // rendering thread will get throttled to the presentation rate (vsync).
+ // This is in effect Example 5 from the VK_KHR_swapchain spec.
+ VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
+ int swapChainBufferCount = 2;
+ int frameLag = 2;
+
+ QSize swapChainImageSize;
+ VkSwapchainKHR swapChain = VK_NULL_HANDLE;
+ bool swapChainSupportsReadBack = false;
+
+ struct ImageResources {
+ VkImage image = VK_NULL_HANDLE;
+ VkImageView imageView = VK_NULL_HANDLE;
+ VkCommandBuffer cmdBuf = VK_NULL_HANDLE;
+ VkFence cmdFence = VK_NULL_HANDLE;
+ bool cmdFenceWaitable = false;
+ VkFramebuffer fb = VK_NULL_HANDLE;
+ VkCommandBuffer presTransCmdBuf = VK_NULL_HANDLE;
+ VkImage msaaImage = VK_NULL_HANDLE;
+ VkImageView msaaImageView = VK_NULL_HANDLE;
+ } imageRes[MAX_SWAPCHAIN_BUFFER_COUNT];
+
+ VkDeviceMemory msaaImageMem = VK_NULL_HANDLE;
+
+ uint32_t currentImage;
+
+ struct FrameResources {
+ VkFence fence = VK_NULL_HANDLE;
+ bool fenceWaitable = false;
+ VkSemaphore imageSem = VK_NULL_HANDLE;
+ VkSemaphore drawSem = VK_NULL_HANDLE;
+ VkSemaphore presTransSem = VK_NULL_HANDLE;
+ bool imageAcquired = false;
+ bool imageSemWaitable = false;
+ } frameRes[MAX_FRAME_LAG];
+
+ uint32_t currentFrame;
+
+ VkRenderPass defaultRenderPass = VK_NULL_HANDLE;
+
+ VkDeviceMemory dsMem = VK_NULL_HANDLE;
+ VkImage dsImage = VK_NULL_HANDLE;
+ VkImageView dsView = VK_NULL_HANDLE;
+
+ bool framePending = false;
+ bool frameGrabbing = false;
+ QImage frameGrabTargetImage;
+ VkImage frameGrabImage = VK_NULL_HANDLE;
+ VkDeviceMemory frameGrabImageMem = VK_NULL_HANDLE;
+
+ QMatrix4x4 m_clipCorrect;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_CONFIG(vulkan)
+
+#endif
diff --git a/src/gui/vulkan/vk.xml b/src/gui/vulkan/vk.xml
new file mode 100644
index 0000000000..779875b819
--- /dev/null
+++ b/src/gui/vulkan/vk.xml
@@ -0,0 +1,5269 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<registry>
+ <comment>
+Copyright (c) 2015-2017 The Khronos Group Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Materials.
+
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
+
+------------------------------------------------------------------------
+
+This file, vk.xml, is the Vulkan API Registry. It is a critically important
+and normative part of the Vulkan Specification, including a canonical
+machine-readable definition of the API, parameter and member validation
+language incorporated into the Specification and reference pages, and other
+material which is registered by Khronos, such as tags used by extension and
+layer authors. The only authoritative version of vk.xml is the one
+maintained in the master branch of the Khronos Vulkan GitHub project.
+ </comment>
+
+ <!-- SECTION: Vulkan vendor IDs for physical devices without PCI vendor IDs -->
+ <vendorids>
+ <vendorid name="KHR" id="0x10000" comment="This is the next available Khronos vendor ID"/>
+ <vendorid name="VIV" id="0x10001" comment="Vivante vendor ID"/>
+ <vendorid name="VSI" id="0x10002" comment="VeriSilicon vendor ID"/>
+ </vendorids>
+
+ <!-- SECTION: Vulkan vendor/author tags for extensions and layers -->
+ <tags>
+ <tag name="IMG" author="Imagination Technologies" contact="Michael Worcester @michaelworcester"/>
+ <tag name="AMD" author="Advanced Micro Devices, Inc." contact="Daniel Rakos @aqnuep"/>
+ <tag name="ARM" author="ARM Limited" contact="Jan-Harald Fredriksen @janharald"/>
+ <tag name="FSL" author="Freescale Semiconductor, Inc." contact="Norbert Nopper @FslNopper"/>
+ <tag name="BRCM" author="Broadcom Corporation" contact="Graeme Leese @gnl21"/>
+ <tag name="NXP" author="NXP Semiconductors N.V." contact="Norbert Nopper @FslNopper"/>
+ <tag name="NV" author="NVIDIA Corporation" contact="Daniel Koch @dgkoch"/>
+ <tag name="NVX" author="NVIDIA Corporation" contact="Daniel Koch @dgkoch"/>
+ <tag name="VIV" author="Vivante Corporation" contact="Yanjun Zhang @yanjunzhang"/>
+ <tag name="VSI" author="VeriSilicon Holdings Co., Ltd." contact="Yanjun Zhang @yanjunzhang"/>
+ <tag name="KDAB" author="KDAB" contact="Sean Harmer @seanharmer"/>
+ <tag name="ANDROID" author="Google, Inc." contact="Jesse Hall @jessehall"/>
+ <tag name="CHROMIUM" author="Google, Inc." contact="Jesse Hall @jessehall"/>
+ <tag name="GOOGLE" author="Google, Inc." contact="Jesse Hall @jessehall"/>
+ <tag name="QCOM" author="Qualcomm Technologies, Inc." contact="Maurice Ribble @mribble"/>
+ <tag name="LUNARG" author="LunarG, Inc." contact="Karen Ghavam @KarenGhavam"/>
+ <tag name="SAMSUNG" author="Samsung Electronics Co., Ltd." contact="Alon Or-bach @alonorbach"/>
+ <tag name="SEC" author="Samsung Electronics Co., Ltd." contact="Alon Or-bach @alonorbach"/>
+ <tag name="TIZEN" author="Samsung Electronics Co., Ltd." contact="Alon Or-bach @alonorbach"/>
+ <tag name="RENDERDOC" author="RenderDoc (renderdoc.org)" contact="baldurk@baldurk.org"/>
+ <tag name="NN" author="Nintendo Co., Ltd." contact="Yasuhiro Yoshioka @yoshioka_yasuhiro"/>
+ </tags>
+
+ <!-- SECTION: Vulkan type definitions -->
+ <types>
+ <type name="vk_platform" category="include">#include "vk_platform.h"</type>
+ <!-- WSI extensions -->
+ <type category="include">#include "<name>vulkan.h</name>"</type>
+ <type category="include">#include &lt;<name>X11/Xlib.h</name>&gt;</type>
+ <type category="include">#include &lt;<name>X11/extensions/Xrandr.h</name>&gt;</type>
+ <type category="include">#include &lt;<name>android/native_window.h</name>&gt;</type>
+ <type category="include">#include &lt;<name>mir_toolkit/client_types.h</name>&gt;</type>
+ <type category="include">#include &lt;<name>wayland-client.h</name>&gt;</type>
+ <type category="include">#include &lt;<name>windows.h</name>&gt;</type>
+ <type category="include">#include &lt;<name>xcb/xcb.h</name>&gt;</type>
+
+ <type requires="X11/Xlib.h" name="Display"/>
+ <type requires="X11/Xlib.h" name="VisualID"/>
+ <type requires="X11/Xlib.h" name="Window"/>
+ <type requires="X11/extensions/Xrandr.h" name="RROutput"/>
+ <type requires="android/native_window.h" name="ANativeWindow"/>
+ <type requires="mir_toolkit/client_types.h" name="MirConnection"/>
+ <type requires="mir_toolkit/client_types.h" name="MirSurface"/>
+ <type requires="wayland-client.h" name="wl_display"/>
+ <type requires="wayland-client.h" name="wl_surface"/>
+ <type requires="windows.h" name="HINSTANCE"/>
+ <type requires="windows.h" name="HWND"/>
+ <type requires="windows.h" name="HANDLE"/>
+ <type requires="windows.h" name="SECURITY_ATTRIBUTES"/>
+ <type requires="windows.h" name="DWORD"/>
+ <type requires="xcb/xcb.h" name="xcb_connection_t"/>
+ <type requires="xcb/xcb.h" name="xcb_visualid_t"/>
+ <type requires="xcb/xcb.h" name="xcb_window_t"/>
+
+ <type category="define">#define <name>VK_MAKE_VERSION</name>(major, minor, patch) \
+ (((major) &lt;&lt; 22) | ((minor) &lt;&lt; 12) | (patch))</type>
+ <type category="define">#define <name>VK_VERSION_MAJOR</name>(version) ((uint32_t)(version) &gt;&gt; 22)</type>
+ <type category="define">#define <name>VK_VERSION_MINOR</name>(version) (((uint32_t)(version) &gt;&gt; 12) &amp; 0x3ff)</type>
+ <type category="define">#define <name>VK_VERSION_PATCH</name>(version) ((uint32_t)(version) &amp; 0xfff)</type>
+
+ <type category="define">// DEPRECATED: This define has been removed. Specific version defines (e.g. VK_API_VERSION_1_0), or the VK_MAKE_VERSION macro, should be used instead.
+//#define <name>VK_API_VERSION</name> <type>VK_MAKE_VERSION</type>(1, 0, 0)</type> <!-- The patch version here should never be set to anything other than 0 -->
+ <type category="define">// Vulkan 1.0 version number
+#define <name>VK_API_VERSION_1_0</name> <type>VK_MAKE_VERSION</type>(1, 0, 0)</type> <!-- The patch version here should never be set to anything other than 0 -->
+ <type category="define">// Version of this file
+#define <name>VK_HEADER_VERSION</name> 39</type>
+
+ <type category="define">
+#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;</type>
+
+ <type category="define" name="VK_DEFINE_NON_DISPATCHABLE_HANDLE">
+#if !defined(VK_DEFINE_NON_DISPATCHABLE_HANDLE)
+#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) &amp;&amp; !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
+ #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef struct object##_T *object;
+#else
+ #define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+#endif
+#endif
+ </type>
+
+ <type category="define">
+#define <name>VK_NULL_HANDLE</name> 0
+ </type>
+
+ <type category="basetype">typedef <type>uint32_t</type> <name>VkSampleMask</name>;</type>
+ <type category="basetype">typedef <type>uint32_t</type> <name>VkBool32</name>;</type>
+ <type category="basetype">typedef <type>uint32_t</type> <name>VkFlags</name>;</type>
+ <type category="basetype">typedef <type>uint64_t</type> <name>VkDeviceSize</name>;</type>
+ <!-- Basic C types, pulled in via vk_platform.h -->
+ <type requires="vk_platform" name="void"/>
+ <type requires="vk_platform" name="char"/>
+ <type requires="vk_platform" name="float"/>
+ <type requires="vk_platform" name="uint8_t"/>
+ <type requires="vk_platform" name="uint32_t"/>
+ <type requires="vk_platform" name="uint64_t"/>
+ <type requires="vk_platform" name="int32_t"/>
+ <type requires="vk_platform" name="size_t"/>
+ <!-- Bitmask types -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkFramebufferCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkQueryPoolCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkRenderPassCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkSamplerCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineLayoutCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCacheCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineDepthStencilStateCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineDynamicStateCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineColorBlendStateCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineMultisampleStateCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineRasterizationStateCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineViewportStateCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineTessellationStateCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineInputAssemblyStateCreateFlags</name>;</type><!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineVertexInputStateCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineShaderStageCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkDescriptorSetLayoutCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkBufferViewCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkInstanceCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkDeviceCreateFlags</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkDeviceQueueCreateFlags</name>;</type> <!-- creation flags -->
+ <type requires="VkQueueFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkQueueFlags</name>;</type> <!-- Queue capabilities -->
+ <type requires="VkMemoryPropertyFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkMemoryPropertyFlags</name>;</type> <!-- Memory properties passed into vkAllocateMemory(). -->
+ <type requires="VkMemoryHeapFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkMemoryHeapFlags</name>;</type> <!-- Memory heap flags -->
+ <type requires="VkAccessFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkAccessFlags</name>;</type> <!-- Memory access flags passed to barrier/dependency operations -->
+ <type requires="VkBufferUsageFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkBufferUsageFlags</name>;</type> <!-- Buffer usage flags -->
+ <type requires="VkBufferCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkBufferCreateFlags</name>;</type> <!-- Buffer creation flags -->
+ <type requires="VkShaderStageFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkShaderStageFlags</name>;</type> <!-- Shader stage flags -->
+ <type requires="VkImageUsageFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkImageUsageFlags</name>;</type> <!-- Image usage flags -->
+ <type requires="VkImageCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkImageCreateFlags</name>;</type> <!-- Image creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkImageViewCreateFlags</name>;</type> <!-- Image view creation flags (no bits yet) -->
+ <type requires="VkPipelineCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineCreateFlags</name>;</type> <!-- Pipeline creation flags -->
+ <type requires="VkColorComponentFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkColorComponentFlags</name>;</type> <!-- Color component flags -->
+ <type requires="VkFenceCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkFenceCreateFlags</name>;</type> <!-- Fence creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkSemaphoreCreateFlags</name>;</type> <!-- Semaphore creation flags -->
+ <type requires="VkFormatFeatureFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkFormatFeatureFlags</name>;</type> <!-- Format capability flags -->
+ <type requires="VkQueryControlFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkQueryControlFlags</name>;</type> <!-- Query control flags -->
+ <type requires="VkQueryResultFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkQueryResultFlags</name>;</type> <!-- Query result flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkShaderModuleCreateFlags</name>;</type> <!-- Shader module creation flags (no bits yet) -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkEventCreateFlags</name>;</type> <!-- Event creation flags (no bits yet) -->
+ <type requires="VkCommandPoolCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkCommandPoolCreateFlags</name>;</type> <!-- Command pool creation flags -->
+ <type requires="VkCommandPoolResetFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkCommandPoolResetFlags</name>;</type> <!-- Command pool reset flags -->
+ <type requires="VkCommandBufferResetFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkCommandBufferResetFlags</name>;</type> <!-- Command buffer reset flags -->
+ <type requires="VkCommandBufferUsageFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkCommandBufferUsageFlags</name>;</type> <!-- Command buffer usage flags -->
+ <type requires="VkQueryPipelineStatisticFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkQueryPipelineStatisticFlags</name>;</type> <!-- Pipeline statistics flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkMemoryMapFlags</name>;</type> <!-- Memory mapping flags (no bits yet) -->
+ <type requires="VkImageAspectFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkImageAspectFlags</name>;</type> <!-- Bitmask of image aspects -->
+ <type requires="VkSparseMemoryBindFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkSparseMemoryBindFlags</name>;</type> <!-- Sparse memory bind flags -->
+ <type requires="VkSparseImageFormatFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkSparseImageFormatFlags</name>;</type> <!-- Sparse image memory requirements flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkSubpassDescriptionFlags</name>;</type> <!-- Subpass description flags -->
+ <type requires="VkPipelineStageFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkPipelineStageFlags</name>;</type> <!-- Pipeline stages -->
+ <type requires="VkSampleCountFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkSampleCountFlags</name>;</type> <!-- Pipeline stages -->
+ <type requires="VkAttachmentDescriptionFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkAttachmentDescriptionFlags</name>;</type> <!-- Render pass attachment description flags -->
+ <type requires="VkStencilFaceFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkStencilFaceFlags</name>;</type> <!-- Stencil face flags -->
+ <type requires="VkCullModeFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkCullModeFlags</name>;</type> <!-- Cull mode flags -->
+ <type requires="VkDescriptorPoolCreateFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkDescriptorPoolCreateFlags</name>;</type> <!-- Descriptor pool creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkDescriptorPoolResetFlags</name>;</type> <!-- Descriptor pool reset flags -->
+ <type requires="VkDependencyFlagBits" category="bitmask">typedef <type>VkFlags</type> <name>VkDependencyFlags</name>;</type> <!-- Pipeline barrier and subpass dependency flags -->
+
+ <type requires="VkIndirectCommandsLayoutUsageFlagBitsNVX" category="bitmask">typedef <type>VkFlags</type> <name>VkIndirectCommandsLayoutUsageFlagsNVX</name>;</type> <!-- Device generated commands usage flags -->
+ <type requires="VkObjectEntryUsageFlagBitsNVX" category="bitmask">typedef <type>VkFlags</type> <name>VkObjectEntryUsageFlagsNVX</name>;</type> <!-- Object usage flags -->
+
+ <!-- WSI extensions -->
+ <type requires="VkCompositeAlphaFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkCompositeAlphaFlagsKHR</name>;</type>
+ <type requires="VkDisplayPlaneAlphaFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkDisplayPlaneAlphaFlagsKHR</name>;</type>
+ <type requires="VkSurfaceTransformFlagBitsKHR" category="bitmask">typedef <type>VkFlags</type> <name>VkSurfaceTransformFlagsKHR</name>;</type>
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkSwapchainCreateFlagsKHR</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkDisplayModeCreateFlagsKHR</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkDisplaySurfaceCreateFlagsKHR</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkAndroidSurfaceCreateFlagsKHR</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkMirSurfaceCreateFlagsKHR</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkViSurfaceCreateFlagsNN</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkWaylandSurfaceCreateFlagsKHR</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkWin32SurfaceCreateFlagsKHR</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkXlibSurfaceCreateFlagsKHR</name>;</type> <!-- creation flags -->
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkXcbSurfaceCreateFlagsKHR</name>;</type> <!-- creation flags -->
+
+ <type requires="VkDebugReportFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkDebugReportFlagsEXT</name>;</type>
+ <type category="bitmask">typedef <type>VkFlags</type> <name>VkCommandPoolTrimFlagsKHR</name>;</type>
+ <type requires="VkExternalMemoryHandleTypeFlagBitsNV" category="bitmask">typedef <type>VkFlags</type> <name>VkExternalMemoryHandleTypeFlagsNV</name>;</type>
+ <type requires="VkExternalMemoryFeatureFlagBitsNV" category="bitmask">typedef <type>VkFlags</type> <name>VkExternalMemoryFeatureFlagsNV</name>;</type>
+ <type requires="VkSurfaceCounterFlagBitsEXT" category="bitmask">typedef <type>VkFlags</type> <name>VkSurfaceCounterFlagsEXT</name>;</type>
+
+ <!-- Types which can be void pointers or class pointers, selected at compile time -->
+ <type category="handle"><type>VK_DEFINE_HANDLE</type>(<name>VkInstance</name>)</type>
+ <type category="handle" parent="VkInstance"><type>VK_DEFINE_HANDLE</type>(<name>VkPhysicalDevice</name>)</type>
+ <type category="handle" parent="VkPhysicalDevice"><type>VK_DEFINE_HANDLE</type>(<name>VkDevice</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_HANDLE</type>(<name>VkQueue</name>)</type>
+ <type category="handle" parent="VkCommandPool"><type>VK_DEFINE_HANDLE</type>(<name>VkCommandBuffer</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDeviceMemory</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkCommandPool</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkBuffer</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkBufferView</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkImage</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkImageView</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkShaderModule</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkPipeline</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkPipelineLayout</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkSampler</name>)</type>
+ <type category="handle" parent="VkDescriptorPool"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDescriptorSet</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDescriptorSetLayout</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDescriptorPool</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkFence</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkSemaphore</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkEvent</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkQueryPool</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkFramebuffer</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkRenderPass</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkPipelineCache</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkObjectTableNVX</name>)</type>
+ <type category="handle" parent="VkDevice"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkIndirectCommandsLayoutNVX</name>)</type>
+
+ <!-- WSI extensions -->
+ <type category="handle"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDisplayKHR</name>)</type>
+ <type category="handle" parent="VkPhysicalDevice,VkDisplayKHR"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDisplayModeKHR</name>)</type>
+ <type category="handle" parent="VkInstance"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkSurfaceKHR</name>)</type>
+ <type category="handle" parent="VkSurfaceKHR"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkSwapchainKHR</name>)</type>
+ <type category="handle" parent="VkInstance"><type>VK_DEFINE_NON_DISPATCHABLE_HANDLE</type>(<name>VkDebugReportCallbackEXT</name>)</type>
+
+ <!-- Types generated from corresponding <enums> tags below -->
+ <type name="VkAttachmentLoadOp" category="enum"/>
+ <type name="VkAttachmentStoreOp" category="enum"/>
+ <type name="VkBlendFactor" category="enum"/>
+ <type name="VkBlendOp" category="enum"/>
+ <type name="VkBorderColor" category="enum"/>
+ <type name="VkFramebufferCreateFlagBits" category="enum"/>
+ <type name="VkQueryPoolCreateFlagBits" category="enum"/>
+ <type name="VkRenderPassCreateFlagBits" category="enum"/>
+ <type name="VkSamplerCreateFlagBits" category="enum"/>
+ <type name="VkPipelineCacheHeaderVersion" category="enum"/>
+ <type name="VkPipelineLayoutCreateFlagBits" category="enum"/>
+ <type name="VkPipelineCacheCreateFlagBits" category="enum"/>
+ <type name="VkPipelineDepthStencilStateCreateFlagBits" category="enum"/>
+ <type name="VkPipelineDynamicStateCreateFlagBits" category="enum"/>
+ <type name="VkPipelineColorBlendStateCreateFlagBits" category="enum"/>
+ <type name="VkPipelineMultisampleStateCreateFlagBits" category="enum"/>
+ <type name="VkPipelineRasterizationStateCreateFlagBits" category="enum"/>
+ <type name="VkPipelineViewportStateCreateFlagBits" category="enum"/>
+ <type name="VkPipelineTessellationStateCreateFlagBits" category="enum"/>
+ <type name="VkPipelineInputAssemblyStateCreateFlagBits" category="enum"/>
+ <type name="VkPipelineVertexInputStateCreateFlagBits" category="enum"/>
+ <type name="VkPipelineShaderStageCreateFlagBits" category="enum"/>
+ <type name="VkDescriptorSetLayoutCreateFlagBits" category="enum"/>
+ <type name="VkBufferViewCreateFlagBits" category="enum"/>
+ <type name="VkInstanceCreateFlagBits" category="enum"/>
+ <type name="VkDeviceQueueCreateFlagBits" category="enum"/>
+ <type name="VkBufferCreateFlagBits" category="enum"/>
+ <type name="VkBufferUsageFlagBits" category="enum"/>
+ <type name="VkColorComponentFlagBits" category="enum"/>
+ <type name="VkComponentSwizzle" category="enum"/>
+ <type name="VkCommandPoolCreateFlagBits" category="enum"/>
+ <type name="VkCommandPoolResetFlagBits" category="enum"/>
+ <type name="VkCommandBufferResetFlagBits" category="enum"/>
+ <type name="VkCommandBufferLevel" category="enum"/>
+ <type name="VkCommandBufferUsageFlagBits" category="enum"/>
+ <type name="VkCompareOp" category="enum"/>
+ <type name="VkCullModeFlagBits" category="enum"/>
+ <type name="VkDescriptorType" category="enum"/>
+ <type name="VkDeviceCreateFlagBits" category="enum"/>
+ <type name="VkDynamicState" category="enum"/>
+ <type name="VkFenceCreateFlagBits" category="enum"/>
+ <type name="VkPolygonMode" category="enum"/>
+ <type name="VkFormat" category="enum"/>
+ <type name="VkFormatFeatureFlagBits" category="enum"/>
+ <type name="VkFrontFace" category="enum"/>
+ <type name="VkImageAspectFlagBits" category="enum"/>
+ <type name="VkImageCreateFlagBits" category="enum"/>
+ <type name="VkImageLayout" category="enum"/>
+ <type name="VkImageTiling" category="enum"/>
+ <type name="VkImageType" category="enum"/>
+ <type name="VkImageUsageFlagBits" category="enum"/>
+ <type name="VkImageViewType" category="enum"/>
+ <type name="VkSharingMode" category="enum"/>
+ <type name="VkIndexType" category="enum"/>
+ <type name="VkLogicOp" category="enum"/>
+ <type name="VkMemoryHeapFlagBits" category="enum"/>
+ <type name="VkAccessFlagBits" category="enum"/>
+ <type name="VkMemoryPropertyFlagBits" category="enum"/>
+ <type name="VkPhysicalDeviceType" category="enum"/>
+ <type name="VkPipelineBindPoint" category="enum"/>
+ <type name="VkPipelineCreateFlagBits" category="enum"/>
+ <type name="VkPrimitiveTopology" category="enum"/>
+ <type name="VkQueryControlFlagBits" category="enum"/>
+ <type name="VkQueryPipelineStatisticFlagBits" category="enum"/>
+ <type name="VkQueryResultFlagBits" category="enum"/>
+ <type name="VkQueryType" category="enum"/>
+ <type name="VkQueueFlagBits" category="enum"/>
+ <type name="VkSubpassContents" category="enum"/>
+ <type name="VkResult" category="enum"/>
+ <type name="VkShaderStageFlagBits" category="enum"/>
+ <type name="VkSparseMemoryBindFlagBits" category="enum"/>
+ <type name="VkStencilFaceFlagBits" category="enum"/>
+ <type name="VkStencilOp" category="enum"/>
+ <type name="VkStructureType" category="enum"/>
+ <type name="VkSystemAllocationScope" category="enum"/>
+ <type name="VkInternalAllocationType" category="enum"/>
+ <type name="VkSamplerAddressMode" category="enum"/>
+ <type name="VkFilter" category="enum"/>
+ <type name="VkSamplerMipmapMode" category="enum"/>
+ <type name="VkVertexInputRate" category="enum"/>
+ <type name="VkPipelineStageFlagBits" category="enum"/>
+ <type name="VkSparseImageFormatFlagBits" category="enum"/>
+ <type name="VkSampleCountFlagBits" category="enum"/>
+ <type name="VkAttachmentDescriptionFlagBits" category="enum"/>
+ <type name="VkDescriptorPoolCreateFlagBits" category="enum"/>
+ <type name="VkDependencyFlagBits" category="enum"/>
+ <type name="VkIndirectCommandsLayoutUsageFlagBitsNVX" category="enum"/>
+ <type name="VkIndirectCommandsTokenTypeNVX" category="enum"/>
+ <type name="VkObjectEntryUsageFlagBitsNVX" category="enum"/>
+ <type name="VkObjectEntryTypeNVX" category="enum"/>
+ <!-- WSI extensions -->
+ <type name="VkColorSpaceKHR" category="enum"/>
+ <type name="VkCompositeAlphaFlagBitsKHR" category="enum"/>
+ <type name="VkDisplayPlaneAlphaFlagBitsKHR" category="enum"/>
+ <type name="VkPresentModeKHR" category="enum"/>
+ <type name="VkSurfaceTransformFlagBitsKHR" category="enum"/>
+ <type name="VkDebugReportFlagBitsEXT" category="enum"/>
+ <type name="VkDebugReportObjectTypeEXT" category="enum"/>
+ <type name="VkDebugReportErrorEXT" category="enum"/>
+ <type name="VkRasterizationOrderAMD" category="enum"/>
+ <type name="VkExternalMemoryHandleTypeFlagBitsNV" category="enum"/>
+ <type name="VkExternalMemoryFeatureFlagBitsNV" category="enum"/>
+ <type name="VkValidationCheckEXT" category="enum"/>
+ <type name="VkSurfaceCounterFlagBitsEXT" category="enum"/>
+ <type name="VkDisplayPowerStateEXT" category="enum"/>
+ <type name="VkDeviceEventTypeEXT" category="enum"/>
+ <type name="VkDisplayEventTypeEXT" category="enum"/>
+
+ <!-- The PFN_vk*Function types are used by VkAllocationCallbacks below -->
+ <type category="funcpointer">typedef void (VKAPI_PTR *<name>PFN_vkInternalAllocationNotification</name>)(
+ <type>void</type>* pUserData,
+ <type>size_t</type> size,
+ <type>VkInternalAllocationType</type> allocationType,
+ <type>VkSystemAllocationScope</type> allocationScope);</type>
+ <type category="funcpointer">typedef void (VKAPI_PTR *<name>PFN_vkInternalFreeNotification</name>)(
+ <type>void</type>* pUserData,
+ <type>size_t</type> size,
+ <type>VkInternalAllocationType</type> allocationType,
+ <type>VkSystemAllocationScope</type> allocationScope);</type>
+ <type category="funcpointer">typedef void* (VKAPI_PTR *<name>PFN_vkReallocationFunction</name>)(
+ <type>void</type>* pUserData,
+ <type>void</type>* pOriginal,
+ <type>size_t</type> size,
+ <type>size_t</type> alignment,
+ <type>VkSystemAllocationScope</type> allocationScope);</type>
+ <type category="funcpointer">typedef void* (VKAPI_PTR *<name>PFN_vkAllocationFunction</name>)(
+ <type>void</type>* pUserData,
+ <type>size_t</type> size,
+ <type>size_t</type> alignment,
+ <type>VkSystemAllocationScope</type> allocationScope);</type>
+ <type category="funcpointer">typedef void (VKAPI_PTR *<name>PFN_vkFreeFunction</name>)(
+ <type>void</type>* pUserData,
+ <type>void</type>* pMemory);</type>
+
+ <!-- The PFN_vkVoidFunction type are used by VkGet*ProcAddr below -->
+ <type category="funcpointer">typedef void (VKAPI_PTR *<name>PFN_vkVoidFunction</name>)(void);</type>
+
+ <!-- The PFN_vkDebugReportCallbackEXT type are used by the DEBUG_REPORT extension-->
+ <type category="funcpointer">typedef VkBool32 (VKAPI_PTR *<name>PFN_vkDebugReportCallbackEXT</name>)(
+ <type>VkDebugReportFlagsEXT</type> flags,
+ <type>VkDebugReportObjectTypeEXT</type> objectType,
+ <type>uint64_t</type> object,
+ <type>size_t</type> location,
+ <type>int32_t</type> messageCode,
+ const <type>char</type>* pLayerPrefix,
+ const <type>char</type>* pMessage,
+ <type>void</type>* pUserData);</type>
+
+ <!-- Struct types -->
+ <type category="struct" name="VkOffset2D">
+ <member><type>int32_t</type> <name>x</name></member>
+ <member><type>int32_t</type> <name>y</name></member>
+ </type>
+ <type category="struct" name="VkOffset3D">
+ <member><type>int32_t</type> <name>x</name></member>
+ <member><type>int32_t</type> <name>y</name></member>
+ <member><type>int32_t</type> <name>z</name></member>
+ </type>
+ <type category="struct" name="VkExtent2D">
+ <member><type>uint32_t</type> <name>width</name></member>
+ <member><type>uint32_t</type> <name>height</name></member>
+ </type>
+ <type category="struct" name="VkExtent3D">
+ <member><type>uint32_t</type> <name>width</name></member>
+ <member><type>uint32_t</type> <name>height</name></member>
+ <member><type>uint32_t</type> <name>depth</name></member>
+ </type>
+ <type category="struct" name="VkViewport">
+ <member><type>float</type> <name>x</name></member>
+ <member><type>float</type> <name>y</name></member>
+ <member><type>float</type> <name>width</name></member>
+ <member><type>float</type> <name>height</name></member>
+ <member><type>float</type> <name>minDepth</name></member>
+ <member><type>float</type> <name>maxDepth</name></member>
+ </type>
+ <type category="struct" name="VkRect2D">
+ <member><type>VkOffset2D</type> <name>offset</name></member>
+ <member><type>VkExtent2D</type> <name>extent</name></member>
+ </type>
+ <type category="struct" name="VkRect3D">
+ <member><type>VkOffset3D</type> <name>offset</name></member>
+ <member><type>VkExtent3D</type> <name>extent</name></member>
+ </type>
+ <type category="struct" name="VkClearRect">
+ <member><type>VkRect2D</type> <name>rect</name></member>
+ <member><type>uint32_t</type> <name>baseArrayLayer</name></member>
+ <member><type>uint32_t</type> <name>layerCount</name></member>
+ </type>
+ <type category="struct" name="VkComponentMapping">
+ <member><type>VkComponentSwizzle</type> <name>r</name></member>
+ <member><type>VkComponentSwizzle</type> <name>g</name></member>
+ <member><type>VkComponentSwizzle</type> <name>b</name></member>
+ <member><type>VkComponentSwizzle</type> <name>a</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceProperties" returnedonly="true">
+ <member><type>uint32_t</type> <name>apiVersion</name></member>
+ <member><type>uint32_t</type> <name>driverVersion</name></member>
+ <member><type>uint32_t</type> <name>vendorID</name></member>
+ <member><type>uint32_t</type> <name>deviceID</name></member>
+ <member><type>VkPhysicalDeviceType</type> <name>deviceType</name></member>
+ <member><type>char</type> <name>deviceName</name>[<enum>VK_MAX_PHYSICAL_DEVICE_NAME_SIZE</enum>]</member>
+ <member><type>uint8_t</type> <name>pipelineCacheUUID</name>[<enum>VK_UUID_SIZE</enum>]</member>
+ <member><type>VkPhysicalDeviceLimits</type> <name>limits</name></member>
+ <member><type>VkPhysicalDeviceSparseProperties</type> <name>sparseProperties</name></member>
+ </type>
+ <type category="struct" name="VkExtensionProperties" returnedonly="true">
+ <member><type>char</type> <name>extensionName</name>[<enum>VK_MAX_EXTENSION_NAME_SIZE</enum>]</member> <!-- extension name -->
+ <member><type>uint32_t</type> <name>specVersion</name></member> <!-- version of the extension specification implemented -->
+ </type>
+ <type category="struct" name="VkLayerProperties" returnedonly="true">
+ <member><type>char</type> <name>layerName</name>[<enum>VK_MAX_EXTENSION_NAME_SIZE</enum>]</member> <!-- layer name -->
+ <member><type>uint32_t</type> <name>specVersion</name></member> <!-- version of the layer specification implemented -->
+ <member><type>uint32_t</type> <name>implementationVersion</name></member> <!-- build or release version of the layer's library -->
+ <member><type>char</type> <name>description</name>[<enum>VK_MAX_DESCRIPTION_SIZE</enum>]</member> <!-- Free-form description of the layer -->
+ </type>
+ <type category="struct" name="VkApplicationInfo">
+ <member values="VK_STRUCTURE_TYPE_APPLICATION_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true" len="null-terminated">const <type>char</type>* <name>pApplicationName</name></member>
+ <member><type>uint32_t</type> <name>applicationVersion</name></member>
+ <member optional="true" len="null-terminated">const <type>char</type>* <name>pEngineName</name></member>
+ <member><type>uint32_t</type> <name>engineVersion</name></member>
+ <member><type>uint32_t</type> <name>apiVersion</name></member>
+ </type>
+ <type category="struct" name="VkAllocationCallbacks">
+ <member optional="true"><type>void</type>* <name>pUserData</name></member>
+ <member><type>PFN_vkAllocationFunction</type> <name>pfnAllocation</name></member>
+ <member><type>PFN_vkReallocationFunction</type> <name>pfnReallocation</name></member>
+ <member><type>PFN_vkFreeFunction</type> <name>pfnFree</name></member>
+ <member optional="true"><type>PFN_vkInternalAllocationNotification</type> <name>pfnInternalAllocation</name></member>
+ <member optional="true"><type>PFN_vkInternalFreeNotification</type> <name>pfnInternalFree</name></member>
+ </type>
+ <type category="struct" name="VkDeviceQueueCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkDeviceQueueCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>uint32_t</type> <name>queueFamilyIndex</name></member>
+ <member><type>uint32_t</type> <name>queueCount</name></member>
+ <member len="queueCount">const <type>float</type>* <name>pQueuePriorities</name></member>
+ </type>
+ <type category="struct" name="VkDeviceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member validextensionstructs="VkPhysicalDeviceFeatures2KHR">const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkDeviceCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>uint32_t</type> <name>queueCreateInfoCount</name></member>
+ <member len="queueCreateInfoCount">const <type>VkDeviceQueueCreateInfo</type>* <name>pQueueCreateInfos</name></member>
+ <member optional="true"><type>uint32_t</type> <name>enabledLayerCount</name></member>
+ <member len="enabledLayerCount,null-terminated">const <type>char</type>* const* <name>ppEnabledLayerNames</name></member> <!-- Ordered list of layer names to be enabled -->
+ <member optional="true"><type>uint32_t</type> <name>enabledExtensionCount</name></member>
+ <member len="enabledExtensionCount,null-terminated">const <type>char</type>* const* <name>ppEnabledExtensionNames</name></member>
+ <member optional="true">const <type>VkPhysicalDeviceFeatures</type>* <name>pEnabledFeatures</name></member>
+ </type>
+ <type category="struct" name="VkInstanceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkInstanceCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member optional="true">const <type>VkApplicationInfo</type>* <name>pApplicationInfo</name></member>
+ <member optional="true"><type>uint32_t</type> <name>enabledLayerCount</name></member>
+ <member len="enabledLayerCount,null-terminated">const <type>char</type>* const* <name>ppEnabledLayerNames</name></member> <!-- Ordered list of layer names to be enabled -->
+ <member optional="true"><type>uint32_t</type> <name>enabledExtensionCount</name></member>
+ <member len="enabledExtensionCount,null-terminated">const <type>char</type>* const* <name>ppEnabledExtensionNames</name></member> <!-- Extension names to be enabled -->
+ </type>
+ <type category="struct" name="VkQueueFamilyProperties" returnedonly="true">
+ <member optional="true"><type>VkQueueFlags</type> <name>queueFlags</name></member> <!-- Queue flags -->
+ <member><type>uint32_t</type> <name>queueCount</name></member>
+ <member><type>uint32_t</type> <name>timestampValidBits</name></member>
+ <member><type>VkExtent3D</type> <name>minImageTransferGranularity</name></member> <!-- Minimum alignment requirement for image transfers -->
+ </type>
+ <type category="struct" name="VkPhysicalDeviceMemoryProperties" returnedonly="true">
+ <member><type>uint32_t</type> <name>memoryTypeCount</name></member>
+ <member><type>VkMemoryType</type> <name>memoryTypes</name>[<enum>VK_MAX_MEMORY_TYPES</enum>]</member>
+ <member><type>uint32_t</type> <name>memoryHeapCount</name></member>
+ <member><type>VkMemoryHeap</type> <name>memoryHeaps</name>[<enum>VK_MAX_MEMORY_HEAPS</enum>]</member>
+ </type>
+ <type category="struct" name="VkMemoryAllocateInfo">
+ <member values="VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member validextensionstructs="VkDedicatedAllocationMemoryAllocateInfoNV">const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkDeviceSize</type> <name>allocationSize</name></member> <!-- Size of memory allocation -->
+ <member><type>uint32_t</type> <name>memoryTypeIndex</name></member> <!-- Index of the of the memory type to allocate from -->
+ </type>
+ <type category="struct" name="VkMemoryRequirements" returnedonly="true">
+ <member><type>VkDeviceSize</type> <name>size</name></member> <!-- Specified in bytes -->
+ <member><type>VkDeviceSize</type> <name>alignment</name></member> <!-- Specified in bytes -->
+ <member><type>uint32_t</type> <name>memoryTypeBits</name></member> <!-- Bitmask of the allowed memory type indices into memoryTypes[] for this object -->
+ </type>
+ <type category="struct" name="VkSparseImageFormatProperties" returnedonly="true">
+ <member optional="true"><type>VkImageAspectFlags</type> <name>aspectMask</name></member>
+ <member><type>VkExtent3D</type> <name>imageGranularity</name></member>
+ <member optional="true"><type>VkSparseImageFormatFlags</type> <name>flags</name></member>
+ </type>
+ <type category="struct" name="VkSparseImageMemoryRequirements" returnedonly="true">
+ <member><type>VkSparseImageFormatProperties</type> <name>formatProperties</name></member>
+ <member><type>uint32_t</type> <name>imageMipTailFirstLod</name></member>
+ <member><type>VkDeviceSize</type> <name>imageMipTailSize</name></member> <!-- Specified in bytes, must be a multiple of sparse block size in bytes / alignment -->
+ <member><type>VkDeviceSize</type> <name>imageMipTailOffset</name></member> <!-- Specified in bytes, must be a multiple of sparse block size in bytes / alignment -->
+ <member><type>VkDeviceSize</type> <name>imageMipTailStride</name></member> <!-- Specified in bytes, must be a multiple of sparse block size in bytes / alignment -->
+ </type>
+ <type category="struct" name="VkMemoryType" returnedonly="true">
+ <member optional="true"><type>VkMemoryPropertyFlags</type> <name>propertyFlags</name></member> <!-- Memory properties of this memory type -->
+ <member><type>uint32_t</type> <name>heapIndex</name></member> <!-- Index of the memory heap allocations of this memory type are taken from -->
+ </type>
+ <type category="struct" name="VkMemoryHeap" returnedonly="true">
+ <member><type>VkDeviceSize</type> <name>size</name></member> <!-- Available memory in the heap-->
+ <member optional="true"><type>VkMemoryHeapFlags</type> <name>flags</name></member> <!-- Flags for the heap-->
+ </type>
+ <type category="struct" name="VkMappedMemoryRange">
+ <member values="VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkDeviceMemory</type> <name>memory</name></member> <!-- Mapped memory object -->
+ <member><type>VkDeviceSize</type> <name>offset</name></member> <!-- Offset within the memory object where the range starts -->
+ <member><type>VkDeviceSize</type> <name>size</name></member> <!-- Size of the range within the memory object -->
+ </type>
+ <type category="struct" name="VkFormatProperties" returnedonly="true">
+ <member optional="true"><type>VkFormatFeatureFlags</type> <name>linearTilingFeatures</name></member> <!-- Format features in case of linear tiling -->
+ <member optional="true"><type>VkFormatFeatureFlags</type> <name>optimalTilingFeatures</name></member> <!-- Format features in case of optimal tiling -->
+ <member optional="true"><type>VkFormatFeatureFlags</type> <name>bufferFeatures</name></member> <!-- Format features supported by buffers -->
+ </type>
+ <type category="struct" name="VkImageFormatProperties" returnedonly="true">
+ <member><type>VkExtent3D</type> <name>maxExtent</name></member> <!-- max image dimensions for this resource type -->
+ <member><type>uint32_t</type> <name>maxMipLevels</name></member> <!-- max number of mipmap levels for this resource type -->
+ <member><type>uint32_t</type> <name>maxArrayLayers</name></member> <!-- max array size for this resource type -->
+ <member optional="true"><type>VkSampleCountFlags</type> <name>sampleCounts</name></member> <!-- supported sample counts for this resource type -->
+ <member><type>VkDeviceSize</type> <name>maxResourceSize</name></member> <!-- max size (in bytes) of this resource type -->
+ </type>
+ <type category="struct" name="VkDescriptorBufferInfo">
+ <member><type>VkBuffer</type> <name>buffer</name></member> <!-- Buffer used for this descriptor slot when the descriptor is UNIFORM_BUFFER[_DYNAMIC] or STORAGE_BUFFER[_DYNAMIC]. VK_NULL_HANDLE otherwise. -->
+ <member><type>VkDeviceSize</type> <name>offset</name></member> <!-- Base offset from buffer start in bytes to update in the descriptor set. -->
+ <member><type>VkDeviceSize</type> <name>range</name></member> <!-- Size in bytes of the buffer resource for this descriptor update. -->
+ </type>
+ <type category="struct" name="VkDescriptorImageInfo">
+ <member noautovalidity="true"><type>VkSampler</type> <name>sampler</name></member> <!-- Sampler to write to the descriptor in case it is a SAMPLER or COMBINED_IMAGE_SAMPLER descriptor. Ignored otherwise. -->
+ <member noautovalidity="true"><type>VkImageView</type> <name>imageView</name></member> <!-- Image view to write to the descriptor in case it is a SAMPLED_IMAGE, STORAGE_IMAGE, COMBINED_IMAGE_SAMPLER, or INPUT_ATTACHMENT descriptor. Ignored otherwise. -->
+ <member noautovalidity="true"><type>VkImageLayout</type> <name>imageLayout</name></member> <!-- Layout the image is expected to be in when accessed using this descriptor (only used if imageView is not VK_NULL_HANDLE). -->
+ </type>
+ <type category="struct" name="VkWriteDescriptorSet">
+ <member values="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkDescriptorSet</type> <name>dstSet</name></member> <!-- Destination descriptor set -->
+ <member><type>uint32_t</type> <name>dstBinding</name></member> <!-- Binding within the destination descriptor set to write -->
+ <member><type>uint32_t</type> <name>dstArrayElement</name></member> <!-- Array element within the destination binding to write -->
+ <member><type>uint32_t</type> <name>descriptorCount</name></member> <!-- Number of descriptors to write (determines the size of the array pointed by pDescriptors) -->
+ <member><type>VkDescriptorType</type> <name>descriptorType</name></member> <!-- Descriptor type to write (determines which members of the array pointed by pDescriptors are going to be used) -->
+ <member noautovalidity="true" len="descriptorCount">const <type>VkDescriptorImageInfo</type>* <name>pImageInfo</name></member> <!-- Sampler, image view, and layout for SAMPLER, COMBINED_IMAGE_SAMPLER, {SAMPLED,STORAGE}_IMAGE, and INPUT_ATTACHMENT descriptor types. -->
+ <member noautovalidity="true" len="descriptorCount">const <type>VkDescriptorBufferInfo</type>* <name>pBufferInfo</name></member> <!-- Raw buffer, size, and offset for {UNIFORM,STORAGE}_BUFFER[_DYNAMIC] descriptor types. -->
+ <member noautovalidity="true" len="descriptorCount">const <type>VkBufferView</type>* <name>pTexelBufferView</name></member> <!-- Buffer view to write to the descriptor for {UNIFORM,STORAGE}_TEXEL_BUFFER descriptor types. -->
+ </type>
+ <type category="struct" name="VkCopyDescriptorSet">
+ <member values="VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkDescriptorSet</type> <name>srcSet</name></member> <!-- Source descriptor set -->
+ <member><type>uint32_t</type> <name>srcBinding</name></member> <!-- Binding within the source descriptor set to copy from -->
+ <member><type>uint32_t</type> <name>srcArrayElement</name></member> <!-- Array element within the source binding to copy from -->
+ <member><type>VkDescriptorSet</type> <name>dstSet</name></member> <!-- Destination descriptor set -->
+ <member><type>uint32_t</type> <name>dstBinding</name></member> <!-- Binding within the destination descriptor set to copy to -->
+ <member><type>uint32_t</type> <name>dstArrayElement</name></member> <!-- Array element within the destination binding to copy to -->
+ <member><type>uint32_t</type> <name>descriptorCount</name></member> <!-- Number of descriptors to write (determines the size of the array pointed by pDescriptors) -->
+ </type>
+ <type category="struct" name="VkBufferCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member validextensionstructs="VkDedicatedAllocationBufferCreateInfoNV">const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure. -->
+ <member optional="true"><type>VkBufferCreateFlags</type> <name>flags</name></member> <!-- Buffer creation flags -->
+ <member><type>VkDeviceSize</type> <name>size</name></member> <!-- Specified in bytes -->
+ <member><type>VkBufferUsageFlags</type> <name>usage</name></member> <!-- Buffer usage flags -->
+ <member><type>VkSharingMode</type> <name>sharingMode</name></member>
+ <member optional="true"><type>uint32_t</type> <name>queueFamilyIndexCount</name></member>
+ <member noautovalidity="true" len="queueFamilyIndexCount">const <type>uint32_t</type>* <name>pQueueFamilyIndices</name></member>
+ </type>
+ <type category="struct" name="VkBufferViewCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure. -->
+ <member optional="true"><type>VkBufferViewCreateFlags</type><name>flags</name></member> <!-- Reserved -->
+ <member><type>VkBuffer</type> <name>buffer</name></member>
+ <member><type>VkFormat</type> <name>format</name></member> <!-- Optionally specifies format of elements -->
+ <member><type>VkDeviceSize</type> <name>offset</name></member> <!-- Specified in bytes -->
+ <member><type>VkDeviceSize</type> <name>range</name></member> <!-- View size specified in bytes -->
+ </type>
+ <type category="struct" name="VkImageSubresource">
+ <member><type>VkImageAspectFlags</type> <name>aspectMask</name></member>
+ <member><type>uint32_t</type> <name>mipLevel</name></member>
+ <member><type>uint32_t</type> <name>arrayLayer</name></member>
+ </type>
+ <type category="struct" name="VkImageSubresourceLayers">
+ <member><type>VkImageAspectFlags</type> <name>aspectMask</name></member>
+ <member><type>uint32_t</type> <name>mipLevel</name></member>
+ <member><type>uint32_t</type> <name>baseArrayLayer</name></member>
+ <member><type>uint32_t</type> <name>layerCount</name></member>
+ </type>
+ <type category="struct" name="VkImageSubresourceRange">
+ <member><type>VkImageAspectFlags</type> <name>aspectMask</name></member>
+ <member><type>uint32_t</type> <name>baseMipLevel</name></member>
+ <member><type>uint32_t</type> <name>levelCount</name></member>
+ <member><type>uint32_t</type> <name>baseArrayLayer</name></member>
+ <member><type>uint32_t</type> <name>layerCount</name></member>
+ </type>
+ <type category="struct" name="VkMemoryBarrier">
+ <member values="VK_STRUCTURE_TYPE_MEMORY_BARRIER"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure. -->
+ <member optional="true"><type>VkAccessFlags</type> <name>srcAccessMask</name></member> <!-- Memory accesses from the source of the dependency to synchronize -->
+ <member optional="true"><type>VkAccessFlags</type> <name>dstAccessMask</name></member> <!-- Memory accesses from the destination of the dependency to synchronize -->
+ </type>
+ <type category="struct" name="VkBufferMemoryBarrier">
+ <member values="VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure. -->
+ <member optional="true"><type>VkAccessFlags</type> <name>srcAccessMask</name></member> <!-- Memory accesses from the source of the dependency to synchronize -->
+ <member optional="true"><type>VkAccessFlags</type> <name>dstAccessMask</name></member> <!-- Memory accesses from the destination of the dependency to synchronize -->
+ <member><type>uint32_t</type> <name>srcQueueFamilyIndex</name></member> <!-- Queue family to transition ownership from -->
+ <member><type>uint32_t</type> <name>dstQueueFamilyIndex</name></member> <!-- Queue family to transition ownership to -->
+ <member><type>VkBuffer</type> <name>buffer</name></member> <!-- Buffer to sync -->
+ <member><type>VkDeviceSize</type> <name>offset</name></member> <!-- Offset within the buffer to sync -->
+ <member><type>VkDeviceSize</type> <name>size</name></member> <!-- Amount of bytes to sync -->
+ </type>
+ <type category="struct" name="VkImageMemoryBarrier">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure. -->
+ <member optional="true"><type>VkAccessFlags</type> <name>srcAccessMask</name></member> <!-- Memory accesses from the source of the dependency to synchronize -->
+ <member optional="true"><type>VkAccessFlags</type> <name>dstAccessMask</name></member> <!-- Memory accesses from the destination of the dependency to synchronize -->
+ <member><type>VkImageLayout</type> <name>oldLayout</name></member> <!-- Current layout of the image -->
+ <member><type>VkImageLayout</type> <name>newLayout</name></member> <!-- New layout to transition the image to -->
+ <member><type>uint32_t</type> <name>srcQueueFamilyIndex</name></member> <!-- Queue family to transition ownership from -->
+ <member><type>uint32_t</type> <name>dstQueueFamilyIndex</name></member> <!-- Queue family to transition ownership to -->
+ <member><type>VkImage</type> <name>image</name></member> <!-- Image to sync -->
+ <member><type>VkImageSubresourceRange</type> <name>subresourceRange</name></member> <!-- Subresource range to sync -->
+ </type>
+ <type category="struct" name="VkImageCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member validextensionstructs="VkDedicatedAllocationImageCreateInfoNV">const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure. -->
+ <member optional="true"><type>VkImageCreateFlags</type> <name>flags</name></member> <!-- Image creation flags -->
+ <member><type>VkImageType</type> <name>imageType</name></member>
+ <member><type>VkFormat</type> <name>format</name></member>
+ <member><type>VkExtent3D</type> <name>extent</name></member>
+ <member><type>uint32_t</type> <name>mipLevels</name></member>
+ <member><type>uint32_t</type> <name>arrayLayers</name></member>
+ <member><type>VkSampleCountFlagBits</type> <name>samples</name></member>
+ <member><type>VkImageTiling</type> <name>tiling</name></member>
+ <member><type>VkImageUsageFlags</type> <name>usage</name></member> <!-- Image usage flags -->
+ <member><type>VkSharingMode</type> <name>sharingMode</name></member> <!-- Cross-queue-family sharing mode -->
+ <member optional="true"><type>uint32_t</type> <name>queueFamilyIndexCount</name></member> <!-- Number of queue families to share across -->
+ <member noautovalidity="true" len="queueFamilyIndexCount">const <type>uint32_t</type>* <name>pQueueFamilyIndices</name></member> <!-- Array of queue family indices to share across -->
+ <member><type>VkImageLayout</type> <name>initialLayout</name></member> <!-- Initial image layout for all subresources -->
+ </type>
+ <type category="struct" name="VkSubresourceLayout" returnedonly="true">
+ <member><type>VkDeviceSize</type> <name>offset</name></member> <!-- Specified in bytes -->
+ <member><type>VkDeviceSize</type> <name>size</name></member> <!-- Specified in bytes -->
+ <member><type>VkDeviceSize</type> <name>rowPitch</name></member> <!-- Specified in bytes -->
+ <member><type>VkDeviceSize</type> <name>arrayPitch</name></member> <!-- Specified in bytes -->
+ <member><type>VkDeviceSize</type> <name>depthPitch</name></member> <!-- Specified in bytes -->
+ </type>
+ <type category="struct" name="VkImageViewCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkImageViewCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkImage</type> <name>image</name></member>
+ <member><type>VkImageViewType</type> <name>viewType</name></member>
+ <member><type>VkFormat</type> <name>format</name></member>
+ <member><type>VkComponentMapping</type> <name>components</name></member>
+ <member><type>VkImageSubresourceRange</type> <name>subresourceRange</name></member>
+ </type>
+ <type category="struct" name="VkBufferCopy">
+ <member><type>VkDeviceSize</type> <name>srcOffset</name></member> <!-- Specified in bytes -->
+ <member><type>VkDeviceSize</type> <name>dstOffset</name></member> <!-- Specified in bytes -->
+ <member><type>VkDeviceSize</type> <name>size</name></member> <!-- Specified in bytes -->
+ </type>
+ <type category="struct" name="VkSparseMemoryBind">
+ <member><type>VkDeviceSize</type> <name>resourceOffset</name></member> <!-- Specified in bytes -->
+ <member><type>VkDeviceSize</type> <name>size</name></member> <!-- Specified in bytes -->
+ <member optional="true"><type>VkDeviceMemory</type> <name>memory</name></member>
+ <member><type>VkDeviceSize</type> <name>memoryOffset</name></member> <!-- Specified in bytes -->
+ <member optional="true"><type>VkSparseMemoryBindFlags</type><name>flags</name></member> <!-- Reserved for future -->
+ </type>
+ <type category="struct" name="VkSparseImageMemoryBind">
+ <member><type>VkImageSubresource</type> <name>subresource</name></member>
+ <member><type>VkOffset3D</type> <name>offset</name></member>
+ <member><type>VkExtent3D</type> <name>extent</name></member>
+ <member optional="true"><type>VkDeviceMemory</type> <name>memory</name></member>
+ <member><type>VkDeviceSize</type> <name>memoryOffset</name></member> <!-- Specified in bytes -->
+ <member optional="true"><type>VkSparseMemoryBindFlags</type><name>flags</name></member> <!-- Reserved for future -->
+ </type>
+ <type category="struct" name="VkSparseBufferMemoryBindInfo">
+ <member><type>VkBuffer</type> <name>buffer</name></member>
+ <member><type>uint32_t</type> <name>bindCount</name></member>
+ <member len="bindCount">const <type>VkSparseMemoryBind</type>* <name>pBinds</name></member>
+ </type>
+ <type category="struct" name="VkSparseImageOpaqueMemoryBindInfo">
+ <member><type>VkImage</type> <name>image</name></member>
+ <member><type>uint32_t</type> <name>bindCount</name></member>
+ <member len="bindCount">const <type>VkSparseMemoryBind</type>* <name>pBinds</name></member>
+ </type>
+ <type category="struct" name="VkSparseImageMemoryBindInfo">
+ <member><type>VkImage</type> <name>image</name></member>
+ <member><type>uint32_t</type> <name>bindCount</name></member>
+ <member len="bindCount">const <type>VkSparseImageMemoryBind</type>* <name>pBinds</name></member>
+ </type>
+ <type category="struct" name="VkBindSparseInfo">
+ <member values="VK_STRUCTURE_TYPE_BIND_SPARSE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure. -->
+ <member optional="true"><type>uint32_t</type> <name>waitSemaphoreCount</name></member>
+ <member len="waitSemaphoreCount">const <type>VkSemaphore</type>* <name>pWaitSemaphores</name></member>
+ <member optional="true"><type>uint32_t</type> <name>bufferBindCount</name></member>
+ <member len="bufferBindCount">const <type>VkSparseBufferMemoryBindInfo</type>* <name>pBufferBinds</name></member>
+ <member optional="true"><type>uint32_t</type> <name>imageOpaqueBindCount</name></member>
+ <member len="imageOpaqueBindCount">const <type>VkSparseImageOpaqueMemoryBindInfo</type>* <name>pImageOpaqueBinds</name></member>
+ <member optional="true"><type>uint32_t</type> <name>imageBindCount</name></member>
+ <member len="imageBindCount">const <type>VkSparseImageMemoryBindInfo</type>* <name>pImageBinds</name></member>
+ <member optional="true"><type>uint32_t</type> <name>signalSemaphoreCount</name></member>
+ <member len="signalSemaphoreCount">const <type>VkSemaphore</type>* <name>pSignalSemaphores</name></member>
+ </type>
+ <type category="struct" name="VkImageCopy">
+ <member><type>VkImageSubresourceLayers</type> <name>srcSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>srcOffset</name></member> <!-- Specified in pixels for both compressed and uncompressed images -->
+ <member><type>VkImageSubresourceLayers</type> <name>dstSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>dstOffset</name></member> <!-- Specified in pixels for both compressed and uncompressed images -->
+ <member><type>VkExtent3D</type> <name>extent</name></member> <!-- Specified in pixels for both compressed and uncompressed images -->
+ </type>
+ <type category="struct" name="VkImageBlit">
+ <member><type>VkImageSubresourceLayers</type> <name>srcSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>srcOffsets</name>[2]</member> <!-- Specified in pixels for both compressed and uncompressed images -->
+ <member><type>VkImageSubresourceLayers</type> <name>dstSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>dstOffsets</name>[2]</member> <!-- Specified in pixels for both compressed and uncompressed images -->
+ </type>
+ <type category="struct" name="VkBufferImageCopy">
+ <member><type>VkDeviceSize</type> <name>bufferOffset</name></member> <!-- Specified in bytes -->
+ <member><type>uint32_t</type> <name>bufferRowLength</name></member> <!-- Specified in texels -->
+ <member><type>uint32_t</type> <name>bufferImageHeight</name></member>
+ <member><type>VkImageSubresourceLayers</type> <name>imageSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>imageOffset</name></member> <!-- Specified in pixels for both compressed and uncompressed images -->
+ <member><type>VkExtent3D</type> <name>imageExtent</name></member> <!-- Specified in pixels for both compressed and uncompressed images -->
+ </type>
+ <type category="struct" name="VkImageResolve">
+ <member><type>VkImageSubresourceLayers</type> <name>srcSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>srcOffset</name></member>
+ <member><type>VkImageSubresourceLayers</type> <name>dstSubresource</name></member>
+ <member><type>VkOffset3D</type> <name>dstOffset</name></member>
+ <member><type>VkExtent3D</type> <name>extent</name></member>
+ </type>
+ <type category="struct" name="VkShaderModuleCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkShaderModuleCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>size_t</type> <name>codeSize</name></member> <!-- Specified in bytes -->
+ <member len="latexmath:[$codeSize \over 4$]">const <type>uint32_t</type>* <name>pCode</name></member> <!-- Binary code of size codeSize -->
+ </type>
+ <type category="struct" name="VkDescriptorSetLayoutBinding">
+ <member><type>uint32_t</type> <name>binding</name></member> <!-- Binding number for this entry -->
+ <member><type>VkDescriptorType</type> <name>descriptorType</name></member> <!-- Type of the descriptors in this binding -->
+ <member optional="true"><type>uint32_t</type> <name>descriptorCount</name></member> <!-- Number of descriptors in this binding -->
+ <member noautovalidity="true"><type>VkShaderStageFlags</type> <name>stageFlags</name></member> <!-- Shader stages this binding is visible to -->
+ <member noautovalidity="true" optional="true" len="descriptorCount">const <type>VkSampler</type>* <name>pImmutableSamplers</name></member> <!-- Immutable samplers (used if descriptor type is SAMPLER or COMBINED_IMAGE_SAMPLER, is either NULL or contains count number of elements) -->
+ </type>
+ <type category="struct" name="VkDescriptorSetLayoutCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkDescriptorSetLayoutCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member optional="true"><type>uint32_t</type> <name>bindingCount</name></member> <!-- Number of bindings in the descriptor set layout -->
+ <member len="bindingCount">const <type>VkDescriptorSetLayoutBinding</type>* <name>pBindings</name></member> <!-- Array of descriptor set layout bindings -->
+ </type>
+ <type category="struct" name="VkDescriptorPoolSize">
+ <member><type>VkDescriptorType</type> <name>type</name></member>
+ <member><type>uint32_t</type> <name>descriptorCount</name></member>
+ </type>
+ <type category="struct" name="VkDescriptorPoolCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkDescriptorPoolCreateFlags</type> <name>flags</name></member>
+ <member><type>uint32_t</type> <name>maxSets</name></member>
+ <member><type>uint32_t</type> <name>poolSizeCount</name></member>
+ <member len="poolSizeCount">const <type>VkDescriptorPoolSize</type>* <name>pPoolSizes</name></member>
+ </type>
+ <type category="struct" name="VkDescriptorSetAllocateInfo">
+ <member values="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkDescriptorPool</type> <name>descriptorPool</name></member>
+ <member><type>uint32_t</type> <name>descriptorSetCount</name></member>
+ <member len="descriptorSetCount">const <type>VkDescriptorSetLayout</type>* <name>pSetLayouts</name></member>
+ </type>
+ <type category="struct" name="VkSpecializationMapEntry">
+ <member><type>uint32_t</type> <name>constantID</name></member> <!-- The SpecConstant ID specified in the BIL -->
+ <member><type>uint32_t</type> <name>offset</name></member> <!-- Offset of the value in the data block -->
+ <member><type>size_t</type> <name>size</name></member> <!-- Size in bytes of the SpecConstant -->
+ </type>
+ <type category="struct" name="VkSpecializationInfo">
+ <member optional="true"><type>uint32_t</type> <name>mapEntryCount</name></member> <!-- Number of entries in the map -->
+ <member len="mapEntryCount" noautovalidity="true">const <type>VkSpecializationMapEntry</type>* <name>pMapEntries</name></member> <!-- Array of map entries -->
+ <member optional="true"><type>size_t</type> <name>dataSize</name></member> <!-- Size in bytes of pData -->
+ <member len="dataSize">const <type>void</type>* <name>pData</name></member> <!-- Pointer to SpecConstant data -->
+ </type>
+ <type category="struct" name="VkPipelineShaderStageCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineShaderStageCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkShaderStageFlagBits</type> <name>stage</name></member> <!-- Shader stage -->
+ <member><type>VkShaderModule</type> <name>module</name></member> <!-- Module containing entry point -->
+ <member len="null-terminated">const <type>char</type>* <name>pName</name></member> <!-- Null-terminated entry point name -->
+ <member optional="true">const <type>VkSpecializationInfo</type>* <name>pSpecializationInfo</name></member>
+ </type>
+ <type category="struct" name="VkComputePipelineCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineCreateFlags</type> <name>flags</name></member> <!-- Pipeline creation flags -->
+ <member><type>VkPipelineShaderStageCreateInfo</type> <name>stage</name></member>
+ <member><type>VkPipelineLayout</type> <name>layout</name></member> <!-- Interface layout of the pipeline -->
+ <member noautovalidity="true" optional="true"><type>VkPipeline</type> <name>basePipelineHandle</name></member> <!-- If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of -->
+ <member><type>int32_t</type> <name>basePipelineIndex</name></member> <!-- If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of -->
+ </type>
+ <type category="struct" name="VkVertexInputBindingDescription">
+ <member><type>uint32_t</type> <name>binding</name></member> <!-- Vertex buffer binding id -->
+ <member><type>uint32_t</type> <name>stride</name></member> <!-- Distance between vertices in bytes (0 = no advancement) -->
+ <member><type>VkVertexInputRate</type> <name>inputRate</name></member> <!-- The rate at which the vertex data is consumed -->
+ </type>
+ <type category="struct" name="VkVertexInputAttributeDescription">
+ <member><type>uint32_t</type> <name>location</name></member> <!-- location of the shader vertex attrib -->
+ <member><type>uint32_t</type> <name>binding</name></member> <!-- Vertex buffer binding id -->
+ <member><type>VkFormat</type> <name>format</name></member> <!-- format of source data -->
+ <member><type>uint32_t</type> <name>offset</name></member> <!-- Offset of first element in bytes from base of vertex -->
+ </type>
+ <type category="struct" name="VkPipelineVertexInputStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineVertexInputStateCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member optional="true"><type>uint32_t</type> <name>vertexBindingDescriptionCount</name></member> <!-- number of bindings -->
+ <member len="vertexBindingDescriptionCount">const <type>VkVertexInputBindingDescription</type>* <name>pVertexBindingDescriptions</name></member>
+ <member optional="true"><type>uint32_t</type> <name>vertexAttributeDescriptionCount</name></member> <!-- number of attributes -->
+ <member len="vertexAttributeDescriptionCount">const <type>VkVertexInputAttributeDescription</type>* <name>pVertexAttributeDescriptions</name></member>
+ </type>
+ <type category="struct" name="VkPipelineInputAssemblyStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineInputAssemblyStateCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkPrimitiveTopology</type> <name>topology</name></member>
+ <member><type>VkBool32</type> <name>primitiveRestartEnable</name></member>
+ </type>
+ <type category="struct" name="VkPipelineTessellationStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineTessellationStateCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>uint32_t</type> <name>patchControlPoints</name></member>
+ </type>
+ <type category="struct" name="VkPipelineViewportStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineViewportStateCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>uint32_t</type> <name>viewportCount</name></member>
+ <member noautovalidity="true" optional="true" len="viewportCount">const <type>VkViewport</type>* <name>pViewports</name></member>
+ <member><type>uint32_t</type> <name>scissorCount</name></member>
+ <member noautovalidity="true" optional="true" len="scissorCount">const <type>VkRect2D</type>* <name>pScissors</name></member>
+ </type>
+ <type category="struct" name="VkPipelineRasterizationStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member validextensionstructs="VkPipelineRasterizationStateRasterizationOrderAMD">const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineRasterizationStateCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkBool32</type> <name>depthClampEnable</name></member>
+ <member><type>VkBool32</type> <name>rasterizerDiscardEnable</name></member>
+ <member><type>VkPolygonMode</type> <name>polygonMode</name></member> <!-- optional (GL45) -->
+ <member optional="true"><type>VkCullModeFlags</type> <name>cullMode</name></member>
+ <member><type>VkFrontFace</type> <name>frontFace</name></member>
+ <member><type>VkBool32</type> <name>depthBiasEnable</name></member>
+ <member><type>float</type> <name>depthBiasConstantFactor</name></member>
+ <member><type>float</type> <name>depthBiasClamp</name></member>
+ <member><type>float</type> <name>depthBiasSlopeFactor</name></member>
+ <member><type>float</type> <name>lineWidth</name></member>
+ </type>
+ <type category="struct" name="VkPipelineMultisampleStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineMultisampleStateCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkSampleCountFlagBits</type> <name>rasterizationSamples</name></member> <!-- Number of samples used for rasterization -->
+ <member><type>VkBool32</type> <name>sampleShadingEnable</name></member> <!-- optional (GL45) -->
+ <member><type>float</type> <name>minSampleShading</name></member> <!-- optional (GL45) -->
+ <member optional="true" len="latexmath:[$\lceil{\mathit{rasterizationSamples} \over 32}\rceil$]">const <type>VkSampleMask</type>* <name>pSampleMask</name></member> <!-- Array of sampleMask words -->
+ <member><type>VkBool32</type> <name>alphaToCoverageEnable</name></member>
+ <member><type>VkBool32</type> <name>alphaToOneEnable</name></member>
+ </type>
+ <type category="struct" name="VkPipelineColorBlendAttachmentState">
+ <member><type>VkBool32</type> <name>blendEnable</name></member>
+ <member><type>VkBlendFactor</type> <name>srcColorBlendFactor</name></member>
+ <member><type>VkBlendFactor</type> <name>dstColorBlendFactor</name></member>
+ <member><type>VkBlendOp</type> <name>colorBlendOp</name></member>
+ <member><type>VkBlendFactor</type> <name>srcAlphaBlendFactor</name></member>
+ <member><type>VkBlendFactor</type> <name>dstAlphaBlendFactor</name></member>
+ <member><type>VkBlendOp</type> <name>alphaBlendOp</name></member>
+ <member optional="true"><type>VkColorComponentFlags</type> <name>colorWriteMask</name></member>
+ </type>
+ <type category="struct" name="VkPipelineColorBlendStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineColorBlendStateCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkBool32</type> <name>logicOpEnable</name></member>
+ <member noautovalidity="true"><type>VkLogicOp</type> <name>logicOp</name></member>
+ <member optional="true"><type>uint32_t</type> <name>attachmentCount</name></member> <!-- # of pAttachments -->
+ <member len="attachmentCount">const <type>VkPipelineColorBlendAttachmentState</type>* <name>pAttachments</name></member>
+ <member><type>float</type> <name>blendConstants</name>[4]</member>
+ </type>
+ <type category="struct" name="VkPipelineDynamicStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineDynamicStateCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>uint32_t</type> <name>dynamicStateCount</name></member>
+ <member len="dynamicStateCount">const <type>VkDynamicState</type>* <name>pDynamicStates</name></member>
+ </type>
+ <type category="struct" name="VkStencilOpState">
+ <member><type>VkStencilOp</type> <name>failOp</name></member>
+ <member><type>VkStencilOp</type> <name>passOp</name></member>
+ <member><type>VkStencilOp</type> <name>depthFailOp</name></member>
+ <member><type>VkCompareOp</type> <name>compareOp</name></member>
+ <member><type>uint32_t</type> <name>compareMask</name></member>
+ <member><type>uint32_t</type> <name>writeMask</name></member>
+ <member><type>uint32_t</type> <name>reference</name></member>
+ </type>
+ <type category="struct" name="VkPipelineDepthStencilStateCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineDepthStencilStateCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkBool32</type> <name>depthTestEnable</name></member>
+ <member><type>VkBool32</type> <name>depthWriteEnable</name></member>
+ <member><type>VkCompareOp</type> <name>depthCompareOp</name></member>
+ <member><type>VkBool32</type> <name>depthBoundsTestEnable</name></member> <!-- optional (depth_bounds_test) -->
+ <member><type>VkBool32</type> <name>stencilTestEnable</name></member>
+ <member><type>VkStencilOpState</type> <name>front</name></member>
+ <member><type>VkStencilOpState</type> <name>back</name></member>
+ <member><type>float</type> <name>minDepthBounds</name></member>
+ <member><type>float</type> <name>maxDepthBounds</name></member>
+ </type>
+ <type category="struct" name="VkGraphicsPipelineCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineCreateFlags</type> <name>flags</name></member> <!-- Pipeline creation flags -->
+ <member><type>uint32_t</type> <name>stageCount</name></member>
+ <member len="stageCount">const <type>VkPipelineShaderStageCreateInfo</type>* <name>pStages</name></member> <!-- One entry for each active shader stage -->
+ <member>const <type>VkPipelineVertexInputStateCreateInfo</type>* <name>pVertexInputState</name></member>
+ <member>const <type>VkPipelineInputAssemblyStateCreateInfo</type>* <name>pInputAssemblyState</name></member>
+ <member noautovalidity="true" optional="true">const <type>VkPipelineTessellationStateCreateInfo</type>* <name>pTessellationState</name></member>
+ <member noautovalidity="true" optional="true">const <type>VkPipelineViewportStateCreateInfo</type>* <name>pViewportState</name></member>
+ <member>const <type>VkPipelineRasterizationStateCreateInfo</type>* <name>pRasterizationState</name></member>
+ <member noautovalidity="true" optional="true">const <type>VkPipelineMultisampleStateCreateInfo</type>* <name>pMultisampleState</name></member>
+ <member noautovalidity="true" optional="true">const <type>VkPipelineDepthStencilStateCreateInfo</type>* <name>pDepthStencilState</name></member>
+ <member noautovalidity="true" optional="true">const <type>VkPipelineColorBlendStateCreateInfo</type>* <name>pColorBlendState</name></member>
+ <member optional="true">const <type>VkPipelineDynamicStateCreateInfo</type>* <name>pDynamicState</name></member>
+ <member><type>VkPipelineLayout</type> <name>layout</name></member> <!-- Interface layout of the pipeline -->
+ <member><type>VkRenderPass</type> <name>renderPass</name></member>
+ <member><type>uint32_t</type> <name>subpass</name></member>
+ <member noautovalidity="true" optional="true"><type>VkPipeline</type> <name>basePipelineHandle</name></member> <!-- If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is nonzero, it specifies the handle of the base pipeline this is a derivative of -->
+ <member><type>int32_t</type> <name>basePipelineIndex</name></member> <!-- If VK_PIPELINE_CREATE_DERIVATIVE_BIT is set and this value is not -1, it specifies an index into pCreateInfos of the base pipeline this is a derivative of -->
+ </type>
+ <type category="struct" name="VkPipelineCacheCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineCacheCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member optional="true"><type>size_t</type> <name>initialDataSize</name></member> <!-- Size of initial data to populate cache, in bytes -->
+ <member len="initialDataSize">const <type>void</type>* <name>pInitialData</name></member> <!-- Initial data to populate cache -->
+ </type>
+ <type category="struct" name="VkPushConstantRange">
+ <member><type>VkShaderStageFlags</type> <name>stageFlags</name></member> <!-- Which stages use the range -->
+ <member><type>uint32_t</type> <name>offset</name></member> <!-- Start of the range, in bytes -->
+ <member><type>uint32_t</type> <name>size</name></member> <!-- Size of the range, in bytes -->
+ </type>
+ <type category="struct" name="VkPipelineLayoutCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkPipelineLayoutCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member optional="true"><type>uint32_t</type> <name>setLayoutCount</name></member> <!-- Number of descriptor sets interfaced by the pipeline -->
+ <member len="setLayoutCount">const <type>VkDescriptorSetLayout</type>* <name>pSetLayouts</name></member> <!-- Array of setCount number of descriptor set layout objects defining the layout of the -->
+ <member optional="true"><type>uint32_t</type> <name>pushConstantRangeCount</name></member> <!-- Number of push-constant ranges used by the pipeline -->
+ <member len="pushConstantRangeCount">const <type>VkPushConstantRange</type>* <name>pPushConstantRanges</name></member> <!-- Array of pushConstantRangeCount number of ranges used by various shader stages -->
+ </type>
+ <type category="struct" name="VkSamplerCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkSamplerCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkFilter</type> <name>magFilter</name></member> <!-- Filter mode for magnification -->
+ <member><type>VkFilter</type> <name>minFilter</name></member> <!-- Filter mode for minifiation -->
+ <member><type>VkSamplerMipmapMode</type> <name>mipmapMode</name></member> <!-- Mipmap selection mode -->
+ <member><type>VkSamplerAddressMode</type> <name>addressModeU</name></member>
+ <member><type>VkSamplerAddressMode</type> <name>addressModeV</name></member>
+ <member><type>VkSamplerAddressMode</type> <name>addressModeW</name></member>
+ <member><type>float</type> <name>mipLodBias</name></member>
+ <member><type>VkBool32</type> <name>anisotropyEnable</name></member>
+ <member><type>float</type> <name>maxAnisotropy</name></member>
+ <member><type>VkBool32</type> <name>compareEnable</name></member>
+ <member noautovalidity="true"><type>VkCompareOp</type> <name>compareOp</name></member>
+ <member><type>float</type> <name>minLod</name></member>
+ <member><type>float</type> <name>maxLod</name></member>
+ <member noautovalidity="true"><type>VkBorderColor</type> <name>borderColor</name></member>
+ <member><type>VkBool32</type> <name>unnormalizedCoordinates</name></member>
+ </type>
+ <type category="struct" name="VkCommandPoolCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkCommandPoolCreateFlags</type> <name>flags</name></member> <!-- Command pool creation flags -->
+ <member><type>uint32_t</type> <name>queueFamilyIndex</name></member>
+ </type>
+ <type category="struct" name="VkCommandBufferAllocateInfo">
+ <member values="VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkCommandPool</type> <name>commandPool</name></member>
+ <member><type>VkCommandBufferLevel</type> <name>level</name></member>
+ <member><type>uint32_t</type> <name>commandBufferCount</name></member>
+ </type>
+ <type category="struct" name="VkCommandBufferInheritanceInfo">
+ <member values="VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true" noautovalidity="true"><type>VkRenderPass</type> <name>renderPass</name></member> <!-- Render pass for secondary command buffers -->
+ <member><type>uint32_t</type> <name>subpass</name></member>
+ <member optional="true" noautovalidity="true"><type>VkFramebuffer</type> <name>framebuffer</name></member> <!-- Framebuffer for secondary command buffers -->
+ <member><type>VkBool32</type> <name>occlusionQueryEnable</name></member> <!-- Whether this secondary command buffer may be executed during an occlusion query -->
+ <member optional="true" noautovalidity="true"><type>VkQueryControlFlags</type> <name>queryFlags</name></member> <!-- Query flags used by this secondary command buffer, if executed during an occlusion query -->
+ <member optional="true" noautovalidity="true"><type>VkQueryPipelineStatisticFlags</type> <name>pipelineStatistics</name></member> <!-- Pipeline statistics that may be counted for this secondary command buffer -->
+ </type>
+ <type category="struct" name="VkCommandBufferBeginInfo">
+ <member values="VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkCommandBufferUsageFlags</type> <name>flags</name></member> <!-- Command buffer usage flags -->
+ <member optional="true" noautovalidity="true">const <type>VkCommandBufferInheritanceInfo</type>* <name>pInheritanceInfo</name></member> <!-- Pointer to inheritance info for secondary command buffers -->
+ </type>
+ <type category="struct" name="VkRenderPassBeginInfo">
+ <member values="VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkRenderPass</type> <name>renderPass</name></member>
+ <member><type>VkFramebuffer</type> <name>framebuffer</name></member>
+ <member><type>VkRect2D</type> <name>renderArea</name></member>
+ <member optional="true"><type>uint32_t</type> <name>clearValueCount</name></member>
+ <member len="clearValueCount" noautovalidity="true">const <type>VkClearValue</type>* <name>pClearValues</name></member>
+ </type>
+ <type category="union" name="VkClearColorValue" comment="// Union allowing specification of floating point, integer, or unsigned integer color data. Actual value selected is based on image/attachment being cleared.">
+ <member><type>float</type> <name>float32</name>[4]</member>
+ <member><type>int32_t</type> <name>int32</name>[4]</member>
+ <member><type>uint32_t</type> <name>uint32</name>[4]</member>
+ </type>
+ <type category="struct" name="VkClearDepthStencilValue">
+ <member><type>float</type> <name>depth</name></member>
+ <member><type>uint32_t</type> <name>stencil</name></member>
+ </type>
+ <type category="union" name="VkClearValue" comment="// Union allowing specification of color or depth and stencil values. Actual value selected is based on attachment being cleared.">
+ <member><type>VkClearColorValue</type> <name>color</name></member>
+ <member><type>VkClearDepthStencilValue</type> <name>depthStencil</name></member>
+ </type>
+ <type category="struct" name="VkClearAttachment">
+ <member><type>VkImageAspectFlags</type> <name>aspectMask</name></member>
+ <member><type>uint32_t</type> <name>colorAttachment</name></member>
+ <member><type>VkClearValue</type> <name>clearValue</name></member>
+ </type>
+ <type category="struct" name="VkAttachmentDescription">
+ <member optional="true"><type>VkAttachmentDescriptionFlags</type> <name>flags</name></member>
+ <member><type>VkFormat</type> <name>format</name></member>
+ <member><type>VkSampleCountFlagBits</type> <name>samples</name></member>
+ <member><type>VkAttachmentLoadOp</type> <name>loadOp</name></member> <!-- Load operation for color or depth data -->
+ <member><type>VkAttachmentStoreOp</type> <name>storeOp</name></member> <!-- Store operation for color or depth data -->
+ <member><type>VkAttachmentLoadOp</type> <name>stencilLoadOp</name></member> <!-- Load operation for stencil data -->
+ <member><type>VkAttachmentStoreOp</type> <name>stencilStoreOp</name></member> <!-- Store operation for stencil data -->
+ <member><type>VkImageLayout</type> <name>initialLayout</name></member>
+ <member><type>VkImageLayout</type> <name>finalLayout</name></member>
+ </type>
+ <type category="struct" name="VkAttachmentReference">
+ <member><type>uint32_t</type> <name>attachment</name></member>
+ <member><type>VkImageLayout</type> <name>layout</name></member>
+ </type>
+ <type category="struct" name="VkSubpassDescription">
+ <member optional="true"><type>VkSubpassDescriptionFlags</type> <name>flags</name></member>
+ <member><type>VkPipelineBindPoint</type> <name>pipelineBindPoint</name></member> <!-- Must be VK_PIPELINE_BIND_POINT_GRAPHICS for now -->
+ <member optional="true"><type>uint32_t</type> <name>inputAttachmentCount</name></member>
+ <member len="inputAttachmentCount">const <type>VkAttachmentReference</type>* <name>pInputAttachments</name></member>
+ <member optional="true"><type>uint32_t</type> <name>colorAttachmentCount</name></member>
+ <member len="colorAttachmentCount">const <type>VkAttachmentReference</type>* <name>pColorAttachments</name></member>
+ <member optional="true" len="colorAttachmentCount">const <type>VkAttachmentReference</type>* <name>pResolveAttachments</name></member>
+ <member optional="true">const <type>VkAttachmentReference</type>* <name>pDepthStencilAttachment</name></member>
+ <member optional="true"><type>uint32_t</type> <name>preserveAttachmentCount</name></member>
+ <member len="preserveAttachmentCount">const <type>uint32_t</type>* <name>pPreserveAttachments</name></member>
+ </type>
+ <type category="struct" name="VkSubpassDependency">
+ <member><type>uint32_t</type> <name>srcSubpass</name></member>
+ <member><type>uint32_t</type> <name>dstSubpass</name></member>
+ <member><type>VkPipelineStageFlags</type> <name>srcStageMask</name></member>
+ <member><type>VkPipelineStageFlags</type> <name>dstStageMask</name></member>
+ <member optional="true"><type>VkAccessFlags</type> <name>srcAccessMask</name></member> <!-- Memory accesses from the source of the dependency to synchronize -->
+ <member optional="true"><type>VkAccessFlags</type> <name>dstAccessMask</name></member> <!-- Memory accesses from the destination of the dependency to synchronize -->
+ <member optional="true"><type>VkDependencyFlags</type> <name>dependencyFlags</name></member>
+ </type>
+ <type category="struct" name="VkRenderPassCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkRenderPassCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member optional="true"><type>uint32_t</type> <name>attachmentCount</name></member>
+ <member len="attachmentCount">const <type>VkAttachmentDescription</type>* <name>pAttachments</name></member>
+ <member><type>uint32_t</type> <name>subpassCount</name></member>
+ <member len="subpassCount">const <type>VkSubpassDescription</type>* <name>pSubpasses</name></member>
+ <member optional="true"><type>uint32_t</type> <name>dependencyCount</name></member>
+ <member len="dependencyCount">const <type>VkSubpassDependency</type>* <name>pDependencies</name></member>
+ </type>
+ <type category="struct" name="VkEventCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_EVENT_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkEventCreateFlags</type> <name>flags</name></member> <!-- Event creation flags -->
+ </type>
+ <type category="struct" name="VkFenceCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_FENCE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkFenceCreateFlags</type> <name>flags</name></member> <!-- Fence creation flags -->
+ </type>
+ <type category="struct" name="VkPhysicalDeviceFeatures">
+ <member><type>VkBool32</type> <name>robustBufferAccess</name></member> <!-- out of bounds buffer accesses are well defined -->
+ <member><type>VkBool32</type> <name>fullDrawIndexUint32</name></member> <!-- full 32-bit range of indices for indexed draw calls -->
+ <member><type>VkBool32</type> <name>imageCubeArray</name></member> <!-- image views which are arrays of cube maps -->
+ <member><type>VkBool32</type> <name>independentBlend</name></member> <!-- blending operations are controlled per-attachment -->
+ <member><type>VkBool32</type> <name>geometryShader</name></member> <!-- geometry stage -->
+ <member><type>VkBool32</type> <name>tessellationShader</name></member> <!-- tessellation control and evaluation stage -->
+ <member><type>VkBool32</type> <name>sampleRateShading</name></member> <!-- per-sample shading and interpolation -->
+ <member><type>VkBool32</type> <name>dualSrcBlend</name></member> <!-- blend operations which take two sources -->
+ <member><type>VkBool32</type> <name>logicOp</name></member> <!-- logic operations -->
+ <member><type>VkBool32</type> <name>multiDrawIndirect</name></member> <!-- multi draw indirect -->
+ <member><type>VkBool32</type> <name>drawIndirectFirstInstance</name></member> <!-- indirect draws can use non-zero firstInstance -->
+ <member><type>VkBool32</type> <name>depthClamp</name></member> <!-- depth clamping -->
+ <member><type>VkBool32</type> <name>depthBiasClamp</name></member> <!-- depth bias clamping -->
+ <member><type>VkBool32</type> <name>fillModeNonSolid</name></member> <!-- point and wireframe fill modes -->
+ <member><type>VkBool32</type> <name>depthBounds</name></member> <!-- depth bounds test -->
+ <member><type>VkBool32</type> <name>wideLines</name></member> <!-- lines with width greater than 1 -->
+ <member><type>VkBool32</type> <name>largePoints</name></member> <!-- points with size greater than 1 -->
+ <member><type>VkBool32</type> <name>alphaToOne</name></member> <!-- the fragment alpha component can be forced to maximum representable alpha value -->
+ <member><type>VkBool32</type> <name>multiViewport</name></member> <!-- viewport arrays -->
+ <member><type>VkBool32</type> <name>samplerAnisotropy</name></member> <!-- anisotropic sampler filtering -->
+ <member><type>VkBool32</type> <name>textureCompressionETC2</name></member> <!-- ETC texture compression formats -->
+ <member><type>VkBool32</type> <name>textureCompressionASTC_LDR</name></member> <!-- ASTC LDR texture compression formats -->
+ <member><type>VkBool32</type> <name>textureCompressionBC</name></member> <!-- BC1-7 texture compressed formats -->
+ <member><type>VkBool32</type> <name>occlusionQueryPrecise</name></member> <!-- precise occlusion queries returning actual sample counts -->
+ <member><type>VkBool32</type> <name>pipelineStatisticsQuery</name></member> <!-- pipeline statistics query -->
+ <member><type>VkBool32</type> <name>vertexPipelineStoresAndAtomics</name></member> <!-- stores and atomic ops on storage buffers and images are supported in vertex, tessellation, and geometry stages -->
+ <member><type>VkBool32</type> <name>fragmentStoresAndAtomics</name></member> <!-- stores and atomic ops on storage buffers and images are supported in the fragment stage -->
+ <member><type>VkBool32</type> <name>shaderTessellationAndGeometryPointSize</name></member><!-- tessellation and geometry stages can export point size -->
+ <member><type>VkBool32</type> <name>shaderImageGatherExtended</name></member> <!-- image gather with run-time values and independent offsets -->
+ <member><type>VkBool32</type> <name>shaderStorageImageExtendedFormats</name></member> <!-- the extended set of formats can be used for storage images -->
+ <member><type>VkBool32</type> <name>shaderStorageImageMultisample</name></member> <!-- multisample images can be used for storage images -->
+ <member><type>VkBool32</type> <name>shaderStorageImageReadWithoutFormat</name></member> <!-- read from storage image does not require format qualifier -->
+ <member><type>VkBool32</type> <name>shaderStorageImageWriteWithoutFormat</name></member> <!-- write to storage image does not require format qualifier -->
+ <member><type>VkBool32</type> <name>shaderUniformBufferArrayDynamicIndexing</name></member> <!-- arrays of uniform buffers can be accessed with dynamically uniform indices -->
+ <member><type>VkBool32</type> <name>shaderSampledImageArrayDynamicIndexing</name></member> <!-- arrays of sampled images can be accessed with dynamically uniform indices -->
+ <member><type>VkBool32</type> <name>shaderStorageBufferArrayDynamicIndexing</name></member> <!-- arrays of storage buffers can be accessed with dynamically uniform indices -->
+ <member><type>VkBool32</type> <name>shaderStorageImageArrayDynamicIndexing</name></member> <!-- arrays of storage images can be accessed with dynamically uniform indices -->
+ <member><type>VkBool32</type> <name>shaderClipDistance</name></member> <!-- clip distance in shaders -->
+ <member><type>VkBool32</type> <name>shaderCullDistance</name></member> <!-- cull distance in shaders -->
+ <member><type>VkBool32</type> <name>shaderFloat64</name></member> <!-- 64-bit floats (doubles) in shaders -->
+ <member><type>VkBool32</type> <name>shaderInt64</name></member> <!-- 64-bit integers in shaders -->
+ <member><type>VkBool32</type> <name>shaderInt16</name></member> <!-- 16-bit integers in shaders -->
+ <member><type>VkBool32</type> <name>shaderResourceResidency</name></member> <!-- shader can use texture operations that return resource residency information (requires sparseNonResident support) -->
+ <member><type>VkBool32</type> <name>shaderResourceMinLod</name></member> <!-- shader can use texture operations that specify minimum resource level of detail -->
+ <member><type>VkBool32</type> <name>sparseBinding</name></member> <!-- Sparse resources support: Resource memory can be managed at opaque page level rather than object level -->
+ <member><type>VkBool32</type> <name>sparseResidencyBuffer</name></member> <!-- Sparse resources support: GPU can access partially resident buffers -->
+ <member><type>VkBool32</type> <name>sparseResidencyImage2D</name></member> <!-- Sparse resources support: GPU can access partially resident 2D (non-MSAA non-depth/stencil) images -->
+ <member><type>VkBool32</type> <name>sparseResidencyImage3D</name></member> <!-- Sparse resources support: GPU can access partially resident 3D images -->
+ <member><type>VkBool32</type> <name>sparseResidency2Samples</name></member> <!-- Sparse resources support: GPU can access partially resident MSAA 2D images with 2 samples -->
+ <member><type>VkBool32</type> <name>sparseResidency4Samples</name></member> <!-- Sparse resources support: GPU can access partially resident MSAA 2D images with 4 samples -->
+ <member><type>VkBool32</type> <name>sparseResidency8Samples</name></member> <!-- Sparse resources support: GPU can access partially resident MSAA 2D images with 8 samples -->
+ <member><type>VkBool32</type> <name>sparseResidency16Samples</name></member> <!-- Sparse resources support: GPU can access partially resident MSAA 2D images with 16 samples -->
+ <member><type>VkBool32</type> <name>sparseResidencyAliased</name></member> <!-- Sparse resources support: GPU can correctly access data aliased into multiple locations (opt-in) -->
+ <member><type>VkBool32</type> <name>variableMultisampleRate</name></member> <!-- multisample rate must be the same for all pipelines in a subpass -->
+ <member><type>VkBool32</type> <name>inheritedQueries</name></member> <!-- Queries may be inherited from primary to secondary command buffers -->
+ </type>
+ <type category="struct" name="VkPhysicalDeviceSparseProperties" returnedonly="true">
+ <member><type>VkBool32</type> <name>residencyStandard2DBlockShape</name></member> <!-- Sparse resources support: GPU will access all 2D (single sample) sparse resources using the standard sparse image block shapes (based on pixel format) -->
+ <member><type>VkBool32</type> <name>residencyStandard2DMultisampleBlockShape</name></member> <!-- Sparse resources support: GPU will access all 2D (multisample) sparse resources using the standard sparse image block shapes (based on pixel format) -->
+ <member><type>VkBool32</type> <name>residencyStandard3DBlockShape</name></member> <!-- Sparse resources support: GPU will access all 3D sparse resources using the standard sparse image block shapes (based on pixel format) -->
+ <member><type>VkBool32</type> <name>residencyAlignedMipSize</name></member> <!-- Sparse resources support: Images with mip level dimensions that are NOT a multiple of the sparse image block dimensions will be placed in the mip tail -->
+ <member><type>VkBool32</type> <name>residencyNonResidentStrict</name></member> <!-- Sparse resources support: GPU can consistently access non-resident regions of a resource, all reads return as if data is 0, writes are discarded -->
+ </type>
+ <type category="struct" name="VkPhysicalDeviceLimits" returnedonly="true">
+ <!-- resource maximum sizes -->
+ <member><type>uint32_t</type> <name>maxImageDimension1D</name></member> <!-- max 1D image dimension -->
+ <member><type>uint32_t</type> <name>maxImageDimension2D</name></member> <!-- max 2D image dimension -->
+ <member><type>uint32_t</type> <name>maxImageDimension3D</name></member> <!-- max 3D image dimension -->
+ <member><type>uint32_t</type> <name>maxImageDimensionCube</name></member> <!-- max cubemap image dimension -->
+ <member><type>uint32_t</type> <name>maxImageArrayLayers</name></member> <!-- max layers for image arrays -->
+ <member><type>uint32_t</type> <name>maxTexelBufferElements</name></member> <!-- max texel buffer size (fstexels) -->
+ <member><type>uint32_t</type> <name>maxUniformBufferRange</name></member> <!-- max uniform buffer range (bytes) -->
+ <member><type>uint32_t</type> <name>maxStorageBufferRange</name></member> <!-- max storage buffer range (bytes) -->
+ <member><type>uint32_t</type> <name>maxPushConstantsSize</name></member> <!-- max size of the push constants pool (bytes) -->
+ <!-- memory limits -->
+ <member><type>uint32_t</type> <name>maxMemoryAllocationCount</name></member> <!-- max number of device memory allocations supported -->
+ <member><type>uint32_t</type> <name>maxSamplerAllocationCount</name></member> <!-- max number of samplers that can be allocated on a device -->
+ <member><type>VkDeviceSize</type> <name>bufferImageGranularity</name></member> <!-- Granularity (in bytes) at which buffers and images can be bound to adjacent memory for simultaneous usage -->
+ <member><type>VkDeviceSize</type> <name>sparseAddressSpaceSize</name></member> <!-- Total address space available for sparse allocations (bytes) -->
+ <!-- descriptor set limits -->
+ <member><type>uint32_t</type> <name>maxBoundDescriptorSets</name></member> <!-- max number of descriptors sets that can be bound to a pipeline -->
+ <member><type>uint32_t</type> <name>maxPerStageDescriptorSamplers</name></member> <!-- max number of samplers allowed per-stage in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxPerStageDescriptorUniformBuffers</name></member> <!-- max number of uniform buffers allowed per-stage in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxPerStageDescriptorStorageBuffers</name></member> <!-- max number of storage buffers allowed per-stage in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxPerStageDescriptorSampledImages</name></member> <!-- max number of sampled images allowed per-stage in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxPerStageDescriptorStorageImages</name></member> <!-- max number of storage images allowed per-stage in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxPerStageDescriptorInputAttachments</name></member> <!-- max number of input attachments allowed per-stage in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxPerStageResources</name></member> <!-- max number of resources allowed by a single stage -->
+ <member><type>uint32_t</type> <name>maxDescriptorSetSamplers</name></member> <!-- max number of samplers allowed in all stages in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxDescriptorSetUniformBuffers</name></member> <!-- max number of uniform buffers allowed in all stages in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxDescriptorSetUniformBuffersDynamic</name></member> <!-- max number of dynamic uniform buffers allowed in all stages in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxDescriptorSetStorageBuffers</name></member> <!-- max number of storage buffers allowed in all stages in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxDescriptorSetStorageBuffersDynamic</name></member> <!-- max number of dynamic storage buffers allowed in all stages in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxDescriptorSetSampledImages</name></member> <!-- max number of sampled images allowed in all stages in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxDescriptorSetStorageImages</name></member> <!-- max number of storage images allowed in all stages in a descriptor set -->
+ <member><type>uint32_t</type> <name>maxDescriptorSetInputAttachments</name></member> <!-- max number of input attachments allowed in all stages in a descriptor set -->
+ <!-- vertex stage limits -->
+ <member><type>uint32_t</type> <name>maxVertexInputAttributes</name></member> <!-- max number of vertex input attribute slots -->
+ <member><type>uint32_t</type> <name>maxVertexInputBindings</name></member> <!-- max number of vertex input binding slots -->
+ <member><type>uint32_t</type> <name>maxVertexInputAttributeOffset</name></member> <!-- max vertex input attribute offset added to vertex buffer offset -->
+ <member><type>uint32_t</type> <name>maxVertexInputBindingStride</name></member> <!-- max vertex input binding stride -->
+ <member><type>uint32_t</type> <name>maxVertexOutputComponents</name></member> <!-- max number of output components written by vertex shader -->
+ <!-- tessellation control stage limits -->
+ <member><type>uint32_t</type> <name>maxTessellationGenerationLevel</name></member> <!-- max level supported by tessellation primitive generator -->
+ <member><type>uint32_t</type> <name>maxTessellationPatchSize</name></member> <!-- max patch size (vertices) -->
+ <member><type>uint32_t</type> <name>maxTessellationControlPerVertexInputComponents</name></member> <!-- max number of input components per-vertex in TCS -->
+ <member><type>uint32_t</type> <name>maxTessellationControlPerVertexOutputComponents</name></member> <!-- max number of output components per-vertex in TCS -->
+ <member><type>uint32_t</type> <name>maxTessellationControlPerPatchOutputComponents</name></member> <!-- max number of output components per-patch in TCS -->
+ <member><type>uint32_t</type> <name>maxTessellationControlTotalOutputComponents</name></member> <!-- max total number of per-vertex and per-patch output components in TCS -->
+ <!-- tessellation evaluation stage limits -->
+ <member><type>uint32_t</type> <name>maxTessellationEvaluationInputComponents</name></member> <!-- max number of input components per vertex in TES -->
+ <member><type>uint32_t</type> <name>maxTessellationEvaluationOutputComponents</name></member> <!-- max number of output components per vertex in TES -->
+ <!-- geometry stage limits -->
+ <member><type>uint32_t</type> <name>maxGeometryShaderInvocations</name></member> <!-- max invocation count supported in geometry shader -->
+ <member><type>uint32_t</type> <name>maxGeometryInputComponents</name></member> <!-- max number of input components read in geometry stage -->
+ <member><type>uint32_t</type> <name>maxGeometryOutputComponents</name></member> <!-- max number of output components written in geometry stage -->
+ <member><type>uint32_t</type> <name>maxGeometryOutputVertices</name></member> <!-- max number of vertices that can be emitted in geometry stage -->
+ <member><type>uint32_t</type> <name>maxGeometryTotalOutputComponents</name></member> <!-- max total number of components (all vertices) written in geometry stage -->
+ <!-- fragment stage limits -->
+ <member><type>uint32_t</type> <name>maxFragmentInputComponents</name></member> <!-- max number of input compontents read in fragment stage -->
+ <member><type>uint32_t</type> <name>maxFragmentOutputAttachments</name></member> <!-- max number of output attachments written in fragment stage -->
+ <member><type>uint32_t</type> <name>maxFragmentDualSrcAttachments</name></member> <!-- max number of output attachments written when using dual source blending -->
+ <member><type>uint32_t</type> <name>maxFragmentCombinedOutputResources</name></member><!-- max total number of storage buffers, storage images and output buffers -->
+ <!-- compute stage limits -->
+ <member><type>uint32_t</type> <name>maxComputeSharedMemorySize</name></member> <!-- max total storage size of work group local storage (bytes) -->
+ <member><type>uint32_t</type> <name>maxComputeWorkGroupCount</name>[3]</member> <!-- max num of compute work groups that may be dispatched by a single command (x,y,z) -->
+ <member><type>uint32_t</type> <name>maxComputeWorkGroupInvocations</name></member> <!-- max total compute invocations in a single local work group -->
+ <member><type>uint32_t</type> <name>maxComputeWorkGroupSize</name>[3]</member> <!-- max local size of a compute work group (x,y,z) -->
+ <member><type>uint32_t</type> <name>subPixelPrecisionBits</name></member> <!-- number bits of subpixel precision in screen x and y-->
+ <member><type>uint32_t</type> <name>subTexelPrecisionBits</name></member> <!-- number bits of precision for selecting texel weights-->
+ <member><type>uint32_t</type> <name>mipmapPrecisionBits</name></member> <!-- number bits of precision for selecting mipmap weights -->
+ <member><type>uint32_t</type> <name>maxDrawIndexedIndexValue</name></member> <!-- max index value for indexed draw calls (for 32-bit indices) -->
+ <member><type>uint32_t</type> <name>maxDrawIndirectCount</name></member> <!-- max draw count for indirect draw calls -->
+ <member><type>float</type> <name>maxSamplerLodBias</name></member> <!-- max absolute sampler level of detail bias -->
+ <member><type>float</type> <name>maxSamplerAnisotropy</name></member> <!-- max degree of sampler anisotropy -->
+ <member><type>uint32_t</type> <name>maxViewports</name></member> <!-- max number of active viewports -->
+ <member><type>uint32_t</type> <name>maxViewportDimensions</name>[2]</member> <!-- max viewport dimensions (x,y) -->
+ <member><type>float</type> <name>viewportBoundsRange</name>[2]</member> <!-- viewport bounds range (min,max) -->
+ <member><type>uint32_t</type> <name>viewportSubPixelBits</name></member> <!-- number bits of subpixel precision for viewport -->
+ <member><type>size_t</type> <name>minMemoryMapAlignment</name></member> <!-- min required alignment of pointers returned by MapMemory (bytes) -->
+ <member><type>VkDeviceSize</type> <name>minTexelBufferOffsetAlignment</name></member> <!-- min required alignment for texel buffer offsets (bytes) -->
+ <member><type>VkDeviceSize</type> <name>minUniformBufferOffsetAlignment</name></member> <!-- min required alignment for uniform buffer sizes and offsets (bytes) -->
+ <member><type>VkDeviceSize</type> <name>minStorageBufferOffsetAlignment</name></member> <!-- min required alignment for storage buffer offsets (bytes) -->
+ <member><type>int32_t</type> <name>minTexelOffset</name></member> <!-- min texel offset for OpTextureSampleOffset -->
+ <member><type>uint32_t</type> <name>maxTexelOffset</name></member> <!-- max texel offset for OpTextureSampleOffset -->
+ <member><type>int32_t</type> <name>minTexelGatherOffset</name></member> <!-- min texel offset for OpTextureGatherOffset -->
+ <member><type>uint32_t</type> <name>maxTexelGatherOffset</name></member> <!-- max texel offset for OpTextureGatherOffset -->
+ <member><type>float</type> <name>minInterpolationOffset</name></member> <!-- furthest negative offset for interpolateAtOffset -->
+ <member><type>float</type> <name>maxInterpolationOffset</name></member> <!-- furthest positive offset for interpolateAtOffset -->
+ <member><type>uint32_t</type> <name>subPixelInterpolationOffsetBits</name></member> <!-- number of subpixel bits for interpolateAtOffset -->
+ <member><type>uint32_t</type> <name>maxFramebufferWidth</name></member> <!-- max width for a framebuffer -->
+ <member><type>uint32_t</type> <name>maxFramebufferHeight</name></member> <!-- max height for a framebuffer -->
+ <member><type>uint32_t</type> <name>maxFramebufferLayers</name></member> <!-- max layer count for a layered framebuffer -->
+ <member optional="true"><type>VkSampleCountFlags</type> <name>framebufferColorSampleCounts</name></member> <!-- supported color sample counts for a framebuffer -->
+ <member optional="true"><type>VkSampleCountFlags</type> <name>framebufferDepthSampleCounts</name></member> <!-- supported depth sample counts for a framebuffer -->
+ <member optional="true"><type>VkSampleCountFlags</type> <name>framebufferStencilSampleCounts</name></member> <!-- supported stencil sample counts for a framebuffer -->
+ <member optional="true"><type>VkSampleCountFlags</type> <name>framebufferNoAttachmentsSampleCounts</name></member> <!-- supported sample counts for a framebuffer with no attachments -->
+ <member><type>uint32_t</type> <name>maxColorAttachments</name></member> <!-- max number of color attachments per subpass -->
+ <member optional="true"><type>VkSampleCountFlags</type> <name>sampledImageColorSampleCounts</name></member> <!-- supported color sample counts for a non-integer sampled image -->
+ <member optional="true"><type>VkSampleCountFlags</type> <name>sampledImageIntegerSampleCounts</name></member> <!-- supported sample counts for an integer image -->
+ <member optional="true"><type>VkSampleCountFlags</type> <name>sampledImageDepthSampleCounts</name></member> <!-- supported depth sample counts for a sampled image -->
+ <member optional="true"><type>VkSampleCountFlags</type> <name>sampledImageStencilSampleCounts</name></member> <!-- supported stencil sample counts for a sampled image -->
+ <member optional="true"><type>VkSampleCountFlags</type> <name>storageImageSampleCounts</name></member> <!-- supported sample counts for a storage image -->
+ <member><type>uint32_t</type> <name>maxSampleMaskWords</name></member> <!-- max number of sample mask words -->
+ <member><type>VkBool32</type> <name>timestampComputeAndGraphics</name></member> <!-- timestamps on graphics and compute queues -->
+ <member><type>float</type> <name>timestampPeriod</name></member> <!-- number of nanoseconds it takes for timestamp query value to increment by 1 -->
+ <member><type>uint32_t</type> <name>maxClipDistances</name></member> <!-- max number of clip distances -->
+ <member><type>uint32_t</type> <name>maxCullDistances</name></member> <!-- max number of cull distances -->
+ <member><type>uint32_t</type> <name>maxCombinedClipAndCullDistances</name></member> <!-- max combined number of user clipping -->
+ <member><type>uint32_t</type> <name>discreteQueuePriorities</name></member> <!-- distinct queue priorities available -->
+ <member><type>float</type> <name>pointSizeRange</name>[2]</member> <!-- range (min,max) of supported point sizes -->
+ <member><type>float</type> <name>lineWidthRange</name>[2]</member> <!-- range (min,max) of supported line widths -->
+ <member><type>float</type> <name>pointSizeGranularity</name></member> <!-- granularity of supported point sizes -->
+ <member><type>float</type> <name>lineWidthGranularity</name></member> <!-- granularity of supported line widths -->
+ <member><type>VkBool32</type> <name>strictLines</name></member> <!-- line rasterization follows preferred rules -->
+ <member><type>VkBool32</type> <name>standardSampleLocations</name></member> <!-- supports standard sample locations for all supported sample counts -->
+ <member><type>VkDeviceSize</type> <name>optimalBufferCopyOffsetAlignment</name></member> <!-- optimal offset of buffer copies -->
+ <member><type>VkDeviceSize</type> <name>optimalBufferCopyRowPitchAlignment</name></member><!-- optimal pitch of buffer copies -->
+ <member><type>VkDeviceSize</type> <name>nonCoherentAtomSize</name></member> <!-- minimum size and alignment for non-coherent host-mapped device memory access -->
+ </type>
+ <type category="struct" name="VkSemaphoreCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkSemaphoreCreateFlags</type> <name>flags</name></member> <!-- Semaphore creation flags -->
+ </type>
+ <type category="struct" name="VkQueryPoolCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkQueryPoolCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkQueryType</type> <name>queryType</name></member>
+ <member><type>uint32_t</type> <name>queryCount</name></member>
+ <member optional="true" noautovalidity="true"><type>VkQueryPipelineStatisticFlags</type> <name>pipelineStatistics</name></member> <!-- Optional -->
+ </type>
+ <type category="struct" name="VkFramebufferCreateInfo">
+ <member values="VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkFramebufferCreateFlags</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkRenderPass</type> <name>renderPass</name></member>
+ <member optional="true"><type>uint32_t</type> <name>attachmentCount</name></member>
+ <member len="attachmentCount">const <type>VkImageView</type>* <name>pAttachments</name></member>
+ <member><type>uint32_t</type> <name>width</name></member>
+ <member><type>uint32_t</type> <name>height</name></member>
+ <member><type>uint32_t</type> <name>layers</name></member>
+ </type>
+ <type category="struct" name="VkDrawIndirectCommand">
+ <member><type>uint32_t</type> <name>vertexCount</name></member>
+ <member><type>uint32_t</type> <name>instanceCount</name></member>
+ <member><type>uint32_t</type> <name>firstVertex</name></member>
+ <member><type>uint32_t</type> <name>firstInstance</name></member>
+ </type>
+ <type category="struct" name="VkDrawIndexedIndirectCommand">
+ <member><type>uint32_t</type> <name>indexCount</name></member>
+ <member><type>uint32_t</type> <name>instanceCount</name></member>
+ <member><type>uint32_t</type> <name>firstIndex</name></member>
+ <member><type>int32_t</type> <name>vertexOffset</name></member>
+ <member><type>uint32_t</type> <name>firstInstance</name></member>
+ </type>
+ <type category="struct" name="VkDispatchIndirectCommand">
+ <member><type>uint32_t</type> <name>x</name></member>
+ <member><type>uint32_t</type> <name>y</name></member>
+ <member><type>uint32_t</type> <name>z</name></member>
+ </type>
+ <type category="struct" name="VkSubmitInfo">
+ <member values="VK_STRUCTURE_TYPE_SUBMIT_INFO"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>uint32_t</type> <name>waitSemaphoreCount</name></member>
+ <member len="waitSemaphoreCount">const <type>VkSemaphore</type>* <name>pWaitSemaphores</name></member>
+ <member len="waitSemaphoreCount">const <type>VkPipelineStageFlags</type>* <name>pWaitDstStageMask</name></member>
+ <member optional="true"><type>uint32_t</type> <name>commandBufferCount</name></member>
+ <member len="commandBufferCount">const <type>VkCommandBuffer</type>* <name>pCommandBuffers</name></member>
+ <member optional="true"><type>uint32_t</type> <name>signalSemaphoreCount</name></member>
+ <member len="signalSemaphoreCount">const <type>VkSemaphore</type>* <name>pSignalSemaphores</name></member>
+ </type>
+ <!-- WSI extensions -->
+ <type category="struct" name="VkDisplayPropertiesKHR" returnedonly="true">
+ <member><type>VkDisplayKHR</type> <name>display</name></member> <!-- Handle of the display object -->
+ <member len="null-terminated">const <type>char</type>* <name>displayName</name></member> <!-- Name of the display -->
+ <member><type>VkExtent2D</type> <name>physicalDimensions</name></member> <!-- In millimeters? -->
+ <member><type>VkExtent2D</type> <name>physicalResolution</name></member> <!-- Max resolution for CRT? -->
+ <member optional="true"><type>VkSurfaceTransformFlagsKHR</type> <name>supportedTransforms</name></member> <!-- one or more bits from VkSurfaceTransformFlagsKHR -->
+ <member><type>VkBool32</type> <name>planeReorderPossible</name></member> <!-- VK_TRUE if the overlay plane's z-order can be changed on this display. -->
+ <member><type>VkBool32</type> <name>persistentContent</name></member> <!-- VK_TRUE if this is a "smart" display that supports self-refresh/internal buffering. -->
+ </type>
+ <type category="struct" name="VkDisplayPlanePropertiesKHR" returnedonly="true">
+ <member><type>VkDisplayKHR</type> <name>currentDisplay</name></member> <!-- Display the plane is currently associated with. Will be VK_NULL_HANDLE if the plane is not in use. -->
+ <member><type>uint32_t</type> <name>currentStackIndex</name></member> <!-- Current z-order of the plane. -->
+ </type>
+ <type category="struct" name="VkDisplayModeParametersKHR">
+ <member><type>VkExtent2D</type> <name>visibleRegion</name></member> <!-- Visible scanout region. -->
+ <member><type>uint32_t</type> <name>refreshRate</name></member> <!-- Number of times per second the display is updated. -->
+ </type>
+ <type category="struct" name="VkDisplayModePropertiesKHR" returnedonly="true">
+ <member><type>VkDisplayModeKHR</type> <name>displayMode</name></member> <!-- Handle of this display mode. -->
+ <member><type>VkDisplayModeParametersKHR</type> <name>parameters</name></member> <!-- The parameters this mode uses. -->
+ </type>
+ <type category="struct" name="VkDisplayModeCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkDisplayModeCreateFlagsKHR</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkDisplayModeParametersKHR</type> <name>parameters</name></member> <!-- The parameters this mode uses. -->
+ </type>
+ <type category="struct" name="VkDisplayPlaneCapabilitiesKHR" returnedonly="true">
+ <member optional="true"><type>VkDisplayPlaneAlphaFlagsKHR</type> <name>supportedAlpha</name></member> <!-- Types of alpha blending supported, if any. -->
+ <member><type>VkOffset2D</type> <name>minSrcPosition</name></member> <!-- Does the plane have any position and extent restrictions? -->
+ <member><type>VkOffset2D</type> <name>maxSrcPosition</name></member>
+ <member><type>VkExtent2D</type> <name>minSrcExtent</name></member>
+ <member><type>VkExtent2D</type> <name>maxSrcExtent</name></member>
+ <member><type>VkOffset2D</type> <name>minDstPosition</name></member>
+ <member><type>VkOffset2D</type> <name>maxDstPosition</name></member>
+ <member><type>VkExtent2D</type> <name>minDstExtent</name></member>
+ <member><type>VkExtent2D</type> <name>maxDstExtent</name></member>
+ </type>
+ <type category="struct" name="VkDisplaySurfaceCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkDisplaySurfaceCreateFlagsKHR</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkDisplayModeKHR</type> <name>displayMode</name></member> <!-- The mode to use when displaying this surface -->
+ <member><type>uint32_t</type> <name>planeIndex</name></member> <!-- The plane on which this surface appears. Must be between 0 and the value returned by vkGetPhysicalDeviceDisplayPlanePropertiesKHR() in pPropertyCount. -->
+ <member><type>uint32_t</type> <name>planeStackIndex</name></member> <!-- The z-order of the plane. -->
+ <member><type>VkSurfaceTransformFlagBitsKHR</type> <name>transform</name></member> <!-- Transform to apply to the images as part of the scanout operation -->
+ <member><type>float</type> <name>globalAlpha</name></member> <!-- Global alpha value. Must be between 0 and 1, inclusive. Ignored if alphaMode is not VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR -->
+ <member><type>VkDisplayPlaneAlphaFlagBitsKHR</type> <name>alphaMode</name></member> <!-- What type of alpha blending to use. Must be a bit from vkGetDisplayPlanePropertiesKHR::supportedAlpha. -->
+ <member><type>VkExtent2D</type> <name>imageExtent</name></member> <!-- size of the images to use with this surface -->
+ </type>
+ <type category="struct" name="VkDisplayPresentInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkRect2D</type> <name>srcRect</name></member> <!-- Rectangle within the presentable image to read pixel data from when presenting to the display. -->
+ <member><type>VkRect2D</type> <name>dstRect</name></member> <!-- Rectangle within the current display mode's visible region to display srcRectangle in. -->
+ <member><type>VkBool32</type> <name>persistent</name></member> <!-- For smart displays, use buffered mode. If the display properties member "persistentMode" is VK_FALSE, this member must always be VK_FALSE. -->
+ </type>
+ <type category="struct" name="VkSurfaceCapabilitiesKHR" returnedonly="true">
+ <member><type>uint32_t</type> <name>minImageCount</name></member> <!-- Supported minimum number of images for the surface -->
+ <member><type>uint32_t</type> <name>maxImageCount</name></member> <!-- Supported maximum number of images for the surface, 0 for unlimited -->
+ <member><type>VkExtent2D</type> <name>currentExtent</name></member> <!-- Current image width and height for the surface, (0, 0) if undefined -->
+ <member><type>VkExtent2D</type> <name>minImageExtent</name></member> <!-- Supported minimum image width and height for the surface -->
+ <member><type>VkExtent2D</type> <name>maxImageExtent</name></member> <!-- Supported maximum image width and height for the surface -->
+ <member><type>uint32_t</type> <name>maxImageArrayLayers</name></member> <!-- Supported maximum number of image layers for the surface -->
+ <member optional="true"><type>VkSurfaceTransformFlagsKHR</type> <name>supportedTransforms</name></member> <!-- 1 or more bits representing the transforms supported -->
+ <member><type>VkSurfaceTransformFlagBitsKHR</type> <name>currentTransform</name></member> <!-- The surface's current transform relative to the device's natural orientation -->
+ <member optional="true"><type>VkCompositeAlphaFlagsKHR</type> <name>supportedCompositeAlpha</name></member> <!-- 1 or more bits representing the alpha compositing modes supported -->
+ <member optional="true"><type>VkImageUsageFlags</type> <name>supportedUsageFlags</name></member> <!-- Supported image usage flags for the surface -->
+ </type>
+ <type category="struct" name="VkAndroidSurfaceCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkAndroidSurfaceCreateFlagsKHR</type> <name>flags</name></member> <!-- Reserved -->
+ <member noautovalidity="true"><type>ANativeWindow</type>* <name>window</name></member>
+ </type>
+ <type category="struct" name="VkMirSurfaceCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkMirSurfaceCreateFlagsKHR</type> <name>flags</name></member> <!-- Reserved -->
+ <member noautovalidity="true"><type>MirConnection</type>* <name>connection</name></member>
+ <member noautovalidity="true"><type>MirSurface</type>* <name>mirSurface</name></member>
+ </type>
+ <type category="struct" name="VkViSurfaceCreateInfoNN">
+ <member values="VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkViSurfaceCreateFlagsNN</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>void</type>* <name>window</name></member>
+ </type>
+ <type category="struct" name="VkWaylandSurfaceCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkWaylandSurfaceCreateFlagsKHR</type> <name>flags</name></member> <!-- Reserved -->
+ <member noautovalidity="true">struct <type>wl_display</type>* <name>display</name></member>
+ <member noautovalidity="true">struct <type>wl_surface</type>* <name>surface</name></member>
+ </type>
+ <type category="struct" name="VkWin32SurfaceCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkWin32SurfaceCreateFlagsKHR</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>HINSTANCE</type> <name>hinstance</name></member>
+ <member><type>HWND</type> <name>hwnd</name></member>
+ </type>
+ <type category="struct" name="VkXlibSurfaceCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkXlibSurfaceCreateFlagsKHR</type> <name>flags</name></member> <!-- Reserved -->
+ <member noautovalidity="true"><type>Display</type>* <name>dpy</name></member>
+ <member><type>Window</type> <name>window</name></member>
+ </type>
+ <type category="struct" name="VkXcbSurfaceCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkXcbSurfaceCreateFlagsKHR</type> <name>flags</name></member> <!-- Reserved -->
+ <member noautovalidity="true"><type>xcb_connection_t</type>* <name>connection</name></member>
+ <member><type>xcb_window_t</type> <name>window</name></member>
+ </type>
+ <type category="struct" name="VkSurfaceFormatKHR" returnedonly="true">
+ <member><type>VkFormat</type> <name>format</name></member> <!-- Supported pair of rendering format -->
+ <member><type>VkColorSpaceKHR</type> <name>colorSpace</name></member> <!-- and color space for the surface -->
+ </type>
+ <type category="struct" name="VkSwapchainCreateInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkSwapchainCreateFlagsKHR</type> <name>flags</name></member> <!-- Reserved -->
+ <member><type>VkSurfaceKHR</type> <name>surface</name></member> <!-- The swapchain's target surface -->
+ <member><type>uint32_t</type> <name>minImageCount</name></member> <!-- Minimum number of presentation images the application needs -->
+ <member><type>VkFormat</type> <name>imageFormat</name></member> <!-- Format of the presentation images -->
+ <member><type>VkColorSpaceKHR</type> <name>imageColorSpace</name></member> <!-- Colorspace of the presentation images -->
+ <member><type>VkExtent2D</type> <name>imageExtent</name></member> <!-- Dimensions of the presentation images -->
+ <member><type>uint32_t</type> <name>imageArrayLayers</name></member> <!-- Determines the number of views for multiview/stereo presentation -->
+ <member><type>VkImageUsageFlags</type> <name>imageUsage</name></member> <!-- Bits indicating how the presentation images will be used -->
+ <member><type>VkSharingMode</type> <name>imageSharingMode</name></member> <!-- Sharing mode used for the presentation images -->
+ <member optional="true"><type>uint32_t</type> <name>queueFamilyIndexCount</name></member> <!-- Number of queue families having access to the images in case of concurrent sharing mode -->
+ <member noautovalidity="true" len="queueFamilyIndexCount">const <type>uint32_t</type>* <name>pQueueFamilyIndices</name></member> <!-- Array of queue family indices having access to the images in case of concurrent sharing mode -->
+ <member><type>VkSurfaceTransformFlagBitsKHR</type> <name>preTransform</name></member> <!-- The transform, relative to the device's natural orientation, applied to the image content prior to presentation -->
+ <member><type>VkCompositeAlphaFlagBitsKHR</type> <name>compositeAlpha</name></member> <!-- The alpha blending mode used when compositing this surface with other surfaces in the window system -->
+ <member><type>VkPresentModeKHR</type> <name>presentMode</name></member> <!-- Which presentation mode to use for presents on this swap chain -->
+ <member><type>VkBool32</type> <name>clipped</name></member> <!-- Specifies whether presentable images may be affected by window clip regions -->
+ <member optional="true"><type>VkSwapchainKHR</type> <name>oldSwapchain</name></member> <!-- Existing swap chain to replace, if any -->
+ </type>
+ <type category="struct" name="VkPresentInfoKHR">
+ <member values="VK_STRUCTURE_TYPE_PRESENT_INFO_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member validextensionstructs="VkDisplayPresentInfoKHR">const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>uint32_t</type> <name>waitSemaphoreCount</name></member> <!-- Number of semaphores to wait for before presenting -->
+ <member optional="true" len="waitSemaphoreCount">const <type>VkSemaphore</type>* <name>pWaitSemaphores</name></member> <!-- Semaphores to wait for before presenting -->
+ <member><type>uint32_t</type> <name>swapchainCount</name></member> <!-- Number of swap chains to present in this call -->
+ <member len="swapchainCount">const <type>VkSwapchainKHR</type>* <name>pSwapchains</name></member> <!-- Swapchains to present an image from -->
+ <member len="swapchainCount">const <type>uint32_t</type>* <name>pImageIndices</name></member> <!-- Indices of which swapchain images to present -->
+ <member optional="true" len="swapchainCount"><type>VkResult</type>* <name>pResults</name></member> <!-- Optional (i.e. if non-NULL) VkResult for each swapchain -->
+ </type>
+ <type category="struct" name="VkDebugReportCallbackCreateInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkDebugReportFlagsEXT</type> <name>flags</name></member> <!-- Indicates which events call this callback-->
+ <member><type>PFN_vkDebugReportCallbackEXT</type> <name>pfnCallback</name></member> <!-- Function pointer of a callback function-->
+ <member optional="true"><type>void</type>* <name>pUserData</name></member> <!-- User data provided to callback function -->
+ </type>
+ <type category="struct" name="VkValidationFlagsEXT">
+ <member><type>VkStructureType</type> <name>sType</name></member> <!-- Must be VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT -->
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>uint32_t</type> <name>disabledValidationCheckCount</name></member> <!-- Number of validation checks to disable -->
+ <member len="disabledValidationCheckCount"><type>VkValidationCheckEXT</type>* <name>pDisabledValidationChecks</name></member> <!-- Validation checks to disable -->
+ </type>
+ <type category="struct" name="VkPipelineRasterizationStateRasterizationOrderAMD">
+ <member values="VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkRasterizationOrderAMD</type> <name>rasterizationOrder</name></member> <!-- Rasterization order to use for the pipeline -->
+ </type>
+ <type category="struct" name="VkDebugMarkerObjectNameInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkDebugReportObjectTypeEXT</type> <name>objectType</name></member> <!-- The type of the object -->
+ <member><type>uint64_t</type> <name>object</name></member> <!-- The handle of the object, cast to uint64_t -->
+ <member len="null-terminated">const <type>char</type>* <name>pObjectName</name></member> <!-- Name to apply to the object -->
+ </type>
+ <type category="struct" name="VkDebugMarkerObjectTagInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkDebugReportObjectTypeEXT</type> <name>objectType</name></member> <!-- The type of the object -->
+ <member><type>uint64_t</type> <name>object</name></member> <!-- The handle of the object, cast to uint64_t -->
+ <member><type>uint64_t</type> <name>tagName</name></member> <!-- The name of the tag to set on the object -->
+ <member><type>size_t</type> <name>tagSize</name></member> <!-- The length in bytes of the tag data -->
+ <member len="tagSize">const <type>void</type>* <name>pTag</name></member> <!-- Tag data to attach to the object -->
+ </type>
+ <type category="struct" name="VkDebugMarkerMarkerInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member len="null-terminated">const <type>char</type>* <name>pMarkerName</name></member> <!-- Name of the debug marker -->
+ <member optional="true"><type>float</type> <name>color</name>[4]</member> <!-- Optional color for debug marker -->
+ </type>
+ <type category="struct" name="VkDedicatedAllocationImageCreateInfoNV">
+ <member values="VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkBool32</type> <name>dedicatedAllocation</name></member> <!-- Whether this image uses a dedicated allocation -->
+ </type>
+ <type category="struct" name="VkDedicatedAllocationBufferCreateInfoNV">
+ <member values="VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkBool32</type> <name>dedicatedAllocation</name></member> <!-- Whether this buffer uses a dedicated allocation -->
+ </type>
+ <type category="struct" name="VkDedicatedAllocationMemoryAllocateInfoNV">
+ <member values="VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member optional="true"><type>VkImage</type> <name>image</name></member> <!-- Image that this allocation will be bound to -->
+ <member optional="true"><type>VkBuffer</type> <name>buffer</name></member> <!-- Buffer that this allocation will be bound to -->
+ </type>
+ <type category="struct" name="VkExternalImageFormatPropertiesNV" returnedonly="true">
+ <member><type>VkImageFormatProperties</type> <name>imageFormatProperties</name></member>
+ <member optional="true"><type>VkExternalMemoryFeatureFlagsNV</type> <name>externalMemoryFeatures</name></member>
+ <member optional="true"><type>VkExternalMemoryHandleTypeFlagsNV</type> <name>exportFromImportedHandleTypes</name></member>
+ <member optional="true"><type>VkExternalMemoryHandleTypeFlagsNV</type> <name>compatibleHandleTypes</name></member>
+ </type>
+ <type category="struct" name="VkExternalMemoryImageCreateInfoNV">
+ <member values="VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkExternalMemoryHandleTypeFlagsNV</type> <name>handleTypes</name></member>
+ </type>
+ <type category="struct" name="VkExportMemoryAllocateInfoNV">
+ <member values="VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkExternalMemoryHandleTypeFlagsNV</type> <name>handleTypes</name></member>
+ </type>
+ <type category="struct" name="VkImportMemoryWin32HandleInfoNV">
+ <member values="VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkExternalMemoryHandleTypeFlagsNV</type> <name>handleType</name></member>
+ <member optional="true"><type>HANDLE</type> <name>handle</name></member>
+ </type>
+ <type category="struct" name="VkExportMemoryWin32HandleInfoNV">
+ <member values="VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member optional="true">const <type>SECURITY_ATTRIBUTES</type>* <name>pAttributes</name></member>
+ <member optional="true"><type>DWORD</type> <name>dwAccess</name></member>
+ </type>
+ <type category="struct" name="VkWin32KeyedMutexAcquireReleaseInfoNV">
+ <member values="VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>uint32_t</type> <name>acquireCount</name></member>
+ <member len="acquireCount">const <type>VkDeviceMemory</type>* <name>pAcquireSyncs</name></member>
+ <member len="acquireCount">const <type>uint64_t</type>* <name>pAcquireKeys</name></member>
+ <member len="acquireCount">const <type>uint32_t</type>* <name>pAcquireTimeoutMilliseconds</name></member>
+ <member optional="true"><type>uint32_t</type> <name>releaseCount</name></member>
+ <member len="releaseCount">const <type>VkDeviceMemory</type>* <name>pReleaseSyncs</name></member>
+ <member len="releaseCount">const <type>uint64_t</type>* <name>pReleaseKeys</name></member>
+ </type>
+
+ <type category="struct" name="VkDeviceGeneratedCommandsFeaturesNVX">
+ <member values="VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkBool32</type> <name>computeBindingPointSupport</name></member>
+ </type>
+ <type category="struct" name="VkDeviceGeneratedCommandsLimitsNVX">
+ <member values="VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>maxIndirectCommandsLayoutTokenCount</name></member>
+ <member><type>uint32_t</type> <name>maxObjectEntryCounts</name></member>
+ <member><type>uint32_t</type> <name>minSequenceCountBufferOffsetAlignment</name></member>
+ <member><type>uint32_t</type> <name>minSequenceIndexBufferOffsetAlignment</name></member>
+ <member><type>uint32_t</type> <name>minCommandsTokenBufferOffsetAlignment</name></member>
+ </type>
+ <type category="struct" name="VkIndirectCommandsTokenNVX">
+ <member><type>VkIndirectCommandsTokenTypeNVX</type> <name>tokenType</name></member>
+ <member><type>VkBuffer</type> <name>buffer</name></member> <!-- buffer containing tableEntries and additional data for indirectCommands -->
+ <member><type>VkDeviceSize</type> <name>offset</name></member> <!-- offset from the base address of the buffer -->
+ </type>
+ <type category="struct" name="VkIndirectCommandsLayoutTokenNVX">
+ <member><type>VkIndirectCommandsTokenTypeNVX</type> <name>tokenType</name></member>
+ <member><type>uint32_t</type> <name>bindingUnit</name></member> <!-- Binding unit for vertex attribute / descriptor set, offset for pushconstants -->
+ <member><type>uint32_t</type> <name>dynamicCount</name></member> <!-- Number of variable dynamic values for descriptor set / push constants -->
+ <member><type>uint32_t</type> <name>divisor</name></member> <!-- Rate the which the array is advanced per element (must be power of 2, minimum 1) -->
+ </type>
+ <type category="struct" name="VkIndirectCommandsLayoutCreateInfoNVX">
+ <member values="VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkPipelineBindPoint</type> <name>pipelineBindPoint</name></member>
+ <member><type>VkIndirectCommandsLayoutUsageFlagsNVX</type> <name>flags</name></member>
+ <member><type>uint32_t</type> <name>tokenCount</name></member>
+ <member len="tokenCount">const <type>VkIndirectCommandsLayoutTokenNVX</type>* <name>pTokens</name></member>
+ </type>
+ <type category="struct" name="VkCmdProcessCommandsInfoNVX">
+ <member values="VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member externsync="true"><type>VkObjectTableNVX</type> <name>objectTable</name></member>
+ <member><type>VkIndirectCommandsLayoutNVX</type> <name>indirectCommandsLayout</name></member>
+ <member><type>uint32_t</type> <name>indirectCommandsTokenCount</name></member>
+ <member len="indirectCommandsTokenCount">const <type>VkIndirectCommandsTokenNVX</type>* <name>pIndirectCommandsTokens</name></member>
+ <member><type>uint32_t</type> <name>maxSequencesCount</name></member>
+ <member optional="true" externsync="true"><type>VkCommandBuffer</type> <name>targetCommandBuffer</name></member>
+ <member optional="true"><type>VkBuffer</type> <name>sequencesCountBuffer</name></member>
+ <member optional="true"><type>VkDeviceSize</type> <name>sequencesCountOffset</name></member>
+ <member optional="true"><type>VkBuffer</type> <name>sequencesIndexBuffer</name></member>
+ <member optional="true"><type>VkDeviceSize</type> <name>sequencesIndexOffset</name></member>
+ </type>
+ <type category="struct" name="VkCmdReserveSpaceForCommandsInfoNVX">
+ <member values="VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member externsync="true"><type>VkObjectTableNVX</type> <name>objectTable</name></member>
+ <member><type>VkIndirectCommandsLayoutNVX</type> <name>indirectCommandsLayout</name></member>
+ <member><type>uint32_t</type> <name>maxSequencesCount</name></member>
+ </type>
+ <type category="struct" name="VkObjectTableCreateInfoNVX">
+ <member values="VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>objectCount</name></member>
+ <member len="objectCount">const <type>VkObjectEntryTypeNVX</type>* <name>pObjectEntryTypes</name></member>
+ <member len="objectCount">const <type>uint32_t</type>* <name>pObjectEntryCounts</name></member>
+ <member len="objectCount">const <type>VkObjectEntryUsageFlagsNVX</type>* <name>pObjectEntryUsageFlags</name></member>
+
+ <member><type>uint32_t</type> <name>maxUniformBuffersPerDescriptor</name></member>
+ <member><type>uint32_t</type> <name>maxStorageBuffersPerDescriptor</name></member>
+ <member><type>uint32_t</type> <name>maxStorageImagesPerDescriptor</name></member>
+ <member><type>uint32_t</type> <name>maxSampledImagesPerDescriptor</name></member>
+ <member><type>uint32_t</type> <name>maxPipelineLayouts</name></member>
+ </type>
+ <type category="struct" name="VkObjectTableEntryNVX">
+ <member><type>VkObjectEntryTypeNVX</type> <name>type</name></member>
+ <member><type>VkObjectEntryUsageFlagsNVX</type> <name>flags</name></member>
+ </type>
+ <type category="struct" name="VkObjectTablePipelineEntryNVX">
+ <member><type>VkObjectEntryTypeNVX</type> <name>type</name></member>
+ <member><type>VkObjectEntryUsageFlagsNVX</type> <name>flags</name></member>
+ <member><type>VkPipeline</type> <name>pipeline</name></member>
+ </type>
+ <type category="struct" name="VkObjectTableDescriptorSetEntryNVX">
+ <member><type>VkObjectEntryTypeNVX</type> <name>type</name></member>
+ <member><type>VkObjectEntryUsageFlagsNVX</type> <name>flags</name></member>
+ <member><type>VkPipelineLayout</type> <name>pipelineLayout</name></member>
+ <member><type>VkDescriptorSet</type> <name>descriptorSet</name></member>
+ </type>
+ <type category="struct" name="VkObjectTableVertexBufferEntryNVX">
+ <member><type>VkObjectEntryTypeNVX</type> <name>type</name></member>
+ <member><type>VkObjectEntryUsageFlagsNVX</type> <name>flags</name></member>
+ <member><type>VkBuffer</type> <name>buffer</name></member>
+ </type>
+ <type category="struct" name="VkObjectTableIndexBufferEntryNVX">
+ <member><type>VkObjectEntryTypeNVX</type> <name>type</name></member>
+ <member><type>VkObjectEntryUsageFlagsNVX</type> <name>flags</name></member>
+ <member><type>VkBuffer</type> <name>buffer</name></member>
+ <member><type>VkIndexType</type> <name>indexType</name></member>
+ </type>
+ <type category="struct" name="VkObjectTablePushConstantEntryNVX">
+ <member><type>VkObjectEntryTypeNVX</type> <name>type</name></member>
+ <member><type>VkObjectEntryUsageFlagsNVX</type> <name>flags</name></member>
+ <member><type>VkPipelineLayout</type> <name>pipelineLayout</name></member>
+ <member><type>VkShaderStageFlags</type> <name>stageFlags</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceFeatures2KHR">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member><type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkPhysicalDeviceFeatures</type> <name>features</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceProperties2KHR" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member><type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkPhysicalDeviceProperties</type> <name>properties</name></member>
+ </type>
+ <type category="struct" name="VkFormatProperties2KHR" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member><type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkFormatProperties</type> <name>formatProperties</name></member>
+ </type>
+ <type category="struct" name="VkImageFormatProperties2KHR" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member><type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkImageFormatProperties</type> <name>imageFormatProperties</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceImageFormatInfo2KHR">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkFormat</type> <name>format</name></member>
+ <member><type>VkImageType</type> <name>type</name></member>
+ <member><type>VkImageTiling</type> <name>tiling</name></member>
+ <member><type>VkImageUsageFlags</type> <name>usage</name></member>
+ <member optional="true"><type>VkImageCreateFlags</type> <name>flags</name></member>
+ </type>
+ <type category="struct" name="VkQueueFamilyProperties2KHR" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member><type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkQueueFamilyProperties</type> <name>queueFamilyProperties</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceMemoryProperties2KHR" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member><type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkPhysicalDeviceMemoryProperties</type> <name>memoryProperties</name></member>
+ </type>
+ <type category="struct" name="VkSparseImageFormatProperties2KHR" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member><type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkSparseImageFormatProperties</type> <name>properties</name></member>
+ </type>
+ <type category="struct" name="VkPhysicalDeviceSparseImageFormatInfo2KHR">
+ <member values="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member> <!-- Pointer to next structure -->
+ <member><type>VkFormat</type> <name>format</name></member>
+ <member><type>VkImageType</type> <name>type</name></member>
+ <member><type>VkSampleCountFlagBits</type> <name>samples</name></member>
+ <member><type>VkImageUsageFlags</type> <name>usage</name></member>
+ <member><type>VkImageTiling</type> <name>tiling</name></member>
+ </type>
+ <type category="struct" name="VkSurfaceCapabilities2EXT" returnedonly="true">
+ <member values="VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member><type>void</type>* <name>pNext</name></member>
+ <member><type>uint32_t</type> <name>minImageCount</name></member> <!-- Supported minimum number of images for the surface -->
+ <member><type>uint32_t</type> <name>maxImageCount</name></member> <!-- Supported maximum number of images for the surface, 0 for unlimited -->
+ <member><type>VkExtent2D</type> <name>currentExtent</name></member> <!-- Current image width and height for the surface, (0, 0) if undefined -->
+ <member><type>VkExtent2D</type> <name>minImageExtent</name></member> <!-- Supported minimum image width and height for the surface -->
+ <member><type>VkExtent2D</type> <name>maxImageExtent</name></member> <!-- Supported maximum image width and height for the surface -->
+ <member><type>uint32_t</type> <name>maxImageArrayLayers</name></member> <!-- Supported maximum number of image layers for the surface -->
+ <member optional="true"><type>VkSurfaceTransformFlagsKHR</type> <name>supportedTransforms</name></member> <!-- 1 or more bits representing the transforms supported -->
+ <member><type>VkSurfaceTransformFlagBitsKHR</type> <name>currentTransform</name></member> <!-- The surface's current transform relative to the device's natural orientation -->
+ <member optional="true"><type>VkCompositeAlphaFlagsKHR</type> <name>supportedCompositeAlpha</name></member> <!-- 1 or more bits representing the alpha compositing modes supported -->
+ <member optional="true"><type>VkImageUsageFlags</type> <name>supportedUsageFlags</name></member> <!-- Supported image usage flags for the surface -->
+ <member optional="true"><type>VkSurfaceCounterFlagsEXT</type> <name>supportedSurfaceCounters</name></member>
+ </type>
+ <type category="struct" name="VkDisplayPowerInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkDisplayPowerStateEXT</type> <name>powerState</name></member>
+ </type>
+ <type category="struct" name="VkDeviceEventInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkDeviceEventTypeEXT</type> <name>deviceEvent</name></member>
+ </type>
+ <type category="struct" name="VkDisplayEventInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member><type>VkDisplayEventTypeEXT</type> <name>displayEvent</name></member>
+ </type>
+ <type category="struct" name="VkSwapchainCounterCreateInfoEXT">
+ <member values="VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT"><type>VkStructureType</type> <name>sType</name></member>
+ <member>const <type>void</type>* <name>pNext</name></member>
+ <member optional="true"><type>VkSurfaceCounterFlagsEXT</type> <name>surfaceCounters</name></member>
+ </type>
+ </types>
+
+ <!-- SECTION: Vulkan enumerant (token) definitions. -->
+
+ <enums name="API Constants" comment="Misc. hardcoded constants - not an enumerated type">
+ <!-- This is part of the header boilerplate -->
+ <enum value="256" name="VK_MAX_PHYSICAL_DEVICE_NAME_SIZE"/>
+ <enum value="16" name="VK_UUID_SIZE"/>
+ <enum value="256" name="VK_MAX_EXTENSION_NAME_SIZE"/>
+ <enum value="256" name="VK_MAX_DESCRIPTION_SIZE"/>
+ <enum value="32" name="VK_MAX_MEMORY_TYPES"/>
+ <enum value="16" name="VK_MAX_MEMORY_HEAPS"/> <!-- The maximum number of unique memory heaps, each of which supporting 1 or more memory types. -->
+ <enum value="1000.0f" name="VK_LOD_CLAMP_NONE"/>
+ <enum value="(~0U)" name="VK_REMAINING_MIP_LEVELS"/>
+ <enum value="(~0U)" name="VK_REMAINING_ARRAY_LAYERS"/>
+ <enum value="(~0ULL)" name="VK_WHOLE_SIZE"/>
+ <enum value="(~0U)" name="VK_ATTACHMENT_UNUSED"/>
+ <enum value="1" name="VK_TRUE"/>
+ <enum value="0" name="VK_FALSE"/>
+ <enum value="(~0U)" name="VK_QUEUE_FAMILY_IGNORED"/>
+ <enum value="(~0U)" name="VK_SUBPASS_EXTERNAL"/>
+ </enums>
+
+ <!-- Unlike OpenGL, most tokens in Vulkan are actual typed enumerants in
+ their own numeric namespaces. The "name" attribute is the C enum
+ type name, and is pulled in from a <type> definition above
+ (slightly clunky, but retains the type / enum distinction). "type"
+ attributes of "enum" or "bitmask" indicate that these values should
+ be generated inside an appropriate definition. -->
+
+ <enums name="VkImageLayout" type="enum">
+ <enum value="0" name="VK_IMAGE_LAYOUT_UNDEFINED" comment="Implicit layout an image is when its contents are undefined due to various reasons (e.g. right after creation)"/>
+ <enum value="1" name="VK_IMAGE_LAYOUT_GENERAL" comment="General layout when image can be used for any kind of access"/>
+ <enum value="2" name="VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL" comment="Optimal layout when image is only used for color attachment read/write"/>
+ <enum value="3" name="VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL" comment="Optimal layout when image is only used for depth/stencil attachment read/write"/>
+ <enum value="4" name="VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL" comment="Optimal layout when image is used for read only depth/stencil attachment and shader access"/>
+ <enum value="5" name="VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL" comment="Optimal layout when image is used for read only shader access"/>
+ <enum value="6" name="VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL" comment="Optimal layout when image is used only as source of transfer operations"/>
+ <enum value="7" name="VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL" comment="Optimal layout when image is used only as destination of transfer operations"/>
+ <enum value="8" name="VK_IMAGE_LAYOUT_PREINITIALIZED" comment="Initial layout used when the data is populated by the CPU"/>
+ </enums>
+ <enums name="VkAttachmentLoadOp" type="enum">
+ <enum value="0" name="VK_ATTACHMENT_LOAD_OP_LOAD"/>
+ <enum value="1" name="VK_ATTACHMENT_LOAD_OP_CLEAR"/>
+ <enum value="2" name="VK_ATTACHMENT_LOAD_OP_DONT_CARE"/>
+ </enums>
+ <enums name="VkAttachmentStoreOp" type="enum">
+ <enum value="0" name="VK_ATTACHMENT_STORE_OP_STORE"/>
+ <enum value="1" name="VK_ATTACHMENT_STORE_OP_DONT_CARE"/>
+ </enums>
+ <enums name="VkImageType" type="enum">
+ <enum value="0" name="VK_IMAGE_TYPE_1D"/>
+ <enum value="1" name="VK_IMAGE_TYPE_2D"/>
+ <enum value="2" name="VK_IMAGE_TYPE_3D"/>
+ </enums>
+ <enums name="VkImageTiling" type="enum">
+ <enum value="0" name="VK_IMAGE_TILING_OPTIMAL"/>
+ <enum value="1" name="VK_IMAGE_TILING_LINEAR"/>
+ </enums>
+ <enums name="VkImageViewType" type="enum">
+ <enum value="0" name="VK_IMAGE_VIEW_TYPE_1D"/>
+ <enum value="1" name="VK_IMAGE_VIEW_TYPE_2D"/>
+ <enum value="2" name="VK_IMAGE_VIEW_TYPE_3D"/>
+ <enum value="3" name="VK_IMAGE_VIEW_TYPE_CUBE"/>
+ <enum value="4" name="VK_IMAGE_VIEW_TYPE_1D_ARRAY"/>
+ <enum value="5" name="VK_IMAGE_VIEW_TYPE_2D_ARRAY"/>
+ <enum value="6" name="VK_IMAGE_VIEW_TYPE_CUBE_ARRAY"/>
+ </enums>
+ <enums name="VkCommandBufferLevel" type="enum">
+ <enum value="0" name="VK_COMMAND_BUFFER_LEVEL_PRIMARY"/>
+ <enum value="1" name="VK_COMMAND_BUFFER_LEVEL_SECONDARY"/>
+ </enums>
+ <enums name="VkComponentSwizzle" type="enum">
+ <enum value="0" name="VK_COMPONENT_SWIZZLE_IDENTITY"/>
+ <enum value="1" name="VK_COMPONENT_SWIZZLE_ZERO"/>
+ <enum value="2" name="VK_COMPONENT_SWIZZLE_ONE"/>
+ <enum value="3" name="VK_COMPONENT_SWIZZLE_R"/>
+ <enum value="4" name="VK_COMPONENT_SWIZZLE_G"/>
+ <enum value="5" name="VK_COMPONENT_SWIZZLE_B"/>
+ <enum value="6" name="VK_COMPONENT_SWIZZLE_A"/>
+ </enums>
+ <enums name="VkDescriptorType" type="enum">
+ <enum value="0" name="VK_DESCRIPTOR_TYPE_SAMPLER"/>
+ <enum value="1" name="VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER"/>
+ <enum value="2" name="VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE"/>
+ <enum value="3" name="VK_DESCRIPTOR_TYPE_STORAGE_IMAGE"/>
+ <enum value="4" name="VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER"/>
+ <enum value="5" name="VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER"/>
+ <enum value="6" name="VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER"/>
+ <enum value="7" name="VK_DESCRIPTOR_TYPE_STORAGE_BUFFER"/>
+ <enum value="8" name="VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC"/>
+ <enum value="9" name="VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC"/>
+ <enum value="10" name="VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT"/>
+ </enums>
+ <enums name="VkQueryType" type="enum">
+ <enum value="0" name="VK_QUERY_TYPE_OCCLUSION"/>
+ <enum value="1" name="VK_QUERY_TYPE_PIPELINE_STATISTICS" comment="Optional"/>
+ <enum value="2" name="VK_QUERY_TYPE_TIMESTAMP"/>
+ </enums>
+ <enums name="VkBorderColor" type="enum">
+ <enum value="0" name="VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK"/>
+ <enum value="1" name="VK_BORDER_COLOR_INT_TRANSPARENT_BLACK"/>
+ <enum value="2" name="VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK"/>
+ <enum value="3" name="VK_BORDER_COLOR_INT_OPAQUE_BLACK"/>
+ <enum value="4" name="VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE"/>
+ <enum value="5" name="VK_BORDER_COLOR_INT_OPAQUE_WHITE"/>
+ </enums>
+ <enums name="VkPipelineBindPoint" type="enum">
+ <enum value="0" name="VK_PIPELINE_BIND_POINT_GRAPHICS"/>
+ <enum value="1" name="VK_PIPELINE_BIND_POINT_COMPUTE"/>
+ </enums>
+ <enums name="VkPipelineCacheHeaderVersion" type="enum">
+ <enum value="1" name="VK_PIPELINE_CACHE_HEADER_VERSION_ONE"/>
+ </enums>
+ <enums name="VkPrimitiveTopology" type="enum">
+ <enum value="0" name="VK_PRIMITIVE_TOPOLOGY_POINT_LIST"/>
+ <enum value="1" name="VK_PRIMITIVE_TOPOLOGY_LINE_LIST"/>
+ <enum value="2" name="VK_PRIMITIVE_TOPOLOGY_LINE_STRIP"/>
+ <enum value="3" name="VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST"/>
+ <enum value="4" name="VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP"/>
+ <enum value="5" name="VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN"/>
+ <enum value="6" name="VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY"/>
+ <enum value="7" name="VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY"/>
+ <enum value="8" name="VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY"/>
+ <enum value="9" name="VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY"/>
+ <enum value="10" name="VK_PRIMITIVE_TOPOLOGY_PATCH_LIST"/>
+ </enums>
+ <enums name="VkSharingMode" type="enum">
+ <enum value="0" name="VK_SHARING_MODE_EXCLUSIVE"/>
+ <enum value="1" name="VK_SHARING_MODE_CONCURRENT"/>
+ </enums>
+ <enums name="VkIndexType" type="enum">
+ <enum value="0" name="VK_INDEX_TYPE_UINT16"/>
+ <enum value="1" name="VK_INDEX_TYPE_UINT32"/>
+ </enums>
+ <enums name="VkFilter" type="enum">
+ <enum value="0" name="VK_FILTER_NEAREST"/>
+ <enum value="1" name="VK_FILTER_LINEAR"/>
+ </enums>
+ <enums name="VkSamplerMipmapMode" type="enum">
+ <enum value="0" name="VK_SAMPLER_MIPMAP_MODE_NEAREST" comment="Choose nearest mip level"/>
+ <enum value="1" name="VK_SAMPLER_MIPMAP_MODE_LINEAR" comment="Linear filter between mip levels"/>
+ </enums>
+ <enums name="VkSamplerAddressMode" type="enum">
+ <enum value="0" name="VK_SAMPLER_ADDRESS_MODE_REPEAT"/>
+ <enum value="1" name="VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT"/>
+ <enum value="2" name="VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE"/>
+ <enum value="3" name="VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER"/>
+ <!-- <enum value="4" name="VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE" comment="Reserved for VK_KHR_sampler_mirror_clamp_to_edge, do not alias!"/> -->
+ </enums>
+ <enums name="VkCompareOp" type="enum">
+ <enum value="0" name="VK_COMPARE_OP_NEVER"/>
+ <enum value="1" name="VK_COMPARE_OP_LESS"/>
+ <enum value="2" name="VK_COMPARE_OP_EQUAL"/>
+ <enum value="3" name="VK_COMPARE_OP_LESS_OR_EQUAL"/>
+ <enum value="4" name="VK_COMPARE_OP_GREATER"/>
+ <enum value="5" name="VK_COMPARE_OP_NOT_EQUAL"/>
+ <enum value="6" name="VK_COMPARE_OP_GREATER_OR_EQUAL"/>
+ <enum value="7" name="VK_COMPARE_OP_ALWAYS"/>
+ </enums>
+ <enums name="VkPolygonMode" type="enum">
+ <enum value="0" name="VK_POLYGON_MODE_FILL"/>
+ <enum value="1" name="VK_POLYGON_MODE_LINE"/>
+ <enum value="2" name="VK_POLYGON_MODE_POINT"/>
+ </enums>
+ <enums name="VkCullModeFlagBits" type="bitmask">
+ <enum value="0" name="VK_CULL_MODE_NONE"/>
+ <enum bitpos="0" name="VK_CULL_MODE_FRONT_BIT"/>
+ <enum bitpos="1" name="VK_CULL_MODE_BACK_BIT"/>
+ <enum value="0x00000003" name="VK_CULL_MODE_FRONT_AND_BACK"/>
+ </enums>
+ <enums name="VkFrontFace" type="enum">
+ <enum value="0" name="VK_FRONT_FACE_COUNTER_CLOCKWISE"/>
+ <enum value="1" name="VK_FRONT_FACE_CLOCKWISE"/>
+ </enums>
+ <enums name="VkBlendFactor" type="enum">
+ <enum value="0" name="VK_BLEND_FACTOR_ZERO"/>
+ <enum value="1" name="VK_BLEND_FACTOR_ONE"/>
+ <enum value="2" name="VK_BLEND_FACTOR_SRC_COLOR"/>
+ <enum value="3" name="VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR"/>
+ <enum value="4" name="VK_BLEND_FACTOR_DST_COLOR"/>
+ <enum value="5" name="VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR"/>
+ <enum value="6" name="VK_BLEND_FACTOR_SRC_ALPHA"/>
+ <enum value="7" name="VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA"/>
+ <enum value="8" name="VK_BLEND_FACTOR_DST_ALPHA"/>
+ <enum value="9" name="VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA"/>
+ <enum value="10" name="VK_BLEND_FACTOR_CONSTANT_COLOR"/>
+ <enum value="11" name="VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR"/>
+ <enum value="12" name="VK_BLEND_FACTOR_CONSTANT_ALPHA"/>
+ <enum value="13" name="VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA"/>
+ <enum value="14" name="VK_BLEND_FACTOR_SRC_ALPHA_SATURATE"/>
+ <enum value="15" name="VK_BLEND_FACTOR_SRC1_COLOR"/>
+ <enum value="16" name="VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR"/>
+ <enum value="17" name="VK_BLEND_FACTOR_SRC1_ALPHA"/>
+ <enum value="18" name="VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA"/>
+ </enums>
+ <enums name="VkBlendOp" type="enum">
+ <enum value="0" name="VK_BLEND_OP_ADD"/>
+ <enum value="1" name="VK_BLEND_OP_SUBTRACT"/>
+ <enum value="2" name="VK_BLEND_OP_REVERSE_SUBTRACT"/>
+ <enum value="3" name="VK_BLEND_OP_MIN"/>
+ <enum value="4" name="VK_BLEND_OP_MAX"/>
+ </enums>
+ <enums name="VkStencilOp" type="enum">
+ <enum value="0" name="VK_STENCIL_OP_KEEP"/>
+ <enum value="1" name="VK_STENCIL_OP_ZERO"/>
+ <enum value="2" name="VK_STENCIL_OP_REPLACE"/>
+ <enum value="3" name="VK_STENCIL_OP_INCREMENT_AND_CLAMP"/>
+ <enum value="4" name="VK_STENCIL_OP_DECREMENT_AND_CLAMP"/>
+ <enum value="5" name="VK_STENCIL_OP_INVERT"/>
+ <enum value="6" name="VK_STENCIL_OP_INCREMENT_AND_WRAP"/>
+ <enum value="7" name="VK_STENCIL_OP_DECREMENT_AND_WRAP"/>
+ </enums>
+ <enums name="VkLogicOp" type="enum">
+ <enum value="0" name="VK_LOGIC_OP_CLEAR"/>
+ <enum value="1" name="VK_LOGIC_OP_AND"/>
+ <enum value="2" name="VK_LOGIC_OP_AND_REVERSE"/>
+ <enum value="3" name="VK_LOGIC_OP_COPY"/>
+ <enum value="4" name="VK_LOGIC_OP_AND_INVERTED"/>
+ <enum value="5" name="VK_LOGIC_OP_NO_OP"/>
+ <enum value="6" name="VK_LOGIC_OP_XOR"/>
+ <enum value="7" name="VK_LOGIC_OP_OR"/>
+ <enum value="8" name="VK_LOGIC_OP_NOR"/>
+ <enum value="9" name="VK_LOGIC_OP_EQUIVALENT"/>
+ <enum value="10" name="VK_LOGIC_OP_INVERT"/>
+ <enum value="11" name="VK_LOGIC_OP_OR_REVERSE"/>
+ <enum value="12" name="VK_LOGIC_OP_COPY_INVERTED"/>
+ <enum value="13" name="VK_LOGIC_OP_OR_INVERTED"/>
+ <enum value="14" name="VK_LOGIC_OP_NAND"/>
+ <enum value="15" name="VK_LOGIC_OP_SET"/>
+ </enums>
+ <enums name="VkInternalAllocationType" type="enum">
+ <enum value="0" name="VK_INTERNAL_ALLOCATION_TYPE_EXECUTABLE"/>
+ </enums>
+ <enums name="VkSystemAllocationScope" type="enum">
+ <enum value="0" name="VK_SYSTEM_ALLOCATION_SCOPE_COMMAND"/>
+ <enum value="1" name="VK_SYSTEM_ALLOCATION_SCOPE_OBJECT"/>
+ <enum value="2" name="VK_SYSTEM_ALLOCATION_SCOPE_CACHE"/>
+ <enum value="3" name="VK_SYSTEM_ALLOCATION_SCOPE_DEVICE"/>
+ <enum value="4" name="VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE"/>
+ </enums>
+ <enums name="VkPhysicalDeviceType" type="enum">
+ <enum value="0" name="VK_PHYSICAL_DEVICE_TYPE_OTHER"/>
+ <enum value="1" name="VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU"/>
+ <enum value="2" name="VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU"/>
+ <enum value="3" name="VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU"/>
+ <enum value="4" name="VK_PHYSICAL_DEVICE_TYPE_CPU"/>
+ </enums>
+ <enums name="VkVertexInputRate" type="enum">
+ <enum value="0" name="VK_VERTEX_INPUT_RATE_VERTEX"/>
+ <enum value="1" name="VK_VERTEX_INPUT_RATE_INSTANCE"/>
+ </enums>
+ <enums name="VkFormat" type="enum" comment="Vulkan format definitions">
+ <enum value="0" name="VK_FORMAT_UNDEFINED"/>
+ <enum value="1" name="VK_FORMAT_R4G4_UNORM_PACK8"/>
+ <enum value="2" name="VK_FORMAT_R4G4B4A4_UNORM_PACK16"/>
+ <enum value="3" name="VK_FORMAT_B4G4R4A4_UNORM_PACK16"/>
+ <enum value="4" name="VK_FORMAT_R5G6B5_UNORM_PACK16"/>
+ <enum value="5" name="VK_FORMAT_B5G6R5_UNORM_PACK16"/>
+ <enum value="6" name="VK_FORMAT_R5G5B5A1_UNORM_PACK16"/>
+ <enum value="7" name="VK_FORMAT_B5G5R5A1_UNORM_PACK16"/>
+ <enum value="8" name="VK_FORMAT_A1R5G5B5_UNORM_PACK16"/>
+ <enum value="9" name="VK_FORMAT_R8_UNORM"/>
+ <enum value="10" name="VK_FORMAT_R8_SNORM"/>
+ <enum value="11" name="VK_FORMAT_R8_USCALED"/>
+ <enum value="12" name="VK_FORMAT_R8_SSCALED"/>
+ <enum value="13" name="VK_FORMAT_R8_UINT"/>
+ <enum value="14" name="VK_FORMAT_R8_SINT"/>
+ <enum value="15" name="VK_FORMAT_R8_SRGB"/>
+ <enum value="16" name="VK_FORMAT_R8G8_UNORM"/>
+ <enum value="17" name="VK_FORMAT_R8G8_SNORM"/>
+ <enum value="18" name="VK_FORMAT_R8G8_USCALED"/>
+ <enum value="19" name="VK_FORMAT_R8G8_SSCALED"/>
+ <enum value="20" name="VK_FORMAT_R8G8_UINT"/>
+ <enum value="21" name="VK_FORMAT_R8G8_SINT"/>
+ <enum value="22" name="VK_FORMAT_R8G8_SRGB"/>
+ <enum value="23" name="VK_FORMAT_R8G8B8_UNORM"/>
+ <enum value="24" name="VK_FORMAT_R8G8B8_SNORM"/>
+ <enum value="25" name="VK_FORMAT_R8G8B8_USCALED"/>
+ <enum value="26" name="VK_FORMAT_R8G8B8_SSCALED"/>
+ <enum value="27" name="VK_FORMAT_R8G8B8_UINT"/>
+ <enum value="28" name="VK_FORMAT_R8G8B8_SINT"/>
+ <enum value="29" name="VK_FORMAT_R8G8B8_SRGB"/>
+ <enum value="30" name="VK_FORMAT_B8G8R8_UNORM"/>
+ <enum value="31" name="VK_FORMAT_B8G8R8_SNORM"/>
+ <enum value="32" name="VK_FORMAT_B8G8R8_USCALED"/>
+ <enum value="33" name="VK_FORMAT_B8G8R8_SSCALED"/>
+ <enum value="34" name="VK_FORMAT_B8G8R8_UINT"/>
+ <enum value="35" name="VK_FORMAT_B8G8R8_SINT"/>
+ <enum value="36" name="VK_FORMAT_B8G8R8_SRGB"/>
+ <enum value="37" name="VK_FORMAT_R8G8B8A8_UNORM"/>
+ <enum value="38" name="VK_FORMAT_R8G8B8A8_SNORM"/>
+ <enum value="39" name="VK_FORMAT_R8G8B8A8_USCALED"/>
+ <enum value="40" name="VK_FORMAT_R8G8B8A8_SSCALED"/>
+ <enum value="41" name="VK_FORMAT_R8G8B8A8_UINT"/>
+ <enum value="42" name="VK_FORMAT_R8G8B8A8_SINT"/>
+ <enum value="43" name="VK_FORMAT_R8G8B8A8_SRGB"/>
+ <enum value="44" name="VK_FORMAT_B8G8R8A8_UNORM"/>
+ <enum value="45" name="VK_FORMAT_B8G8R8A8_SNORM"/>
+ <enum value="46" name="VK_FORMAT_B8G8R8A8_USCALED"/>
+ <enum value="47" name="VK_FORMAT_B8G8R8A8_SSCALED"/>
+ <enum value="48" name="VK_FORMAT_B8G8R8A8_UINT"/>
+ <enum value="49" name="VK_FORMAT_B8G8R8A8_SINT"/>
+ <enum value="50" name="VK_FORMAT_B8G8R8A8_SRGB"/>
+ <enum value="51" name="VK_FORMAT_A8B8G8R8_UNORM_PACK32"/>
+ <enum value="52" name="VK_FORMAT_A8B8G8R8_SNORM_PACK32"/>
+ <enum value="53" name="VK_FORMAT_A8B8G8R8_USCALED_PACK32"/>
+ <enum value="54" name="VK_FORMAT_A8B8G8R8_SSCALED_PACK32"/>
+ <enum value="55" name="VK_FORMAT_A8B8G8R8_UINT_PACK32"/>
+ <enum value="56" name="VK_FORMAT_A8B8G8R8_SINT_PACK32"/>
+ <enum value="57" name="VK_FORMAT_A8B8G8R8_SRGB_PACK32"/>
+ <enum value="58" name="VK_FORMAT_A2R10G10B10_UNORM_PACK32"/>
+ <enum value="59" name="VK_FORMAT_A2R10G10B10_SNORM_PACK32"/>
+ <enum value="60" name="VK_FORMAT_A2R10G10B10_USCALED_PACK32"/>
+ <enum value="61" name="VK_FORMAT_A2R10G10B10_SSCALED_PACK32"/>
+ <enum value="62" name="VK_FORMAT_A2R10G10B10_UINT_PACK32"/>
+ <enum value="63" name="VK_FORMAT_A2R10G10B10_SINT_PACK32"/>
+ <enum value="64" name="VK_FORMAT_A2B10G10R10_UNORM_PACK32"/>
+ <enum value="65" name="VK_FORMAT_A2B10G10R10_SNORM_PACK32"/>
+ <enum value="66" name="VK_FORMAT_A2B10G10R10_USCALED_PACK32"/>
+ <enum value="67" name="VK_FORMAT_A2B10G10R10_SSCALED_PACK32"/>
+ <enum value="68" name="VK_FORMAT_A2B10G10R10_UINT_PACK32"/>
+ <enum value="69" name="VK_FORMAT_A2B10G10R10_SINT_PACK32"/>
+ <enum value="70" name="VK_FORMAT_R16_UNORM"/>
+ <enum value="71" name="VK_FORMAT_R16_SNORM"/>
+ <enum value="72" name="VK_FORMAT_R16_USCALED"/>
+ <enum value="73" name="VK_FORMAT_R16_SSCALED"/>
+ <enum value="74" name="VK_FORMAT_R16_UINT"/>
+ <enum value="75" name="VK_FORMAT_R16_SINT"/>
+ <enum value="76" name="VK_FORMAT_R16_SFLOAT"/>
+ <enum value="77" name="VK_FORMAT_R16G16_UNORM"/>
+ <enum value="78" name="VK_FORMAT_R16G16_SNORM"/>
+ <enum value="79" name="VK_FORMAT_R16G16_USCALED"/>
+ <enum value="80" name="VK_FORMAT_R16G16_SSCALED"/>
+ <enum value="81" name="VK_FORMAT_R16G16_UINT"/>
+ <enum value="82" name="VK_FORMAT_R16G16_SINT"/>
+ <enum value="83" name="VK_FORMAT_R16G16_SFLOAT"/>
+ <enum value="84" name="VK_FORMAT_R16G16B16_UNORM"/>
+ <enum value="85" name="VK_FORMAT_R16G16B16_SNORM"/>
+ <enum value="86" name="VK_FORMAT_R16G16B16_USCALED"/>
+ <enum value="87" name="VK_FORMAT_R16G16B16_SSCALED"/>
+ <enum value="88" name="VK_FORMAT_R16G16B16_UINT"/>
+ <enum value="89" name="VK_FORMAT_R16G16B16_SINT"/>
+ <enum value="90" name="VK_FORMAT_R16G16B16_SFLOAT"/>
+ <enum value="91" name="VK_FORMAT_R16G16B16A16_UNORM"/>
+ <enum value="92" name="VK_FORMAT_R16G16B16A16_SNORM"/>
+ <enum value="93" name="VK_FORMAT_R16G16B16A16_USCALED"/>
+ <enum value="94" name="VK_FORMAT_R16G16B16A16_SSCALED"/>
+ <enum value="95" name="VK_FORMAT_R16G16B16A16_UINT"/>
+ <enum value="96" name="VK_FORMAT_R16G16B16A16_SINT"/>
+ <enum value="97" name="VK_FORMAT_R16G16B16A16_SFLOAT"/>
+ <enum value="98" name="VK_FORMAT_R32_UINT"/>
+ <enum value="99" name="VK_FORMAT_R32_SINT"/>
+ <enum value="100" name="VK_FORMAT_R32_SFLOAT"/>
+ <enum value="101" name="VK_FORMAT_R32G32_UINT"/>
+ <enum value="102" name="VK_FORMAT_R32G32_SINT"/>
+ <enum value="103" name="VK_FORMAT_R32G32_SFLOAT"/>
+ <enum value="104" name="VK_FORMAT_R32G32B32_UINT"/>
+ <enum value="105" name="VK_FORMAT_R32G32B32_SINT"/>
+ <enum value="106" name="VK_FORMAT_R32G32B32_SFLOAT"/>
+ <enum value="107" name="VK_FORMAT_R32G32B32A32_UINT"/>
+ <enum value="108" name="VK_FORMAT_R32G32B32A32_SINT"/>
+ <enum value="109" name="VK_FORMAT_R32G32B32A32_SFLOAT"/>
+ <enum value="110" name="VK_FORMAT_R64_UINT"/>
+ <enum value="111" name="VK_FORMAT_R64_SINT"/>
+ <enum value="112" name="VK_FORMAT_R64_SFLOAT"/>
+ <enum value="113" name="VK_FORMAT_R64G64_UINT"/>
+ <enum value="114" name="VK_FORMAT_R64G64_SINT"/>
+ <enum value="115" name="VK_FORMAT_R64G64_SFLOAT"/>
+ <enum value="116" name="VK_FORMAT_R64G64B64_UINT"/>
+ <enum value="117" name="VK_FORMAT_R64G64B64_SINT"/>
+ <enum value="118" name="VK_FORMAT_R64G64B64_SFLOAT"/>
+ <enum value="119" name="VK_FORMAT_R64G64B64A64_UINT"/>
+ <enum value="120" name="VK_FORMAT_R64G64B64A64_SINT"/>
+ <enum value="121" name="VK_FORMAT_R64G64B64A64_SFLOAT"/>
+ <enum value="122" name="VK_FORMAT_B10G11R11_UFLOAT_PACK32"/>
+ <enum value="123" name="VK_FORMAT_E5B9G9R9_UFLOAT_PACK32"/>
+ <enum value="124" name="VK_FORMAT_D16_UNORM"/>
+ <enum value="125" name="VK_FORMAT_X8_D24_UNORM_PACK32"/>
+ <enum value="126" name="VK_FORMAT_D32_SFLOAT"/>
+ <enum value="127" name="VK_FORMAT_S8_UINT"/>
+ <enum value="128" name="VK_FORMAT_D16_UNORM_S8_UINT"/>
+ <enum value="129" name="VK_FORMAT_D24_UNORM_S8_UINT"/>
+ <enum value="130" name="VK_FORMAT_D32_SFLOAT_S8_UINT"/>
+ <enum value="131" name="VK_FORMAT_BC1_RGB_UNORM_BLOCK"/>
+ <enum value="132" name="VK_FORMAT_BC1_RGB_SRGB_BLOCK"/>
+ <enum value="133" name="VK_FORMAT_BC1_RGBA_UNORM_BLOCK"/>
+ <enum value="134" name="VK_FORMAT_BC1_RGBA_SRGB_BLOCK"/>
+ <enum value="135" name="VK_FORMAT_BC2_UNORM_BLOCK"/>
+ <enum value="136" name="VK_FORMAT_BC2_SRGB_BLOCK"/>
+ <enum value="137" name="VK_FORMAT_BC3_UNORM_BLOCK"/>
+ <enum value="138" name="VK_FORMAT_BC3_SRGB_BLOCK"/>
+ <enum value="139" name="VK_FORMAT_BC4_UNORM_BLOCK"/>
+ <enum value="140" name="VK_FORMAT_BC4_SNORM_BLOCK"/>
+ <enum value="141" name="VK_FORMAT_BC5_UNORM_BLOCK"/>
+ <enum value="142" name="VK_FORMAT_BC5_SNORM_BLOCK"/>
+ <enum value="143" name="VK_FORMAT_BC6H_UFLOAT_BLOCK"/>
+ <enum value="144" name="VK_FORMAT_BC6H_SFLOAT_BLOCK"/>
+ <enum value="145" name="VK_FORMAT_BC7_UNORM_BLOCK"/>
+ <enum value="146" name="VK_FORMAT_BC7_SRGB_BLOCK"/>
+ <enum value="147" name="VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK"/>
+ <enum value="148" name="VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK"/>
+ <enum value="149" name="VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK"/>
+ <enum value="150" name="VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK"/>
+ <enum value="151" name="VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK"/>
+ <enum value="152" name="VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK"/>
+ <enum value="153" name="VK_FORMAT_EAC_R11_UNORM_BLOCK"/>
+ <enum value="154" name="VK_FORMAT_EAC_R11_SNORM_BLOCK"/>
+ <enum value="155" name="VK_FORMAT_EAC_R11G11_UNORM_BLOCK"/>
+ <enum value="156" name="VK_FORMAT_EAC_R11G11_SNORM_BLOCK"/>
+ <enum value="157" name="VK_FORMAT_ASTC_4x4_UNORM_BLOCK"/>
+ <enum value="158" name="VK_FORMAT_ASTC_4x4_SRGB_BLOCK"/>
+ <enum value="159" name="VK_FORMAT_ASTC_5x4_UNORM_BLOCK"/>
+ <enum value="160" name="VK_FORMAT_ASTC_5x4_SRGB_BLOCK"/>
+ <enum value="161" name="VK_FORMAT_ASTC_5x5_UNORM_BLOCK"/>
+ <enum value="162" name="VK_FORMAT_ASTC_5x5_SRGB_BLOCK"/>
+ <enum value="163" name="VK_FORMAT_ASTC_6x5_UNORM_BLOCK"/>
+ <enum value="164" name="VK_FORMAT_ASTC_6x5_SRGB_BLOCK"/>
+ <enum value="165" name="VK_FORMAT_ASTC_6x6_UNORM_BLOCK"/>
+ <enum value="166" name="VK_FORMAT_ASTC_6x6_SRGB_BLOCK"/>
+ <enum value="167" name="VK_FORMAT_ASTC_8x5_UNORM_BLOCK"/>
+ <enum value="168" name="VK_FORMAT_ASTC_8x5_SRGB_BLOCK"/>
+ <enum value="169" name="VK_FORMAT_ASTC_8x6_UNORM_BLOCK"/>
+ <enum value="170" name="VK_FORMAT_ASTC_8x6_SRGB_BLOCK"/>
+ <enum value="171" name="VK_FORMAT_ASTC_8x8_UNORM_BLOCK"/>
+ <enum value="172" name="VK_FORMAT_ASTC_8x8_SRGB_BLOCK"/>
+ <enum value="173" name="VK_FORMAT_ASTC_10x5_UNORM_BLOCK"/>
+ <enum value="174" name="VK_FORMAT_ASTC_10x5_SRGB_BLOCK"/>
+ <enum value="175" name="VK_FORMAT_ASTC_10x6_UNORM_BLOCK"/>
+ <enum value="176" name="VK_FORMAT_ASTC_10x6_SRGB_BLOCK"/>
+ <enum value="177" name="VK_FORMAT_ASTC_10x8_UNORM_BLOCK"/>
+ <enum value="178" name="VK_FORMAT_ASTC_10x8_SRGB_BLOCK"/>
+ <enum value="179" name="VK_FORMAT_ASTC_10x10_UNORM_BLOCK"/>
+ <enum value="180" name="VK_FORMAT_ASTC_10x10_SRGB_BLOCK"/>
+ <enum value="181" name="VK_FORMAT_ASTC_12x10_UNORM_BLOCK"/>
+ <enum value="182" name="VK_FORMAT_ASTC_12x10_SRGB_BLOCK"/>
+ <enum value="183" name="VK_FORMAT_ASTC_12x12_UNORM_BLOCK"/>
+ <enum value="184" name="VK_FORMAT_ASTC_12x12_SRGB_BLOCK"/>
+ </enums>
+ <enums name="VkStructureType" type="enum" comment="Structure type enumerant">
+ <enum value="0" name="VK_STRUCTURE_TYPE_APPLICATION_INFO"/>
+ <enum value="1" name="VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO"/>
+ <enum value="2" name="VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO"/>
+ <enum value="3" name="VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO"/>
+ <enum value="4" name="VK_STRUCTURE_TYPE_SUBMIT_INFO"/>
+ <enum value="5" name="VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO"/>
+ <enum value="6" name="VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE"/>
+ <enum value="7" name="VK_STRUCTURE_TYPE_BIND_SPARSE_INFO"/>
+ <enum value="8" name="VK_STRUCTURE_TYPE_FENCE_CREATE_INFO"/>
+ <enum value="9" name="VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO"/>
+ <enum value="10" name="VK_STRUCTURE_TYPE_EVENT_CREATE_INFO"/>
+ <enum value="11" name="VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO"/>
+ <enum value="12" name="VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO"/>
+ <enum value="13" name="VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO"/>
+ <enum value="14" name="VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO"/>
+ <enum value="15" name="VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO"/>
+ <enum value="16" name="VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO"/>
+ <enum value="17" name="VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO"/>
+ <enum value="18" name="VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO"/>
+ <enum value="19" name="VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO"/>
+ <enum value="20" name="VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO"/>
+ <enum value="21" name="VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO"/>
+ <enum value="22" name="VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO"/>
+ <enum value="23" name="VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO"/>
+ <enum value="24" name="VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO"/>
+ <enum value="25" name="VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO"/>
+ <enum value="26" name="VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO"/>
+ <enum value="27" name="VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO"/>
+ <enum value="28" name="VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO"/>
+ <enum value="29" name="VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO"/>
+ <enum value="30" name="VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO"/>
+ <enum value="31" name="VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO"/>
+ <enum value="32" name="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO"/>
+ <enum value="33" name="VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO"/>
+ <enum value="34" name="VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO"/>
+ <enum value="35" name="VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET"/>
+ <enum value="36" name="VK_STRUCTURE_TYPE_COPY_DESCRIPTOR_SET"/>
+ <enum value="37" name="VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO"/>
+ <enum value="38" name="VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO"/>
+ <enum value="39" name="VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO"/>
+ <enum value="40" name="VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO"/>
+ <enum value="41" name="VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO"/>
+ <enum value="42" name="VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO"/>
+ <enum value="43" name="VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO"/>
+ <enum value="44" name="VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER"/>
+ <enum value="45" name="VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER"/>
+ <enum value="46" name="VK_STRUCTURE_TYPE_MEMORY_BARRIER"/>
+ <enum value="47" name="VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO"/> <!-- Reserved for internal use by the loader, layers, and ICDs -->
+ <enum value="48" name="VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO"/> <!-- Reserved for internal use by the loader, layers, and ICDs -->
+ </enums>
+ <enums name="VkSubpassContents" type="enum">
+ <enum value="0" name="VK_SUBPASS_CONTENTS_INLINE"/>
+ <enum value="1" name="VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS"/>
+ </enums>
+ <enums name="VkResult" type="enum" comment="Error and return codes">
+ <!-- Return codes for successful operation execution (positive values) -->
+ <enum value="0" name="VK_SUCCESS" comment="Command completed successfully"/>
+ <enum value="1" name="VK_NOT_READY" comment="A fence or query has not yet completed"/>
+ <enum value="2" name="VK_TIMEOUT" comment="A wait operation has not completed in the specified time"/>
+ <enum value="3" name="VK_EVENT_SET" comment="An event is signaled"/>
+ <enum value="4" name="VK_EVENT_RESET" comment="An event is unsignaled"/>
+ <enum value="5" name="VK_INCOMPLETE" comment="A return array was too small for the result"/>
+ <!-- Error codes (negative values) -->
+ <enum value="-1" name="VK_ERROR_OUT_OF_HOST_MEMORY" comment="A host memory allocation has failed"/>
+ <enum value="-2" name="VK_ERROR_OUT_OF_DEVICE_MEMORY" comment="A device memory allocation has failed"/>
+ <enum value="-3" name="VK_ERROR_INITIALIZATION_FAILED" comment="Initialization of a object has failed"/>
+ <enum value="-4" name="VK_ERROR_DEVICE_LOST" comment="The logical device has been lost. See &lt;&lt;devsandqueues-lost-device&gt;&gt;"/>
+ <enum value="-5" name="VK_ERROR_MEMORY_MAP_FAILED" comment="Mapping of a memory object has failed"/>
+ <enum value="-6" name="VK_ERROR_LAYER_NOT_PRESENT" comment="Layer specified does not exist"/>
+ <enum value="-7" name="VK_ERROR_EXTENSION_NOT_PRESENT" comment="Extension specified does not exist"/>
+ <enum value="-8" name="VK_ERROR_FEATURE_NOT_PRESENT" comment="Requested feature is not available on this device"/>
+ <enum value="-9" name="VK_ERROR_INCOMPATIBLE_DRIVER" comment="Unable to find a Vulkan driver"/>
+ <enum value="-10" name="VK_ERROR_TOO_MANY_OBJECTS" comment="Too many objects of the type have already been created"/>
+ <enum value="-11" name="VK_ERROR_FORMAT_NOT_SUPPORTED" comment="Requested format is not supported on this device"/>
+ <enum value="-12" name="VK_ERROR_FRAGMENTED_POOL" comment="A requested pool allocation has failed due to fragmentation of the pool's memory"/>
+ <unused start="-12"/>
+ </enums>
+ <enums name="VkDynamicState" type="enum">
+ <enum value="0" name="VK_DYNAMIC_STATE_VIEWPORT"/>
+ <enum value="1" name="VK_DYNAMIC_STATE_SCISSOR"/>
+ <enum value="2" name="VK_DYNAMIC_STATE_LINE_WIDTH"/>
+ <enum value="3" name="VK_DYNAMIC_STATE_DEPTH_BIAS"/>
+ <enum value="4" name="VK_DYNAMIC_STATE_BLEND_CONSTANTS"/>
+ <enum value="5" name="VK_DYNAMIC_STATE_DEPTH_BOUNDS"/>
+ <enum value="6" name="VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK"/>
+ <enum value="7" name="VK_DYNAMIC_STATE_STENCIL_WRITE_MASK"/>
+ <enum value="8" name="VK_DYNAMIC_STATE_STENCIL_REFERENCE"/>
+ </enums>
+
+ <!-- Flags -->
+ <enums name="VkQueueFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_QUEUE_GRAPHICS_BIT" comment="Queue supports graphics operations"/>
+ <enum bitpos="1" name="VK_QUEUE_COMPUTE_BIT" comment="Queue supports compute operations"/>
+ <enum bitpos="2" name="VK_QUEUE_TRANSFER_BIT" comment="Queue supports transfer operations"/>
+ <enum bitpos="3" name="VK_QUEUE_SPARSE_BINDING_BIT" comment="Queue supports sparse resource memory management operations"/>
+ </enums>
+ <enums name="VkMemoryPropertyFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT" comment="If otherwise stated, then allocate memory on device"/>
+ <enum bitpos="1" name="VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT" comment="Memory is mappable by host"/>
+ <enum bitpos="2" name="VK_MEMORY_PROPERTY_HOST_COHERENT_BIT" comment="Memory will have i/o coherency. If not set, application may need to use vkFlushMappedMemoryRanges and vkInvalidateMappedMemoryRanges to flush/invalidate host cache"/>
+ <enum bitpos="3" name="VK_MEMORY_PROPERTY_HOST_CACHED_BIT" comment="Memory will be cached by the host"/>
+ <enum bitpos="4" name="VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT" comment="Memory may be allocated by the driver when it is required"/>
+ </enums>
+ <enums name="VkMemoryHeapFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_MEMORY_HEAP_DEVICE_LOCAL_BIT" comment="If set, heap represents device memory"/>
+ </enums>
+ <enums name="VkAccessFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_ACCESS_INDIRECT_COMMAND_READ_BIT" comment="Controls coherency of indirect command reads"/>
+ <enum bitpos="1" name="VK_ACCESS_INDEX_READ_BIT" comment="Controls coherency of index reads"/>
+ <enum bitpos="2" name="VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT" comment="Controls coherency of vertex attribute reads"/>
+ <enum bitpos="3" name="VK_ACCESS_UNIFORM_READ_BIT" comment="Controls coherency of uniform buffer reads"/>
+ <enum bitpos="4" name="VK_ACCESS_INPUT_ATTACHMENT_READ_BIT" comment="Controls coherency of input attachment reads"/>
+ <enum bitpos="5" name="VK_ACCESS_SHADER_READ_BIT" comment="Controls coherency of shader reads"/>
+ <enum bitpos="6" name="VK_ACCESS_SHADER_WRITE_BIT" comment="Controls coherency of shader writes"/>
+ <enum bitpos="7" name="VK_ACCESS_COLOR_ATTACHMENT_READ_BIT" comment="Controls coherency of color attachment reads"/>
+ <enum bitpos="8" name="VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT" comment="Controls coherency of color attachment writes"/>
+ <enum bitpos="9" name="VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT" comment="Controls coherency of depth/stencil attachment reads"/>
+ <enum bitpos="10" name="VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT" comment="Controls coherency of depth/stencil attachment writes"/>
+ <enum bitpos="11" name="VK_ACCESS_TRANSFER_READ_BIT" comment="Controls coherency of transfer reads"/>
+ <enum bitpos="12" name="VK_ACCESS_TRANSFER_WRITE_BIT" comment="Controls coherency of transfer writes"/>
+ <enum bitpos="13" name="VK_ACCESS_HOST_READ_BIT" comment="Controls coherency of host reads"/>
+ <enum bitpos="14" name="VK_ACCESS_HOST_WRITE_BIT" comment="Controls coherency of host writes"/>
+ <enum bitpos="15" name="VK_ACCESS_MEMORY_READ_BIT" comment="Controls coherency of memory reads"/>
+ <enum bitpos="16" name="VK_ACCESS_MEMORY_WRITE_BIT" comment="Controls coherency of memory writes"/>
+ </enums>
+ <enums name="VkBufferUsageFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_BUFFER_USAGE_TRANSFER_SRC_BIT" comment="Can be used as a source of transfer operations"/>
+ <enum bitpos="1" name="VK_BUFFER_USAGE_TRANSFER_DST_BIT" comment="Can be used as a destination of transfer operations"/>
+ <enum bitpos="2" name="VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT" comment="Can be used as TBO"/>
+ <enum bitpos="3" name="VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT" comment="Can be used as IBO"/>
+ <enum bitpos="4" name="VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT" comment="Can be used as UBO"/>
+ <enum bitpos="5" name="VK_BUFFER_USAGE_STORAGE_BUFFER_BIT" comment="Can be used as SSBO"/>
+ <enum bitpos="6" name="VK_BUFFER_USAGE_INDEX_BUFFER_BIT" comment="Can be used as source of fixed-function index fetch (index buffer)"/>
+ <enum bitpos="7" name="VK_BUFFER_USAGE_VERTEX_BUFFER_BIT" comment="Can be used as source of fixed-function vertex fetch (VBO)"/>
+ <enum bitpos="8" name="VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT" comment="Can be the source of indirect parameters (e.g. indirect buffer, parameter buffer)"/>
+ </enums>
+ <enums name="VkBufferCreateFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_BUFFER_CREATE_SPARSE_BINDING_BIT" comment="Buffer should support sparse backing"/>
+ <enum bitpos="1" name="VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT" comment="Buffer should support sparse backing with partial residency"/>
+ <enum bitpos="2" name="VK_BUFFER_CREATE_SPARSE_ALIASED_BIT" comment="Buffer should support constent data access to physical memory ranges mapped into multiple locations of sparse buffers"/>
+ </enums>
+ <enums name="VkShaderStageFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_SHADER_STAGE_VERTEX_BIT"/>
+ <enum bitpos="1" name="VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT"/>
+ <enum bitpos="2" name="VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT"/>
+ <enum bitpos="3" name="VK_SHADER_STAGE_GEOMETRY_BIT"/>
+ <enum bitpos="4" name="VK_SHADER_STAGE_FRAGMENT_BIT"/>
+ <enum bitpos="5" name="VK_SHADER_STAGE_COMPUTE_BIT"/>
+ <enum value="0x0000001F" name="VK_SHADER_STAGE_ALL_GRAPHICS"/>
+ <enum value="0x7FFFFFFF" name="VK_SHADER_STAGE_ALL"/>
+ </enums>
+ <enums name="VkImageUsageFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_IMAGE_USAGE_TRANSFER_SRC_BIT" comment="Can be used as a source of transfer operations"/>
+ <enum bitpos="1" name="VK_IMAGE_USAGE_TRANSFER_DST_BIT" comment="Can be used as a destination of transfer operations"/>
+ <enum bitpos="2" name="VK_IMAGE_USAGE_SAMPLED_BIT" comment="Can be sampled from (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)"/>
+ <enum bitpos="3" name="VK_IMAGE_USAGE_STORAGE_BIT" comment="Can be used as storage image (STORAGE_IMAGE descriptor type)"/>
+ <enum bitpos="4" name="VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT" comment="Can be used as framebuffer color attachment"/>
+ <enum bitpos="5" name="VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT" comment="Can be used as framebuffer depth/stencil attachment"/>
+ <enum bitpos="6" name="VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT" comment="Image data not needed outside of rendering"/>
+ <enum bitpos="7" name="VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT" comment="Can be used as framebuffer input attachment"/>
+ </enums>
+ <enums name="VkImageCreateFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_IMAGE_CREATE_SPARSE_BINDING_BIT" comment="Image should support sparse backing"/>
+ <enum bitpos="1" name="VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT" comment="Image should support sparse backing with partial residency"/>
+ <enum bitpos="2" name="VK_IMAGE_CREATE_SPARSE_ALIASED_BIT" comment="Image should support constent data access to physical memory ranges mapped into multiple locations of sparse images"/>
+ <enum bitpos="3" name="VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT" comment="Allows image views to have different format than the base image"/>
+ <enum bitpos="4" name="VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT" comment="Allows creating image views with cube type from the created image"/>
+ </enums>
+ <enums name="VkPipelineCreateFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT"/>
+ <enum bitpos="1" name="VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT"/>
+ <enum bitpos="2" name="VK_PIPELINE_CREATE_DERIVATIVE_BIT"/>
+ </enums>
+ <enums name="VkColorComponentFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_COLOR_COMPONENT_R_BIT"/>
+ <enum bitpos="1" name="VK_COLOR_COMPONENT_G_BIT"/>
+ <enum bitpos="2" name="VK_COLOR_COMPONENT_B_BIT"/>
+ <enum bitpos="3" name="VK_COLOR_COMPONENT_A_BIT"/>
+ </enums>
+ <enums name="VkFenceCreateFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_FENCE_CREATE_SIGNALED_BIT"/>
+ </enums>
+ <enums name="VkFormatFeatureFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT" comment="Format can be used for sampled images (SAMPLED_IMAGE and COMBINED_IMAGE_SAMPLER descriptor types)"/>
+ <enum bitpos="1" name="VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT" comment="Format can be used for storage images (STORAGE_IMAGE descriptor type)"/>
+ <enum bitpos="2" name="VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT" comment="Format supports atomic operations in case it is used for storage images"/>
+ <enum bitpos="3" name="VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT" comment="Format can be used for uniform texel buffers (TBOs)"/>
+ <enum bitpos="4" name="VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT" comment="Format can be used for storage texel buffers (IBOs)"/>
+ <enum bitpos="5" name="VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT" comment="Format supports atomic operations in case it is used for storage texel buffers"/>
+ <enum bitpos="6" name="VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT" comment="Format can be used for vertex buffers (VBOs)"/>
+ <enum bitpos="7" name="VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT" comment="Format can be used for color attachment images"/>
+ <enum bitpos="8" name="VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT" comment="Format supports blending in case it is used for color attachment images"/>
+ <enum bitpos="9" name="VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT" comment="Format can be used for depth/stencil attachment images"/>
+ <enum bitpos="10" name="VK_FORMAT_FEATURE_BLIT_SRC_BIT" comment="Format can be used as the source image of blits with vkCmdBlitImage"/>
+ <enum bitpos="11" name="VK_FORMAT_FEATURE_BLIT_DST_BIT" comment="Format can be used as the destination image of blits with vkCmdBlitImage"/>
+ <enum bitpos="12" name="VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT" comment="Format can be filtered with VK_FILTER_LINEAR when being sampled"/>
+ </enums>
+ <enums name="VkQueryControlFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_QUERY_CONTROL_PRECISE_BIT" comment="Require precise results to be collected by the query"/>
+ </enums>
+ <enums name="VkQueryResultFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_QUERY_RESULT_64_BIT" comment="Results of the queries are written to the destination buffer as 64-bit values"/>
+ <enum bitpos="1" name="VK_QUERY_RESULT_WAIT_BIT" comment="Results of the queries are waited on before proceeding with the result copy"/>
+ <enum bitpos="2" name="VK_QUERY_RESULT_WITH_AVAILABILITY_BIT" comment="Besides the results of the query, the availability of the results is also written"/>
+ <enum bitpos="3" name="VK_QUERY_RESULT_PARTIAL_BIT" comment="Copy the partial results of the query even if the final results are not available"/>
+ </enums>
+ <enums name="VkCommandBufferUsageFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT"/>
+ <enum bitpos="1" name="VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT"/>
+ <enum bitpos="2" name="VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT" comment="Command buffer may be submitted/executed more than once simultaneously"/>
+ </enums>
+ <enums name="VkQueryPipelineStatisticFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT" comment="Optional"/>
+ <enum bitpos="1" name="VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT" comment="Optional"/>
+ <enum bitpos="2" name="VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT" comment="Optional"/>
+ <enum bitpos="3" name="VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT" comment="Optional"/>
+ <enum bitpos="4" name="VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT" comment="Optional"/>
+ <enum bitpos="5" name="VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT" comment="Optional"/>
+ <enum bitpos="6" name="VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT" comment="Optional"/>
+ <enum bitpos="7" name="VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT" comment="Optional"/>
+ <enum bitpos="8" name="VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT" comment="Optional"/>
+ <enum bitpos="9" name="VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT" comment="Optional"/>
+ <enum bitpos="10" name="VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT" comment="Optional"/>
+ </enums>
+ <enums name="VkImageAspectFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_IMAGE_ASPECT_COLOR_BIT"/>
+ <enum bitpos="1" name="VK_IMAGE_ASPECT_DEPTH_BIT"/>
+ <enum bitpos="2" name="VK_IMAGE_ASPECT_STENCIL_BIT"/>
+ <enum bitpos="3" name="VK_IMAGE_ASPECT_METADATA_BIT"/>
+ </enums>
+ <enums name="VkSparseImageFormatFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT" comment="Image uses a single mip tail region for all array layers"/>
+ <enum bitpos="1" name="VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT" comment="Image requires mip level dimensions to be an integer multiple of the sparse image block dimensions for non-tail mip levels."/>
+ <enum bitpos="2" name="VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT" comment="Image uses a non-standard sparse image block dimensions"/>
+ </enums>
+ <enums name="VkSparseMemoryBindFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_SPARSE_MEMORY_BIND_METADATA_BIT" comment="Operation binds resource metadata to memory"/>
+ </enums>
+ <enums name="VkPipelineStageFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT" comment="Before subsequent commands are processed"/>
+ <enum bitpos="1" name="VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT" comment="Draw/DispatchIndirect command fetch"/>
+ <enum bitpos="2" name="VK_PIPELINE_STAGE_VERTEX_INPUT_BIT" comment="Vertex/index fetch"/>
+ <enum bitpos="3" name="VK_PIPELINE_STAGE_VERTEX_SHADER_BIT" comment="Vertex shading"/>
+ <enum bitpos="4" name="VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT" comment="Tessellation control shading"/>
+ <enum bitpos="5" name="VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT" comment="Tessellation evaluation shading"/>
+ <enum bitpos="6" name="VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT" comment="Geometry shading"/>
+ <enum bitpos="7" name="VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT" comment="Fragment shading"/>
+ <enum bitpos="8" name="VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT" comment="Early fragment (depth and stencil) tests"/>
+ <enum bitpos="9" name="VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT" comment="Late fragment (depth and stencil) tests"/>
+ <enum bitpos="10" name="VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT" comment="Color attachment writes"/>
+ <enum bitpos="11" name="VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT" comment="Compute shading"/>
+ <enum bitpos="12" name="VK_PIPELINE_STAGE_TRANSFER_BIT" comment="Transfer/copy operations"/>
+ <enum bitpos="13" name="VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT" comment="After previous commands have completed"/>
+ <enum bitpos="14" name="VK_PIPELINE_STAGE_HOST_BIT" comment="Indicates host (CPU) is a source/sink of the dependency"/>
+ <enum bitpos="15" name="VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT" comment="All stages of the graphics pipeline"/>
+ <enum bitpos="16" name="VK_PIPELINE_STAGE_ALL_COMMANDS_BIT" comment="All stages supported on the queue"/>
+ </enums>
+ <enums name="VkCommandPoolCreateFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_COMMAND_POOL_CREATE_TRANSIENT_BIT" comment="Command buffers have a short lifetime"/>
+ <enum bitpos="1" name="VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT" comment="Command buffers may release their memory individually"/>
+ </enums>
+ <enums name="VkCommandPoolResetFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT" comment="Release resources owned by the pool"/>
+ </enums>
+ <enums name="VkCommandBufferResetFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT" comment="Release resources owned by the buffer"/>
+ </enums>
+ <enums name="VkSampleCountFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_SAMPLE_COUNT_1_BIT" comment="Sample count 1 supported"/>
+ <enum bitpos="1" name="VK_SAMPLE_COUNT_2_BIT" comment="Sample count 2 supported"/>
+ <enum bitpos="2" name="VK_SAMPLE_COUNT_4_BIT" comment="Sample count 4 supported"/>
+ <enum bitpos="3" name="VK_SAMPLE_COUNT_8_BIT" comment="Sample count 8 supported"/>
+ <enum bitpos="4" name="VK_SAMPLE_COUNT_16_BIT" comment="Sample count 16 supported"/>
+ <enum bitpos="5" name="VK_SAMPLE_COUNT_32_BIT" comment="Sample count 32 supported"/>
+ <enum bitpos="6" name="VK_SAMPLE_COUNT_64_BIT" comment="Sample count 64 supported"/>
+ </enums>
+ <enums name="VkAttachmentDescriptionFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT" comment="The attachment may alias physical memory of another attachment in the same render pass"/>
+ </enums>
+ <enums name="VkStencilFaceFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_STENCIL_FACE_FRONT_BIT" comment="Front face"/>
+ <enum bitpos="1" name="VK_STENCIL_FACE_BACK_BIT" comment="Back face"/>
+ <enum value="0x00000003" name="VK_STENCIL_FRONT_AND_BACK" comment="Front and back faces"/>
+ </enums>
+ <enums name="VkDescriptorPoolCreateFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT" comment="Descriptor sets may be freed individually"/>
+ </enums>
+ <enums name="VkDependencyFlagBits" type="bitmask">
+ <enum bitpos="0" name="VK_DEPENDENCY_BY_REGION_BIT" comment="Dependency is per pixel region "/>
+ </enums>
+ <!-- WSI extensions -->
+ <enums name="VkPresentModeKHR" type="enum">
+ <enum value="0" name="VK_PRESENT_MODE_IMMEDIATE_KHR"/>
+ <enum value="1" name="VK_PRESENT_MODE_MAILBOX_KHR"/>
+ <enum value="2" name="VK_PRESENT_MODE_FIFO_KHR"/>
+ <enum value="3" name="VK_PRESENT_MODE_FIFO_RELAXED_KHR"/>
+ </enums>
+ <enums name="VkColorSpaceKHR" type="enum">
+ <enum value="0" name="VK_COLOR_SPACE_SRGB_NONLINEAR_KHR"/>
+ </enums>
+ <enums name="VkDisplayPlaneAlphaFlagBitsKHR" type="bitmask">
+ <enum bitpos="0" name="VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR"/>
+ <enum bitpos="1" name="VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR"/>
+ <enum bitpos="2" name="VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR"/>
+ <enum bitpos="3" name="VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR"/>
+ </enums>
+ <enums name="VkCompositeAlphaFlagBitsKHR" type="bitmask">
+ <enum bitpos="0" name="VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR"/>
+ <enum bitpos="1" name="VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR"/>
+ <enum bitpos="2" name="VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR"/>
+ <enum bitpos="3" name="VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR"/>
+ </enums>
+ <enums name="VkSurfaceTransformFlagBitsKHR" type="bitmask">
+ <enum bitpos="0" name="VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR"/>
+ <enum bitpos="1" name="VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR"/>
+ <enum bitpos="2" name="VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR"/>
+ <enum bitpos="3" name="VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR"/>
+ <enum bitpos="4" name="VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR"/>
+ <enum bitpos="5" name="VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR"/>
+ <enum bitpos="6" name="VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR"/>
+ <enum bitpos="7" name="VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR"/>
+ <enum bitpos="8" name="VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR"/>
+ </enums>
+ <enums name="VkDebugReportFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_DEBUG_REPORT_INFORMATION_BIT_EXT"/>
+ <enum bitpos="1" name="VK_DEBUG_REPORT_WARNING_BIT_EXT"/>
+ <enum bitpos="2" name="VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT"/>
+ <enum bitpos="3" name="VK_DEBUG_REPORT_ERROR_BIT_EXT"/>
+ <enum bitpos="4" name="VK_DEBUG_REPORT_DEBUG_BIT_EXT"/>
+ </enums>
+ <enums name="VkDebugReportObjectTypeEXT" type="enum">
+ <enum value="0" name="VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT"/>
+ <enum value="1" name="VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT"/>
+ <enum value="2" name="VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT"/>
+ <enum value="3" name="VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT"/>
+ <enum value="4" name="VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT"/>
+ <enum value="5" name="VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT"/>
+ <enum value="6" name="VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT"/>
+ <enum value="7" name="VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT"/>
+ <enum value="8" name="VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT"/>
+ <enum value="9" name="VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT"/>
+ <enum value="10" name="VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT"/>
+ <enum value="11" name="VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT"/>
+ <enum value="12" name="VK_DEBUG_REPORT_OBJECT_TYPE_QUERY_POOL_EXT"/>
+ <enum value="13" name="VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_VIEW_EXT"/>
+ <enum value="14" name="VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_VIEW_EXT"/>
+ <enum value="15" name="VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT"/>
+ <enum value="16" name="VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_CACHE_EXT"/>
+ <enum value="17" name="VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT"/>
+ <enum value="18" name="VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT"/>
+ <enum value="19" name="VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT"/>
+ <enum value="20" name="VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT"/>
+ <enum value="21" name="VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT"/>
+ <enum value="22" name="VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT"/>
+ <enum value="23" name="VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT"/>
+ <enum value="24" name="VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT"/>
+ <enum value="25" name="VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_POOL_EXT"/>
+ <enum value="26" name="VK_DEBUG_REPORT_OBJECT_TYPE_SURFACE_KHR_EXT"/>
+ <enum value="27" name="VK_DEBUG_REPORT_OBJECT_TYPE_SWAPCHAIN_KHR_EXT"/>
+ <enum value="28" name="VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT"/>
+ <enum value="29" name="VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_KHR_EXT"/>
+ <enum value="30" name="VK_DEBUG_REPORT_OBJECT_TYPE_DISPLAY_MODE_KHR_EXT"/>
+ <enum value="31" name="VK_DEBUG_REPORT_OBJECT_TYPE_OBJECT_TABLE_NVX_EXT"/>
+ <enum value="32" name="VK_DEBUG_REPORT_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NVX_EXT"/>
+ </enums>
+ <enums name="VkDebugReportErrorEXT" type="enum">
+ <enum value="0" name="VK_DEBUG_REPORT_ERROR_NONE_EXT"/> <!-- Used for INFO & other non-error messages -->
+ <enum value="1" name="VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT"/> <!-- Callbacks were not destroyed prior to calling DestroyInstance -->
+ </enums>
+ <enums name="VkRasterizationOrderAMD" type="enum">
+ <enum value="0" name="VK_RASTERIZATION_ORDER_STRICT_AMD"/> <!-- Rasterization order strictly follows API order -->
+ <enum value="1" name="VK_RASTERIZATION_ORDER_RELAXED_AMD"/> <!-- Rasterization order may not follow API order -->
+ </enums>
+ <enums name="VkExternalMemoryHandleTypeFlagBitsNV" type="bitmask">
+ <enum bitpos="0" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT_NV"/>
+ <enum bitpos="1" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_KMT_BIT_NV"/>
+ <enum bitpos="2" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_BIT_NV"/>
+ <enum bitpos="3" name="VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_IMAGE_KMT_BIT_NV"/>
+ </enums>
+ <enums name="VkExternalMemoryFeatureFlagBitsNV" type="bitmask">
+ <enum bitpos="0" name="VK_EXTERNAL_MEMORY_FEATURE_DEDICATED_ONLY_BIT_NV"/>
+ <enum bitpos="1" name="VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT_NV"/>
+ <enum bitpos="2" name="VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT_NV"/>
+ </enums>
+ <enums name="VkValidationCheckEXT" type="enum">
+ <enum value="0" name="VK_VALIDATION_CHECK_ALL_EXT"/>
+ <!-- Placeholder for validation enums to be defined for VK_EXT_Validation_flags extension -->
+ </enums>
+ <enums name="VkIndirectCommandsLayoutUsageFlagBitsNVX" type="bitmask">
+ <enum bitpos="0" name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_UNORDERED_SEQUENCES_BIT_NVX"/> <!-- sequences can be processed in implementation-dependent order -->
+ <enum bitpos="1" name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_SPARSE_SEQUENCES_BIT_NVX"/> <!-- likely generated with a high difference in actual sequencesCount and maxSequencesCount -->
+ <enum bitpos="2" name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_EMPTY_EXECUTIONS_BIT_NVX"/> <!-- likely to contain draw/dispatch calls that are zero-sized -->
+ <enum bitpos="3" name="VK_INDIRECT_COMMANDS_LAYOUT_USAGE_INDEXED_SEQUENCES_BIT_NVX"/> <!-- custom sequence index permutation (32-bit) is provided -->
+ </enums>
+ <enums name="VkObjectEntryUsageFlagBitsNVX" type="bitmask">
+ <enum bitpos="0" name="VK_OBJECT_ENTRY_USAGE_GRAPHICS_BIT_NVX"/>
+ <enum bitpos="1" name="VK_OBJECT_ENTRY_USAGE_COMPUTE_BIT_NVX"/>
+ </enums>
+ <enums name="VkIndirectCommandsTokenTypeNVX" type="enum">
+ <enum value="0" name="VK_INDIRECT_COMMANDS_TOKEN_PIPELINE_NVX"/> <!-- array of 32bit tableEntry in the object table -->
+ <enum value="1" name="VK_INDIRECT_COMMANDS_TOKEN_DESCRIPTOR_SET_NVX"/> <!-- array of (32 bit tableEntry + variable count 32bit offsets) -->
+ <enum value="2" name="VK_INDIRECT_COMMANDS_TOKEN_INDEX_BUFFER_NVX"/> <!-- array of (32 bit tableEntry + optional 32bit offset) -->
+ <enum value="3" name="VK_INDIRECT_COMMANDS_TOKEN_VERTEX_BUFFER_NVX"/> <!-- array of (32 bit tableEntry + optional 32bit offset) -->
+ <enum value="4" name="VK_INDIRECT_COMMANDS_TOKEN_PUSH_CONSTANT_NVX"/> <!-- array of (32 bit tableEntry + variable count 32bit values ) -->
+ <enum value="5" name="VK_INDIRECT_COMMANDS_TOKEN_DRAW_INDEXED_NVX"/> <!-- array of VkDrawIndexedIndirectCommand -->
+ <enum value="6" name="VK_INDIRECT_COMMANDS_TOKEN_DRAW_NVX"/> <!-- array of VkDrawIndirectCommand -->
+ <enum value="7" name="VK_INDIRECT_COMMANDS_TOKEN_DISPATCH_NVX"/> <!-- array of VkDispatchIndirectCommand -->
+ </enums>
+ <enums name="VkObjectEntryTypeNVX" type="enum">
+ <enum value="0" name="VK_OBJECT_ENTRY_DESCRIPTOR_SET_NVX"/>
+ <enum value="1" name="VK_OBJECT_ENTRY_PIPELINE_NVX"/>
+ <enum value="2" name="VK_OBJECT_ENTRY_INDEX_BUFFER_NVX"/>
+ <enum value="3" name="VK_OBJECT_ENTRY_VERTEX_BUFFER_NVX"/>
+ <enum value="4" name="VK_OBJECT_ENTRY_PUSH_CONSTANT_NVX"/>
+ </enums>
+ <enums name="VkSurfaceCounterFlagBitsEXT" type="bitmask">
+ <enum bitpos="0" name="VK_SURFACE_COUNTER_VBLANK_EXT"/>
+ </enums>
+ <enums name="VkDisplayPowerStateEXT" type="enum">
+ <enum value="0" name="VK_DISPLAY_POWER_STATE_OFF_EXT"/>
+ <enum value="1" name="VK_DISPLAY_POWER_STATE_SUSPEND_EXT"/>
+ <enum value="2" name="VK_DISPLAY_POWER_STATE_ON_EXT"/>
+ </enums>
+ <enums name="VkDeviceEventTypeEXT" type="enum">
+ <enum value="0" name="VK_DEVICE_EVENT_TYPE_DISPLAY_HOTPLUG_EXT"/>
+ </enums>
+ <enums name="VkDisplayEventTypeEXT" type="enum">
+ <enum value="0" name="VK_DISPLAY_EVENT_TYPE_FIRST_PIXEL_OUT_EXT"/>
+ </enums>
+
+ <!-- SECTION: Vulkan command definitions -->
+ <commands>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_LAYER_NOT_PRESENT,VK_ERROR_EXTENSION_NOT_PRESENT,VK_ERROR_INCOMPATIBLE_DRIVER">
+ <proto><type>VkResult</type> <name>vkCreateInstance</name></proto>
+ <param>const <type>VkInstanceCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkInstance</type>* <name>pInstance</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyInstance</name></proto>
+ <param optional="true" externsync="true"><type>VkInstance</type> <name>instance</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED">
+ <proto><type>VkResult</type> <name>vkEnumeratePhysicalDevices</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPhysicalDeviceCount</name></param>
+ <param optional="true" len="pPhysicalDeviceCount"><type>VkPhysicalDevice</type>* <name>pPhysicalDevices</name></param>
+ </command>
+ <command>
+ <proto><type>PFN_vkVoidFunction</type> <name>vkGetDeviceProcAddr</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param len="null-terminated">const <type>char</type>* <name>pName</name></param>
+ </command>
+ <command>
+ <proto><type>PFN_vkVoidFunction</type> <name>vkGetInstanceProcAddr</name></proto>
+ <param optional="true"><type>VkInstance</type> <name>instance</name></param>
+ <param len="null-terminated">const <type>char</type>* <name>pName</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceProperties</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkPhysicalDeviceProperties</type>* <name>pProperties</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceQueueFamilyProperties</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pQueueFamilyPropertyCount</name></param>
+ <param optional="true" len="pQueueFamilyPropertyCount"><type>VkQueueFamilyProperties</type>* <name>pQueueFamilyProperties</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceMemoryProperties</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkPhysicalDeviceMemoryProperties</type>* <name>pMemoryProperties</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceFeatures</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkPhysicalDeviceFeatures</type>* <name>pFeatures</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceFormatProperties</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkFormat</type> <name>format</name></param>
+ <param><type>VkFormatProperties</type>* <name>pFormatProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_FORMAT_NOT_SUPPORTED">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceImageFormatProperties</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkFormat</type> <name>format</name></param>
+ <param><type>VkImageType</type> <name>type</name></param>
+ <param><type>VkImageTiling</type> <name>tiling</name></param>
+ <param><type>VkImageUsageFlags</type> <name>usage</name></param>
+ <param optional="true"><type>VkImageCreateFlags</type> <name>flags</name></param>
+ <param><type>VkImageFormatProperties</type>* <name>pImageFormatProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED,VK_ERROR_EXTENSION_NOT_PRESENT,VK_ERROR_FEATURE_NOT_PRESENT,VK_ERROR_TOO_MANY_OBJECTS,VK_ERROR_DEVICE_LOST">
+ <proto><type>VkResult</type> <name>vkCreateDevice</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param>const <type>VkDeviceCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkDevice</type>* <name>pDevice</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyDevice</name></proto>
+ <param optional="true" externsync="true"><type>VkDevice</type> <name>device</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkEnumerateInstanceLayerProperties</name></proto>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
+ <param optional="true" len="pPropertyCount"><type>VkLayerProperties</type>* <name>pProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_LAYER_NOT_PRESENT">
+ <proto><type>VkResult</type> <name>vkEnumerateInstanceExtensionProperties</name></proto>
+ <param optional="true" len="null-terminated">const <type>char</type>* <name>pLayerName</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
+ <param optional="true" len="pPropertyCount"><type>VkExtensionProperties</type>* <name>pProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkEnumerateDeviceLayerProperties</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
+ <param optional="true" len="pPropertyCount"><type>VkLayerProperties</type>* <name>pProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_LAYER_NOT_PRESENT">
+ <proto><type>VkResult</type> <name>vkEnumerateDeviceExtensionProperties</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param optional="true" len="null-terminated">const <type>char</type>* <name>pLayerName</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
+ <param optional="true" len="pPropertyCount"><type>VkExtensionProperties</type>* <name>pProperties</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetDeviceQueue</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>uint32_t</type> <name>queueFamilyIndex</name></param>
+ <param><type>uint32_t</type> <name>queueIndex</name></param>
+ <param><type>VkQueue</type>* <name>pQueue</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST">
+ <proto><type>VkResult</type> <name>vkQueueSubmit</name></proto>
+ <param externsync="true"><type>VkQueue</type> <name>queue</name></param>
+ <param optional="true"><type>uint32_t</type> <name>submitCount</name></param>
+ <param len="submitCount" externsync="pSubmits[].pWaitSemaphores[],pSubmits[].pSignalSemaphores[]">const <type>VkSubmitInfo</type>* <name>pSubmits</name></param>
+ <param optional="true" externsync="true"><type>VkFence</type> <name>fence</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST">
+ <proto><type>VkResult</type> <name>vkQueueWaitIdle</name></proto>
+ <param><type>VkQueue</type> <name>queue</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST">
+ <proto><type>VkResult</type> <name>vkDeviceWaitIdle</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <implicitexternsyncparams>
+ <param>all sname:VkQueue objects created from pname:device</param>
+ </implicitexternsyncparams>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_TOO_MANY_OBJECTS">
+ <proto><type>VkResult</type> <name>vkAllocateMemory</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkMemoryAllocateInfo</type>* <name>pAllocateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkDeviceMemory</type>* <name>pMemory</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkFreeMemory</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkDeviceMemory</type> <name>memory</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_MEMORY_MAP_FAILED">
+ <proto><type>VkResult</type> <name>vkMapMemory</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkDeviceMemory</type> <name>memory</name></param>
+ <param><type>VkDeviceSize</type> <name>offset</name></param>
+ <param><type>VkDeviceSize</type> <name>size</name></param>
+ <param optional="true"><type>VkMemoryMapFlags</type> <name>flags</name></param>
+ <param><type>void</type>** <name>ppData</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkUnmapMemory</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkDeviceMemory</type> <name>memory</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkFlushMappedMemoryRanges</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>uint32_t</type> <name>memoryRangeCount</name></param>
+ <param len="memoryRangeCount">const <type>VkMappedMemoryRange</type>* <name>pMemoryRanges</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkInvalidateMappedMemoryRanges</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>uint32_t</type> <name>memoryRangeCount</name></param>
+ <param len="memoryRangeCount">const <type>VkMappedMemoryRange</type>* <name>pMemoryRanges</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetDeviceMemoryCommitment</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkDeviceMemory</type> <name>memory</name></param>
+ <param><type>VkDeviceSize</type>* <name>pCommittedMemoryInBytes</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetBufferMemoryRequirements</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkBuffer</type> <name>buffer</name></param>
+ <param><type>VkMemoryRequirements</type>* <name>pMemoryRequirements</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkBindBufferMemory</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkBuffer</type> <name>buffer</name></param>
+ <param><type>VkDeviceMemory</type> <name>memory</name></param>
+ <param><type>VkDeviceSize</type> <name>memoryOffset</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetImageMemoryRequirements</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkImage</type> <name>image</name></param>
+ <param><type>VkMemoryRequirements</type>* <name>pMemoryRequirements</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkBindImageMemory</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkImage</type> <name>image</name></param>
+ <param><type>VkDeviceMemory</type> <name>memory</name></param>
+ <param><type>VkDeviceSize</type> <name>memoryOffset</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetImageSparseMemoryRequirements</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkImage</type> <name>image</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pSparseMemoryRequirementCount</name></param>
+ <param optional="true" len="pSparseMemoryRequirementCount"><type>VkSparseImageMemoryRequirements</type>* <name>pSparseMemoryRequirements</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceSparseImageFormatProperties</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkFormat</type> <name>format</name></param>
+ <param><type>VkImageType</type> <name>type</name></param>
+ <param><type>VkSampleCountFlagBits</type> <name>samples</name></param>
+ <param><type>VkImageUsageFlags</type> <name>usage</name></param>
+ <param><type>VkImageTiling</type> <name>tiling</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
+ <param optional="true" len="pPropertyCount"><type>VkSparseImageFormatProperties</type>* <name>pProperties</name></param>
+ </command>
+ <command queues="sparse_binding" successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST">
+ <proto><type>VkResult</type> <name>vkQueueBindSparse</name></proto>
+ <param externsync="true"><type>VkQueue</type> <name>queue</name></param>
+ <param optional="true"><type>uint32_t</type> <name>bindInfoCount</name></param>
+ <param len="bindInfoCount" externsync="pBindInfo[].pWaitSemaphores[],pBindInfo[].pSignalSemaphores[],pBindInfo[].pBufferBinds[].buffer,pBindInfo[].pImageOpaqueBinds[].image,pBindInfo[].pImageBinds[].image">const <type>VkBindSparseInfo</type>* <name>pBindInfo</name></param>
+ <param optional="true" externsync="true"><type>VkFence</type> <name>fence</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateFence</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkFenceCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkFence</type>* <name>pFence</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyFence</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkFence</type> <name>fence</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkResetFences</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>uint32_t</type> <name>fenceCount</name></param>
+ <param len="fenceCount" externsync="true">const <type>VkFence</type>* <name>pFences</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_NOT_READY" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST">
+ <proto><type>VkResult</type> <name>vkGetFenceStatus</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkFence</type> <name>fence</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_TIMEOUT" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST">
+ <proto><type>VkResult</type> <name>vkWaitForFences</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>uint32_t</type> <name>fenceCount</name></param>
+ <param len="fenceCount">const <type>VkFence</type>* <name>pFences</name></param>
+ <param><type>VkBool32</type> <name>waitAll</name></param>
+ <param><type>uint64_t</type> <name>timeout</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateSemaphore</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkSemaphoreCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSemaphore</type>* <name>pSemaphore</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroySemaphore</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkSemaphore</type> <name>semaphore</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateEvent</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkEventCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkEvent</type>* <name>pEvent</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyEvent</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkEvent</type> <name>event</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_EVENT_SET,VK_EVENT_RESET" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST">
+ <proto><type>VkResult</type> <name>vkGetEventStatus</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkEvent</type> <name>event</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkSetEvent</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkEvent</type> <name>event</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkResetEvent</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkEvent</type> <name>event</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateQueryPool</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkQueryPoolCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkQueryPool</type>* <name>pQueryPool</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyQueryPool</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkQueryPool</type> <name>queryPool</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_NOT_READY" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST">
+ <proto><type>VkResult</type> <name>vkGetQueryPoolResults</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkQueryPool</type> <name>queryPool</name></param>
+ <param><type>uint32_t</type> <name>firstQuery</name></param>
+ <param><type>uint32_t</type> <name>queryCount</name></param>
+ <param><type>size_t</type> <name>dataSize</name></param>
+ <param len="dataSize"><type>void</type>* <name>pData</name></param>
+ <param><type>VkDeviceSize</type> <name>stride</name></param>
+ <param optional="true"><type>VkQueryResultFlags</type> <name>flags</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateBuffer</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkBufferCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkBuffer</type>* <name>pBuffer</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyBuffer</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkBuffer</type> <name>buffer</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateBufferView</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkBufferViewCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkBufferView</type>* <name>pView</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyBufferView</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkBufferView</type> <name>bufferView</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateImage</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkImageCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkImage</type>* <name>pImage</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyImage</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkImage</type> <name>image</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetImageSubresourceLayout</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkImage</type> <name>image</name></param>
+ <param>const <type>VkImageSubresource</type>* <name>pSubresource</name></param>
+ <param><type>VkSubresourceLayout</type>* <name>pLayout</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateImageView</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkImageViewCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkImageView</type>* <name>pView</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyImageView</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkImageView</type> <name>imageView</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_SHADER_NV">
+ <proto><type>VkResult</type> <name>vkCreateShaderModule</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkShaderModuleCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkShaderModule</type>* <name>pShaderModule</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyShaderModule</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkShaderModule</type> <name>shaderModule</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreatePipelineCache</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkPipelineCacheCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkPipelineCache</type>* <name>pPipelineCache</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyPipelineCache</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkPipelineCache</type> <name>pipelineCache</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetPipelineCacheData</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkPipelineCache</type> <name>pipelineCache</name></param>
+ <param optional="false,true"><type>size_t</type>* <name>pDataSize</name></param>
+ <param optional="true" len="pDataSize"><type>void</type>* <name>pData</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkMergePipelineCaches</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkPipelineCache</type> <name>dstCache</name></param>
+ <param><type>uint32_t</type> <name>srcCacheCount</name></param>
+ <param len="srcCacheCount">const <type>VkPipelineCache</type>* <name>pSrcCaches</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_SHADER_NV">
+ <proto><type>VkResult</type> <name>vkCreateGraphicsPipelines</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true"><type>VkPipelineCache</type> <name>pipelineCache</name></param>
+ <param><type>uint32_t</type> <name>createInfoCount</name></param>
+ <param len="createInfoCount">const <type>VkGraphicsPipelineCreateInfo</type>* <name>pCreateInfos</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param len="createInfoCount"><type>VkPipeline</type>* <name>pPipelines</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INVALID_SHADER_NV">
+ <proto><type>VkResult</type> <name>vkCreateComputePipelines</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true"><type>VkPipelineCache</type> <name>pipelineCache</name></param>
+ <param><type>uint32_t</type> <name>createInfoCount</name></param>
+ <param len="createInfoCount">const <type>VkComputePipelineCreateInfo</type>* <name>pCreateInfos</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param len="createInfoCount"><type>VkPipeline</type>* <name>pPipelines</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyPipeline</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkPipeline</type> <name>pipeline</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreatePipelineLayout</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkPipelineLayoutCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkPipelineLayout</type>* <name>pPipelineLayout</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyPipelineLayout</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkPipelineLayout</type> <name>pipelineLayout</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_TOO_MANY_OBJECTS">
+ <proto><type>VkResult</type> <name>vkCreateSampler</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkSamplerCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSampler</type>* <name>pSampler</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroySampler</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkSampler</type> <name>sampler</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateDescriptorSetLayout</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkDescriptorSetLayoutCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkDescriptorSetLayout</type>* <name>pSetLayout</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyDescriptorSetLayout</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkDescriptorSetLayout</type> <name>descriptorSetLayout</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateDescriptorPool</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkDescriptorPoolCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkDescriptorPool</type>* <name>pDescriptorPool</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyDescriptorPool</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkDescriptorPool</type> <name>descriptorPool</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkResetDescriptorPool</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkDescriptorPool</type> <name>descriptorPool</name></param>
+ <param optional="true"><type>VkDescriptorPoolResetFlags</type> <name>flags</name></param>
+ <implicitexternsyncparams>
+ <param>any sname:VkDescriptorSet objects allocated from pname:descriptorPool</param>
+ </implicitexternsyncparams>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_FRAGMENTED_POOL">
+ <proto><type>VkResult</type> <name>vkAllocateDescriptorSets</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="pAllocateInfo::descriptorPool">const <type>VkDescriptorSetAllocateInfo</type>* <name>pAllocateInfo</name></param>
+ <param len="pAllocateInfo::descriptorSetCount"><type>VkDescriptorSet</type>* <name>pDescriptorSets</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkFreeDescriptorSets</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkDescriptorPool</type> <name>descriptorPool</name></param>
+ <param><type>uint32_t</type> <name>descriptorSetCount</name></param>
+ <param noautovalidity="true" externsync="true" len="descriptorSetCount">const <type>VkDescriptorSet</type>* <name>pDescriptorSets</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkUpdateDescriptorSets</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true"><type>uint32_t</type> <name>descriptorWriteCount</name></param>
+ <param len="descriptorWriteCount" externsync="pDescriptorWrites[].dstSet">const <type>VkWriteDescriptorSet</type>* <name>pDescriptorWrites</name></param>
+ <param optional="true"><type>uint32_t</type> <name>descriptorCopyCount</name></param>
+ <param len="descriptorCopyCount" externsync="pDescriptorCopies[].dstSet">const <type>VkCopyDescriptorSet</type>* <name>pDescriptorCopies</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateFramebuffer</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkFramebufferCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkFramebuffer</type>* <name>pFramebuffer</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyFramebuffer</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkFramebuffer</type> <name>framebuffer</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateRenderPass</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkRenderPassCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkRenderPass</type>* <name>pRenderPass</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyRenderPass</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkRenderPass</type> <name>renderPass</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetRenderAreaGranularity</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkRenderPass</type> <name>renderPass</name></param>
+ <param><type>VkExtent2D</type>* <name>pGranularity</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateCommandPool</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkCommandPoolCreateInfo</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkCommandPool</type>* <name>pCommandPool</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyCommandPool</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkCommandPool</type> <name>commandPool</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkResetCommandPool</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkCommandPool</type> <name>commandPool</name></param>
+ <param optional="true"><type>VkCommandPoolResetFlags</type> <name>flags</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkAllocateCommandBuffers</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="pAllocateInfo::commandPool">const <type>VkCommandBufferAllocateInfo</type>* <name>pAllocateInfo</name></param>
+ <param len="pAllocateInfo::commandBufferCount"><type>VkCommandBuffer</type>* <name>pCommandBuffers</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkFreeCommandBuffers</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkCommandPool</type> <name>commandPool</name></param>
+ <param><type>uint32_t</type> <name>commandBufferCount</name></param>
+ <param noautovalidity="true" externsync="true" len="commandBufferCount">const <type>VkCommandBuffer</type>* <name>pCommandBuffers</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkBeginCommandBuffer</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkCommandBufferBeginInfo</type>* <name>pBeginInfo</name></param>
+ <implicitexternsyncparams>
+ <param>the sname:VkCommandPool that pname:commandBuffer was allocated from</param>
+ </implicitexternsyncparams>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkEndCommandBuffer</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <implicitexternsyncparams>
+ <param>the sname:VkCommandPool that pname:commandBuffer was allocated from</param>
+ </implicitexternsyncparams>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkResetCommandBuffer</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param optional="true"><type>VkCommandBufferResetFlags</type> <name>flags</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdBindPipeline</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkPipelineBindPoint</type> <name>pipelineBindPoint</name></param>
+ <param><type>VkPipeline</type> <name>pipeline</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetViewport</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>firstViewport</name></param>
+ <param><type>uint32_t</type> <name>viewportCount</name></param>
+ <param len="viewportCount" noautovalidity="true">const <type>VkViewport</type>* <name>pViewports</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetScissor</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>firstScissor</name></param>
+ <param><type>uint32_t</type> <name>scissorCount</name></param>
+ <param len="scissorCount">const <type>VkRect2D</type>* <name>pScissors</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetLineWidth</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>float</type> <name>lineWidth</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetDepthBias</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>float</type> <name>depthBiasConstantFactor</name></param>
+ <param><type>float</type> <name>depthBiasClamp</name></param>
+ <param><type>float</type> <name>depthBiasSlopeFactor</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetBlendConstants</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>float</type> <name>blendConstants</name>[4]</param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetDepthBounds</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>float</type> <name>minDepthBounds</name></param>
+ <param><type>float</type> <name>maxDepthBounds</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetStencilCompareMask</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkStencilFaceFlags</type> <name>faceMask</name></param>
+ <param><type>uint32_t</type> <name>compareMask</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetStencilWriteMask</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkStencilFaceFlags</type> <name>faceMask</name></param>
+ <param><type>uint32_t</type> <name>writeMask</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetStencilReference</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkStencilFaceFlags</type> <name>faceMask</name></param>
+ <param><type>uint32_t</type> <name>reference</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdBindDescriptorSets</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkPipelineBindPoint</type> <name>pipelineBindPoint</name></param>
+ <param><type>VkPipelineLayout</type> <name>layout</name></param>
+ <param><type>uint32_t</type> <name>firstSet</name></param>
+ <param><type>uint32_t</type> <name>descriptorSetCount</name></param>
+ <param len="descriptorSetCount">const <type>VkDescriptorSet</type>* <name>pDescriptorSets</name></param>
+ <param optional="true"><type>uint32_t</type> <name>dynamicOffsetCount</name></param>
+ <param len="dynamicOffsetCount">const <type>uint32_t</type>* <name>pDynamicOffsets</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdBindIndexBuffer</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBuffer</type> <name>buffer</name></param>
+ <param><type>VkDeviceSize</type> <name>offset</name></param>
+ <param><type>VkIndexType</type> <name>indexType</name></param>
+ </command>
+ <command queues="graphics" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdBindVertexBuffers</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>firstBinding</name></param>
+ <param><type>uint32_t</type> <name>bindingCount</name></param>
+ <param len="bindingCount">const <type>VkBuffer</type>* <name>pBuffers</name></param>
+ <param len="bindingCount">const <type>VkDeviceSize</type>* <name>pOffsets</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <proto><type>void</type> <name>vkCmdDraw</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>vertexCount</name></param>
+ <param><type>uint32_t</type> <name>instanceCount</name></param>
+ <param><type>uint32_t</type> <name>firstVertex</name></param>
+ <param><type>uint32_t</type> <name>firstInstance</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <proto><type>void</type> <name>vkCmdDrawIndexed</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>indexCount</name></param>
+ <param><type>uint32_t</type> <name>instanceCount</name></param>
+ <param><type>uint32_t</type> <name>firstIndex</name></param>
+ <param><type>int32_t</type> <name>vertexOffset</name></param>
+ <param><type>uint32_t</type> <name>firstInstance</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <proto><type>void</type> <name>vkCmdDrawIndirect</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBuffer</type> <name>buffer</name></param>
+ <param><type>VkDeviceSize</type> <name>offset</name></param>
+ <param><type>uint32_t</type> <name>drawCount</name></param>
+ <param><type>uint32_t</type> <name>stride</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <proto><type>void</type> <name>vkCmdDrawIndexedIndirect</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBuffer</type> <name>buffer</name></param>
+ <param><type>VkDeviceSize</type> <name>offset</name></param>
+ <param><type>uint32_t</type> <name>drawCount</name></param>
+ <param><type>uint32_t</type> <name>stride</name></param>
+ </command>
+ <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="compute">
+ <proto><type>void</type> <name>vkCmdDispatch</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>x</name></param>
+ <param><type>uint32_t</type> <name>y</name></param>
+ <param><type>uint32_t</type> <name>z</name></param>
+ </command>
+ <command queues="compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="compute">
+ <proto><type>void</type> <name>vkCmdDispatchIndirect</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBuffer</type> <name>buffer</name></param>
+ <param><type>VkDeviceSize</type> <name>offset</name></param>
+ </command>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdCopyBuffer</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBuffer</type> <name>srcBuffer</name></param>
+ <param><type>VkBuffer</type> <name>dstBuffer</name></param>
+ <param><type>uint32_t</type> <name>regionCount</name></param>
+ <param len="regionCount">const <type>VkBufferCopy</type>* <name>pRegions</name></param>
+ </command>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdCopyImage</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkImage</type> <name>srcImage</name></param>
+ <param><type>VkImageLayout</type> <name>srcImageLayout</name></param>
+ <param><type>VkImage</type> <name>dstImage</name></param>
+ <param><type>VkImageLayout</type> <name>dstImageLayout</name></param>
+ <param><type>uint32_t</type> <name>regionCount</name></param>
+ <param len="regionCount">const <type>VkImageCopy</type>* <name>pRegions</name></param>
+ </command>
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdBlitImage</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkImage</type> <name>srcImage</name></param>
+ <param><type>VkImageLayout</type> <name>srcImageLayout</name></param>
+ <param><type>VkImage</type> <name>dstImage</name></param>
+ <param><type>VkImageLayout</type> <name>dstImageLayout</name></param>
+ <param><type>uint32_t</type> <name>regionCount</name></param>
+ <param len="regionCount">const <type>VkImageBlit</type>* <name>pRegions</name></param>
+ <param><type>VkFilter</type> <name>filter</name></param>
+ </command>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdCopyBufferToImage</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBuffer</type> <name>srcBuffer</name></param>
+ <param><type>VkImage</type> <name>dstImage</name></param>
+ <param><type>VkImageLayout</type> <name>dstImageLayout</name></param>
+ <param><type>uint32_t</type> <name>regionCount</name></param>
+ <param len="regionCount">const <type>VkBufferImageCopy</type>* <name>pRegions</name></param>
+ </command>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdCopyImageToBuffer</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkImage</type> <name>srcImage</name></param>
+ <param><type>VkImageLayout</type> <name>srcImageLayout</name></param>
+ <param><type>VkBuffer</type> <name>dstBuffer</name></param>
+ <param><type>uint32_t</type> <name>regionCount</name></param>
+ <param len="regionCount">const <type>VkBufferImageCopy</type>* <name>pRegions</name></param>
+ </command>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdUpdateBuffer</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBuffer</type> <name>dstBuffer</name></param>
+ <param><type>VkDeviceSize</type> <name>dstOffset</name></param>
+ <param><type>VkDeviceSize</type> <name>dataSize</name></param>
+ <param len="dataSize">const <type>void</type>* <name>pData</name></param>
+ </command>
+ <command queues="transfer,graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer" comment="transfer support is only available when VK_KHR_maintenance1 is enabled, as documented in valid usage language in the specification">
+ <proto><type>void</type> <name>vkCmdFillBuffer</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBuffer</type> <name>dstBuffer</name></param>
+ <param><type>VkDeviceSize</type> <name>dstOffset</name></param>
+ <param><type>VkDeviceSize</type> <name>size</name></param>
+ <param><type>uint32_t</type> <name>data</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdClearColorImage</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkImage</type> <name>image</name></param>
+ <param><type>VkImageLayout</type> <name>imageLayout</name></param>
+ <param>const <type>VkClearColorValue</type>* <name>pColor</name></param>
+ <param><type>uint32_t</type> <name>rangeCount</name></param>
+ <param len="rangeCount">const <type>VkImageSubresourceRange</type>* <name>pRanges</name></param>
+ </command>
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdClearDepthStencilImage</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkImage</type> <name>image</name></param>
+ <param><type>VkImageLayout</type> <name>imageLayout</name></param>
+ <param>const <type>VkClearDepthStencilValue</type>* <name>pDepthStencil</name></param>
+ <param><type>uint32_t</type> <name>rangeCount</name></param>
+ <param len="rangeCount">const <type>VkImageSubresourceRange</type>* <name>pRanges</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <proto><type>void</type> <name>vkCmdClearAttachments</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>attachmentCount</name></param>
+ <param len="attachmentCount">const <type>VkClearAttachment</type>* <name>pAttachments</name></param>
+ <param><type>uint32_t</type> <name>rectCount</name></param>
+ <param len="rectCount">const <type>VkClearRect</type>* <name>pRects</name></param>
+ </command>
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdResolveImage</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkImage</type> <name>srcImage</name></param>
+ <param><type>VkImageLayout</type> <name>srcImageLayout</name></param>
+ <param><type>VkImage</type> <name>dstImage</name></param>
+ <param><type>VkImageLayout</type> <name>dstImageLayout</name></param>
+ <param><type>uint32_t</type> <name>regionCount</name></param>
+ <param len="regionCount">const <type>VkImageResolve</type>* <name>pRegions</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdSetEvent</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkEvent</type> <name>event</name></param>
+ <param><type>VkPipelineStageFlags</type> <name>stageMask</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdResetEvent</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkEvent</type> <name>event</name></param>
+ <param><type>VkPipelineStageFlags</type> <name>stageMask</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdWaitEvents</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>eventCount</name></param>
+ <param len="eventCount">const <type>VkEvent</type>* <name>pEvents</name></param>
+ <param><type>VkPipelineStageFlags</type> <name>srcStageMask</name></param>
+ <param><type>VkPipelineStageFlags</type> <name>dstStageMask</name></param>
+ <param optional="true"><type>uint32_t</type> <name>memoryBarrierCount</name></param>
+ <param len="memoryBarrierCount">const <type>VkMemoryBarrier</type>* <name>pMemoryBarriers</name></param>
+ <param optional="true"><type>uint32_t</type> <name>bufferMemoryBarrierCount</name></param>
+ <param len="bufferMemoryBarrierCount">const <type>VkBufferMemoryBarrier</type>* <name>pBufferMemoryBarriers</name></param>
+ <param optional="true"><type>uint32_t</type> <name>imageMemoryBarrierCount</name></param>
+ <param len="imageMemoryBarrierCount">const <type>VkImageMemoryBarrier</type>* <name>pImageMemoryBarriers</name></param>
+ </command>
+ <command queues="transfer,graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdPipelineBarrier</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkPipelineStageFlags</type> <name>srcStageMask</name></param>
+ <param><type>VkPipelineStageFlags</type> <name>dstStageMask</name></param>
+ <param optional="true"><type>VkDependencyFlags</type> <name>dependencyFlags</name></param>
+ <param optional="true"><type>uint32_t</type> <name>memoryBarrierCount</name></param>
+ <param len="memoryBarrierCount">const <type>VkMemoryBarrier</type>* <name>pMemoryBarriers</name></param>
+ <param optional="true"><type>uint32_t</type> <name>bufferMemoryBarrierCount</name></param>
+ <param len="bufferMemoryBarrierCount">const <type>VkBufferMemoryBarrier</type>* <name>pBufferMemoryBarriers</name></param>
+ <param optional="true"><type>uint32_t</type> <name>imageMemoryBarrierCount</name></param>
+ <param len="imageMemoryBarrierCount">const <type>VkImageMemoryBarrier</type>* <name>pImageMemoryBarriers</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdBeginQuery</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkQueryPool</type> <name>queryPool</name></param>
+ <param><type>uint32_t</type> <name>query</name></param>
+ <param optional="true"><type>VkQueryControlFlags</type> <name>flags</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdEndQuery</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkQueryPool</type> <name>queryPool</name></param>
+ <param><type>uint32_t</type> <name>query</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdResetQueryPool</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkQueryPool</type> <name>queryPool</name></param>
+ <param><type>uint32_t</type> <name>firstQuery</name></param>
+ <param><type>uint32_t</type> <name>queryCount</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdWriteTimestamp</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkPipelineStageFlagBits</type> <name>pipelineStage</name></param>
+ <param><type>VkQueryPool</type> <name>queryPool</name></param>
+ <param><type>uint32_t</type> <name>query</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="outside" cmdbufferlevel="primary,secondary" pipeline="transfer">
+ <proto><type>void</type> <name>vkCmdCopyQueryPoolResults</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkQueryPool</type> <name>queryPool</name></param>
+ <param><type>uint32_t</type> <name>firstQuery</name></param>
+ <param><type>uint32_t</type> <name>queryCount</name></param>
+ <param><type>VkBuffer</type> <name>dstBuffer</name></param>
+ <param><type>VkDeviceSize</type> <name>dstOffset</name></param>
+ <param><type>VkDeviceSize</type> <name>stride</name></param>
+ <param optional="true"><type>VkQueryResultFlags</type> <name>flags</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdPushConstants</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkPipelineLayout</type> <name>layout</name></param>
+ <param><type>VkShaderStageFlags</type> <name>stageFlags</name></param>
+ <param><type>uint32_t</type> <name>offset</name></param>
+ <param><type>uint32_t</type> <name>size</name></param>
+ <param len="size">const <type>void</type>* <name>pValues</name></param>
+ </command>
+ <command queues="graphics" renderpass="outside" cmdbufferlevel="primary" pipeline="graphics">
+ <proto><type>void</type> <name>vkCmdBeginRenderPass</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkRenderPassBeginInfo</type>* <name>pRenderPassBegin</name></param>
+ <param><type>VkSubpassContents</type> <name>contents</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary" pipeline="graphics">
+ <proto><type>void</type> <name>vkCmdNextSubpass</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkSubpassContents</type> <name>contents</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary" pipeline="graphics">
+ <proto><type>void</type> <name>vkCmdEndRenderPass</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ </command>
+ <command queues="transfer,graphics,compute" renderpass="both" cmdbufferlevel="primary">
+ <proto><type>void</type> <name>vkCmdExecuteCommands</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>uint32_t</type> <name>commandBufferCount</name></param>
+ <param len="commandBufferCount">const <type>VkCommandBuffer</type>* <name>pCommandBuffers</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_NATIVE_WINDOW_IN_USE_KHR">
+ <proto><type>VkResult</type> <name>vkCreateAndroidSurfaceKHR</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param>const <type>VkAndroidSurfaceCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSurfaceKHR</type>* <name>pSurface</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceDisplayPropertiesKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
+ <param optional="true" len="pPropertyCount"><type>VkDisplayPropertiesKHR</type>* <name>pProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceDisplayPlanePropertiesKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
+ <param optional="true" len="pPropertyCount"><type>VkDisplayPlanePropertiesKHR</type>* <name>pProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetDisplayPlaneSupportedDisplaysKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>uint32_t</type> <name>planeIndex</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pDisplayCount</name></param>
+ <param optional="true" len="pDisplayCount"><type>VkDisplayKHR</type>* <name>pDisplays</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetDisplayModePropertiesKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkDisplayKHR</type> <name>display</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
+ <param optional="true" len="pPropertyCount"><type>VkDisplayModePropertiesKHR</type>* <name>pProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INITIALIZATION_FAILED">
+ <proto><type>VkResult</type> <name>vkCreateDisplayModeKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param externsync="true"><type>VkDisplayKHR</type> <name>display</name></param>
+ <param>const <type>VkDisplayModeCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkDisplayModeKHR</type>* <name>pMode</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetDisplayPlaneCapabilitiesKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param externsync="true"><type>VkDisplayModeKHR</type> <name>mode</name></param>
+ <param><type>uint32_t</type> <name>planeIndex</name></param>
+ <param><type>VkDisplayPlaneCapabilitiesKHR</type>* <name>pCapabilities</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateDisplayPlaneSurfaceKHR</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param>const <type>VkDisplaySurfaceCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSurfaceKHR</type>* <name>pSurface</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_INCOMPATIBLE_DISPLAY_KHR,VK_ERROR_DEVICE_LOST,VK_ERROR_SURFACE_LOST_KHR">
+ <proto><type>VkResult</type> <name>vkCreateSharedSwapchainsKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>uint32_t</type> <name>swapchainCount</name></param>
+ <param len="swapchainCount" externsync="pCreateInfos[].surface,pCreateInfos[].oldSwapchain">const <type>VkSwapchainCreateInfoKHR</type>* <name>pCreateInfos</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param len="swapchainCount"><type>VkSwapchainKHR</type>* <name>pSwapchains</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateMirSurfaceKHR</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param>const <type>VkMirSurfaceCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSurfaceKHR</type>* <name>pSurface</name></param>
+ </command>
+ <command>
+ <proto><type>VkBool32</type> <name>vkGetPhysicalDeviceMirPresentationSupportKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>uint32_t</type> <name>queueFamilyIndex</name></param>
+ <param><type>MirConnection</type>* <name>connection</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroySurfaceKHR</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param optional="true" externsync="true"><type>VkSurfaceKHR</type> <name>surface</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceSurfaceSupportKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>uint32_t</type> <name>queueFamilyIndex</name></param>
+ <param><type>VkSurfaceKHR</type> <name>surface</name></param>
+ <param><type>VkBool32</type>* <name>pSupported</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceSurfaceCapabilitiesKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkSurfaceKHR</type> <name>surface</name></param>
+ <param><type>VkSurfaceCapabilitiesKHR</type>* <name>pSurfaceCapabilities</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceSurfaceFormatsKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkSurfaceKHR</type> <name>surface</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pSurfaceFormatCount</name></param>
+ <param optional="true" len="pSurfaceFormatCount"><type>VkSurfaceFormatKHR</type>* <name>pSurfaceFormats</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceSurfacePresentModesKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkSurfaceKHR</type> <name>surface</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPresentModeCount</name></param>
+ <param optional="true" len="pPresentModeCount"><type>VkPresentModeKHR</type>* <name>pPresentModes</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_SURFACE_LOST_KHR,VK_ERROR_NATIVE_WINDOW_IN_USE_KHR">
+ <proto><type>VkResult</type> <name>vkCreateSwapchainKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="pCreateInfo.surface,pCreateInfo.oldSwapchain">const <type>VkSwapchainCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSwapchainKHR</type>* <name>pSwapchain</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroySwapchainKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param optional="true" externsync="true"><type>VkSwapchainKHR</type> <name>swapchain</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetSwapchainImagesKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkSwapchainKHR</type> <name>swapchain</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pSwapchainImageCount</name></param>
+ <param optional="true" len="pSwapchainImageCount"><type>VkImage</type>* <name>pSwapchainImages</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_TIMEOUT,VK_NOT_READY,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR">
+ <proto><type>VkResult</type> <name>vkAcquireNextImageKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkSwapchainKHR</type> <name>swapchain</name></param>
+ <param><type>uint64_t</type> <name>timeout</name></param>
+ <param optional="true" externsync="true"><type>VkSemaphore</type> <name>semaphore</name></param>
+ <param optional="true" externsync="true"><type>VkFence</type> <name>fence</name></param>
+ <param><type>uint32_t</type>* <name>pImageIndex</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR">
+ <proto><type>VkResult</type> <name>vkQueuePresentKHR</name></proto>
+ <param externsync="true"><type>VkQueue</type> <name>queue</name></param>
+ <param externsync="pPresentInfo.pWaitSemaphores[],pPresentInfo.pSwapchains[]">const <type>VkPresentInfoKHR</type>* <name>pPresentInfo</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_NATIVE_WINDOW_IN_USE_KHR">
+ <proto><type>VkResult</type> <name>vkCreateViSurfaceNN</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param>const <type>VkViSurfaceCreateInfoNN</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSurfaceKHR</type>* <name>pSurface</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateWaylandSurfaceKHR</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param>const <type>VkWaylandSurfaceCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSurfaceKHR</type>* <name>pSurface</name></param>
+ </command>
+ <command>
+ <proto><type>VkBool32</type> <name>vkGetPhysicalDeviceWaylandPresentationSupportKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>uint32_t</type> <name>queueFamilyIndex</name></param>
+ <param>struct <type>wl_display</type>* <name>display</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateWin32SurfaceKHR</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param>const <type>VkWin32SurfaceCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSurfaceKHR</type>* <name>pSurface</name></param>
+ </command>
+ <command>
+ <proto><type>VkBool32</type> <name>vkGetPhysicalDeviceWin32PresentationSupportKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>uint32_t</type> <name>queueFamilyIndex</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateXlibSurfaceKHR</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param>const <type>VkXlibSurfaceCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSurfaceKHR</type>* <name>pSurface</name></param>
+ </command>
+ <command>
+ <proto><type>VkBool32</type> <name>vkGetPhysicalDeviceXlibPresentationSupportKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>uint32_t</type> <name>queueFamilyIndex</name></param>
+ <param><type>Display</type>* <name>dpy</name></param>
+ <param><type>VisualID</type> <name>visualID</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateXcbSurfaceKHR</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param>const <type>VkXcbSurfaceCreateInfoKHR</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkSurfaceKHR</type>* <name>pSurface</name></param>
+ </command>
+ <command>
+ <proto><type>VkBool32</type> <name>vkGetPhysicalDeviceXcbPresentationSupportKHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>uint32_t</type> <name>queueFamilyIndex</name></param>
+ <param><type>xcb_connection_t</type>* <name>connection</name></param>
+ <param><type>xcb_visualid_t</type> <name>visual_id</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateDebugReportCallbackEXT</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param>const <type>VkDebugReportCallbackCreateInfoEXT</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkDebugReportCallbackEXT</type>* <name>pCallback</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyDebugReportCallbackEXT</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param externsync="true"><type>VkDebugReportCallbackEXT</type> <name>callback</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDebugReportMessageEXT</name></proto>
+ <param><type>VkInstance</type> <name>instance</name></param>
+ <param><type>VkDebugReportFlagsEXT</type> <name>flags</name></param>
+ <param><type>VkDebugReportObjectTypeEXT</type> <name>objectType</name></param>
+ <param><type>uint64_t</type> <name>object</name></param>
+ <param><type>size_t</type> <name>location</name></param>
+ <param><type>int32_t</type> <name>messageCode</name></param>
+ <param len="null-terminated">const <type>char</type>* <name>pLayerPrefix</name></param>
+ <param len="null-terminated">const <type>char</type>* <name>pMessage</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkDebugMarkerSetObjectNameEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="pNameInfo.object"><type>VkDebugMarkerObjectNameInfoEXT</type>* <name>pNameInfo</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkDebugMarkerSetObjectTagEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="pTagInfo.object"><type>VkDebugMarkerObjectTagInfoEXT</type>* <name>pTagInfo</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdDebugMarkerBeginEXT</name></proto>
+ <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkDebugMarkerMarkerInfoEXT</type>* <name>pMarkerInfo</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdDebugMarkerEndEXT</name></proto>
+ <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="both" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdDebugMarkerInsertEXT</name></proto>
+ <param><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkDebugMarkerMarkerInfoEXT</type>* <name>pMarkerInfo</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_FORMAT_NOT_SUPPORTED">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceExternalImageFormatPropertiesNV</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkFormat</type> <name>format</name></param>
+ <param><type>VkImageType</type> <name>type</name></param>
+ <param><type>VkImageTiling</type> <name>tiling</name></param>
+ <param><type>VkImageUsageFlags</type> <name>usage</name></param>
+ <param optional="true"><type>VkImageCreateFlags</type> <name>flags</name></param>
+ <param optional="true"><type>VkExternalMemoryHandleTypeFlagsNV</type> <name>externalHandleType</name></param>
+ <param><type>VkExternalImageFormatPropertiesNV</type>* <name>pExternalImageFormatProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_TOO_MANY_OBJECTS,VK_ERROR_OUT_OF_HOST_MEMORY">
+ <proto><type>VkResult</type> <name>vkGetMemoryWin32HandleNV</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkDeviceMemory</type> <name>memory</name></param>
+ <param><type>VkExternalMemoryHandleTypeFlagsNV</type> <name>handleType</name></param>
+ <param><type>HANDLE</type>* <name>pHandle</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <proto><type>void</type> <name>vkCmdDrawIndirectCountAMD</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBuffer</type> <name>buffer</name></param>
+ <param><type>VkDeviceSize</type> <name>offset</name></param>
+ <param><type>VkBuffer</type> <name>countBuffer</name></param>
+ <param><type>VkDeviceSize</type> <name>countBufferOffset</name></param>
+ <param><type>uint32_t</type> <name>maxDrawCount</name></param>
+ <param><type>uint32_t</type> <name>stride</name></param>
+ </command>
+ <command queues="graphics" renderpass="inside" cmdbufferlevel="primary,secondary" pipeline="graphics">
+ <proto><type>void</type> <name>vkCmdDrawIndexedIndirectCountAMD</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param><type>VkBuffer</type> <name>buffer</name></param>
+ <param><type>VkDeviceSize</type> <name>offset</name></param>
+ <param><type>VkBuffer</type> <name>countBuffer</name></param>
+ <param><type>VkDeviceSize</type> <name>countBufferOffset</name></param>
+ <param><type>uint32_t</type> <name>maxDrawCount</name></param>
+ <param><type>uint32_t</type> <name>stride</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="inside" cmdbufferlevel="primary,secondary">
+ <proto><type>void</type> <name>vkCmdProcessCommandsNVX</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkCmdProcessCommandsInfoNVX</type>* <name>pProcessCommandsInfo</name></param>
+ </command>
+ <command queues="graphics,compute" renderpass="inside" cmdbufferlevel="secondary">
+ <proto><type>void</type> <name>vkCmdReserveSpaceForCommandsNVX</name></proto>
+ <param externsync="true"><type>VkCommandBuffer</type> <name>commandBuffer</name></param>
+ <param>const <type>VkCmdReserveSpaceForCommandsInfoNVX</type>* <name>pReserveSpaceInfo</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateIndirectCommandsLayoutNVX</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkIndirectCommandsLayoutCreateInfoNVX</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkIndirectCommandsLayoutNVX</type>* <name>pIndirectCommandsLayout</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyIndirectCommandsLayoutNVX</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkIndirectCommandsLayoutNVX</type> <name>indirectCommandsLayout</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkCreateObjectTableNVX</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkObjectTableCreateInfoNVX</type>* <name>pCreateInfo</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkObjectTableNVX</type>* <name>pObjectTable</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkDestroyObjectTableNVX</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkObjectTableNVX</type> <name>objectTable</name></param>
+ <param optional="true">const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkRegisterObjectsNVX</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkObjectTableNVX</type> <name>objectTable</name></param>
+ <param><type>uint32_t</type> <name>objectCount</name></param>
+ <param len="objectCount">const <type>VkObjectTableEntryNVX</type>* const* <name>ppObjectTableEntries</name></param>
+ <param len="objectCount">const <type>uint32_t</type>* <name>pObjectIndices</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
+ <proto><type>VkResult</type> <name>vkUnregisterObjectsNVX</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkObjectTableNVX</type> <name>objectTable</name></param>
+ <param><type>uint32_t</type> <name>objectCount</name></param>
+ <param len="objectCount">const <type>VkObjectEntryTypeNVX</type>* <name>pObjectEntryTypes</name></param>
+ <param len="objectCount">const <type>uint32_t</type>* <name>pObjectIndices</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkDeviceGeneratedCommandsFeaturesNVX</type>* <name>pFeatures</name></param>
+ <param><type>VkDeviceGeneratedCommandsLimitsNVX</type>* <name>pLimits</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceFeatures2KHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkPhysicalDeviceFeatures2KHR</type>* <name>pFeatures</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceProperties2KHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkPhysicalDeviceProperties2KHR</type>* <name>pProperties</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceFormatProperties2KHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkFormat</type> <name>format</name></param>
+ <param><type>VkFormatProperties2KHR</type>* <name>pFormatProperties</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_FORMAT_NOT_SUPPORTED">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceImageFormatProperties2KHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param>const <type>VkPhysicalDeviceImageFormatInfo2KHR</type>* <name>pImageFormatInfo</name></param>
+ <param><type>VkImageFormatProperties2KHR</type>* <name>pImageFormatProperties</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceQueueFamilyProperties2KHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pQueueFamilyPropertyCount</name></param>
+ <param optional="true" len="pQueueFamilyPropertyCount"><type>VkQueueFamilyProperties2KHR</type>* <name>pQueueFamilyProperties</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceMemoryProperties2KHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkPhysicalDeviceMemoryProperties2KHR</type>* <name>pMemoryProperties</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkGetPhysicalDeviceSparseImageFormatProperties2KHR</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param>const <type>VkPhysicalDeviceSparseImageFormatInfo2KHR</type>* <name>pFormatInfo</name></param>
+ <param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
+ <param optional="true" len="pPropertyCount"><type>VkSparseImageFormatProperties2KHR</type>* <name>pProperties</name></param>
+ </command>
+ <command>
+ <proto><type>void</type> <name>vkTrimCommandPoolKHR</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param externsync="true"><type>VkCommandPool</type> <name>commandPool</name></param>
+ <param optional="true"><type>VkCommandPoolTrimFlagsKHR</type> <name>flags</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS">
+ <proto><type>VkResult</type> <name>vkReleaseDisplayEXT</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkDisplayKHR</type> <name>display</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS">
+ <proto><type>VkResult</type> <name>vkAcquireXlibDisplayEXT</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>Display</type>* <name>dpy</name></param>
+ <param><type>VkDisplayKHR</type> <name>display</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS">
+ <proto><type>VkResult</type> <name>vkGetRandROutputDisplayEXT</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>Display</type>* <name>dpy</name></param>
+ <param><type>RROutput</type> <name>rrOutput</name></param>
+ <param><type>VkDisplayKHR</type>* <name>pDisplay</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS">
+ <proto><type>VkResult</type> <name>vkDisplayPowerControlEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkDisplayKHR</type> <name>display</name></param>
+ <param>const <type>VkDisplayPowerInfoEXT</type>* <name>pDisplayPowerInfo</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS">
+ <proto><type>VkResult</type> <name>vkRegisterDeviceEventEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param>const <type>VkDeviceEventInfoEXT</type>* <name>pDeviceEventInfo</name></param>
+ <param>const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkFence</type>* <name>pFence</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS">
+ <proto><type>VkResult</type> <name>vkRegisterDisplayEventEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkDisplayKHR</type> <name>display</name></param>
+ <param>const <type>VkDisplayEventInfoEXT</type>* <name>pDisplayEventInfo</name></param>
+ <param>const <type>VkAllocationCallbacks</type>* <name>pAllocator</name></param>
+ <param><type>VkFence</type>* <name>pFence</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR">
+ <proto><type>VkResult</type> <name>vkGetSwapchainCounterEXT</name></proto>
+ <param><type>VkDevice</type> <name>device</name></param>
+ <param><type>VkSwapchainKHR</type> <name>swapchain</name></param>
+ <param><type>VkSurfaceCounterFlagBitsEXT</type> <name>counter</name></param>
+ <param><type>uint64_t</type>* <name>pCounterValue</name></param>
+ </command>
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
+ <proto><type>VkResult</type> <name>vkGetPhysicalDeviceSurfaceCapabilities2EXT</name></proto>
+ <param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
+ <param><type>VkSurfaceKHR</type> <name>surface</name></param>
+ <param><type>VkSurfaceCapabilities2EXT</type>* <name>pSurfaceCapabilities</name></param>
+ </command>
+ </commands>
+
+ <!-- SECTION: Vulkan API interface definitions -->
+ <feature api="vulkan" name="VK_VERSION_1_0" number="1.0">
+ <require comment="Header boilerplate">
+ <type name="vk_platform"/>
+ </require>
+ <require comment="API version">
+ <type name="VK_API_VERSION"/>
+ <type name="VK_API_VERSION_1_0"/>
+ <type name="VK_VERSION_MAJOR"/>
+ <type name="VK_VERSION_MINOR"/>
+ <type name="VK_VERSION_PATCH"/>
+ <type name="VK_HEADER_VERSION"/>
+ </require>
+ <require comment="API constants">
+ <enum name="VK_LOD_CLAMP_NONE"/>
+ <enum name="VK_REMAINING_MIP_LEVELS"/>
+ <enum name="VK_REMAINING_ARRAY_LAYERS"/>
+ <enum name="VK_WHOLE_SIZE"/>
+ <enum name="VK_ATTACHMENT_UNUSED"/>
+ <enum name="VK_TRUE"/>
+ <enum name="VK_FALSE"/>
+ <type name="VK_NULL_HANDLE"/>
+ <enum name="VK_QUEUE_FAMILY_IGNORED"/>
+ <enum name="VK_SUBPASS_EXTERNAL"/>
+ <type name="VkPipelineCacheHeaderVersion"/>
+ </require>
+ <require comment="Device initialization">
+ <command name="vkCreateInstance"/>
+ <command name="vkDestroyInstance"/>
+ <command name="vkEnumeratePhysicalDevices"/>
+ <command name="vkGetPhysicalDeviceFeatures"/>
+ <command name="vkGetPhysicalDeviceFormatProperties"/>
+ <command name="vkGetPhysicalDeviceImageFormatProperties"/>
+ <command name="vkGetPhysicalDeviceProperties"/>
+ <command name="vkGetPhysicalDeviceQueueFamilyProperties"/>
+ <command name="vkGetPhysicalDeviceMemoryProperties"/>
+ <command name="vkGetInstanceProcAddr"/>
+ <command name="vkGetDeviceProcAddr"/>
+ </require>
+ <require comment="Device commands">
+ <command name="vkCreateDevice"/>
+ <command name="vkDestroyDevice"/>
+ </require>
+ <require comment="Extension discovery commands">
+ <command name="vkEnumerateInstanceExtensionProperties"/>
+ <command name="vkEnumerateDeviceExtensionProperties"/>
+ </require>
+ <require comment="Layer discovery commands">
+ <command name="vkEnumerateInstanceLayerProperties"/>
+ <command name="vkEnumerateDeviceLayerProperties"/>
+ </require>
+ <require comment="queue commands">
+ <command name="vkGetDeviceQueue"/>
+ <command name="vkQueueSubmit"/>
+ <command name="vkQueueWaitIdle"/>
+ <command name="vkDeviceWaitIdle"/>
+ </require>
+ <require comment="Memory commands">
+ <command name="vkAllocateMemory"/>
+ <command name="vkFreeMemory"/>
+ <command name="vkMapMemory"/>
+ <command name="vkUnmapMemory"/>
+ <command name="vkFlushMappedMemoryRanges"/>
+ <command name="vkInvalidateMappedMemoryRanges"/>
+ <command name="vkGetDeviceMemoryCommitment"/>
+ </require>
+ <require comment="Memory management API commands">
+ <command name="vkBindBufferMemory"/>
+ <command name="vkBindImageMemory"/>
+ <command name="vkGetBufferMemoryRequirements"/>
+ <command name="vkGetImageMemoryRequirements"/>
+ </require>
+ <require comment="Sparse resource memory management API commands">
+ <command name="vkGetImageSparseMemoryRequirements"/>
+ <command name="vkGetPhysicalDeviceSparseImageFormatProperties"/>
+ <command name="vkQueueBindSparse"/>
+ </require>
+ <require comment="Fence commands">
+ <command name="vkCreateFence"/>
+ <command name="vkDestroyFence"/>
+ <command name="vkResetFences"/>
+ <command name="vkGetFenceStatus"/>
+ <command name="vkWaitForFences"/>
+ </require>
+ <require comment="Queue semaphore commands">
+ <command name="vkCreateSemaphore"/>
+ <command name="vkDestroySemaphore"/>
+ </require>
+ <require comment="Event commands">
+ <command name="vkCreateEvent"/>
+ <command name="vkDestroyEvent"/>
+ <command name="vkGetEventStatus"/>
+ <command name="vkSetEvent"/>
+ <command name="vkResetEvent"/>
+ </require>
+ <require comment="Query commands">
+ <command name="vkCreateQueryPool"/>
+ <command name="vkDestroyQueryPool"/>
+ <command name="vkGetQueryPoolResults"/>
+ </require>
+ <require comment="Buffer commands">
+ <command name="vkCreateBuffer"/>
+ <command name="vkDestroyBuffer"/>
+ </require>
+ <require comment="Buffer view commands">
+ <command name="vkCreateBufferView"/>
+ <command name="vkDestroyBufferView"/>
+ </require>
+ <require comment="Image commands">
+ <command name="vkCreateImage"/>
+ <command name="vkDestroyImage"/>
+ <command name="vkGetImageSubresourceLayout"/>
+ </require>
+ <require comment="Image view commands">
+ <command name="vkCreateImageView"/>
+ <command name="vkDestroyImageView"/>
+ </require>
+ <require comment="Shader commands">
+ <command name="vkCreateShaderModule"/>
+ <command name="vkDestroyShaderModule"/>
+ </require>
+ <require comment="Pipeline Cache commands">
+ <command name="vkCreatePipelineCache"/>
+ <command name="vkDestroyPipelineCache"/>
+ <command name="vkGetPipelineCacheData"/>
+ <command name="vkMergePipelineCaches"/>
+ </require>
+ <require comment="Pipeline commands">
+ <command name="vkCreateGraphicsPipelines"/>
+ <command name="vkCreateComputePipelines"/>
+ <command name="vkDestroyPipeline"/>
+ </require>
+ <require comment="Pipeline layout commands">
+ <command name="vkCreatePipelineLayout"/>
+ <command name="vkDestroyPipelineLayout"/>
+ </require>
+ <require comment="Sampler commands">
+ <command name="vkCreateSampler"/>
+ <command name="vkDestroySampler"/>
+ </require>
+ <require comment="Descriptor set commands">
+ <command name="vkCreateDescriptorSetLayout"/>
+ <command name="vkDestroyDescriptorSetLayout"/>
+ <command name="vkCreateDescriptorPool"/>
+ <command name="vkDestroyDescriptorPool"/>
+ <command name="vkResetDescriptorPool"/>
+ <command name="vkAllocateDescriptorSets"/>
+ <command name="vkFreeDescriptorSets"/>
+ <command name="vkUpdateDescriptorSets"/>
+ </require>
+ <require comment="Pass commands">
+ <command name="vkCreateFramebuffer"/>
+ <command name="vkDestroyFramebuffer"/>
+ <command name="vkCreateRenderPass"/>
+ <command name="vkDestroyRenderPass"/>
+ <command name="vkGetRenderAreaGranularity"/>
+ </require>
+ <require comment="Command pool commands">
+ <command name="vkCreateCommandPool"/>
+ <command name="vkDestroyCommandPool"/>
+ <command name="vkResetCommandPool"/>
+ </require>
+ <require comment="Command buffer commands">
+ <command name="vkAllocateCommandBuffers"/>
+ <command name="vkFreeCommandBuffers"/>
+ <command name="vkBeginCommandBuffer"/>
+ <command name="vkEndCommandBuffer"/>
+ <command name="vkResetCommandBuffer"/>
+ </require>
+ <require comment="Command buffer building commands">
+ <command name="vkCmdBindPipeline"/>
+ <command name="vkCmdSetViewport"/>
+ <command name="vkCmdSetScissor"/>
+ <command name="vkCmdSetLineWidth"/>
+ <command name="vkCmdSetDepthBias"/>
+ <command name="vkCmdSetBlendConstants"/>
+ <command name="vkCmdSetDepthBounds"/>
+ <command name="vkCmdSetStencilCompareMask"/>
+ <command name="vkCmdSetStencilWriteMask"/>
+ <command name="vkCmdSetStencilReference"/>
+ <command name="vkCmdBindDescriptorSets"/>
+ <command name="vkCmdBindIndexBuffer"/>
+ <command name="vkCmdBindVertexBuffers"/>
+ <command name="vkCmdDraw"/>
+ <command name="vkCmdDrawIndexed"/>
+ <command name="vkCmdDrawIndirect"/>
+ <command name="vkCmdDrawIndexedIndirect"/>
+ <command name="vkCmdDispatch"/>
+ <command name="vkCmdDispatchIndirect"/>
+ <command name="vkCmdCopyBuffer"/>
+ <command name="vkCmdCopyImage"/>
+ <command name="vkCmdBlitImage"/>
+ <command name="vkCmdCopyBufferToImage"/>
+ <command name="vkCmdCopyImageToBuffer"/>
+ <command name="vkCmdUpdateBuffer"/>
+ <command name="vkCmdFillBuffer"/>
+ <command name="vkCmdClearColorImage"/>
+ <command name="vkCmdClearDepthStencilImage"/>
+ <command name="vkCmdClearAttachments"/>
+ <command name="vkCmdResolveImage"/>
+ <command name="vkCmdSetEvent"/>
+ <command name="vkCmdResetEvent"/>
+ <command name="vkCmdWaitEvents"/>
+ <command name="vkCmdPipelineBarrier"/>
+ <command name="vkCmdBeginQuery"/>
+ <command name="vkCmdEndQuery"/>
+ <command name="vkCmdResetQueryPool"/>
+ <command name="vkCmdWriteTimestamp"/>
+ <command name="vkCmdCopyQueryPoolResults"/>
+ <command name="vkCmdPushConstants"/>
+ <command name="vkCmdBeginRenderPass"/>
+ <command name="vkCmdNextSubpass"/>
+ <command name="vkCmdEndRenderPass"/>
+ <command name="vkCmdExecuteCommands"/>
+ </require>
+ <require comment="Types not directly used by the API">
+ <!-- Include <type name="typename"/> here for e.g. structs that
+ are not parameter types of commands, but still need to be
+ defined in the API.
+ -->
+ <type name="VkBufferMemoryBarrier"/>
+ <type name="VkDispatchIndirectCommand"/>
+ <type name="VkDrawIndexedIndirectCommand"/>
+ <type name="VkDrawIndirectCommand"/>
+ <type name="VkImageMemoryBarrier"/>
+ <type name="VkMemoryBarrier"/>
+ </require>
+ </feature>
+
+ <!-- SECTION: Vulkan extension interface definitions -->
+ <extensions>
+ <!-- WSI extensions -->
+ <extension name="VK_KHR_surface" number="1" type="instance" supported="vulkan">
+ <require>
+ <enum value="25" name="VK_KHR_SURFACE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_surface&quot;" name="VK_KHR_SURFACE_EXTENSION_NAME"/>
+ <enum offset="0" dir="-" extends="VkResult" name="VK_ERROR_SURFACE_LOST_KHR"/>
+ <enum offset="1" dir="-" extends="VkResult" name="VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"/>
+ <enum value="VK_COLOR_SPACE_SRGB_NONLINEAR_KHR" name="VK_COLORSPACE_SRGB_NONLINEAR_KHR"/>
+ <command name="vkDestroySurfaceKHR"/>
+ <command name="vkGetPhysicalDeviceSurfaceSupportKHR"/>
+ <command name="vkGetPhysicalDeviceSurfaceCapabilitiesKHR"/>
+ <command name="vkGetPhysicalDeviceSurfaceFormatsKHR"/>
+ <command name="vkGetPhysicalDeviceSurfacePresentModesKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_swapchain" number="2" type="device" requires="VK_KHR_surface" supported="vulkan">
+ <require>
+ <enum value="68" name="VK_KHR_SWAPCHAIN_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_swapchain&quot;" name="VK_KHR_SWAPCHAIN_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PRESENT_INFO_KHR"/>
+ <enum offset="2" extends="VkImageLayout" name="VK_IMAGE_LAYOUT_PRESENT_SRC_KHR"/>
+ <enum offset="3" extends="VkResult" name="VK_SUBOPTIMAL_KHR"/>
+ <enum offset="4" dir="-" extends="VkResult" name="VK_ERROR_OUT_OF_DATE_KHR"/>
+ <command name="vkCreateSwapchainKHR"/>
+ <command name="vkDestroySwapchainKHR"/>
+ <command name="vkGetSwapchainImagesKHR"/>
+ <command name="vkAcquireNextImageKHR"/>
+ <command name="vkQueuePresentKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_display" number="3" type="instance" requires="VK_KHR_surface" supported="vulkan">
+ <require>
+ <enum value="21" name="VK_KHR_DISPLAY_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_display&quot;" name="VK_KHR_DISPLAY_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_MODE_CREATE_INFO_KHR"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR"/>
+ <type name="VkDisplayPlaneAlphaFlagsKHR"/>
+ <type name="VkDisplayPlaneAlphaFlagBitsKHR"/>
+ <type name="VkDisplayPropertiesKHR"/>
+ <type name="VkDisplayModeParametersKHR"/>
+ <type name="VkDisplayModePropertiesKHR"/>
+ <type name="VkDisplayModeCreateInfoKHR"/>
+ <type name="VkDisplayPlaneCapabilitiesKHR"/>
+ <type name="VkDisplayPlanePropertiesKHR"/>
+ <type name="VkDisplaySurfaceCreateInfoKHR"/>
+ <command name="vkGetPhysicalDeviceDisplayPropertiesKHR"/>
+ <command name="vkGetPhysicalDeviceDisplayPlanePropertiesKHR"/>
+ <command name="vkGetDisplayPlaneSupportedDisplaysKHR"/>
+ <command name="vkGetDisplayModePropertiesKHR"/>
+ <command name="vkCreateDisplayModeKHR"/>
+ <command name="vkGetDisplayPlaneCapabilitiesKHR"/>
+ <command name="vkCreateDisplayPlaneSurfaceKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_display_swapchain" number="4" type="device" requires="VK_KHR_swapchain,VK_KHR_display" supported="vulkan">
+ <require>
+ <enum value="9" name="VK_KHR_DISPLAY_SWAPCHAIN_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_display_swapchain&quot;" name="VK_KHR_DISPLAY_SWAPCHAIN_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_PRESENT_INFO_KHR"/>
+ <enum offset="1" dir="-" extends="VkResult" name="VK_ERROR_INCOMPATIBLE_DISPLAY_KHR"/>
+ <type name="VkDisplayPresentInfoKHR"/>
+ <command name="vkCreateSharedSwapchainsKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_xlib_surface" number="5" type="instance" requires="VK_KHR_surface" protect="VK_USE_PLATFORM_XLIB_KHR" supported="vulkan">
+ <require>
+ <enum value="6" name="VK_KHR_XLIB_SURFACE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_xlib_surface&quot;" name="VK_KHR_XLIB_SURFACE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR"/>
+ <type name="VkXlibSurfaceCreateFlagsKHR"/>
+ <type name="VkXlibSurfaceCreateInfoKHR"/>
+ <command name="vkCreateXlibSurfaceKHR"/>
+ <command name="vkGetPhysicalDeviceXlibPresentationSupportKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_xcb_surface" number="6" type="instance" requires="VK_KHR_surface" protect="VK_USE_PLATFORM_XCB_KHR" supported="vulkan">
+ <require>
+ <enum value="6" name="VK_KHR_XCB_SURFACE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_xcb_surface&quot;" name="VK_KHR_XCB_SURFACE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR"/>
+ <type name="VkXcbSurfaceCreateFlagsKHR"/>
+ <type name="VkXcbSurfaceCreateInfoKHR"/>
+ <command name="vkCreateXcbSurfaceKHR"/>
+ <command name="vkGetPhysicalDeviceXcbPresentationSupportKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_wayland_surface" number="7" type="instance" requires="VK_KHR_surface" protect="VK_USE_PLATFORM_WAYLAND_KHR" supported="vulkan">
+ <require>
+ <enum value="5" name="VK_KHR_WAYLAND_SURFACE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_wayland_surface&quot;" name="VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR"/>
+ <type name="VkWaylandSurfaceCreateFlagsKHR"/>
+ <type name="VkWaylandSurfaceCreateInfoKHR"/>
+ <command name="vkCreateWaylandSurfaceKHR"/>
+ <command name="vkGetPhysicalDeviceWaylandPresentationSupportKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_mir_surface" number="8" type="instance" requires="VK_KHR_surface" protect="VK_USE_PLATFORM_MIR_KHR" supported="vulkan">
+ <require>
+ <enum value="4" name="VK_KHR_MIR_SURFACE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_mir_surface&quot;" name="VK_KHR_MIR_SURFACE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR"/>
+ <type name="VkMirSurfaceCreateFlagsKHR"/>
+ <type name="VkMirSurfaceCreateInfoKHR"/>
+ <command name="vkCreateMirSurfaceKHR"/>
+ <command name="vkGetPhysicalDeviceMirPresentationSupportKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_android_surface" number="9" type="instance" requires="VK_KHR_surface" protect="VK_USE_PLATFORM_ANDROID_KHR" supported="vulkan">
+ <require>
+ <enum value="6" name="VK_KHR_ANDROID_SURFACE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_android_surface&quot;" name="VK_KHR_ANDROID_SURFACE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR"/>
+ <type name="VkAndroidSurfaceCreateFlagsKHR"/>
+ <type name="VkAndroidSurfaceCreateInfoKHR"/>
+ <command name="vkCreateAndroidSurfaceKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_win32_surface" number="10" type="instance" requires="VK_KHR_surface" protect="VK_USE_PLATFORM_WIN32_KHR" supported="vulkan">
+ <require>
+ <enum value="5" name="VK_KHR_WIN32_SURFACE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_win32_surface&quot;" name="VK_KHR_WIN32_SURFACE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR"/>
+ <type name="VkWin32SurfaceCreateFlagsKHR"/>
+ <type name="VkWin32SurfaceCreateInfoKHR"/>
+ <command name="vkCreateWin32SurfaceKHR"/>
+ <command name="vkGetPhysicalDeviceWin32PresentationSupportKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_ANDROID_native_buffer" number="11" supported="disabled">
+ <require>
+ <enum value="4" name="VK_ANDROID_NATIVE_BUFFER_SPEC_VERSION"/>
+ <enum value="11" name="VK_ANDROID_NATIVE_BUFFER_NUMBER"/>
+ <enum value="&quot;VK_ANDROID_native_buffer&quot;" name="VK_ANDROID_NATIVE_BUFFER_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_debug_report" number="12" type="instance" author="Google, Inc." contact="Courtney Goeltzenleuchter @courtney" supported="vulkan">
+ <require>
+ <enum value="4" name="VK_EXT_DEBUG_REPORT_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_debug_report&quot;" name="VK_EXT_DEBUG_REPORT_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT"/>
+ <enum offset="1" dir="-" extends="VkResult" name="VK_ERROR_VALIDATION_FAILED_EXT"/>
+ <enum value="VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT" name="VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT"/>
+ <type name="VkDebugReportObjectTypeEXT"/>
+ <type name="VkDebugReportErrorEXT"/>
+ <command name="vkCreateDebugReportCallbackEXT"/>
+ <command name="vkDestroyDebugReportCallbackEXT"/>
+ <command name="vkDebugReportMessageEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_glsl_shader" number="13" type="device" author="NVIDIA" contact="Piers Daniell @pdaniell" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_NV_GLSL_SHADER_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_glsl_shader&quot;" name="VK_NV_GLSL_SHADER_EXTENSION_NAME"/>
+ <enum offset="0" dir="-" extends="VkResult" name="VK_ERROR_INVALID_SHADER_NV"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_1" number="14" author="NVIDIA" contact="Piers Daniell @pdaniell" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_1_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_1&quot;" name="VK_NV_EXTENSION_1_EXTENSION_NAME"/>
+ <enum offset="0" dir="-" extends="VkResult" name="VK_NV_EXTENSION_1_ERROR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_sampler_mirror_clamp_to_edge" type="device" number="15" author="KHR" contact="Tobias Hector @tobias" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_sampler_mirror_clamp_to_edge&quot;" name="VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME"/>
+ <enum value="4" extends="VkSamplerAddressMode" name="VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE" comment="Note that this defines what was previously a core enum, and so uses the 'value' attribute rather than 'offset', and does not have a suffix. This is a special case, and should not be repeated"/>
+ </require>
+ </extension>
+ <extension name="VK_IMG_filter_cubic" number="16" type="device" author="IMG" contact="Tobias Hector @tobias" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_IMG_FILTER_CUBIC_SPEC_VERSION"/>
+ <enum value="&quot;VK_IMG_filter_cubic&quot;" name="VK_IMG_FILTER_CUBIC_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkFilter" name="VK_FILTER_CUBIC_IMG"/>
+ <enum bitpos="13" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG" comment="Format can be filtered with VK_FILTER_CUBIC_IMG when being sampled"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_17" number="17" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_17_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_17&quot;" name="VK_AMD_EXTENSION_17_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_18" number="18" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_18_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_18&quot;" name="VK_AMD_EXTENSION_18_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_rasterization_order" number="19" type="device" author="AMD" contact="Daniel Rakos @aqnuep" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_AMD_RASTERIZATION_ORDER_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_rasterization_order&quot;" name="VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_RASTERIZATION_ORDER_AMD"/>
+ <type name="VkRasterizationOrderAMD"/>
+ <type name="VkPipelineRasterizationStateRasterizationOrderAMD"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_20" number="20" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_20_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_20&quot;" name="VK_AMD_EXTENSION_20_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_shader_trinary_minmax" number="21" type="device" author="AMD" contact="quentin.lin@amd.com" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_shader_trinary_minmax&quot;" name="VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_shader_explicit_vertex_parameter" number="22" type="device" author="AMD" contact="quentin.lin@amd.com" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_shader_explicit_vertex_parameter&quot;" name="VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_debug_marker" number="23" type="device" author="Baldur Karlsson" contact="baldurk@baldurk.org" supported="vulkan">
+ <require>
+ <enum value="3" name="VK_EXT_DEBUG_MARKER_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_debug_marker&quot;" name="VK_EXT_DEBUG_MARKER_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT"/>
+ <type name="VkDebugMarkerObjectNameInfoEXT"/>
+ <type name="VkDebugMarkerObjectTagInfoEXT"/>
+ <type name="VkDebugMarkerMarkerInfoEXT"/>
+ <command name="vkDebugMarkerSetObjectTagEXT"/>
+ <command name="vkDebugMarkerSetObjectNameEXT"/>
+ <command name="vkCmdDebugMarkerBeginEXT"/>
+ <command name="vkCmdDebugMarkerEndEXT"/>
+ <command name="vkCmdDebugMarkerInsertEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_24" number="24" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_24_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_24&quot;" name="VK_AMD_EXTENSION_24_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_25" number="25" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_25_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_25&quot;" name="VK_AMD_EXTENSION_25_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_gcn_shader" number="26" type="device" author="AMD" contact="dominik.witczak@amd.com" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_AMD_GCN_SHADER_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_gcn_shader&quot;" name="VK_AMD_GCN_SHADER_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_dedicated_allocation" number="27" type="device" author="NVIDIA" contact="Jeff Bolz @jbolz" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_NV_DEDICATED_ALLOCATION_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_dedicated_allocation&quot;" name="VK_NV_DEDICATED_ALLOCATION_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_IMAGE_CREATE_INFO_NV"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_BUFFER_CREATE_INFO_NV"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEDICATED_ALLOCATION_MEMORY_ALLOCATE_INFO_NV"/>
+ <type name="VkDedicatedAllocationImageCreateInfoNV"/>
+ <type name="VkDedicatedAllocationBufferCreateInfoNV"/>
+ <type name="VkDedicatedAllocationMemoryAllocateInfoNV"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_28" number="28" author="NVIDIA" contact="Piers Daniell @pdaniell" supported="disabled">
+ <require>
+ <enum value="0" name="VK_EXT_EXTENSION_28_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_28&quot;" name="VK_EXT_EXTENSION_28_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NVX_extension_29" number="29" author="NVIDIA" contact="Jeff Juliano @jjuliano" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NVX_EXTENSION_29_SPEC_VERSION"/>
+ <enum value="&quot;VK_NVX_extension_29&quot;" name="VK_NVX_EXTENSION_29_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NVX_extension_30" number="30" author="NVIDIA" contact="Jeff Juliano @jjuliano" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NVX_EXTENSION_30_SPEC_VERSION"/>
+ <enum value="&quot;VK_NVX_extension_30&quot;" name="VK_NVX_EXTENSION_30_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NVX_extension_31" number="31" author="NVIDIA" contact="Jeff Juliano @jjuliano" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NVX_EXTENSION_31_SPEC_VERSION"/>
+ <enum value="&quot;VK_NVX_extension_31&quot;" name="VK_NVX_EXTENSION_31_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_32" number="32" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_32_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_32&quot;" name="VK_AMD_EXTENSION_32_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_33" number="33" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_33_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_33&quot;" name="VK_AMD_EXTENSION_33_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_draw_indirect_count" number="34" type="device" author="AMD" contact="Daniel Rakos @aqnuep" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_AMD_DRAW_INDIRECT_COUNT_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_draw_indirect_count&quot;" name="VK_AMD_DRAW_INDIRECT_COUNT_EXTENSION_NAME"/>
+ <command name="vkCmdDrawIndirectCountAMD"/>
+ <command name="vkCmdDrawIndexedIndirectCountAMD"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_35" number="35" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_35_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_35&quot;" name="VK_AMD_EXTENSION_35_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_negative_viewport_height" number="36" type="device" author="AMD" contact="Matthaeus G. Chajdas @anteru" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_negative_viewport_height&quot;" name="VK_AMD_NEGATIVE_VIEWPORT_HEIGHT_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_gpu_shader_half_float" number="37" type="device" author="AMD" contact="Dominik Witczak @dominikwitczak_amd" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_AMD_GPU_SHADER_HALF_FLOAT_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_gpu_shader_half_float&quot;" name="VK_AMD_GPU_SHADER_HALF_FLOAT_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_shader_ballot" number="38" type="device" author="AMD" contact="Dominik Witczak @dominikwitczak_amd" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_AMD_SHADER_BALLOT_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_shader_ballot&quot;" name="VK_AMD_SHADER_BALLOT_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_39" number="39" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_39_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_39&quot;" name="VK_AMD_EXTENSION_39_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_40" number="40" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_40_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_40&quot;" name="VK_AMD_EXTENSION_40_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_41" number="41" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_41_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_41&quot;" name="VK_AMD_EXTENSION_41_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_42" number="42" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_42_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_42&quot;" name="VK_AMD_EXTENSION_42_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_43" number="43" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_43_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_43&quot;" name="VK_AMD_EXTENSION_43_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_44" number="44" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_44_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_44&quot;" name="VK_AMD_EXTENSION_44_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_45" number="45" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_45_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_45&quot;" name="VK_AMD_EXTENSION_45_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_46" number="46" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_46_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_46&quot;" name="VK_AMD_EXTENSION_46_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_AMD_extension_47" number="47" author="AMD" contact="Daniel Rakos @aqnuep" supported="disabled">
+ <require>
+ <enum value="0" name="VK_AMD_EXTENSION_47_SPEC_VERSION"/>
+ <enum value="&quot;VK_AMD_extension_47&quot;" name="VK_AMD_EXTENSION_47_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NVX_extension_48" number="48" author="NVIDIA" contact="James Jones @cubanismo" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NVX_EXTENSION_48_SPEC_VERSION"/>
+ <enum value="&quot;VK_NVX_extension_48&quot;" name="VK_NVX_EXTENSION_48_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GOOGLE_extension_49" number="49" author="GOOGLE" contact="Jean-Francois Roy @jfroy" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GOOGLE_EXTENSION_49_SPEC_VERSION"/>
+ <enum value="&quot;VK_GOOGLE_extension_49&quot;" name="VK_GOOGLE_EXTENSION_49_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_GOOGLE_extension_50" number="50" author="GOOGLE" contact="Jean-Francois Roy @jfroy" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GOOGLE_EXTENSION_50_SPEC_VERSION"/>
+ <enum value="&quot;VK_GOOGLE_extension_50&quot;" name="VK_GOOGLE_EXTENSION_50_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NVX_extension_51" number="51" author="NVIDIA" contact="James Jones @cubanismo" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NVX_EXTENSION_51_SPEC_VERSION"/>
+ <enum value="&quot;VK_NVX_extension_51&quot;" name="VK_NVX_EXTENSION_51_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NVX_extension_52" number="52" author="NVIDIA" contact="James Jones @cubanismo" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NVX_EXTENSION_52_SPEC_VERSION"/>
+ <enum value="&quot;VK_NVX_extension_52&quot;" name="VK_NVX_EXTENSION_52_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_53" number="53" author="NVIDIA" contact="Jeff Bolz @jbolz" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_53_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_53&quot;" name="VK_NV_EXTENSION_53_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_54" number="54" author="NVIDIA" contact="Jeff Bolz @jbolz" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_54_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_54&quot;" name="VK_NV_EXTENSION_54_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_IMG_format_pvrtc" number="55" type="device" author="IMG" contact="Tobias Hector @tobias" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_IMG_FORMAT_PVRTC_SPEC_VERSION"/>
+ <enum value="&quot;VK_IMG_format_pvrtc&quot;" name="VK_IMG_FORMAT_PVRTC_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkFormat" name="VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG"/>
+ <enum offset="1" extends="VkFormat" name="VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG"/>
+ <enum offset="2" extends="VkFormat" name="VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG"/>
+ <enum offset="3" extends="VkFormat" name="VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG"/>
+ <enum offset="4" extends="VkFormat" name="VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG"/>
+ <enum offset="5" extends="VkFormat" name="VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG"/>
+ <enum offset="6" extends="VkFormat" name="VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG"/>
+ <enum offset="7" extends="VkFormat" name="VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_external_memory_capabilities" number="56" type="instance" author="NVIDIA" contact="James jones @cubanismo" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_external_memory_capabilities&quot;" name="VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME"/>
+ <type name="VkExternalMemoryHandleTypeFlagsNV"/>
+ <type name="VkExternalMemoryHandleTypeFlagBitsNV"/>
+ <type name="VkExternalMemoryFeatureFlagsNV"/>
+ <type name="VkExternalMemoryFeatureFlagBitsNV"/>
+ <type name="VkExternalImageFormatPropertiesNV"/>
+ <command name="vkGetPhysicalDeviceExternalImageFormatPropertiesNV"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_external_memory" number="57" type="device" requires="VK_NV_external_memory_capabilities" author="NVIDIA" contact="James jones @cubanismo" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_NV_EXTERNAL_MEMORY_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_external_memory&quot;" name="VK_NV_EXTERNAL_MEMORY_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_NV"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_NV"/>
+ <type name="VkExternalMemoryImageCreateInfoNV"/>
+ <type name="VkExportMemoryAllocateInfoNV"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_external_memory_win32" number="58" type="device" requires="VK_NV_external_memory_capabilities,VK_NV_external_memory" author="NVIDIA" contact="James jones @cubanismo" protect="VK_USE_PLATFORM_WIN32_KHR" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_NV_EXTERNAL_MEMORY_WIN32_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_external_memory_win32&quot;" name="VK_NV_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_NV"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_EXPORT_MEMORY_WIN32_HANDLE_INFO_NV"/>
+ <type name="VkImportMemoryWin32HandleInfoNV"/>
+ <type name="VkExportMemoryWin32HandleInfoNV"/>
+ <command name="vkGetMemoryWin32HandleNV"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_win32_keyed_mutex" number="59" type="device" requires="VK_NV_external_memory_capabilities,VK_NV_external_memory_win32" author="NVIDIA" contact="Carsten Rohde" protect="VK_USE_PLATFORM_WIN32_KHR" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_NV_WIN32_KEYED_MUTEX_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_win32_keyed_mutex&quot;" name="VK_NV_WIN32_KEYED_MUTEX_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_WIN32_KEYED_MUTEX_ACQUIRE_RELEASE_INFO_NV"/>
+ <type name="VkWin32KeyedMutexAcquireReleaseInfoNV"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_get_physical_device_properties2" number="60" author="KHR" contact="Jeff Bolz @jbolz" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_get_physical_device_properties2&quot;" name="VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2_KHR"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2_KHR"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2_KHR"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR"/>
+ <enum offset="6" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR"/>
+ <enum offset="7" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SPARSE_IMAGE_FORMAT_PROPERTIES_2_KHR"/>
+ <enum offset="8" extends="VkStructureType" name="VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SPARSE_IMAGE_FORMAT_INFO_2_KHR"/>
+ <type name="VkPhysicalDeviceFeatures2KHR"/>
+ <type name="VkPhysicalDeviceProperties2KHR"/>
+ <type name="VkFormatProperties2KHR"/>
+ <type name="VkImageFormatProperties2KHR"/>
+ <type name="VkPhysicalDeviceImageFormatInfo2KHR"/>
+ <type name="VkQueueFamilyProperties2KHR"/>
+ <type name="VkPhysicalDeviceMemoryProperties2KHR"/>
+ <type name="VkSparseImageFormatProperties2KHR"/>
+ <type name="VkPhysicalDeviceSparseImageFormatInfo2KHR"/>
+ <command name="vkGetPhysicalDeviceFeatures2KHR"/>
+ <command name="vkGetPhysicalDeviceProperties2KHR"/>
+ <command name="vkGetPhysicalDeviceFormatProperties2KHR"/>
+ <command name="vkGetPhysicalDeviceImageFormatProperties2KHR"/>
+ <command name="vkGetPhysicalDeviceQueueFamilyProperties2KHR"/>
+ <command name="vkGetPhysicalDeviceMemoryProperties2KHR"/>
+ <command name="vkGetPhysicalDeviceSparseImageFormatProperties2KHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_61" number="61" author="KHR" contact="Jeff Bolz @jbolz" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_61_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_61&quot;" name="VK_KHR_EXTENSION_61_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_validation_flags" number="62" type="instance" author="Google, Inc." contact="Tobin Ehlis @tobine" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_VALIDATION_FLAGS_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_validation_flags&quot;" name="VK_EXT_VALIDATION_FLAGS_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT"/>
+ <type name="VkValidationFlagsEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_NN_vi_surface" number="63" author="NN" contact="Mathias Heyer @mheyer" type="instance" requires="VK_KHR_surface" protect="VK_USE_PLATFORM_VI_NN" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_NN_VI_SURFACE_SPEC_VERSION"/>
+ <enum value="&quot;VK_NN_vi_surface&quot;" name="VK_NN_VI_SURFACE_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_VI_SURFACE_CREATE_INFO_NN"/>
+ <type name="VkViSurfaceCreateFlagsNN"/>
+ <type name="VkViSurfaceCreateInfoNN"/>
+ <command name="vkCreateViSurfaceNN"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_shader_draw_parameters" number="64" type="device" author="KHR" contact="Daniel Koch @dgkoch" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_KHR_SHADER_DRAW_PARAMETERS_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_shader_draw_parameters&quot;" name="VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_shader_subgroup_ballot" number="65" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_SHADER_SUBGROUP_BALLOT_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_shader_subgroup_ballot&quot;" name="VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_shader_subgroup_vote" number="66" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_SHADER_SUBGROUP_VOTE_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_shader_subgroup_vote&quot;" name="VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_ARM_extension_01" number="67" type="device" author="ARM" contact="Jan-Harald Fredriksen @janharald" supported="disabled">
+ <require>
+ <enum value="0" name="VK_ARM_EXTENSION_01_SPEC_VERSION"/>
+ <enum value="&quot;VK_ARM_extension_01&quot;" name="VK_ARM_EXTENSION_01_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_ARM_extension_02" number="68" type="device" author="ARM" contact="Jan-Harald Fredriksen @janharald" supported="disabled">
+ <require>
+ <enum value="0" name="VK_ARM_EXTENSION_02_SPEC_VERSION"/>
+ <enum value="&quot;VK_ARM_extension_02&quot;" name="VK_ARM_EXTENSION_02_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_IMG_extension_69" number="69" type="device" author="IMG" contact="Tobias Hector @tobias" supported="disabled">
+ <require>
+ <enum value="0" name="VK_IMG_EXTENSION_69_SPEC_VERSION"/>
+ <enum value="&quot;VK_IMG_extension_69&quot;" name="VK_IMG_EXTENSION_69_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_maintenance1" number="70" author="KHR" contact="Piers Daniell @pdaniell" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_KHR_MAINTENANCE1_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_maintenance1&quot;" name="VK_KHR_MAINTENANCE1_EXTENSION_NAME"/>
+ <enum offset="0" dir="-" extends="VkResult" name="VK_ERROR_OUT_OF_POOL_MEMORY_KHR"/>
+ <enum bitpos="14" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR" comment="Format can be used as the source image of image transfer commands"/>
+ <enum bitpos="15" extends="VkFormatFeatureFlagBits" name="VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR" comment="Format can be used as the destination image of image transfer commands"/>
+ <enum bitpos="5" extends="VkImageCreateFlagBits" name="VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT_KHR" comment="The 3D image can be viewed as a 2D or 2D array image"/>
+ <command name="vkTrimCommandPoolKHR"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_71" number="71" author="KHR" contact="Jeff Bolz @jbolz" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_71_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_71&quot;" name="VK_KHR_EXTENSION_71_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_72" number="72" author="KHR" contact="James Jones @cubanismo" supported="disable">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_72_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_72&quot;" name="VK_KHR_EXTENSION_72_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_73" number="73" author="KHR" contact="James Jones @cubanismo" supported="disable">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_73_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_73&quot;" name="VK_KHR_EXTENSION_73_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_74" number="74" author="KHR" contact="James Jones @cubanismo" supported="disable">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_74_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_74&quot;" name="VK_KHR_EXTENSION_74_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_75" number="75" author="KHR" contact="James Jones @cubanismo" supported="disable">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_75_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_75&quot;" name="VK_KHR_EXTENSION_75_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_76" number="76" author="KHR" contact="James Jones @cubanismo" supported="disable">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_76_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_76&quot;" name="VK_KHR_EXTENSION_76_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_77" number="77" author="KHR" contact="James Jones @cubanismo" supported="disable">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_77_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_77&quot;" name="VK_KHR_EXTENSION_77_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_78" number="78" author="KHR" contact="James Jones @cubanismo" supported="disable">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_78_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_78&quot;" name="VK_KHR_EXTENSION_78_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_79" number="79" author="KHR" contact="James Jones @cubanismo" supported="disable">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_79_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_79&quot;" name="VK_KHR_EXTENSION_79_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_80" number="80" author="KHR" contact="James Jones @cubanismo" supported="disable">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_80_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_80&quot;" name="VK_KHR_EXTENSION_80_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_81" number="81" author="KHR" contact="Jeff Bolz @jbolz" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_81_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_81&quot;" name="VK_KHR_EXTENSION_81_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_82" number="82" author="KHR" contact="Jeff Bolz @jbolz" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_82_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_82&quot;" name="VK_KHR_EXTENSION_82_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_83" number="83" author="KHR" contact="Jan-Harald Fredriksen @janharald" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_83_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_83&quot;" name="VK_KHR_EXTENSION_83_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_84" number="84" author="KHR" contact="Jan-Harald Fredriksen @janharald" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_84_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_84&quot;" name="VK_KHR_EXTENSION_84_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_85" number="85" author="KHR" contact="Ian Elliott @ianelliott" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_85_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_85&quot;" name="VK_KHR_EXTENSION_85_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_86" number="86" author="KHR" contact="Markus Tavenrath @mtavenrath" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_86_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_86&quot;" name="VK_KHR_EXTENSION_86_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NVX_device_generated_commands" number="87" type="device" author="NVIDIA" contact="Christoph Kubisch @pixeljetstream" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_NVX_DEVICE_GENERATED_COMMANDS_SPEC_VERSION"/>
+ <enum value="&quot;VK_NVX_device_generated_commands&quot;" name="VK_NVX_DEVICE_GENERATED_COMMANDS_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_OBJECT_TABLE_CREATE_INFO_NVX"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_INDIRECT_COMMANDS_LAYOUT_CREATE_INFO_NVX"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_CMD_PROCESS_COMMANDS_INFO_NVX"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_CMD_RESERVE_SPACE_FOR_COMMANDS_INFO_NVX"/>
+ <enum offset="4" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_LIMITS_NVX"/>
+ <enum offset="5" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_GENERATED_COMMANDS_FEATURES_NVX"/>
+ <enum bitpos="17" extends="VkPipelineStageFlagBits" name="VK_PIPELINE_STAGE_COMMAND_PROCESS_BIT_NVX"/>
+ <enum bitpos="17" extends="VkAccessFlagBits" name="VK_ACCESS_COMMAND_PROCESS_READ_BIT_NVX"/>
+ <enum bitpos="18" extends="VkAccessFlagBits" name="VK_ACCESS_COMMAND_PROCESS_WRITE_BIT_NVX"/>
+ <type name="VkObjectTableNVX"/>
+ <type name="VkIndirectCommandsLayoutNVX"/>
+ <type name="VkIndirectCommandsLayoutUsageFlagsNVX"/>
+ <type name="VkObjectEntryUsageFlagsNVX"/>
+ <type name="VkIndirectCommandsLayoutUsageFlagBitsNVX"/>
+ <type name="VkIndirectCommandsTokenTypeNVX"/>
+ <type name="VkObjectEntryUsageFlagBitsNVX"/>
+ <type name="VkObjectEntryTypeNVX"/>
+ <type name="VkDeviceGeneratedCommandsFeaturesNVX"/>
+ <type name="VkDeviceGeneratedCommandsLimitsNVX"/>
+ <type name="VkIndirectCommandsTokenNVX"/>
+ <type name="VkIndirectCommandsLayoutTokenNVX"/>
+ <type name="VkIndirectCommandsLayoutCreateInfoNVX"/>
+ <type name="VkCmdProcessCommandsInfoNVX"/>
+ <type name="VkCmdReserveSpaceForCommandsInfoNVX"/>
+ <type name="VkObjectTableCreateInfoNVX"/>
+ <type name="VkObjectTableEntryNVX"/>
+ <type name="VkObjectTablePipelineEntryNVX"/>
+ <type name="VkObjectTableDescriptorSetEntryNVX"/>
+ <type name="VkObjectTableVertexBufferEntryNVX"/>
+ <type name="VkObjectTableIndexBufferEntryNVX"/>
+ <type name="VkObjectTablePushConstantEntryNVX"/>
+ <command name="vkCmdProcessCommandsNVX"/>
+ <command name="vkCmdReserveSpaceForCommandsNVX"/>
+ <command name="vkCreateIndirectCommandsLayoutNVX"/>
+ <command name="vkDestroyIndirectCommandsLayoutNVX"/>
+ <command name="vkCreateObjectTableNVX"/>
+ <command name="vkDestroyObjectTableNVX"/>
+ <command name="vkRegisterObjectsNVX"/>
+ <command name="vkUnregisterObjectsNVX"/>
+ <command name="vkGetPhysicalDeviceGeneratedCommandsPropertiesNVX"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_88" number="88" author="NV" contact="Eric Werness @ewerness" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_88_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_88&quot;" name="VK_KHR_EXTENSION_88_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_direct_mode_display" number="89" type="instance" requires="VK_KHR_display" author="NVIDIA" contact="James Jones @cubanismo" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_DIRECT_MODE_DISPLAY_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_direct_mode_display&quot;" name="VK_EXT_DIRECT_MODE_DISPLAY_EXTENSION_NAME"/>
+ <command name="vkReleaseDisplayEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_acquire_xlib_display" number="90" type="instance" requires="VK_EXT_direct_mode_display,VK_KHR_display" author="NVIDIA" contact="James Jones @cubanismo" protect="VK_USE_PLATFORM_XLIB_XRANDR_EXT" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_ACQUIRE_XLIB_DISPLAY_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_acquire_xlib_display&quot;" name="VK_EXT_ACQUIRE_XLIB_DISPLAY_EXTENSION_NAME"/>
+ <command name="vkAcquireXlibDisplayEXT"/>
+ <command name="vkGetRandROutputDisplayEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_display_surface_counter" number="91" type="instance" requires="VK_KHR_display" author="NVIDIA" contact="James Jones @cubanismo" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_DISPLAY_SURFACE_COUNTER_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_display_surface_counter&quot;" name="VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES2_EXT"/>
+ <type name="VkSurfaceCounterFlagsEXT"/>
+ <type name="VkSurfaceCounterFlagBitsEXT"/>
+ <type name="VkSurfaceCapabilities2EXT"/>
+ <command name="vkGetPhysicalDeviceSurfaceCapabilities2EXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_display_control" number="92" type="device" requires="VK_KHR_display,VK_EXT_display_surface_counter,VK_KHR_swapchain" author="NVIDIA" contact="James Jones @cubanismo" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_EXT_DISPLAY_CONTROL_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_display_control&quot;" name="VK_EXT_DISPLAY_CONTROL_EXTENSION_NAME"/>
+ <enum offset="0" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_POWER_INFO_EXT"/>
+ <enum offset="1" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DEVICE_EVENT_INFO_EXT"/>
+ <enum offset="2" extends="VkStructureType" name="VK_STRUCTURE_TYPE_DISPLAY_EVENT_INFO_EXT"/>
+ <enum offset="3" extends="VkStructureType" name="VK_STRUCTURE_TYPE_SWAPCHAIN_COUNTER_CREATE_INFO_EXT"/>
+ <type name="VkDisplayPowerStateEXT"/>
+ <type name="VkDeviceEventTypeEXT"/>
+ <type name="VkDisplayEventTypeEXT"/>
+ <type name="VkDisplayPowerInfoEXT"/>
+ <type name="VkDeviceEventInfoEXT"/>
+ <type name="VkDisplayEventInfoEXT"/>
+ <type name="VkSwapchainCounterCreateInfoEXT"/>
+ <command name="vkDisplayPowerControlEXT"/>
+ <command name="vkRegisterDeviceEventEXT"/>
+ <command name="vkRegisterDisplayEventEXT"/>
+ <command name="vkGetSwapchainCounterEXT"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_93" number="93" author="GOOGLE" contact="Ian Elliott @ianelliott" supported="disabled">
+ <require>
+ <enum value="0" name="VK_GOOGLE_EXTENSION_93_SPEC_VERSION"/>
+ <enum value="&quot;VK_GOOGLE_extension_93&quot;" name="VK_GOOGLE_EXTENSION_93_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_94" number="94" author="Codeplay" contact="Neil Henning @neil_henning" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_94_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_94&quot;" name="VK_KHR_EXTENSION_94_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_95" number="95" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_95_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_95&quot;" name="VK_NV_EXTENSION_95_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_96" number="96" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_96_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_96&quot;" name="VK_NV_EXTENSION_96_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_97" number="97" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_97_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_97&quot;" name="VK_NV_EXTENSION_97_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_98" number="98" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_98_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_98&quot;" name="VK_NV_EXTENSION_98_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_99" number="99" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_99_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_99&quot;" name="VK_NV_EXTENSION_99_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_100" number="100" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_100_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_100&quot;" name="VK_NV_EXTENSION_100_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_101" number="101" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_101_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_101&quot;" name="VK_NV_EXTENSION_101_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_102" number="102" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_102_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_102&quot;" name="VK_NV_EXTENSION_102_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_103" number="103" author="NVIDIA" contact="Daniel Koch @dgkoch" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_103_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_103&quot;" name="VK_NV_EXTENSION_103_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_NV_extension_104" number="104" author="NVIDIA" contact="Mathias Schott @mschott" supported="disabled">
+ <require>
+ <enum value="0" name="VK_NV_EXTENSION_104_SPEC_VERSION"/>
+ <enum value="&quot;VK_NV_extension_104&quot;" name="VK_NV_EXTENSION_104_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_swapchain_colorspace" number="105" author="GOOGLE" contact="Courtney Goeltzenleuchter @courtneygo" requires="VK_KHR_surface" supported="vulkan">
+ <require>
+ <enum value="1" name="VK_SWAPCHAIN_COLOR_SPACE_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_swapchain_colorspace&quot;" name="VK_SWAPCHAIN_COLOR_SPACE_EXTENSION_NAME"/>
+ <enum offset="1" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_DISPLAY_P3_LINEAR_EXT"/>
+ <enum offset="2" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_DISPLAY_P3_NONLINEAR_EXT"/>
+ <enum offset="3" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_SCRGB_LINEAR_EXT"/>
+ <enum offset="4" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_SCRGB_NONLINEAR_EXT"/>
+ <enum offset="5" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_DCI_P3_LINEAR_EXT"/>
+ <enum offset="6" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_DCI_P3_NONLINEAR_EXT"/>
+ <enum offset="7" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_BT709_LINEAR_EXT"/>
+ <enum offset="8" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_BT709_NONLINEAR_EXT"/>
+ <enum offset="9" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_BT2020_LINEAR_EXT"/>
+ <enum offset="10" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_BT2020_NONLINEAR_EXT"/>
+ <enum offset="11" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_ADOBERGB_LINEAR_EXT"/>
+ <enum offset="12" extends="VkColorSpaceKHR" name="VK_COLOR_SPACE_ADOBERGB_NONLINEAR_EXT"/>
+ </require>
+ </extension>
+ <extension name="VK_EXT_extension_106" number="106" author="GOOGLE" contact="Courtney Goeltzenleuchter @courtneygo" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_106_SPEC_VERSION"/>
+ <enum value="&quot;VK_EXT_extension_106&quot;" name="VK_KHR_EXTENSION_106_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_IMG_extension_107" number="107" author="IMG" contact="Michael Worcester @michaelworcester" supported="disabled">
+ <require>
+ <enum value="0" name="VK_IMG_EXTENSION_107_SPEC_VERSION"/>
+ <enum value="&quot;VK_IMG_extension_107&quot;" name="VK_IMG_EXTENSION_107_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_IMG_extension_108" number="108" author="IMG" contact="Michael Worcester @michaelworcester" supported="disabled">
+ <require>
+ <enum value="0" name="VK_IMG_EXTENSION_108_SPEC_VERSION"/>
+ <enum value="&quot;VK_IMG_extension_108&quot;" name="VK_IMG_EXTENSION_108_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_IMG_extension_109" number="109" author="IMG" contact="Michael Worcester @michaelworcester" supported="disabled">
+ <require>
+ <enum value="0" name="VK_IMG_EXTENSION_109_SPEC_VERSION"/>
+ <enum value="&quot;VK_IMG_extension_109&quot;" name="VK_IMG_EXTENSION_109_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_IMG_extension_110" number="110" author="IMG" contact="Michael Worcester @michaelworcester" supported="disabled">
+ <require>
+ <enum value="0" name="VK_IMG_EXTENSION_110_SPEC_VERSION"/>
+ <enum value="&quot;VK_IMG_extension_110&quot;" name="VK_IMG_EXTENSION_110_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_IMG_extension_111" number="111" author="IMG" contact="Michael Worcester @michaelworcester" supported="disabled">
+ <require>
+ <enum value="0" name="VK_IMG_EXTENSION_111_SPEC_VERSION"/>
+ <enum value="&quot;VK_IMG_extension_111&quot;" name="VK_IMG_EXTENSION_111_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_112" number="112" author="KHR" contact="Alon Or-bach @alonorbach" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_112_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_112&quot;" name="VK_KHR_EXTENSION_112_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_113" number="113" author="KHX" contact="Cass Everitt @casseveritt" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_113_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_113&quot;" name="VK_KHR_EXTENSION_113_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_114" number="114" author="KHX" contact="Cass Everitt @casseveritt" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_114_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_114&quot;" name="VK_KHR_EXTENSION_114_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_115" number="115" author="KHX" contact="Cass Everitt @casseveritt" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_115_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_115&quot;" name="VK_KHR_EXTENSION_115_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_116" number="116" author="KHX" contact="Cass Everitt @casseveritt" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_116_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_116&quot;" name="VK_KHR_EXTENSION_116_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ <extension name="VK_KHR_extension_117" number="117" author="KHR" contact="Kenneth Benzie @kbenzie" supported="disabled">
+ <require>
+ <enum value="0" name="VK_KHR_EXTENSION_117_SPEC_VERSION"/>
+ <enum value="&quot;VK_KHR_extension_117&quot;" name="VK_KHR_EXTENSION_117_EXTENSION_NAME"/>
+ </require>
+ </extension>
+ </extensions>
+</registry>
diff --git a/src/gui/vulkan/vulkan.pri b/src/gui/vulkan/vulkan.pri
new file mode 100644
index 0000000000..9bd7391235
--- /dev/null
+++ b/src/gui/vulkan/vulkan.pri
@@ -0,0 +1,55 @@
+qtConfig(vulkan) {
+ CONFIG += generated_privates
+
+ HEADERS += \
+ vulkan/qvulkaninstance.h \
+ vulkan/qplatformvulkaninstance.h \
+ vulkan/qvulkanwindow.h \
+ vulkan/qvulkanwindow_p.h
+
+ SOURCES += \
+ vulkan/qvulkaninstance.cpp \
+ vulkan/qplatformvulkaninstance.cpp \
+ vulkan/qvulkanfunctions.cpp \
+ vulkan/qvulkanwindow.cpp
+
+ # Applications must inherit the Vulkan header include path.
+ QMAKE_USE += vulkan/nolink
+}
+
+# Generate qvulkanfunctions.h, qvulkanfunctions_p.h, qvulkanfunctions_p.cpp
+QMAKE_QVKGEN_INPUT = vulkan/vk.xml
+QMAKE_QVKGEN_LICENSE_HEADER = $$QT_SOURCE_TREE/header.LGPL
+qtPrepareTool(QMAKE_QVKGEN, qvkgen)
+
+qvkgen_h.commands = $$QMAKE_QVKGEN ${QMAKE_FILE_IN} $$shell_quote($$QMAKE_QVKGEN_LICENSE_HEADER) ${QMAKE_FILE_OUT_PATH}/${QMAKE_FILE_OUT_BASE}
+qvkgen_h.output = $$OUT_PWD/vulkan/qvulkanfunctions.h
+qvkgen_h.input = QMAKE_QVKGEN_INPUT
+qtConfig(vulkan): \
+ qvkgen_h.variable_out = HEADERS
+else: \
+ qvkgen_h.CONFIG += target_predeps no_link
+QMAKE_EXTRA_COMPILERS += qvkgen_h
+
+qvkgen_ph.commands = $$escape_expand(\\n)
+qvkgen_ph.output = $$OUT_PWD/vulkan/qvulkanfunctions_p.h
+qvkgen_ph.input = QMAKE_QVKGEN_INPUT
+qvkgen_ph.depends += $$OUT_PWD/vulkan/qvulkanfunctions.h
+qtConfig(vulkan): \
+ qvkgen_ph.variable_out = HEADERS
+else: \
+ qvkgen_ph.CONFIG += target_predeps no_link
+QMAKE_EXTRA_COMPILERS += qvkgen_ph
+
+qvkgen_pimpl.commands = $$escape_expand(\\n)
+qvkgen_pimpl.output = $$OUT_PWD/vulkan/qvulkanfunctions_p.cpp
+qvkgen_pimpl.input = QMAKE_QVKGEN_INPUT
+qvkgen_pimpl.depends += $$OUT_PWD/vulkan/qvulkanfunctions_p.h
+qtConfig(vulkan): \
+ qvkgen_pimpl.variable_out = SOURCES
+else: \
+ qvkgen_pimpl.CONFIG += target_predeps no_link
+QMAKE_EXTRA_COMPILERS += qvkgen_pimpl
+
+# Ensure qvulkanfunctions.h gets installed correctly
+targ_headers.CONFIG += no_check_exist
diff --git a/src/network/access/access.pri b/src/network/access/access.pri
index 13d52ea44a..4281a870a7 100644
--- a/src/network/access/access.pri
+++ b/src/network/access/access.pri
@@ -41,7 +41,8 @@ HEADERS += \
access/qnetworkfile_p.h \
access/qhttp2protocolhandler_p.h \
access/qhsts_p.h \
- access/qhstspolicy.h
+ access/qhstspolicy.h \
+ access/qhstsstore_p.h
SOURCES += \
access/qftp.cpp \
@@ -76,7 +77,8 @@ SOURCES += \
access/qnetworkfile.cpp \
access/qhttp2protocolhandler.cpp \
access/qhsts.cpp \
- access/qhstspolicy.cpp
+ access/qhstspolicy.cpp \
+ access/qhstsstore.cpp
mac: LIBS_PRIVATE += -framework Security
diff --git a/src/network/access/qhsts.cpp b/src/network/access/qhsts.cpp
index ca9f3b977b..6a731afc2f 100644
--- a/src/network/access/qhsts.cpp
+++ b/src/network/access/qhsts.cpp
@@ -37,6 +37,7 @@
**
****************************************************************************/
+#include "qhstsstore_p.h"
#include "qhsts_p.h"
#include "QtCore/private/qipaddress_p.h"
@@ -80,14 +81,24 @@ void QHstsCache::updateFromHeaders(const QList<QPair<QByteArray, QByteArray>> &h
return;
QHstsHeaderParser parser;
- if (parser.parse(headers))
+ if (parser.parse(headers)) {
updateKnownHost(url.host(), parser.expirationDate(), parser.includeSubDomains());
+ if (hstsStore)
+ hstsStore->synchronize();
+ }
}
void QHstsCache::updateFromPolicies(const QVector<QHstsPolicy> &policies)
{
for (const auto &policy : policies)
updateKnownHost(policy.host(), policy.expiry(), policy.includesSubDomains());
+
+ if (hstsStore && policies.size()) {
+ // These policies are coming either from store or from QNAM's setter
+ // function. As a result we can notice expired or new policies, time
+ // to sync ...
+ hstsStore->synchronize();
+ }
}
void QHstsCache::updateKnownHost(const QUrl &url, const QDateTime &expires,
@@ -97,6 +108,8 @@ void QHstsCache::updateKnownHost(const QUrl &url, const QDateTime &expires,
return;
updateKnownHost(url.host(), expires, includeSubDomains);
+ if (hstsStore)
+ hstsStore->synchronize();
}
void QHstsCache::updateKnownHost(const QString &host, const QDateTime &expires,
@@ -124,13 +137,20 @@ void QHstsCache::updateKnownHost(const QString &host, const QDateTime &expires,
}
knownHosts.insert(pos, hostName, newPolicy);
+ if (hstsStore)
+ hstsStore->addToObserved(newPolicy);
return;
}
if (newPolicy.isExpired())
knownHosts.erase(pos);
- else
+ else if (*pos != newPolicy)
*pos = std::move(newPolicy);
+ else
+ return;
+
+ if (hstsStore)
+ hstsStore->addToObserved(newPolicy);
}
bool QHstsCache::isKnownHost(const QUrl &url) const
@@ -165,10 +185,15 @@ bool QHstsCache::isKnownHost(const QUrl &url) const
while (nameToTest.fragment.size()) {
auto const pos = knownHosts.find(nameToTest);
if (pos != knownHosts.end()) {
- if (pos.value().isExpired())
+ if (pos.value().isExpired()) {
knownHosts.erase(pos);
- else if (!superDomainMatch || pos.value().includesSubDomains())
+ if (hstsStore) {
+ // Inform our store that this policy has expired.
+ hstsStore->addToObserved(pos.value());
+ }
+ } else if (!superDomainMatch || pos.value().includesSubDomains()) {
return true;
+ }
}
const int dot = nameToTest.fragment.indexOf(QLatin1Char('.'));
@@ -196,6 +221,34 @@ QVector<QHstsPolicy> QHstsCache::policies() const
return values;
}
+void QHstsCache::setStore(QHstsStore *store)
+{
+ // Caller retains ownership of store, which must outlive this cache.
+ if (store != hstsStore) {
+ hstsStore = store;
+
+ if (!hstsStore)
+ return;
+
+ // First we augment our store with the policies we already know about
+ // (and thus the cached policy takes priority over whatever policy we
+ // had in the store for the same host, if any).
+ if (knownHosts.size()) {
+ const QVector<QHstsPolicy> observed(policies());
+ for (const auto &policy : observed)
+ hstsStore->addToObserved(policy);
+ hstsStore->synchronize();
+ }
+
+ // Now we update the cache with anything we have not observed yet, but
+ // the store knows about (well, it can happen we synchronize again as a
+ // result if some policies managed to expire or if we add a new one
+ // from the store to cache):
+ const QVector<QHstsPolicy> restored(store->readPolicies());
+ updateFromPolicies(restored);
+ }
+}
+
// The parser is quite simple: 'nextToken' knowns exactly what kind of tokens
// are valid and it will return false if something else was found; then
// we immediately stop parsing. 'parseDirective' knows how these tokens can
diff --git a/src/network/access/qhsts_p.h b/src/network/access/qhsts_p.h
index ab3ca536fb..2feb73b446 100644
--- a/src/network/access/qhsts_p.h
+++ b/src/network/access/qhsts_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+#include <QtNetwork/private/qtnetworkglobal_p.h>
+
#include <QtNetwork/qhstspolicy.h>
#include <QtCore/qbytearray.h>
@@ -66,6 +68,8 @@ QT_BEGIN_NAMESPACE
template<typename T> class QList;
template <typename T> class QVector;
+class QHstsStore;
+
class Q_AUTOTEST_EXPORT QHstsCache
{
public:
@@ -80,6 +84,8 @@ public:
QVector<QHstsPolicy> policies() const;
+ void setStore(QHstsStore *store);
+
private:
void updateKnownHost(const QString &hostName, const QDateTime &expires,
@@ -112,6 +118,7 @@ private:
};
mutable QMap<HostName, QHstsPolicy> knownHosts;
+ QHstsStore *hstsStore = nullptr;
};
class Q_AUTOTEST_EXPORT QHstsHeaderParser
diff --git a/src/network/access/qhstsstore.cpp b/src/network/access/qhstsstore.cpp
new file mode 100644
index 0000000000..239a52b7a4
--- /dev/null
+++ b/src/network/access/qhstsstore.cpp
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhstsstore_p.h"
+#include "qhstspolicy.h"
+
+#include "qstandardpaths.h"
+#include "qdatastream.h"
+#include "qbytearray.h"
+#include "qdatetime.h"
+#include "qvariant.h"
+#include "qstring.h"
+#include "qdir.h"
+
+#include <utility>
+
+QT_BEGIN_NAMESPACE
+
+static QString host_name_to_settings_key(const QString &hostName)
+{
+ const QByteArray hostNameAsHex(hostName.toUtf8().toHex());
+ return QString::fromLatin1(hostNameAsHex);
+}
+
+static QString settings_key_to_host_name(const QString &key)
+{
+ const QByteArray hostNameAsUtf8(QByteArray::fromHex(key.toLatin1()));
+ return QString::fromUtf8(hostNameAsUtf8);
+}
+
+QHstsStore::QHstsStore(const QString &dirName)
+ : store(absoluteFilePath(dirName), QSettings::IniFormat)
+{
+ // Disable fallbacks, we do not want to use anything but our own ini file.
+ store.setFallbacksEnabled(false);
+}
+
+QHstsStore::~QHstsStore()
+{
+ synchronize();
+}
+
+QVector<QHstsPolicy> QHstsStore::readPolicies()
+{
+ // This function only attempts to read policies, making no decision about
+ // expired policies. It's up to a user (QHstsCache) to mark these policies
+ // for deletion and sync the store later. But we immediately remove keys/values
+ // (if the store isWritable) for the policies that we fail to read.
+ QVector<QHstsPolicy> policies;
+
+ beginHstsGroups();
+
+ const QStringList keys = store.childKeys();
+ for (const auto &key : keys) {
+ QHstsPolicy restoredPolicy;
+ if (deserializePolicy(key, restoredPolicy)) {
+ restoredPolicy.setHost(settings_key_to_host_name(key));
+ policies.push_back(std::move(restoredPolicy));
+ } else if (isWritable()) {
+ evictPolicy(key);
+ }
+ }
+
+ endHstsGroups();
+
+ return policies;
+}
+
+void QHstsStore::addToObserved(const QHstsPolicy &policy)
+{
+ observedPolicies.push_back(policy);
+}
+
+void QHstsStore::synchronize()
+{
+ if (!isWritable())
+ return;
+
+ if (observedPolicies.size()) {
+ beginHstsGroups();
+ for (const QHstsPolicy &policy : observedPolicies) {
+ const QString key(host_name_to_settings_key(policy.host()));
+ // If we fail to write a new, updated policy, we also remove the old one.
+ if (policy.isExpired() || !serializePolicy(key, policy))
+ evictPolicy(key);
+ }
+ observedPolicies.clear();
+ endHstsGroups();
+ }
+
+ store.sync();
+}
+
+bool QHstsStore::isWritable() const
+{
+ return store.isWritable();
+}
+
+QString QHstsStore::absoluteFilePath(const QString &dirName)
+{
+ const QDir dir(dirName.isEmpty() ? QStandardPaths::writableLocation(QStandardPaths::CacheLocation)
+ : dirName);
+ return dir.absoluteFilePath(QLatin1String("hstsstore"));
+}
+
+void QHstsStore::beginHstsGroups()
+{
+ store.beginGroup(QLatin1String("StrictTransportSecurity"));
+ store.beginGroup(QLatin1String("Policies"));
+}
+
+void QHstsStore::endHstsGroups()
+{
+ store.endGroup();
+ store.endGroup();
+}
+
+bool QHstsStore::deserializePolicy(const QString &key, QHstsPolicy &policy)
+{
+ Q_ASSERT(store.contains(key));
+
+ const QVariant data(store.value(key));
+ if (data.isNull() || !data.canConvert<QByteArray>())
+ return false;
+
+ const QByteArray serializedData(data.toByteArray());
+ QDataStream streamer(serializedData);
+ qint64 expiryInMS = 0;
+ streamer >> expiryInMS;
+ if (streamer.status() != QDataStream::Ok)
+ return false;
+ bool includesSubDomains = false;
+ streamer >> includesSubDomains;
+ if (streamer.status() != QDataStream::Ok)
+ return false;
+
+ policy.setExpiry(QDateTime::fromMSecsSinceEpoch(expiryInMS));
+ policy.setIncludesSubDomains(includesSubDomains);
+
+ return true;
+}
+
+bool QHstsStore::serializePolicy(const QString &key, const QHstsPolicy &policy)
+{
+ Q_ASSERT(store.isWritable());
+
+ QByteArray serializedData;
+ QDataStream streamer(&serializedData, QIODevice::WriteOnly);
+ streamer << policy.expiry().toMSecsSinceEpoch();
+ streamer << policy.includesSubDomains();
+
+ if (streamer.status() != QDataStream::Ok)
+ return false;
+
+ store.setValue(key, serializedData);
+ return true;
+}
+
+void QHstsStore::evictPolicy(const QString &key)
+{
+ Q_ASSERT(store.isWritable());
+ if (store.contains(key))
+ store.remove(key);
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/access/qhstsstore_p.h b/src/network/access/qhstsstore_p.h
new file mode 100644
index 0000000000..13042839c4
--- /dev/null
+++ b/src/network/access/qhstsstore_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHSTSSTORE_P_H
+#define QHSTSSTORE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Network Access API. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtNetwork/private/qtnetworkglobal_p.h>
+
+#include <QtCore/qsettings.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+class QHstsPolicy;
+class QByteArray;
+class QString;
+
+class Q_AUTOTEST_EXPORT QHstsStore
+{
+public:
+ explicit QHstsStore(const QString &dirName);
+ ~QHstsStore();
+
+ QVector<QHstsPolicy> readPolicies();
+ void addToObserved(const QHstsPolicy &policy);
+ void synchronize();
+
+ bool isWritable() const;
+
+ static QString absoluteFilePath(const QString &dirName);
+private:
+ void beginHstsGroups();
+ bool serializePolicy(const QString &key, const QHstsPolicy &policy);
+ bool deserializePolicy(const QString &key, QHstsPolicy &policy);
+ void evictPolicy(const QString &key);
+ void endHstsGroups();
+
+ QVector<QHstsPolicy> observedPolicies;
+ QSettings store;
+
+ Q_DISABLE_COPY(QHstsStore)
+};
+
+QT_END_NAMESPACE
+
+#endif // QHSTSSTORE_P_H
diff --git a/src/network/access/qhttpmultipart.cpp b/src/network/access/qhttpmultipart.cpp
index 5c704efeef..303c145394 100644
--- a/src/network/access/qhttpmultipart.cpp
+++ b/src/network/access/qhttpmultipart.cpp
@@ -41,7 +41,7 @@
#include "qhttpmultipart_p.h"
#include "QtCore/qdatetime.h" // for initializing the random number generator with QTime
#include "QtCore/qmutex.h"
-#include "QtCore/qthreadstorage.h"
+#include "QtCore/qrandom.h"
QT_BEGIN_NAMESPACE
@@ -431,23 +431,16 @@ void QHttpPartPrivate::checkHeaderCreated() const
}
}
-Q_GLOBAL_STATIC(QThreadStorage<bool *>, seedCreatedStorage);
-
QHttpMultiPartPrivate::QHttpMultiPartPrivate() : contentType(QHttpMultiPart::MixedType), device(new QHttpMultiPartIODevice(this))
{
- if (!seedCreatedStorage()->hasLocalData()) {
- qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()) ^ reinterpret_cast<quintptr>(this));
- seedCreatedStorage()->setLocalData(new bool(true));
- }
-
- boundary = QByteArray("boundary_.oOo._")
- + QByteArray::number(qrand()).toBase64()
- + QByteArray::number(qrand()).toBase64()
- + QByteArray::number(qrand()).toBase64();
+ // 24 random bytes, becomes 32 characters when encoded to Base64
+ quint32 random[6];
+ QRandomGenerator::fillRange(random);
+ boundary = "boundary_.oOo._"
+ + QByteArray::fromRawData(reinterpret_cast<char *>(random), sizeof(random)).toBase64();
// boundary must not be longer than 70 characters, see RFC 2046, section 5.1.1
- if (boundary.count() > 70)
- boundary = boundary.left(70);
+ Q_ASSERT(boundary.count() <= 70);
}
qint64 QHttpMultiPartIODevice::size() const
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index da055de2da..ae30d3a8cf 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -644,6 +644,7 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor
channels[0].spdyRequestsToSend.insertMulti(request.priority(), pair);
}
+#ifndef Q_OS_WINRT
// For Happy Eyeballs the networkLayerState is set to Unknown
// untill we have started the first connection attempt. So no
// request will be started untill we know if IPv4 or IPv6
@@ -651,6 +652,13 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor
if (networkLayerState == Unknown || networkLayerState == HostLookupPending) {
startHostInfoLookup();
} else if ( networkLayerState == IPv4 || networkLayerState == IPv6 ) {
+#else // !Q_OS_WINRT
+ {
+ // Skip the host lookup part for winrt. Host lookup and proxy handling are done by Windows
+ // internally and networkLayerPreference is ignored on this platform. Instead of refactoring
+ // the whole approach we just pretend that everything important is known here.
+ networkLayerState = IPv4;
+#endif
// this used to be called via invokeMethod and a QueuedConnection
// It is the only place _q_startNextRequest is called directly without going
// through the event loop using a QueuedConnection.
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index c86cc9d8c9..84681561f2 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -55,7 +55,6 @@
# include <private/qsslsocket_p.h>
# include <QtNetwork/qsslkey.h>
# include <QtNetwork/qsslcipher.h>
-# include <QtNetwork/qsslconfiguration.h>
#endif
#ifndef QT_NO_BEARERMANAGEMENT
@@ -176,8 +175,8 @@ void QHttpNetworkConnectionChannel::init()
if (!ignoreSslErrorsList.isEmpty())
sslSocket->ignoreSslErrors(ignoreSslErrorsList);
- if (!sslConfiguration.isNull())
- sslSocket->setSslConfiguration(sslConfiguration);
+ if (sslConfiguration.data() && !sslConfiguration->isNull())
+ sslSocket->setSslConfiguration(*sslConfiguration);
} else {
#endif // !QT_NO_SSL
if (connection->connectionType() != QHttpNetworkConnection::ConnectionTypeHTTP2)
@@ -656,7 +655,10 @@ void QHttpNetworkConnectionChannel::setSslConfiguration(const QSslConfiguration
if (socket)
static_cast<QSslSocket *>(socket)->setSslConfiguration(config);
- sslConfiguration = config;
+ if (sslConfiguration.data())
+ *sslConfiguration = config;
+ else
+ sslConfiguration.reset(new QSslConfiguration(config));
}
#endif
@@ -1085,8 +1087,15 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
Q_FALLTHROUGH();
case QSslConfiguration::NextProtocolNegotiationNone: {
protocolHandler.reset(new QHttpProtocolHandler(this));
+ if (!sslConfiguration.data()) {
+ // Our own auto-tests bypass the normal initialization (done by
+ // QHttpThreadDelegate), this means in the past we'd have here
+ // the default constructed QSslConfiguration without any protocols
+ // to negotiate. Let's create it now:
+ sslConfiguration.reset(new QSslConfiguration);
+ }
- QList<QByteArray> protocols = sslConfiguration.allowedNextProtocols();
+ QList<QByteArray> protocols = sslConfiguration->allowedNextProtocols();
const int nProtocols = protocols.size();
// Clear the protocol that we failed to negotiate, so we do not try
// it again on other channels that our connection can create/open.
@@ -1096,10 +1105,10 @@ void QHttpNetworkConnectionChannel::_q_encrypted()
protocols.removeAll(QSslConfiguration::NextProtocolSpdy3_0);
if (nProtocols > protocols.size()) {
- sslConfiguration.setAllowedNextProtocols(protocols);
+ sslConfiguration->setAllowedNextProtocols(protocols);
const int channelCount = connection->d_func()->channelCount;
for (int i = 0; i < channelCount; ++i)
- connection->d_func()->channels[i].setSslConfiguration(sslConfiguration);
+ connection->d_func()->channels[i].setSslConfiguration(*sslConfiguration);
}
connection->setConnectionType(QHttpNetworkConnection::ConnectionTypeHTTP);
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 61aea9d35d..584d52ddb7 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -78,6 +78,8 @@
# include <QtNetwork/qtcpsocket.h>
#endif
+#include <QtCore/qscopedpointer.h>
+
QT_BEGIN_NAMESPACE
class QHttpNetworkRequest;
@@ -128,7 +130,7 @@ public:
#ifndef QT_NO_SSL
bool ignoreAllSslErrors;
QList<QSslError> ignoreSslErrorsList;
- QSslConfiguration sslConfiguration;
+ QScopedPointer<QSslConfiguration> sslConfiguration;
void ignoreSslErrors();
void ignoreSslErrors(const QList<QSslError> &errors);
void setSslConfiguration(const QSslConfiguration &config);
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 9d874b4d94..3d17664ed4 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -44,6 +44,7 @@
#include <QTimer>
#include <QAuthenticator>
#include <QEventLoop>
+#include <QCryptographicHash>
#include "private/qhttpnetworkreply_p.h"
#include "private/qnetworkaccesscache_p.h"
@@ -158,7 +159,10 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy)
}
if (!key.scheme().isEmpty()) {
+ const QByteArray obfuscatedPassword = QCryptographicHash::hash(proxy->password().toUtf8(),
+ QCryptographicHash::Sha1).toHex();
key.setUserName(proxy->user());
+ key.setPassword(QString::fromUtf8(obfuscatedPassword));
key.setHost(proxy->hostName());
key.setPort(proxy->port());
key.setQuery(result);
@@ -290,18 +294,21 @@ void QHttpThreadDelegate::startRequest()
: QHttpNetworkConnection::ConnectionTypeHTTP;
#ifndef QT_NO_SSL
+ if (ssl && !incomingSslConfiguration.data())
+ incomingSslConfiguration.reset(new QSslConfiguration);
+
if (httpRequest.isHTTP2Allowed() && ssl) {
QList<QByteArray> protocols;
protocols << QSslConfiguration::ALPNProtocolHTTP2
<< QSslConfiguration::NextProtocolHttp1_1;
- incomingSslConfiguration.setAllowedNextProtocols(protocols);
+ incomingSslConfiguration->setAllowedNextProtocols(protocols);
} else if (httpRequest.isSPDYAllowed() && ssl) {
connectionType = QHttpNetworkConnection::ConnectionTypeSPDY;
urlCopy.setScheme(QStringLiteral("spdy")); // to differentiate SPDY requests from HTTPS requests
QList<QByteArray> nextProtocols;
nextProtocols << QSslConfiguration::NextProtocolSpdy3_0
<< QSslConfiguration::NextProtocolHttp1_1;
- incomingSslConfiguration.setAllowedNextProtocols(nextProtocols);
+ incomingSslConfiguration->setAllowedNextProtocols(nextProtocols);
}
#endif // QT_NO_SSL
@@ -330,9 +337,8 @@ void QHttpThreadDelegate::startRequest()
#endif
#ifndef QT_NO_SSL
// Set the QSslConfiguration from this QNetworkRequest.
- if (ssl && incomingSslConfiguration != QSslConfiguration::defaultConfiguration()) {
- httpConnection->setSslConfiguration(incomingSslConfiguration);
- }
+ if (ssl)
+ httpConnection->setSslConfiguration(*incomingSslConfiguration);
#endif
#ifndef QT_NO_NETWORKPROXY
diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h
index 6d1ea11f29..2f6954aa3b 100644
--- a/src/network/access/qhttpthreaddelegate_p.h
+++ b/src/network/access/qhttpthreaddelegate_p.h
@@ -63,7 +63,7 @@
#include "qhttpnetworkrequest_p.h"
#include "qhttpnetworkconnection_p.h"
#include <QSharedPointer>
-#include "qsslconfiguration.h"
+#include <QScopedPointer>
#include "private/qnoncontiguousbytedevice_p.h"
#include "qnetworkaccessauthenticationmanager_p.h"
@@ -88,7 +88,7 @@ public:
// incoming
bool ssl;
#ifndef QT_NO_SSL
- QSslConfiguration incomingSslConfiguration;
+ QScopedPointer<QSslConfiguration> incomingSslConfiguration;
#endif
QHttpNetworkRequest httpRequest;
qint64 downloadBufferMaximumSize;
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 9c223dd32f..272dd22097 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -396,30 +396,8 @@ bool QNetworkAccessBackend::start()
#endif
#ifndef QT_NO_NETWORKPROXY
-#ifndef QT_NO_BEARERMANAGEMENT
- // Get the proxy settings from the network session (in the case of service networks,
- // the proxy settings change depending which AP was activated)
- QNetworkSession *session = networkSession.data();
- QNetworkConfiguration config;
- if (session) {
- QNetworkConfigurationManager configManager;
- // The active configuration tells us what IAP is in use
- QVariant v = session->sessionProperty(QLatin1String("ActiveConfiguration"));
- if (v.isValid())
- config = configManager.configurationFromIdentifier(qvariant_cast<QString>(v));
- // Fallback to using the configuration if no active configuration
- if (!config.isValid())
- config = session->configuration();
- // or unspecified configuration if that is no good either
- if (!config.isValid())
- config = QNetworkConfiguration();
- }
- reply->proxyList = manager->queryProxy(QNetworkProxyQuery(config, url()));
-#else // QT_NO_BEARERMANAGEMENT
- // Without bearer management, the proxy depends only on the url
reply->proxyList = manager->queryProxy(QNetworkProxyQuery(url()));
#endif
-#endif
// now start the request
open();
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index d57acc2f6b..eeee82a87c 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -730,9 +730,51 @@ bool QNetworkAccessManager::isStrictTransportSecurityEnabled() const
}
/*!
+ \since 5.10
+
+ If \a enabled is \c true, the internal HSTS cache will use a persistent store
+ to read and write HSTS policies. \a storeDir defines where this store will be
+ located. The default location is defined by QStandardPaths::CacheLocation.
+ If there is no writable QStandartPaths::CacheLocation and \a storeDir is an
+ empty string, the store will be located in the program's working directory.
+
+ \note If HSTS cache already contains HSTS policies by the time persistent
+ store is enabled, these policies will be preserved in the store. In case both
+ cache and store contain the same known hosts, policies from cache are considered
+ to be more up-to-date (and thus will overwrite the previous values in the store).
+ If this behavior is undesired, enable HSTS store before enabling Strict Tranport
+ Security. By default, the persistent store of HSTS policies is disabled.
+
+ \sa isStrictTransportSecurityStoreEnabled(), setStrictTransportSecurityEnabled(),
+ QStandardPaths::standardLocations()
+*/
+
+void QNetworkAccessManager::enableStrictTransportSecurityStore(bool enabled, const QString &storeDir)
+{
+ Q_D(QNetworkAccessManager);
+ d->stsStore.reset(enabled ? new QHstsStore(storeDir) : nullptr);
+ d->stsCache.setStore(d->stsStore.data());
+}
+
+/*!
+ \since 5.10
+
+ Returns true if HSTS cache uses a permanent store to load and store HSTS
+ policies.
+
+ \sa enableStrictTransportSecurityStore()
+*/
+
+bool QNetworkAccessManager::isStrictTransportSecurityStoreEnabled() const
+{
+ Q_D(const QNetworkAccessManager);
+ return bool(d->stsStore.data());
+}
+
+/*!
\since 5.9
- Adds HTTP Strict Transport Security policies into HSTS cache.
+ Adds HTTP Strict Transport Security policies contained in \a knownHosts into HSTS cache.
\note An expired policy will remove a known host from the cache, if previously
present.
@@ -744,7 +786,7 @@ bool QNetworkAccessManager::isStrictTransportSecurityEnabled() const
policies, but this information can be overridden by "Strict-Transport-Security"
response headers.
- \sa addStrictTransportSecurityHosts(), QHstsPolicy
+ \sa addStrictTransportSecurityHosts(), enableStrictTransportSecurityStore(), QHstsPolicy
*/
void QNetworkAccessManager::addStrictTransportSecurityHosts(const QVector<QHstsPolicy> &knownHosts)
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index f035ac5b00..4806ec0475 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -42,6 +42,7 @@
#include <QtNetwork/qtnetworkglobal.h>
#include <QtNetwork/qnetworkrequest.h>
+#include <QtCore/QString>
#include <QtCore/QVector>
#include <QtCore/QObject>
#ifndef QT_NO_SSL
@@ -124,6 +125,8 @@ public:
void setStrictTransportSecurityEnabled(bool enabled);
bool isStrictTransportSecurityEnabled() const;
+ void enableStrictTransportSecurityStore(bool enabled, const QString &storeDir = QString());
+ bool isStrictTransportSecurityStoreEnabled() const;
void addStrictTransportSecurityHosts(const QVector<QHstsPolicy> &knownHosts);
QVector<QHstsPolicy> strictTransportSecurityHosts() const;
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index 13a26a54f1..e5257251a4 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -56,6 +56,7 @@
#include "qnetworkaccesscache_p.h"
#include "qnetworkaccessbackend_p.h"
#include "qnetworkrequest.h"
+#include "qhstsstore_p.h"
#include "qhsts_p.h"
#include "private/qobject_p.h"
#include "QtNetwork/qnetworkproxy.h"
@@ -211,6 +212,7 @@ public:
Q_AUTOTEST_EXPORT static void clearConnectionCache(QNetworkAccessManager *manager);
QHstsCache stsCache;
+ QScopedPointer<QHstsStore> stsStore;
bool stsEnabled = false;
#ifndef QT_NO_BEARERMANAGEMENT
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index 8e7059de0f..cabea86521 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -311,9 +311,11 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
When client code handling the redirected() signal has verified the new URL,
it emits this signal to allow the redirect to go ahead. This protocol applies
to network requests whose redirects policy is set to
- QNetworkRequest::UserVerifiedRedirectsPolicy.
+ QNetworkRequest::UserVerifiedRedirectPolicy
- \sa QNetworkRequest::UserVerifiedRedirectPolicy, QNetworkAccessManager::setRedirectPolicy(), QNetworkRequest::RedirectPolicyAttribute
+ \sa QNetworkRequest::UserVerifiedRedirectPolicy,
+ QNetworkAccessManager::setRedirectPolicy(),
+ QNetworkRequest::RedirectPolicyAttribute
*/
/*!
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index fec3b0a100..84b1ddf5ac 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -180,7 +180,8 @@ QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager* const manage
d->outgoingData = outgoingData;
d->url = request.url();
#ifndef QT_NO_SSL
- d->sslConfiguration = request.sslConfiguration();
+ if (request.url().scheme() == QLatin1String("https"))
+ d->sslConfiguration.reset(new QSslConfiguration(request.sslConfiguration()));
#endif
// FIXME Later maybe set to Unbuffered, especially if it is zerocopy or from cache?
@@ -419,7 +420,10 @@ void QNetworkReplyHttpImpl::setSslConfigurationImplementation(const QSslConfigur
void QNetworkReplyHttpImpl::sslConfigurationImplementation(QSslConfiguration &configuration) const
{
Q_D(const QNetworkReplyHttpImpl);
- configuration = d->sslConfiguration;
+ if (d->sslConfiguration.data())
+ configuration = *d->sslConfiguration;
+ else
+ configuration = request().sslConfiguration();
}
#endif
@@ -786,7 +790,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
delegate->ssl = ssl;
#ifndef QT_NO_SSL
if (ssl)
- delegate->incomingSslConfiguration = newHttpRequest.sslConfiguration();
+ delegate->incomingSslConfiguration.reset(new QSslConfiguration(newHttpRequest.sslConfiguration()));
#endif
// Do we use synchronous HTTP?
@@ -1411,10 +1415,13 @@ void QNetworkReplyHttpImplPrivate::replySslErrors(
*toBeIgnored = pendingIgnoreSslErrorsList;
}
-void QNetworkReplyHttpImplPrivate::replySslConfigurationChanged(const QSslConfiguration &sslConfiguration)
+void QNetworkReplyHttpImplPrivate::replySslConfigurationChanged(const QSslConfiguration &newSslConfiguration)
{
// Receiving the used SSL configuration from the HTTP thread
- this->sslConfiguration = sslConfiguration;
+ if (sslConfiguration.data())
+ *sslConfiguration = newSslConfiguration;
+ else
+ sslConfiguration.reset(new QSslConfiguration(newSslConfiguration));
}
void QNetworkReplyHttpImplPrivate::replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *authenticator)
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 9383149124..26b16e8386 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -58,6 +58,7 @@
#include "QtCore/qpointer.h"
#include "QtCore/qdatetime.h"
#include "QtCore/qsharedpointer.h"
+#include "QtCore/qscopedpointer.h"
#include "qatomic.h"
#include <QtNetwork/QNetworkCacheMetaData>
@@ -260,7 +261,7 @@ public:
#ifndef QT_NO_SSL
- QSslConfiguration sslConfiguration;
+ QScopedPointer<QSslConfiguration> sslConfiguration;
bool pendingIgnoreAllSslErrors;
QList<QSslError> pendingIgnoreSslErrorsList;
#endif
@@ -290,7 +291,7 @@ public:
#ifndef QT_NO_SSL
void replyEncrypted();
void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *);
- void replySslConfigurationChanged(const QSslConfiguration&);
+ void replySslConfigurationChanged(const QSslConfiguration &newSslConfiguration);
void replyPreSharedKeyAuthenticationRequiredSlot(QSslPreSharedKeyAuthenticator *);
#endif
#ifndef QT_NO_NETWORKPROXY
diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp
index f1619ab7c0..3367de80c8 100644
--- a/src/network/bearer/qnetworkconfiguration.cpp
+++ b/src/network/bearer/qnetworkconfiguration.cpp
@@ -111,7 +111,7 @@ QT_BEGIN_NAMESPACE
Depending on the type of configuration some states are transient in nature. A GPRS/UMTS
connection may almost always be \l Discovered if the GSM/UMTS network is available.
- However if the GSM/UMTS network looses the connection the associated configuration may change its state
+ However if the GSM/UMTS network loses the connection the associated configuration may change its state
from \l Discovered to \l Defined as well. A similar use case might be triggered by
WLAN availability. QNetworkConfigurationManager::updateConfigurations() can be used to
manually trigger updates of states. Note that some platforms do not require such updates
diff --git a/src/network/configure.json b/src/network/configure.json
index 6e7ce25051..de40872e16 100644
--- a/src/network/configure.json
+++ b/src/network/configure.json
@@ -153,6 +153,12 @@
]
},
"use": "network"
+ },
+ "openssl11": {
+ "label": "OpenSSL v. 1.1 support",
+ "type": "compile",
+ "test": "unix/openssl11",
+ "use": "network"
}
},
@@ -220,6 +226,11 @@
"condition": "config.winrt || features.securetransport || features.openssl",
"output": [ "publicFeature", "feature" ]
},
+ "opensslv11": {
+ "label": "OpenSSL v. 1.1",
+ "condition": "tests.openssl11",
+ "output": ["publicFeature", "feature"]
+ },
"sctp": {
"label": "SCTP",
"autoDetect": false,
@@ -253,14 +264,13 @@
"label": "QNetworkProxy",
"purpose": "Provides network proxy support.",
"section": "Networking",
- "condition": "!config.winrt",
"output": [ "publicFeature", "feature" ]
},
"socks5": {
"label": "SOCKS5",
"purpose": "Provides SOCKS5 support in QNetworkProxy.",
"section": "Networking",
- "condition": "!config.winrt && features.networkproxy",
+ "condition": "features.networkproxy",
"output": [ "publicFeature", "feature" ]
},
"networkinterface": {
diff --git a/src/network/kernel/kernel.pri b/src/network/kernel/kernel.pri
index a80b2d387e..c3fcf25233 100644
--- a/src/network/kernel/kernel.pri
+++ b/src/network/kernel/kernel.pri
@@ -60,7 +60,7 @@ mac {
}
osx:SOURCES += kernel/qnetworkproxy_mac.cpp
-else:win32:SOURCES += kernel/qnetworkproxy_win.cpp
+else:win32:!winrt: SOURCES += kernel/qnetworkproxy_win.cpp
else: qtConfig(libproxy) {
SOURCES += kernel/qnetworkproxy_libproxy.cpp
QMAKE_USE_PRIVATE += libproxy
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index 46123eb8a7..0156e22d41 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -279,6 +279,27 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver,
}
/*!
+ \fn QHostInfo &QHostInfo::operator=(QHostInfo &&other)
+
+ Move-assigns \a other to this QHostInfo instance.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new value.
+
+ \since 5.10
+*/
+
+/*!
+ \fn void QHostInfo::swap(QHostInfo &other)
+
+ Swaps host-info \a other with this host-info. This operation is
+ very fast and never fails.
+
+ \since 5.10
+*/
+
+/*!
\fn int QHostInfo::lookupHost(const QString &name, const QObject *receiver, PointerToMemberFunction function)
\since 5.9
diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h
index 4484d718bd..c5727bb6eb 100644
--- a/src/network/kernel/qhostinfo.h
+++ b/src/network/kernel/qhostinfo.h
@@ -63,8 +63,11 @@ public:
explicit QHostInfo(int lookupId = -1);
QHostInfo(const QHostInfo &d);
QHostInfo &operator=(const QHostInfo &d);
+ QHostInfo &operator=(QHostInfo &&other) Q_DECL_NOTHROW { swap(other); return *this; }
~QHostInfo();
+ void swap(QHostInfo &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+
QString hostName() const;
void setHostName(const QString &name);
@@ -125,7 +128,7 @@ public:
!std::is_same<const char *, Func>::value, int>::type
lookupHost(const QString &name, Func slot)
{
- return lookupHost(name, nullptr, slot);
+ return lookupHost(name, nullptr, std::move(slot));
}
// lookupHost to a functor or function pointer (with context)
@@ -141,7 +144,7 @@ public:
auto slotObj = new QtPrivate::QFunctorSlotObject<Func1, 1,
typename QtPrivate::List<QHostInfo>,
- void>(slot);
+ void>(std::move(slot));
return lookupHostImpl(name, context, slotObj);
}
#endif // Q_QDOC
@@ -154,6 +157,8 @@ private:
QtPrivate::QSlotObjectBase *slotObj);
};
+Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QHostInfo)
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QHostInfo)
diff --git a/src/network/kernel/qnetworkinterface_win.cpp b/src/network/kernel/qnetworkinterface_win.cpp
index 3002b2497b..c2efcea625 100644
--- a/src/network/kernel/qnetworkinterface_win.cpp
+++ b/src/network/kernel/qnetworkinterface_win.cpp
@@ -63,33 +63,6 @@
QT_BEGIN_NAMESPACE
-typedef NETIO_STATUS (WINAPI *PtrConvertInterfaceIndexToLuid)(NET_IFINDEX, PNET_LUID);
-typedef NETIO_STATUS (WINAPI *PtrConvertInterfaceLuidToName)(const NET_LUID *, PWSTR, SIZE_T);
-typedef NETIO_STATUS (WINAPI *PtrConvertInterfaceLuidToIndex)(const NET_LUID *, PNET_IFINDEX);
-typedef NETIO_STATUS (WINAPI *PtrConvertInterfaceNameToLuid)(const WCHAR *, PNET_LUID);
-static PtrConvertInterfaceIndexToLuid ptrConvertInterfaceIndexToLuid = 0;
-static PtrConvertInterfaceLuidToName ptrConvertInterfaceLuidToName = 0;
-static PtrConvertInterfaceLuidToIndex ptrConvertInterfaceLuidToIndex = 0;
-static PtrConvertInterfaceNameToLuid ptrConvertInterfaceNameToLuid = 0;
-
-static void resolveLibs()
-{
- // try to find the functions we need from Iphlpapi.dll
- static bool done = false;
-
- if (!done) {
- HINSTANCE iphlpapiHnd = GetModuleHandle(L"iphlpapi");
- Q_ASSERT(iphlpapiHnd);
-
- // since Windows Vista
- ptrConvertInterfaceIndexToLuid = (PtrConvertInterfaceIndexToLuid)GetProcAddress(iphlpapiHnd, "ConvertInterfaceIndexToLuid");
- ptrConvertInterfaceLuidToName = (PtrConvertInterfaceLuidToName)GetProcAddress(iphlpapiHnd, "ConvertInterfaceLuidToNameW");
- ptrConvertInterfaceLuidToIndex = (PtrConvertInterfaceLuidToIndex)GetProcAddress(iphlpapiHnd, "ConvertInterfaceLuidToIndex");
- ptrConvertInterfaceNameToLuid = (PtrConvertInterfaceNameToLuid)GetProcAddress(iphlpapiHnd, "ConvertInterfaceNameToLuidW");
- done = true;
- }
-}
-
static QHostAddress addressFromSockaddr(sockaddr *sa)
{
QHostAddress address;
@@ -111,30 +84,22 @@ static QHostAddress addressFromSockaddr(sockaddr *sa)
uint QNetworkInterfaceManager::interfaceIndexFromName(const QString &name)
{
- resolveLibs();
- if (!ptrConvertInterfaceNameToLuid || !ptrConvertInterfaceLuidToIndex)
- return 0;
-
NET_IFINDEX id;
NET_LUID luid;
- if (ptrConvertInterfaceNameToLuid(reinterpret_cast<const wchar_t *>(name.constData()), &luid) == NO_ERROR
- && ptrConvertInterfaceLuidToIndex(&luid, &id) == NO_ERROR)
+ if (ConvertInterfaceNameToLuidW(reinterpret_cast<const wchar_t *>(name.constData()), &luid) == NO_ERROR
+ && ConvertInterfaceLuidToIndex(&luid, &id) == NO_ERROR)
return uint(id);
return 0;
}
QString QNetworkInterfaceManager::interfaceNameFromIndex(uint index)
{
- resolveLibs();
- if (ptrConvertInterfaceIndexToLuid && ptrConvertInterfaceLuidToName) {
- NET_LUID luid;
- if (ptrConvertInterfaceIndexToLuid(index, &luid) == NO_ERROR) {
- WCHAR buf[IF_MAX_STRING_SIZE + 1];
- if (ptrConvertInterfaceLuidToName(&luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
- return QString::fromWCharArray(buf);
- }
+ NET_LUID luid;
+ if (ConvertInterfaceIndexToLuid(index, &luid) == NO_ERROR) {
+ WCHAR buf[IF_MAX_STRING_SIZE + 1];
+ if (ConvertInterfaceLuidToNameW(&luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
+ return QString::fromWCharArray(buf);
}
-
return QString::number(index);
}
@@ -223,11 +188,11 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
if (ptr->IfType == IF_TYPE_PPP)
iface->flags |= QNetworkInterface::IsPointToPoint;
- if (ptrConvertInterfaceLuidToName && ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, Luid)) {
- // use ConvertInterfaceLuidToName because that returns a friendlier name, though not
+ if (ptr->Length >= offsetof(IP_ADAPTER_ADDRESSES, Luid)) {
+ // use ConvertInterfaceLuidToNameW because that returns a friendlier name, though not
// as friendly as FriendlyName below
WCHAR buf[IF_MAX_STRING_SIZE + 1];
- if (ptrConvertInterfaceLuidToName(&ptr->Luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
+ if (ConvertInterfaceLuidToNameW(&ptr->Luid, buf, sizeof(buf)/sizeof(buf[0])) == NO_ERROR)
iface->name = QString::fromWCharArray(buf);
}
if (iface->name.isEmpty())
@@ -275,14 +240,11 @@ static QList<QNetworkInterfacePrivate *> interfaceListingWinXP()
QList<QNetworkInterfacePrivate *> QNetworkInterfaceManager::scan()
{
- resolveLibs();
return interfaceListingWinXP();
}
QString QHostInfo::localDomainName()
{
- resolveLibs();
-
FIXED_INFO info, *pinfo;
ULONG bufSize = sizeof info;
pinfo = &info;
diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp
index 11e8fa6264..37f3f84653 100644
--- a/src/network/kernel/qnetworkproxy.cpp
+++ b/src/network/kernel/qnetworkproxy.cpp
@@ -915,9 +915,6 @@ public:
QUrl remote;
int localPort;
QNetworkProxyQuery::QueryType type;
-#ifndef QT_NO_BEARERMANAGEMENT
- QNetworkConfiguration config;
-#endif
};
template<> void QSharedDataPointer<QNetworkProxyQueryPrivate>::detach()
@@ -1129,29 +1126,32 @@ QNetworkProxyQuery::QNetworkProxyQuery(quint16 bindPort, const QString &protocol
d->type = queryType;
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#if !defined(QT_NO_BEARERMANAGEMENT) && QT_DEPRECATED_SINCE(5, 10)
/*!
+ \deprecated
+
Constructs a QNetworkProxyQuery with the URL \a requestUrl and
sets the query type to \a queryType. The specified \a networkConfiguration
- is used to resolve the proxy settings.
+ parameter is ignored.
\sa protocolTag(), peerHostName(), peerPort(), networkConfiguration()
*/
QNetworkProxyQuery::QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
const QUrl &requestUrl, QueryType queryType)
{
- d->config = networkConfiguration;
+ Q_UNUSED(networkConfiguration)
d->remote = requestUrl;
d->type = queryType;
}
/*!
+ \deprecated
+
Constructs a QNetworkProxyQuery of type \a queryType and sets the
protocol tag to be \a protocolTag. This constructor is suitable
for QNetworkProxyQuery::TcpSocket queries, because it sets the
peer hostname to \a hostname and the peer's port number to \a
- port. The specified \a networkConfiguration
- is used to resolve the proxy settings.
+ port. The specified \a networkConfiguration parameter is ignored.
\sa networkConfiguration()
*/
@@ -1160,7 +1160,7 @@ QNetworkProxyQuery::QNetworkProxyQuery(const QNetworkConfiguration &networkConfi
const QString &protocolTag,
QueryType queryType)
{
- d->config = networkConfiguration;
+ Q_UNUSED(networkConfiguration);
d->remote.setScheme(protocolTag);
d->remote.setHost(hostname);
d->remote.setPort(port);
@@ -1168,11 +1168,13 @@ QNetworkProxyQuery::QNetworkProxyQuery(const QNetworkConfiguration &networkConfi
}
/*!
+ \deprecated
+
Constructs a QNetworkProxyQuery of type \a queryType and sets the
protocol tag to be \a protocolTag. This constructor is suitable
for QNetworkProxyQuery::TcpSocket queries because it sets the
local port number to \a bindPort. The specified \a networkConfiguration
- is used to resolve the proxy settings.
+ parameter is ignored.
Note that \a bindPort is of type quint16 to indicate the exact
port number that is requested. The value of -1 (unknown) is not
@@ -1184,12 +1186,12 @@ QNetworkProxyQuery::QNetworkProxyQuery(const QNetworkConfiguration &networkConfi
quint16 bindPort, const QString &protocolTag,
QueryType queryType)
{
- d->config = networkConfiguration;
+ Q_UNUSED(networkConfiguration);
d->remote.setScheme(protocolTag);
d->localPort = bindPort;
d->type = queryType;
}
-#endif
+#endif // !defined(QT_NO_BEARERMANAGEMENT) && QT_DEPRECATED_SINCE(5, 10)
/*!
Constructs a QNetworkProxyQuery object that is a copy of \a other.
@@ -1413,34 +1415,32 @@ void QNetworkProxyQuery::setUrl(const QUrl &url)
d->remote = url;
}
-#ifndef QT_NO_BEARERMANAGEMENT
+#if !defined(QT_NO_BEARERMANAGEMENT) && QT_DEPRECATED_SINCE(5, 10)
/*!
- Returns the network configuration component of the query.
+ \deprecated
+
+ Returns QNetworkConfiguration().
\sa setNetworkConfiguration()
*/
QNetworkConfiguration QNetworkProxyQuery::networkConfiguration() const
{
- return d ? d->config : QNetworkConfiguration();
+ return QNetworkConfiguration();
}
/*!
- Sets the network configuration component of this QNetworkProxyQuery
- object to be \a networkConfiguration. The network configuration can
- be used to return different proxy settings based on the network in
- use, for example WLAN vs cellular networks on a mobile phone.
+ \deprecated
- In the case of "user choice" or "service network" configurations,
- you should first start the QNetworkSession and obtain the active
- configuration from its properties.
+ This function does nothing. The specified \a networkConfiguration parameter
+ is ignored.
\sa networkConfiguration()
*/
void QNetworkProxyQuery::setNetworkConfiguration(const QNetworkConfiguration &networkConfiguration)
{
- d->config = networkConfiguration;
+ Q_UNUSED(networkConfiguration);
}
-#endif
+#endif // !defined(QT_NO_BEARERMANAGEMENT) && QT_DEPRECATED_SINCE(5, 10)
/*!
\class QNetworkProxyFactory
diff --git a/src/network/kernel/qnetworkproxy.h b/src/network/kernel/qnetworkproxy.h
index 8699c313e9..7e3e6906a8 100644
--- a/src/network/kernel/qnetworkproxy.h
+++ b/src/network/kernel/qnetworkproxy.h
@@ -75,12 +75,15 @@ public:
QueryType queryType = TcpSocket);
explicit QNetworkProxyQuery(quint16 bindPort, const QString &protocolTag = QString(),
QueryType queryType = TcpServer);
-#ifndef QT_NO_BEARERMANAGEMENT
+#if !defined(QT_NO_BEARERMANAGEMENT) && QT_DEPRECATED_SINCE(5, 10)
+ Q_DECL_DEPRECATED_X("QNetworkConfiguration support in QNetworkProxy is deprecated")
QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
const QUrl &requestUrl, QueryType queryType = UrlRequest);
+ Q_DECL_DEPRECATED_X("QNetworkConfiguration support in QNetworkProxy is deprecated")
QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
const QString &hostname, int port, const QString &protocolTag = QString(),
QueryType queryType = TcpSocket);
+ Q_DECL_DEPRECATED_X("QNetworkConfiguration support in QNetworkProxy is deprecated")
QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
quint16 bindPort, const QString &protocolTag = QString(),
QueryType queryType = TcpServer);
@@ -116,8 +119,10 @@ public:
QUrl url() const;
void setUrl(const QUrl &url);
-#ifndef QT_NO_BEARERMANAGEMENT
+#if !defined(QT_NO_BEARERMANAGEMENT) && QT_DEPRECATED_SINCE(5, 10)
+ Q_DECL_DEPRECATED_X("QNetworkConfiguration support in QNetworkProxy is deprecated")
QNetworkConfiguration networkConfiguration() const;
+ Q_DECL_DEPRECATED_X("QNetworkConfiguration support in QNetworkProxy is deprecated")
void setNetworkConfiguration(const QNetworkConfiguration &networkConfiguration);
#endif
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index 7ecbf35489..9cb6c4be57 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -943,7 +943,9 @@ void QAbstractSocketPrivate::resolveProxy(const QString &hostname, quint16 port)
// DefaultProxy here will raise an error
proxyInUse = QNetworkProxy();
}
+#endif // !QT_NO_NETWORKPROXY
+#if !defined(QT_NO_NETWORKPROXY) || defined(Q_OS_WINRT)
/*!
\internal
@@ -981,7 +983,7 @@ void QAbstractSocketPrivate::startConnectingByName(const QString &host)
emit q->stateChanged(state);
}
-#endif
+#endif // !QT_NO_NETWORKPROXY || Q_OS_WINRT
/*! \internal
@@ -1113,10 +1115,6 @@ void QAbstractSocketPrivate::_q_connectToNextAddress()
// (localhost address on BSD or any UDP connect), emit
// connected() and return.
if (
-#if defined(Q_OS_WINRT) && _MSC_VER >= 1900
- !qEnvironmentVariableIsEmpty("QT_WINRT_USE_THREAD_NETWORK_CONTEXT") ?
- socketEngine->connectToHostByName(hostName, port) :
-#endif
socketEngine->connectToHost(host, port)) {
//_q_testConnection();
fetchConnectionParameters();
@@ -1712,6 +1710,7 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port,
QIODevice::open(openMode);
d->readChannelCount = d->writeChannelCount = 0;
+#ifndef Q_OS_WINRT
d->state = HostLookupState;
emit stateChanged(d->state);
@@ -1749,6 +1748,10 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port,
(d->state == ConnectingState || d->state == HostLookupState)
? " (connection in progress)" : "");
#endif
+#else // !Q_OS_WINRT
+ // On WinRT we should always connect by name. Lookup and proxy handling are done by the API.
+ d->startConnectingByName(hostName);
+#endif
}
/*! \overload
diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp
index 3fcec954e7..a9789b7d04 100644
--- a/src/network/socket/qlocalserver.cpp
+++ b/src/network/socket/qlocalserver.cpp
@@ -41,6 +41,10 @@
#include "qlocalserver_p.h"
#include "qlocalsocket.h"
+#if defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
+#include <QtCore/qt_windows.h>
+#endif
+
QT_BEGIN_NAMESPACE
/*!
@@ -181,6 +185,42 @@ QLocalServer::SocketOptions QLocalServer::socketOptions() const
}
/*!
+ \since 5.10
+ Returns the native socket descriptor the server uses to listen
+ for incoming instructions, or -1 if the server is not listening.
+
+ The type of the descriptor depends on the platform:
+ \list
+ \li On Windows, the returned value is a
+ \l{https://msdn.microsoft.com/en-us/library/windows/desktop/ms740522(v=vs.85).aspx}
+ {Winsock 2 Socket Handle}.
+
+ \li With WinRT and on INTEGRITY, the returned value is the
+ QTcpServer socket descriptor and the type is defined by
+ \l{QTcpServer::socketDescriptor}{socketDescriptor}.
+
+ \li On all other UNIX-like operating systems, the type is
+ a file descriptor representing a listening socket.
+ \endlist
+
+ \sa listen()
+*/
+qintptr QLocalServer::socketDescriptor() const
+{
+ Q_D(const QLocalServer);
+ if (!isListening())
+ return -1;
+#if defined(QT_LOCALSOCKET_TCP)
+ return d->tcpServer.socketDescriptor();
+#elif defined(Q_OS_WIN)
+ const auto handle = d->connectionEventNotifier->handle();
+ return handle != INVALID_HANDLE_VALUE ? qintptr(handle) : -1;
+#else
+ return d->socketNotifier->socket();
+#endif
+}
+
+/*!
Stop listening for incoming connections. Existing connections are not
affected, but any new connections will be refused.
diff --git a/src/network/socket/qlocalserver.h b/src/network/socket/qlocalserver.h
index 9bd2990389..454ac30c9b 100644
--- a/src/network/socket/qlocalserver.h
+++ b/src/network/socket/qlocalserver.h
@@ -92,6 +92,8 @@ public:
void setSocketOptions(SocketOptions options);
SocketOptions socketOptions() const;
+ qintptr socketDescriptor() const;
+
protected:
virtual void incomingConnection(quintptr socketDescriptor);
diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp
index 090a9e98c6..6fec2fdbd2 100644
--- a/src/network/socket/qlocalsocket.cpp
+++ b/src/network/socket/qlocalsocket.cpp
@@ -126,6 +126,20 @@ QT_BEGIN_NAMESPACE
The socket descriptor is not available when QLocalSocket
is in UnconnectedState.
+ The type of the descriptor depends on the platform:
+
+ \list
+ \li On Windows, the returned value is a
+ \l{https://msdn.microsoft.com/en-us/library/windows/desktop/ms740522(v=vs.85).aspx}
+ {Winsock 2 Socket Handle}.
+
+ \li With WinRT and on INTEGRITY, the returned value is the
+ QTcpSocket socket descriptor and the type is defined by
+ \l{QTcpSocket::socketDescriptor}{socketDescriptor}.
+
+ \li On all other UNIX-like operating systems, the type is
+ a file descriptor representing a socket.
+ \endlist
\sa setSocketDescriptor()
*/
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index 312c934632..ae94cb9d51 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -183,10 +183,8 @@ void QLocalSocket::connectToServer(OpenMode openMode)
}
// we have a valid handle
- if (setSocketDescriptor((qintptr)localSocket, ConnectedState, openMode)) {
- d->handle = localSocket;
+ if (setSocketDescriptor((qintptr)localSocket, ConnectedState, openMode))
emit connected();
- }
}
// This is reading from the buffer
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 3cf65b3553..13ceb4c612 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -670,8 +670,7 @@ static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6));
mreq6.ipv6mr_interface = interface.index();
- } else
- if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
+ } else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
level = IPPROTO_IP;
sockOpt = how4;
sockArg = &mreq4;
diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp
index eb633eb1d2..e21bf29d4b 100644
--- a/src/network/socket/qnativesocketengine_win.cpp
+++ b/src/network/socket/qnativesocketengine_win.cpp
@@ -944,9 +944,7 @@ static bool multicastMembershipHelper(QNativeSocketEnginePrivate *d,
Q_IPV6ADDR ip6 = groupAddress.toIPv6Address();
memcpy(&mreq6.ipv6mr_multiaddr, &ip6, sizeof(ip6));
mreq6.ipv6mr_interface = iface.index();
- } else
-
- if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
+ } else if (groupAddress.protocol() == QAbstractSocket::IPv4Protocol) {
level = IPPROTO_IP;
sockOpt = how4;
sockArg = reinterpret_cast<char *>(&mreq4);
diff --git a/src/network/socket/qtcpserver_p.h b/src/network/socket/qtcpserver_p.h
index 71dc4d985f..b7fae4c105 100644
--- a/src/network/socket/qtcpserver_p.h
+++ b/src/network/socket/qtcpserver_p.h
@@ -63,7 +63,8 @@
QT_BEGIN_NAMESPACE
-class QTcpServerPrivate : public QObjectPrivate, public QAbstractSocketEngineReceiver
+class Q_NETWORK_EXPORT QTcpServerPrivate : public QObjectPrivate,
+ public QAbstractSocketEngineReceiver
{
Q_DECLARE_PUBLIC(QTcpServer)
public:
diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp
index 28b7eda54a..71e514a025 100644
--- a/src/network/ssl/qsslcertificate_openssl.cpp
+++ b/src/network/ssl/qsslcertificate_openssl.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -64,12 +65,14 @@ bool QSslCertificate::operator==(const QSslCertificate &other) const
uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW
{
if (X509 * const x509 = key.d->x509) {
- (void)q_X509_cmp(x509, x509); // populate x509->sha1_hash
- // (if someone knows a better way...)
- return qHashBits(x509->sha1_hash, SHA_DIGEST_LENGTH, seed);
- } else {
- return seed;
+ const EVP_MD *sha1 = q_EVP_sha1();
+ unsigned int len = 0;
+ unsigned char md[EVP_MAX_MD_SIZE];
+ q_X509_digest(x509, sha1, md, &len);
+ return qHashBits(md, len, seed);
}
+
+ return seed;
}
bool QSslCertificate::isNull() const
@@ -89,8 +92,7 @@ QByteArray QSslCertificate::version() const
{
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
if (d->versionString.isEmpty() && d->x509)
- d->versionString =
- QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1);
+ d->versionString = QByteArray::number(qlonglong(q_X509_get_version(d->x509)) + 1);
return d->versionString;
}
@@ -99,7 +101,7 @@ QByteArray QSslCertificate::serialNumber() const
{
QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
if (d->serialNumberString.isEmpty() && d->x509) {
- ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber;
+ ASN1_INTEGER *serialNumber = q_X509_get_serialNumber(d->x509);
QByteArray hexString;
hexString.reserve(serialNumber->length * 3);
for (int a = 0; a < serialNumber->length; ++a) {
@@ -199,14 +201,15 @@ QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlter
continue;
}
- const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(genName->d.ia5));
+ const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(genName->d.ia5));
const QString altName = QString::fromLatin1(altNameStr, len);
if (genName->type == GEN_DNS)
result.insert(QSsl::DnsEntry, altName);
else if (genName->type == GEN_EMAIL)
result.insert(QSsl::EmailEntry, altName);
}
- q_sk_pop_free((STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_sk_free));
+
+ q_OPENSSL_sk_pop_free((OPENSSL_STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_OPENSSL_sk_free));
}
return result;
@@ -235,25 +238,26 @@ QSslKey QSslCertificate::publicKey() const
QSslKey key;
key.d->type = QSsl::PublicKey;
- X509_PUBKEY *xkey = d->x509->cert_info->key;
- EVP_PKEY *pkey = q_X509_PUBKEY_get(xkey);
+
+ EVP_PKEY *pkey = q_X509_get_pubkey(d->x509);
Q_ASSERT(pkey);
+ const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey));
- if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA) {
+ if (keyType == EVP_PKEY_RSA) {
key.d->rsa = q_EVP_PKEY_get1_RSA(pkey);
key.d->algorithm = QSsl::Rsa;
key.d->isNull = false;
- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA) {
+ } else if (keyType == EVP_PKEY_DSA) {
key.d->dsa = q_EVP_PKEY_get1_DSA(pkey);
key.d->algorithm = QSsl::Dsa;
key.d->isNull = false;
#ifndef OPENSSL_NO_EC
- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_EC) {
+ } else if (keyType == EVP_PKEY_EC) {
key.d->ec = q_EVP_PKEY_get1_EC_KEY(pkey);
key.d->algorithm = QSsl::Ec;
key.d->isNull = false;
#endif
- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DH) {
+ } else if (keyType == EVP_PKEY_DH) {
// DH unsupported
} else {
// error?
@@ -275,7 +279,7 @@ static QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext)
X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext));
if (!meth) {
ASN1_OCTET_STRING *value = q_X509_EXTENSION_get_data(ext);
- QByteArray result( reinterpret_cast<const char *>(q_ASN1_STRING_data(value)),
+ QByteArray result( reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(value)),
q_ASN1_STRING_length(value));
return result;
}
@@ -371,7 +375,7 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext)
continue;
}
- const char *uriStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(name->d.uniformResourceIdentifier));
+ const char *uriStr = reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(name->d.uniformResourceIdentifier));
const QString uri = QString::fromUtf8(uriStr, len);
result[QString::fromUtf8(QSslCertificatePrivate::asn1ObjectName(ad->method))] = uri;
@@ -380,11 +384,7 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext)
}
}
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- q_sk_pop_free((_STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free));
-#else
- q_sk_pop_free((STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free));
-#endif
+ q_OPENSSL_sk_pop_free((OPENSSL_STACK*)info, reinterpret_cast<void(*)(void *)>(q_OPENSSL_sk_free));
return result;
}
break;
@@ -607,7 +607,11 @@ static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name)
unsigned char *data = 0;
int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e));
info.insertMulti(name, QString::fromUtf8((char*)data, size));
+#if QT_CONFIG(opensslv11)
+ q_CRYPTO_free(data, 0, 0);
+#else
q_CRYPTO_free(data);
+#endif
}
return info;
@@ -619,8 +623,9 @@ QSslCertificate QSslCertificatePrivate::QSslCertificate_from_X509(X509 *x509)
if (!x509 || !QSslSocket::supportsSsl())
return certificate;
- ASN1_TIME *nbef = q_X509_get_notBefore(x509);
- ASN1_TIME *naft = q_X509_get_notAfter(x509);
+ ASN1_TIME *nbef = q_X509_getm_notBefore(x509);
+ ASN1_TIME *naft = q_X509_getm_notAfter(x509);
+
certificate.d->notValidBefore = q_getTimeFromASN1(nbef);
certificate.d->notValidAfter = q_getTimeFromASN1(naft);
certificate.d->null = false;
diff --git a/src/network/ssl/qsslcertificate_qt.cpp b/src/network/ssl/qsslcertificate_qt.cpp
index 5e8f4cfac7..1cc2b1f964 100644
--- a/src/network/ssl/qsslcertificate_qt.cpp
+++ b/src/network/ssl/qsslcertificate_qt.cpp
@@ -272,17 +272,12 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteAr
static QByteArray colonSeparatedHex(const QByteArray &value)
{
- QByteArray hexString;
- hexString.reserve(value.size() * 3);
- for (int a = 0; a < value.size(); ++a) {
- const quint8 b = value.at(a);
- if (b || !hexString.isEmpty()) { // skip leading zeros
- hexString += QByteArray::number(b, 16).rightJustified(2, '0');
- hexString += ':';
- }
- }
- hexString.chop(1);
- return hexString;
+ const int size = value.size();
+ int i = 0;
+ while (i < size && !value.at(i)) // skip leading zeros
+ ++i;
+
+ return value.mid(i).toHex(':');
}
bool QSslCertificatePrivate::parse(const QByteArray &data)
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
index c92d8fc3f8..cef503710c 100644
--- a/src/network/ssl/qsslcontext_openssl.cpp
+++ b/src/network/ssl/qsslcontext_openssl.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
** Copyright (C) 2014 Governikus GmbH & Co. KG.
** Contact: https://www.qt.io/licensing/
@@ -41,22 +41,14 @@
#include <QtNetwork/qsslsocket.h>
-#include <QtNetwork/qssldiffiehellmanparameters.h>
-#include <QtCore/qmutex.h>
#include "private/qssl_p.h"
#include "private/qsslcontext_openssl_p.h"
-#include "private/qsslsocket_p.h"
#include "private/qsslsocket_openssl_p.h"
#include "private/qsslsocket_openssl_symbols_p.h"
-#include "private/qssldiffiehellmanparameters_p.h"
QT_BEGIN_NAMESPACE
-// defined in qsslsocket_openssl.cpp:
-extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
-extern QString getErrorsFromOpenSsl();
-
QSslContext::QSslContext()
: ctx(0),
pkey(0),
@@ -78,301 +70,6 @@ QSslContext::~QSslContext()
q_SSL_SESSION_free(session);
}
-static inline QString msgErrorSettingEllipticCurves(const QString &why)
-{
- return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
-}
-
-// static
-void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
-{
- sslContext->sslConfiguration = configuration;
- sslContext->errorCode = QSslError::NoError;
-
- bool client = (mode == QSslSocket::SslClientMode);
-
- bool reinitialized = false;
- bool unsupportedProtocol = false;
-init_context:
- switch (sslContext->sslConfiguration.protocol()) {
- case QSsl::SslV2:
-#ifndef OPENSSL_NO_SSL2
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
-#else
- // SSL 2 not supported by the system, but chosen deliberately -> error
- sslContext->ctx = 0;
- unsupportedProtocol = true;
-#endif
- break;
- case QSsl::SslV3:
-#ifndef OPENSSL_NO_SSL3_METHOD
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
-#else
- // SSL 3 not supported by the system, but chosen deliberately -> error
- sslContext->ctx = 0;
- unsupportedProtocol = true;
-#endif
- break;
- case QSsl::SecureProtocols:
- // SSLv2 and SSLv3 will be disabled by SSL options
- // But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32.
- case QSsl::TlsV1SslV3:
- // SSLv2 will will be disabled by SSL options
- case QSsl::AnyProtocol:
- default:
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
- break;
- case QSsl::TlsV1_0:
- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method());
- break;
- case QSsl::TlsV1_1:
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method());
-#else
- // TLS 1.1 not supported by the system, but chosen deliberately -> error
- sslContext->ctx = 0;
- unsupportedProtocol = true;
-#endif
- break;
- case QSsl::TlsV1_2:
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method());
-#else
- // TLS 1.2 not supported by the system, but chosen deliberately -> error
- sslContext->ctx = 0;
- unsupportedProtocol = true;
-#endif
- break;
- case QSsl::TlsV1_0OrLater:
- // Specific protocols will be specified via SSL options.
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
- break;
- case QSsl::TlsV1_1OrLater:
- case QSsl::TlsV1_2OrLater:
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- // Specific protocols will be specified via SSL options.
- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
-#else
- // TLS 1.1/1.2 not supported by the system, but chosen deliberately -> error
- sslContext->ctx = 0;
- unsupportedProtocol = true;
-#endif
- break;
- }
-
- if (!sslContext->ctx) {
- // After stopping Flash 10 the SSL library looses its ciphers. Try re-adding them
- // by re-initializing the library.
- if (!reinitialized) {
- reinitialized = true;
- if (q_SSL_library_init() == 1)
- goto init_context;
- }
-
- sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
- unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
- );
- sslContext->errorCode = QSslError::UnspecifiedError;
- return;
- }
-
- // Enable bug workarounds.
- long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
- q_SSL_CTX_set_options(sslContext->ctx, options);
-
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- // Tell OpenSSL to release memory early
- // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
- if (q_SSLeay() >= 0x10000000L)
- q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
-#endif
-
- // Initialize ciphers
- QByteArray cipherString;
- bool first = true;
- QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
- if (ciphers.isEmpty())
- ciphers = QSslSocketPrivate::defaultCiphers();
- for (const QSslCipher &cipher : qAsConst(ciphers)) {
- if (first)
- first = false;
- else
- cipherString.append(':');
- cipherString.append(cipher.name().toLatin1());
- }
-
- if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
- sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
- sslContext->errorCode = QSslError::UnspecifiedError;
- return;
- }
-
- const QDateTime now = QDateTime::currentDateTimeUtc();
-
- // Add all our CAs to this store.
- const auto caCertificates = sslContext->sslConfiguration.caCertificates();
- for (const QSslCertificate &caCertificate : caCertificates) {
- // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
- //
- // If several CA certificates matching the name, key identifier, and
- // serial number condition are available, only the first one will be
- // examined. This may lead to unexpected results if the same CA
- // certificate is available with different expiration dates. If a
- // ``certificate expired'' verification error occurs, no other
- // certificate will be searched. Make sure to not have expired
- // certificates mixed with valid ones.
- //
- // See also: QSslSocketBackendPrivate::verify()
- if (caCertificate.expiryDate() >= now) {
- q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
- }
- }
-
- if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
- // tell OpenSSL the directories where to look up the root certs on demand
- const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
- for (const QByteArray &unixDir : unixDirs)
- q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDir.constData());
- }
-
- if (!sslContext->sslConfiguration.localCertificate().isNull()) {
- // Require a private key as well.
- if (sslContext->sslConfiguration.privateKey().isNull()) {
- sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
- sslContext->errorCode = QSslError::UnspecifiedError;
- return;
- }
-
- // Load certificate
- if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
- sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
- sslContext->errorCode = QSslError::UnspecifiedError;
- return;
- }
-
- if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
- sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
- } else {
- // Load private key
- sslContext->pkey = q_EVP_PKEY_new();
- // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
- // this lead to a memory leak. Now we use the *_set1_* functions which do not
- // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
- if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
- q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
- else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
- q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
-#ifndef OPENSSL_NO_EC
- else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
- q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
-#endif
- }
-
- if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
- sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
- sslContext->errorCode = QSslError::UnspecifiedError;
- return;
- }
- if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
- sslContext->pkey = 0; // Don't free the private key, it belongs to QSslKey
-
- // Check if the certificate matches the private key.
- if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
- sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
- sslContext->errorCode = QSslError::UnspecifiedError;
- return;
- }
-
- // If we have any intermediate certificates then we need to add them to our chain
- bool first = true;
- for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
- if (first) {
- first = false;
- continue;
- }
- q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
- q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
- }
- }
-
- // Initialize peer verification.
- if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
- q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0);
- } else {
- q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
- }
-
- // Set verification depth.
- if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
- q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
-
- // set persisted session if the user set it
- if (!configuration.sessionTicket().isEmpty())
- sslContext->setSessionASN1(configuration.sessionTicket());
-
- // Set temp DH params
- QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
-
- if (!dhparams.isValid()) {
- sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
- sslContext->errorCode = QSslError::UnspecifiedError;
- return;
- }
-
- if (!dhparams.isEmpty()) {
- const QByteArray &params = dhparams.d->derData;
- const char *ptr = params.constData();
- DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length());
- if (dh == NULL)
- qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
- q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
- q_DH_free(dh);
- }
-
-#ifndef OPENSSL_NO_EC
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
- if (q_SSLeay() >= 0x10002000L) {
- q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL);
- } else
-#endif
- {
- // Set temp ECDH params
- EC_KEY *ecdh = 0;
- ecdh = q_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
- q_SSL_CTX_set_tmp_ecdh(sslContext->ctx, ecdh);
- q_EC_KEY_free(ecdh);
- }
-#endif // OPENSSL_NO_EC
-
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
- if (!client)
- q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
-#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
-
- const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
- if (!qcurves.isEmpty()) {
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
- // Set the curves to be used
- if (q_SSLeay() >= 0x10002000L) {
- // SSL_CTX_ctrl wants a non-const pointer as last argument,
- // but let's avoid a copy into a temporary array
- if (!q_SSL_CTX_ctrl(sslContext->ctx,
- SSL_CTRL_SET_CURVES,
- qcurves.size(),
- const_cast<int *>(reinterpret_cast<const int *>(qcurves.data())))) {
- sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
- sslContext->errorCode = QSslError::UnspecifiedError;
- }
- } else
-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
- {
- // specific curves requested, but not possible to set -> error
- sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
- sslContext->errorCode = QSslError::UnspecifiedError;
- }
- }
-}
-
QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
{
QSslContext *sslContext = new QSslContext();
@@ -463,7 +160,7 @@ SSL* QSslContext::createSsl()
m_npnContext.len = m_supportedNPNVersions.count();
m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
- if (q_SSLeay() >= 0x10002000L) {
+ if (QSslSocket::sslLibraryVersionNumber() >= 0x10002000L) {
// Callback's type has a parameter 'const unsigned char ** out'
// since it was introduced in 1.0.2. Internally, OpenSSL's own code
// (tests/examples) cast it to unsigned char * (since it's 'out').
@@ -508,7 +205,7 @@ bool QSslContext::cacheSession(SSL* ssl)
unsigned char *data = reinterpret_cast<unsigned char *>(m_sessionASN1.data());
if (!q_i2d_SSL_SESSION(session, &data))
qCWarning(lcSsl, "could not store persistent version of SSL session");
- m_sessionTicketLifeTimeHint = session->tlsext_tick_lifetime_hint;
+ m_sessionTicketLifeTimeHint = q_SSL_SESSION_get_ticket_lifetime_hint(session);
}
}
diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp
new file mode 100644
index 0000000000..787b6ae3f5
--- /dev/null
+++ b/src/network/ssl/qsslcontext_openssl11.cpp
@@ -0,0 +1,277 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+** Copyright (C) 2014 Governikus GmbH & Co. KG.
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtNetwork/qsslsocket.h>
+#include <QtNetwork/qssldiffiehellmanparameters.h>
+
+#include "private/qssl_p.h"
+#include "private/qsslcontext_openssl_p.h"
+#include "private/qsslsocket_p.h"
+#include "private/qsslsocket_openssl_p.h"
+#include "private/qsslsocket_openssl_symbols_p.h"
+#include "private/qssldiffiehellmanparameters_p.h"
+
+#include <vector>
+
+QT_BEGIN_NAMESPACE
+
+// defined in qsslsocket_openssl.cpp:
+extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
+extern QString getErrorsFromOpenSsl();
+
+static inline QString msgErrorSettingEllipticCurves(const QString &why)
+{
+ return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
+}
+
+// static
+void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
+{
+ sslContext->sslConfiguration = configuration;
+ sslContext->errorCode = QSslError::NoError;
+
+ bool client = (mode == QSslSocket::SslClientMode);
+
+ bool reinitialized = false;
+ bool unsupportedProtocol = false;
+init_context:
+ if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) {
+ // SSL 2 is no longer supported, but chosen deliberately -> error
+ sslContext->ctx = nullptr;
+ unsupportedProtocol = true;
+ } else {
+ // The ssl options will actually control the supported methods
+ sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method());
+ }
+
+ if (!sslContext->ctx) {
+ // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
+ // by re-initializing the library.
+ if (!reinitialized) {
+ reinitialized = true;
+ if (q_OPENSSL_init_ssl(0, nullptr) == 1)
+ goto init_context;
+ }
+
+ sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
+ unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
+ );
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ // Enable bug workarounds.
+ long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
+ q_SSL_CTX_set_options(sslContext->ctx, options);
+
+ // Tell OpenSSL to release memory early
+ // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
+ q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
+
+ // Initialize ciphers
+ QByteArray cipherString;
+ bool first = true;
+ QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
+ if (ciphers.isEmpty())
+ ciphers = QSslSocketPrivate::defaultCiphers();
+ for (const QSslCipher &cipher : qAsConst(ciphers)) {
+ if (first)
+ first = false;
+ else
+ cipherString.append(':');
+ cipherString.append(cipher.name().toLatin1());
+ }
+
+ if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
+ sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ const QDateTime now = QDateTime::currentDateTimeUtc();
+
+ // Add all our CAs to this store.
+ const auto caCertificates = sslContext->sslConfiguration.caCertificates();
+ for (const QSslCertificate &caCertificate : caCertificates) {
+ // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
+ //
+ // If several CA certificates matching the name, key identifier, and
+ // serial number condition are available, only the first one will be
+ // examined. This may lead to unexpected results if the same CA
+ // certificate is available with different expiration dates. If a
+ // ``certificate expired'' verification error occurs, no other
+ // certificate will be searched. Make sure to not have expired
+ // certificates mixed with valid ones.
+ //
+ // See also: QSslSocketBackendPrivate::verify()
+ if (caCertificate.expiryDate() >= now) {
+ q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
+ }
+ }
+
+ if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
+ // tell OpenSSL the directories where to look up the root certs on demand
+ const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
+ for (const QByteArray &unixDir : unixDirs)
+ q_SSL_CTX_load_verify_locations(sslContext->ctx, nullptr, unixDir.constData());
+ }
+
+ if (!sslContext->sslConfiguration.localCertificate().isNull()) {
+ // Require a private key as well.
+ if (sslContext->sslConfiguration.privateKey().isNull()) {
+ sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ // Load certificate
+ if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
+ sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
+ sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
+ } else {
+ // Load private key
+ sslContext->pkey = q_EVP_PKEY_new();
+ // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
+ // this lead to a memory leak. Now we use the *_set1_* functions which do not
+ // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
+ if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
+ q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
+ else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
+ q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
+#ifndef OPENSSL_NO_EC
+ else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
+ q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
+#endif
+ }
+
+ if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
+ sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+ if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
+ sslContext->pkey = nullptr; // Don't free the private key, it belongs to QSslKey
+
+ // Check if the certificate matches the private key.
+ if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
+ sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ // If we have any intermediate certificates then we need to add them to our chain
+ bool first = true;
+ for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
+ if (first) {
+ first = false;
+ continue;
+ }
+ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
+ q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
+ }
+ }
+
+ // Initialize peer verification.
+ if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
+ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr);
+ } else {
+ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
+ }
+
+ // Set verification depth.
+ if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
+ q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
+
+ // set persisted session if the user set it
+ if (!configuration.sessionTicket().isEmpty())
+ sslContext->setSessionASN1(configuration.sessionTicket());
+
+ // Set temp DH params
+ QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
+
+ if (!dhparams.isValid()) {
+ sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ if (!dhparams.isEmpty()) {
+ const QByteArray &params = dhparams.d->derData;
+ const char *ptr = params.constData();
+ DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length());
+ if (dh == NULL)
+ qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
+ q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
+ q_DH_free(dh);
+ }
+
+#ifndef OPENSSL_NO_PSK
+ if (!client)
+ q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
+#endif // !OPENSSL_NO_PSK
+
+ const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
+ if (!qcurves.isEmpty()) {
+#ifdef OPENSSL_NO_EC
+ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version with disabled elliptic curves"));
+ sslContext->errorCode = QSslError::UnspecifiedError;
+#else
+ // Set the curves to be used.
+ std::vector<int> curves;
+ curves.reserve(qcurves.size());
+ for (const auto &sslCurve : qcurves)
+ curves.push_back(sslCurve.id);
+ if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES, long(curves.size()), &curves[0])) {
+ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ }
+#endif
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslcontext_opensslpre11.cpp b/src/network/ssl/qsslcontext_opensslpre11.cpp
new file mode 100644
index 0000000000..9c01c2f2dc
--- /dev/null
+++ b/src/network/ssl/qsslcontext_opensslpre11.cpp
@@ -0,0 +1,354 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+** Copyright (C) 2014 Governikus GmbH & Co. KG.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtNetwork/qsslsocket.h>
+#include <QtNetwork/qssldiffiehellmanparameters.h>
+
+#include "private/qssl_p.h"
+#include "private/qsslcontext_openssl_p.h"
+#include "private/qsslsocket_p.h"
+#include "private/qsslsocket_openssl_p.h"
+#include "private/qsslsocket_openssl_symbols_p.h"
+#include "private/qssldiffiehellmanparameters_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// defined in qsslsocket_openssl.cpp:
+extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
+extern QString getErrorsFromOpenSsl();
+
+static inline QString msgErrorSettingEllipticCurves(const QString &why)
+{
+ return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
+}
+
+// static
+void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
+{
+ sslContext->sslConfiguration = configuration;
+ sslContext->errorCode = QSslError::NoError;
+
+ bool client = (mode == QSslSocket::SslClientMode);
+
+ bool reinitialized = false;
+ bool unsupportedProtocol = false;
+init_context:
+ switch (sslContext->sslConfiguration.protocol()) {
+ case QSsl::SslV2:
+#ifndef OPENSSL_NO_SSL2
+ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
+#else
+ // SSL 2 not supported by the system, but chosen deliberately -> error
+ sslContext->ctx = 0;
+ unsupportedProtocol = true;
+#endif
+ break;
+ case QSsl::SslV3:
+#ifndef OPENSSL_NO_SSL3_METHOD
+ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
+#else
+ // SSL 3 not supported by the system, but chosen deliberately -> error
+ sslContext->ctx = 0;
+ unsupportedProtocol = true;
+#endif
+ break;
+ case QSsl::SecureProtocols:
+ // SSLv2 and SSLv3 will be disabled by SSL options
+ // But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32.
+ case QSsl::TlsV1SslV3:
+ // SSLv2 will will be disabled by SSL options
+ case QSsl::AnyProtocol:
+ default:
+ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
+ break;
+ case QSsl::TlsV1_0:
+ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method());
+ break;
+ case QSsl::TlsV1_1:
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method());
+#else
+ // TLS 1.1 not supported by the system, but chosen deliberately -> error
+ sslContext->ctx = 0;
+ unsupportedProtocol = true;
+#endif
+ break;
+ case QSsl::TlsV1_2:
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method());
+#else
+ // TLS 1.2 not supported by the system, but chosen deliberately -> error
+ sslContext->ctx = 0;
+ unsupportedProtocol = true;
+#endif
+ break;
+ case QSsl::TlsV1_0OrLater:
+ // Specific protocols will be specified via SSL options.
+ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
+ break;
+ case QSsl::TlsV1_1OrLater:
+ case QSsl::TlsV1_2OrLater:
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ // Specific protocols will be specified via SSL options.
+ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
+#else
+ // TLS 1.1/1.2 not supported by the system, but chosen deliberately -> error
+ sslContext->ctx = 0;
+ unsupportedProtocol = true;
+#endif
+ break;
+ }
+
+ if (!sslContext->ctx) {
+ // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
+ // by re-initializing the library.
+ if (!reinitialized) {
+ reinitialized = true;
+ if (q_SSL_library_init() == 1)
+ goto init_context;
+ }
+
+ sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
+ unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
+ );
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ // Enable bug workarounds.
+ long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
+ q_SSL_CTX_set_options(sslContext->ctx, options);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ // Tell OpenSSL to release memory early
+ // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
+ if (q_SSLeay() >= 0x10000000L)
+ q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
+#endif
+
+ // Initialize ciphers
+ QByteArray cipherString;
+ bool first = true;
+ QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
+ if (ciphers.isEmpty())
+ ciphers = QSslSocketPrivate::defaultCiphers();
+ for (const QSslCipher &cipher : qAsConst(ciphers)) {
+ if (first)
+ first = false;
+ else
+ cipherString.append(':');
+ cipherString.append(cipher.name().toLatin1());
+ }
+
+ if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
+ sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ const QDateTime now = QDateTime::currentDateTimeUtc();
+
+ // Add all our CAs to this store.
+ const auto caCertificates = sslContext->sslConfiguration.caCertificates();
+ for (const QSslCertificate &caCertificate : caCertificates) {
+ // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
+ //
+ // If several CA certificates matching the name, key identifier, and
+ // serial number condition are available, only the first one will be
+ // examined. This may lead to unexpected results if the same CA
+ // certificate is available with different expiration dates. If a
+ // ``certificate expired'' verification error occurs, no other
+ // certificate will be searched. Make sure to not have expired
+ // certificates mixed with valid ones.
+ //
+ // See also: QSslSocketBackendPrivate::verify()
+ if (caCertificate.expiryDate() >= now) {
+ q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
+ }
+ }
+
+ if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
+ // tell OpenSSL the directories where to look up the root certs on demand
+ const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
+ for (const QByteArray &unixDir : unixDirs)
+ q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDir.constData());
+ }
+
+ if (!sslContext->sslConfiguration.localCertificate().isNull()) {
+ // Require a private key as well.
+ if (sslContext->sslConfiguration.privateKey().isNull()) {
+ sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ // Load certificate
+ if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
+ sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
+ sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
+ } else {
+ // Load private key
+ sslContext->pkey = q_EVP_PKEY_new();
+ // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
+ // this lead to a memory leak. Now we use the *_set1_* functions which do not
+ // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
+ if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
+ q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
+ else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
+ q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
+#ifndef OPENSSL_NO_EC
+ else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
+ q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
+#endif
+ }
+
+ if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
+ sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+ if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
+ sslContext->pkey = 0; // Don't free the private key, it belongs to QSslKey
+
+ // Check if the certificate matches the private key.
+ if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
+ sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ // If we have any intermediate certificates then we need to add them to our chain
+ bool first = true;
+ for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
+ if (first) {
+ first = false;
+ continue;
+ }
+ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
+ q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
+ }
+ }
+
+ // Initialize peer verification.
+ if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
+ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0);
+ } else {
+ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
+ }
+
+ // Set verification depth.
+ if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
+ q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
+
+ // set persisted session if the user set it
+ if (!configuration.sessionTicket().isEmpty())
+ sslContext->setSessionASN1(configuration.sessionTicket());
+
+ // Set temp DH params
+ QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
+
+ if (!dhparams.isValid()) {
+ sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ return;
+ }
+
+ if (!dhparams.isEmpty()) {
+ const QByteArray &params = dhparams.d->derData;
+ const char *ptr = params.constData();
+ DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length());
+ if (dh == NULL)
+ qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
+ q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
+ q_DH_free(dh);
+ }
+
+#ifndef OPENSSL_NO_EC
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ if (q_SSLeay() >= 0x10002000L) {
+ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL);
+ } else
+#endif
+ {
+ // Set temp ECDH params
+ EC_KEY *ecdh = 0;
+ ecdh = q_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ q_SSL_CTX_set_tmp_ecdh(sslContext->ctx, ecdh);
+ q_EC_KEY_free(ecdh);
+ }
+#endif // OPENSSL_NO_EC
+
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
+ if (!client)
+ q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
+#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
+
+ const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
+ if (!qcurves.isEmpty()) {
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
+ // Set the curves to be used
+ if (q_SSLeay() >= 0x10002000L) {
+ // SSL_CTX_ctrl wants a non-const pointer as last argument,
+ // but let's avoid a copy into a temporary array
+ if (!q_SSL_CTX_ctrl(sslContext->ctx,
+ SSL_CTRL_SET_CURVES,
+ qcurves.size(),
+ const_cast<int *>(reinterpret_cast<const int *>(qcurves.data())))) {
+ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ }
+ } else
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
+ {
+ // specific curves requested, but not possible to set -> error
+ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
+ sslContext->errorCode = QSslError::UnspecifiedError;
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
index 90687b05c5..5ebad822f1 100644
--- a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
+++ b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -50,8 +51,8 @@
#include <QtCore/qdebug.h>
#endif
-// For q_BN_is_word.
#include <openssl/bn.h>
+#include <openssl/dh.h>
QT_BEGIN_NAMESPACE
@@ -62,13 +63,6 @@ static bool isSafeDH(DH *dh)
QSslSocketPrivate::ensureInitialized();
- // Mark p < 1024 bits as unsafe.
- if (q_BN_num_bits(dh->p) < 1024) {
- return false;
- }
-
- if (q_DH_check(dh, &status) != 1)
- return false;
// From https://wiki.openssl.org/index.php/Diffie-Hellman_parameters:
//
@@ -81,11 +75,39 @@ static bool isSafeDH(DH *dh)
// Without the test, the IETF parameters would
// fail validation. For details, see Diffie-Hellman
// Parameter Check (when g = 2, must p mod 24 == 11?).
+#if QT_CONFIG(opensslv11)
+ // Mark p < 1024 bits as unsafe.
+ if (q_DH_bits(dh) < 1024)
+ return false;
+
+ if (q_DH_check(dh, &status) != 1)
+ return false;
+
+ const BIGNUM *p = nullptr;
+ const BIGNUM *q = nullptr;
+ const BIGNUM *g = nullptr;
+ q_DH_get0_pqg(dh, &p, &q, &g);
+
+ if (q_BN_is_word(const_cast<BIGNUM *>(g), DH_GENERATOR_2)) {
+ long residue = q_BN_mod_word(p, 24);
+ if (residue == 11 || residue == 23)
+ status &= ~DH_NOT_SUITABLE_GENERATOR;
+ }
+
+#else
+ // Mark p < 1024 bits as unsafe.
+ if (q_BN_num_bits(dh->p) < 1024)
+ return false;
+
+ if (q_DH_check(dh, &status) != 1)
+ return false;
+
if (q_BN_is_word(dh->g, DH_GENERATOR_2)) {
long residue = q_BN_mod_word(dh->p, 24);
if (residue == 11 || residue == 23)
status &= ~DH_NOT_SUITABLE_GENERATOR;
}
+#endif
bad |= DH_CHECK_P_NOT_PRIME;
bad |= DH_CHECK_P_NOT_SAFE_PRIME;
diff --git a/src/network/ssl/qsslellipticcurve.h b/src/network/ssl/qsslellipticcurve.h
index 231566063e..57dda19bad 100644
--- a/src/network/ssl/qsslellipticcurve.h
+++ b/src/network/ssl/qsslellipticcurve.h
@@ -80,6 +80,7 @@ private:
friend Q_DECL_CONSTEXPR bool operator==(QSslEllipticCurve lhs, QSslEllipticCurve rhs) Q_DECL_NOTHROW;
friend Q_DECL_CONSTEXPR uint qHash(QSslEllipticCurve curve, uint seed) Q_DECL_NOTHROW;
+ friend class QSslContext;
friend class QSslSocketPrivate;
friend class QSslSocketBackendPrivate;
};
diff --git a/src/network/ssl/qsslellipticcurve_openssl.cpp b/src/network/ssl/qsslellipticcurve_openssl.cpp
index e18197b703..8cd14837f0 100644
--- a/src/network/ssl/qsslellipticcurve_openssl.cpp
+++ b/src/network/ssl/qsslellipticcurve_openssl.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2014 Governikus GmbH & Co. KG.
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -78,17 +79,18 @@ QSslEllipticCurve QSslEllipticCurve::fromShortName(const QString &name)
QSslEllipticCurve result;
#ifndef OPENSSL_NO_EC
- const QByteArray curveNameLatin1 = name.toLatin1();
+ const QByteArray curveNameLatin1 = name.toLatin1();
int nid = q_OBJ_sn2nid(curveNameLatin1.data());
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
- if (nid == 0 && q_SSLeay() >= 0x10002000L)
+ if (nid == 0 && QSslSocket::sslLibraryVersionNumber() >= 0x10002000L)
nid = q_EC_curve_nist2nid(curveNameLatin1.data());
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
result.id = nid;
-#endif
+
+#endif // !OPENSSL_NO_EC
return result;
}
diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp
index 79df33ecca..be7033c8aa 100644
--- a/src/network/ssl/qsslkey_openssl.cpp
+++ b/src/network/ssl/qsslkey_openssl.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -84,33 +85,30 @@ void QSslKeyPrivate::clear(bool deep)
bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey)
{
- if (pkey->type == EVP_PKEY_RSA) {
+#if QT_CONFIG(opensslv11)
+ const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey));
+#else
+ const int keyType = pkey->type;
+#endif
+ if (keyType == EVP_PKEY_RSA) {
isNull = false;
algorithm = QSsl::Rsa;
type = QSsl::PrivateKey;
-
- rsa = q_RSA_new();
- memcpy(rsa, q_EVP_PKEY_get1_RSA(pkey), sizeof(RSA));
-
+ rsa = q_EVP_PKEY_get1_RSA(pkey);
return true;
- }
- else if (pkey->type == EVP_PKEY_DSA) {
+ } else if (keyType == EVP_PKEY_DSA) {
isNull = false;
algorithm = QSsl::Dsa;
type = QSsl::PrivateKey;
-
- dsa = q_DSA_new();
- memcpy(dsa, q_EVP_PKEY_get1_DSA(pkey), sizeof(DSA));
-
+ dsa = q_EVP_PKEY_get1_DSA(pkey);
return true;
}
#ifndef OPENSSL_NO_EC
- else if (pkey->type == EVP_PKEY_EC) {
+ else if (keyType == EVP_PKEY_EC) {
isNull = false;
algorithm = QSsl::Ec;
type = QSsl::PrivateKey;
- ec = q_EC_KEY_dup(q_EVP_PKEY_get1_EC_KEY(pkey));
-
+ ec = q_EVP_PKEY_get1_EC_KEY(pkey);
return true;
}
#endif
@@ -178,8 +176,8 @@ int QSslKeyPrivate::length() const
return -1;
switch (algorithm) {
- case QSsl::Rsa: return q_BN_num_bits(rsa->n);
- case QSsl::Dsa: return q_BN_num_bits(dsa->p);
+ case QSsl::Rsa: return q_RSA_bits(rsa);
+ case QSsl::Dsa: return q_DSA_bits(dsa);
#ifndef OPENSSL_NO_EC
case QSsl::Ec: return q_EC_GROUP_get_degree(q_EC_KEY_get0_group(ec));
#endif
@@ -273,7 +271,13 @@ Qt::HANDLE QSslKeyPrivate::handle() const
static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv, int enc)
{
- EVP_CIPHER_CTX ctx;
+#if QT_CONFIG(opensslv11)
+ EVP_CIPHER_CTX *ctx = q_EVP_CIPHER_CTX_new();
+#else
+ EVP_CIPHER_CTX evpCipherContext;
+ EVP_CIPHER_CTX *ctx = &evpCipherContext;
+#endif
+
const EVP_CIPHER* type = 0;
int i = 0, len = 0;
@@ -291,21 +295,44 @@ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data,
QByteArray output;
output.resize(data.size() + EVP_MAX_BLOCK_LENGTH);
- q_EVP_CIPHER_CTX_init(&ctx);
- q_EVP_CipherInit(&ctx, type, NULL, NULL, enc);
- q_EVP_CIPHER_CTX_set_key_length(&ctx, key.size());
+
+#if QT_CONFIG(opensslv11)
+ q_EVP_CIPHER_CTX_reset(ctx);
+#else
+ q_EVP_CIPHER_CTX_init(ctx);
+#endif
+
+ q_EVP_CipherInit(ctx, type, NULL, NULL, enc);
+ q_EVP_CIPHER_CTX_set_key_length(ctx, key.size());
if (cipher == QSslKeyPrivate::Rc2Cbc)
- q_EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), NULL);
- q_EVP_CipherInit(&ctx, NULL,
+ q_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), NULL);
+
+#if QT_CONFIG(opensslv11)
+ // EVP_CipherInit in 1.1 resets the context thus making the calls above useless.
+ // We call EVP_CipherInit_ex instead.
+ q_EVP_CipherInit_ex(ctx, nullptr, nullptr,
+ reinterpret_cast<const unsigned char *>(key.constData()),
+ reinterpret_cast<const unsigned char *>(iv.constData()),
+ enc);
+#else
+ q_EVP_CipherInit(ctx, NULL,
reinterpret_cast<const unsigned char *>(key.constData()),
reinterpret_cast<const unsigned char *>(iv.constData()), enc);
- q_EVP_CipherUpdate(&ctx,
+#endif // opensslv11
+
+ q_EVP_CipherUpdate(ctx,
reinterpret_cast<unsigned char *>(output.data()), &len,
reinterpret_cast<const unsigned char *>(data.constData()), data.size());
- q_EVP_CipherFinal(&ctx,
+ q_EVP_CipherFinal(ctx,
reinterpret_cast<unsigned char *>(output.data()) + len, &i);
len += i;
- q_EVP_CIPHER_CTX_cleanup(&ctx);
+
+#if QT_CONFIG(opensslv11)
+ q_EVP_CIPHER_CTX_reset(ctx);
+ q_EVP_CIPHER_CTX_free(ctx);
+#else
+ q_EVP_CIPHER_CTX_cleanup(ctx);
+#endif
return output.left(len);
}
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index 84b8f3a8d9..9b62240767 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -1993,6 +1993,8 @@ qint64 QSslSocket::readData(char *data, qint64 maxlen)
// possibly trigger another transmit() to decrypt more data from the socket
if (d->plainSocket->bytesAvailable())
QMetaObject::invokeMethod(this, "_q_flushReadBuffer", Qt::QueuedConnection);
+ else if (d->state != QAbstractSocket::ConnectedState)
+ return maxlen ? qint64(-1) : qint64(0);
}
return readBytes;
@@ -2013,7 +2015,10 @@ qint64 QSslSocket::writeData(const char *data, qint64 len)
d->writeBuffer.append(data, len);
// make sure we flush to the plain socket's buffer
- QMetaObject::invokeMethod(this, "_q_flushWriteBuffer", Qt::QueuedConnection);
+ if (!d->flushTriggered) {
+ d->flushTriggered = true;
+ QMetaObject::invokeMethod(this, "_q_flushWriteBuffer", Qt::QueuedConnection);
+ }
return len;
}
@@ -2032,6 +2037,7 @@ QSslSocketPrivate::QSslSocketPrivate()
, allowRootCertOnDemandLoading(true)
, plainSocket(0)
, paused(false)
+ , flushTriggered(false)
{
QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration);
}
@@ -2054,6 +2060,7 @@ void QSslSocketPrivate::init()
ignoreAllSslErrors = false;
shutdown = false;
pendingClose = false;
+ flushTriggered = false;
// we don't want to clear the ignoreErrorsList, so
// that it is possible setting it before connecting
@@ -2510,6 +2517,10 @@ void QSslSocketPrivate::_q_channelBytesWrittenSlot(int channel, qint64 written)
void QSslSocketPrivate::_q_flushWriteBuffer()
{
Q_Q(QSslSocket);
+
+ // need to notice if knock-on effects of this flush (e.g. a readReady() via transmit())
+ // make another necessary, so clear flag before calling:
+ flushTriggered = false;
if (!writeBuffer.isEmpty())
q->flush();
}
diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp
index 2aecf3407f..68c8ccff89 100644
--- a/src/network/ssl/qsslsocket_mac.cpp
+++ b/src/network/ssl/qsslsocket_mac.cpp
@@ -96,16 +96,14 @@ EphemeralSecKeychain::EphemeralSecKeychain()
return;
}
- QString uuidAsString(uuid.toString());
- Q_ASSERT(uuidAsString.size() > 2);
- Q_ASSERT(uuidAsString.startsWith(QLatin1Char('{'))
- && uuidAsString.endsWith(QLatin1Char('}')));
- uuidAsString = uuidAsString.mid(1, uuidAsString.size() - 2);
-
- QString keychainName(QDir::tempPath());
- keychainName.append(QDir::separator());
- keychainName += uuidAsString;
- keychainName += QLatin1String(".keychain");
+ const QByteArray uuidAsByteArray = uuid.toByteArray();
+ Q_ASSERT(uuidAsByteArray.size() > 2);
+ Q_ASSERT(uuidAsByteArray.startsWith('{'));
+ Q_ASSERT(uuidAsByteArray.endsWith('}'));
+ const auto uuidAsString = QLatin1String(uuidAsByteArray.data(), uuidAsByteArray.size()).mid(1, uuidAsByteArray.size() - 2);
+
+ const QString keychainName
+ = QDir::tempPath() + QDir::separator() + uuidAsString + QLatin1String(".keychain");
// SecKeychainCreate, pathName parameter:
//
// "A constant character string representing the POSIX path indicating where
@@ -1108,6 +1106,12 @@ bool QSslSocketBackendPrivate::verifySessionProtocol() const
protocolOk = (sessionProtocol() >= QSsl::SslV3);
else if (configuration.protocol == QSsl::SecureProtocols)
protocolOk = (sessionProtocol() >= QSsl::TlsV1_0);
+ else if (configuration.protocol == QSsl::TlsV1_0OrLater)
+ protocolOk = (sessionProtocol() >= QSsl::TlsV1_0);
+ else if (configuration.protocol == QSsl::TlsV1_1OrLater)
+ protocolOk = (sessionProtocol() >= QSsl::TlsV1_1);
+ else if (configuration.protocol == QSsl::TlsV1_2OrLater)
+ protocolOk = (sessionProtocol() >= QSsl::TlsV1_2);
else
protocolOk = (sessionProtocol() == configuration.protocol);
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 644dfdb6a8..650d37fdbb 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2014 Governikus GmbH & Co. KG
** Contact: https://www.qt.io/licensing/
**
@@ -97,70 +97,6 @@ bool QSslSocketPrivate::s_loadRootCertsOnDemand = false;
int QSslSocketBackendPrivate::s_indexForSSLExtraData = -1;
#endif
-/* \internal
-
- From OpenSSL's thread(3) manual page:
-
- OpenSSL can safely be used in multi-threaded applications provided that at
- least two callback functions are set.
-
- locking_function(int mode, int n, const char *file, int line) is needed to
- perform locking on shared data structures. (Note that OpenSSL uses a
- number of global data structures that will be implicitly shared
- whenever multiple threads use OpenSSL.) Multi-threaded
- applications will crash at random if it is not set. ...
- ...
- id_function(void) is a function that returns a thread ID. It is not
- needed on Windows nor on platforms where getpid() returns a different
- ID for each thread (most notably Linux)
-*/
-class QOpenSslLocks
-{
-public:
- inline QOpenSslLocks()
- : initLocker(QMutex::Recursive),
- locksLocker(QMutex::Recursive)
- {
- QMutexLocker locker(&locksLocker);
- int numLocks = q_CRYPTO_num_locks();
- locks = new QMutex *[numLocks];
- memset(locks, 0, numLocks * sizeof(QMutex *));
- }
- inline ~QOpenSslLocks()
- {
- QMutexLocker locker(&locksLocker);
- for (int i = 0; i < q_CRYPTO_num_locks(); ++i)
- delete locks[i];
- delete [] locks;
-
- QSslSocketPrivate::deinitialize();
- }
- inline QMutex *lock(int num)
- {
- QMutexLocker locker(&locksLocker);
- QMutex *tmp = locks[num];
- if (!tmp)
- tmp = locks[num] = new QMutex(QMutex::Recursive);
- return tmp;
- }
-
- QMutex *globalLock()
- {
- return &locksLocker;
- }
-
- QMutex *initLock()
- {
- return &initLocker;
- }
-
-private:
- QMutex initLocker;
- QMutex locksLocker;
- QMutex **locks;
-};
-Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks)
-
QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
{
QString errorString;
@@ -175,20 +111,6 @@ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
}
extern "C" {
-static void locking_function(int mode, int lockNumber, const char *, int)
-{
- QMutex *mutex = openssl_locks()->lock(lockNumber);
-
- // Lock or unlock it
- if (mode & CRYPTO_LOCK)
- mutex->lock();
- else
- mutex->unlock();
-}
-static unsigned long id_function()
-{
- return (quintptr)QThread::currentThreadId();
-}
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
static unsigned int q_ssl_psk_client_callback(SSL *ssl,
@@ -227,7 +149,7 @@ QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
destroySslContext();
}
-QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher)
+QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher)
{
QSslCipher ciph;
@@ -268,12 +190,12 @@ QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *ciph
}
// static
-inline QSslErrorEntry QSslErrorEntry::fromStoreContext(X509_STORE_CTX *ctx) {
- QSslErrorEntry result = {
+inline QSslErrorEntry QSslErrorEntry::fromStoreContext(X509_STORE_CTX *ctx)
+{
+ return {
q_X509_STORE_CTX_get_error(ctx),
q_X509_STORE_CTX_get_error_depth(ctx)
};
- return result;
}
// ### This list is shared between all threads, and protected by a
@@ -283,6 +205,7 @@ struct QSslErrorList
QMutex mutex;
QVector<QSslErrorEntry> errors;
};
+
Q_GLOBAL_STATIC(QSslErrorList, _q_sslErrorList)
int q_X509Callback(int ok, X509_STORE_CTX *ctx)
@@ -312,7 +235,7 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
}
#endif
}
- // Always return OK to allow verification to continue. We're handle the
+ // Always return OK to allow verification to continue. We handle the
// errors gracefully after collecting all errors, after verification has
// completed.
return 1;
@@ -397,7 +320,7 @@ bool QSslSocketBackendPrivate::initSslContext()
if (configuration.protocol != QSsl::SslV2 &&
configuration.protocol != QSsl::SslV3 &&
configuration.protocol != QSsl::UnknownProtocol &&
- mode == QSslSocket::SslClientMode && q_SSLeay() >= 0x00090806fL) {
+ mode == QSslSocket::SslClientMode && QSslSocket::sslLibraryVersionNumber() >= 0x00090806fL) {
// Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
if (tlsHostName.isEmpty())
@@ -438,13 +361,13 @@ bool QSslSocketBackendPrivate::initSslContext()
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
// Save a pointer to this object into the SSL structure.
- if (q_SSLeay() >= 0x10001000L)
+ if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L)
q_SSL_set_ex_data(ssl, s_indexForSSLExtraData, this);
#endif
#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
// Set the client callback for PSK
- if (q_SSLeay() >= 0x10001000L) {
+ if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L) {
if (mode == QSslSocket::SslClientMode)
q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback);
else if (mode == QSslSocket::SslServerMode)
@@ -466,16 +389,6 @@ void QSslSocketBackendPrivate::destroySslContext()
/*!
\internal
-*/
-void QSslSocketPrivate::deinitialize()
-{
- q_CRYPTO_set_id_callback(0);
- q_CRYPTO_set_locking_callback(0);
- q_ERR_free_strings();
-}
-
-/*!
- \internal
Does the minimum amount of initialization to determine whether SSL
is supported or not.
@@ -486,91 +399,6 @@ bool QSslSocketPrivate::supportsSsl()
return ensureLibraryLoaded();
}
-bool QSslSocketPrivate::ensureLibraryLoaded()
-{
- if (!q_resolveOpenSslSymbols())
- return false;
-
- // Check if the library itself needs to be initialized.
- QMutexLocker locker(openssl_locks()->initLock());
-
- if (!s_libraryLoaded) {
- s_libraryLoaded = true;
-
- // Initialize OpenSSL.
- q_CRYPTO_set_id_callback(id_function);
- q_CRYPTO_set_locking_callback(locking_function);
- if (q_SSL_library_init() != 1)
- return false;
- q_SSL_load_error_strings();
- q_OpenSSL_add_all_algorithms();
-
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- if (q_SSLeay() >= 0x10001000L)
- QSslSocketBackendPrivate::s_indexForSSLExtraData = q_SSL_get_ex_new_index(0L, NULL, NULL, NULL, NULL);
-#endif
-
- // Initialize OpenSSL's random seed.
- if (!q_RAND_status()) {
- qWarning("Random number generator not seeded, disabling SSL support");
- return false;
- }
- }
- return true;
-}
-
-void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
-{
- QMutexLocker locker(openssl_locks()->initLock());
- if (s_loadedCiphersAndCerts)
- return;
- s_loadedCiphersAndCerts = true;
-
- resetDefaultCiphers();
- resetDefaultEllipticCurves();
-
-#if QT_CONFIG(library)
- //load symbols needed to receive certificates from system store
-#if defined(Q_OS_WIN)
- HINSTANCE hLib = LoadLibraryW(L"Crypt32");
- if (hLib) {
- ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
- ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
- ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
- if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
- qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
- } else {
- qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
- }
-#elif defined(Q_OS_QNX)
- s_loadRootCertsOnDemand = true;
-#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
- // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
- QList<QByteArray> dirs = unixRootCertDirectories();
- QStringList symLinkFilter;
- symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
- for (int a = 0; a < dirs.count(); ++a) {
- QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
- if (iterator.hasNext()) {
- s_loadRootCertsOnDemand = true;
- break;
- }
- }
-#endif
-#endif // QT_CONFIG(library)
- // if on-demand loading was not enabled, load the certs now
- if (!s_loadRootCertsOnDemand)
- setDefaultCaCertificates(systemCaCertificates());
-#ifdef Q_OS_WIN
- //Enabled for fetching additional root certs from windows update on windows 6+
- //This flag is set false by setDefaultCaCertificates() indicating the app uses
- //its own cert bundle rather than the system one.
- //Same logic that disables the unix on demand cert loading.
- //Unlike unix, we do preload the certificates from the cert store.
- if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
- s_loadRootCertsOnDemand = true;
-#endif
-}
/*!
\internal
@@ -587,26 +415,6 @@ void QSslSocketPrivate::ensureInitialized()
ensureCiphersAndCertsLoaded();
}
-long QSslSocketPrivate::sslLibraryVersionNumber()
-{
- if (!supportsSsl())
- return 0;
-
- return q_SSLeay();
-}
-
-QString QSslSocketPrivate::sslLibraryVersionString()
-{
- if (!supportsSsl())
- return QString();
-
- const char *versionString = q_SSLeay_version(SSLEAY_VERSION);
- if (!versionString)
- return QString();
-
- return QString::fromLatin1(versionString);
-}
-
long QSslSocketPrivate::sslLibraryBuildVersionNumber()
{
return OPENSSL_VERSION_NUMBER;
@@ -628,7 +436,11 @@ QString QSslSocketPrivate::sslLibraryBuildVersionString()
*/
void QSslSocketPrivate::resetDefaultCiphers()
{
+#if QT_CONFIG(opensslv11)
+ SSL_CTX *myCtx = q_SSL_CTX_new(q_TLS_client_method());
+#else
SSL_CTX *myCtx = q_SSL_CTX_new(q_SSLv23_client_method());
+#endif
SSL *mySsl = q_SSL_new(myCtx);
QList<QSslCipher> ciphers;
@@ -664,7 +476,7 @@ void QSslSocketPrivate::resetDefaultEllipticCurves()
QVector<QSslEllipticCurve> curves;
#ifndef OPENSSL_NO_EC
- const size_t curveCount = q_EC_get_builtin_curves(NULL, 0);
+ const size_t curveCount = q_EC_get_builtin_curves(nullptr, 0);
QVarLengthArray<EC_builtin_curve> builtinCurves(static_cast<int>(curveCount));
@@ -698,13 +510,14 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
HCERTSTORE hSystemStore;
hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT");
- if(hSystemStore) {
- PCCERT_CONTEXT pc = NULL;
- while(1) {
- pc = ptrCertFindCertificateInStore( hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pc);
- if(!pc)
+ if (hSystemStore) {
+ PCCERT_CONTEXT pc = nullptr;
+ while (1) {
+ pc = ptrCertFindCertificateInStore(hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, pc);
+ if (!pc)
break;
- QByteArray der((const char *)(pc->pbCertEncoded), static_cast<int>(pc->cbCertEncoded));
+ QByteArray der(reinterpret_cast<const char *>(pc->pbCertEncoded),
+ static_cast<int>(pc->cbCertEncoded));
QSslCertificate cert(der, QSsl::Der);
systemCerts.append(cert);
}
@@ -943,15 +756,15 @@ void QSslSocketBackendPrivate::transmit()
// we have a readBufferMaxSize. There's no point in leaving data there
// just so that readBuffer.size() == readBufferMaxSize.
int readBytes = 0;
- data.resize(4096);
- ::memset(data.data(), 0, data.size());
+ const int bytesToRead = 4096;
do {
// Don't use SSL_pending(). It's very unreliable.
- if ((readBytes = q_SSL_read(ssl, data.data(), data.size())) > 0) {
+ readBytes = q_SSL_read(ssl, buffer.reserve(bytesToRead), bytesToRead);
+ if (readBytes > 0) {
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "QSslSocketBackendPrivate::transmit: decrypted" << readBytes << "bytes";
#endif
- buffer.append(data.constData(), readBytes);
+ buffer.chop(bytesToRead - readBytes);
if (readyReadEmittedPointer)
*readyReadEmittedPointer = true;
@@ -960,6 +773,7 @@ void QSslSocketBackendPrivate::transmit()
transmitting = true;
continue;
}
+ buffer.chop(bytesToRead);
// Error.
switch (q_SSL_get_error(ssl, readBytes)) {
@@ -1502,14 +1316,8 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const
{
if (!ssl)
return QSslCipher();
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- // FIXME This is fairly evil, but needed to keep source level compatibility
- // with the OpenSSL 0.9.x implementation at maximum -- some other functions
- // don't take a const SSL_CIPHER* when they should
- SSL_CIPHER *sessionCipher = const_cast<SSL_CIPHER *>(q_SSL_get_current_cipher(ssl));
-#else
- SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
-#endif
+
+ const SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
}
@@ -1535,112 +1343,6 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
return QSsl::UnknownProtocol;
}
-void QSslSocketBackendPrivate::continueHandshake()
-{
- Q_Q(QSslSocket);
- // if we have a max read buffer size, reset the plain socket's to match
- if (readBufferMaxSize)
- plainSocket->setReadBufferSize(readBufferMaxSize);
-
- if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL))
- configuration.peerSessionShared = true;
-
-#ifdef QT_DECRYPT_SSL_TRAFFIC
- if (ssl->session && ssl->s3) {
- const char *mk = reinterpret_cast<const char *>(ssl->session->master_key);
- QByteArray masterKey(mk, ssl->session->master_key_length);
- const char *random = reinterpret_cast<const char *>(ssl->s3->client_random);
- QByteArray clientRandom(random, SSL3_RANDOM_SIZE);
-
- // different format, needed for e.g. older Wireshark versions:
-// const char *sid = reinterpret_cast<const char *>(ssl->session->session_id);
-// QByteArray sessionID(sid, ssl->session->session_id_length);
-// QByteArray debugLineRSA("RSA Session-ID:");
-// debugLineRSA.append(sessionID.toHex().toUpper());
-// debugLineRSA.append(" Master-Key:");
-// debugLineRSA.append(masterKey.toHex().toUpper());
-// debugLineRSA.append("\n");
-
- QByteArray debugLineClientRandom("CLIENT_RANDOM ");
- debugLineClientRandom.append(clientRandom.toHex().toUpper());
- debugLineClientRandom.append(" ");
- debugLineClientRandom.append(masterKey.toHex().toUpper());
- debugLineClientRandom.append("\n");
-
- QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
- QFile file(sslKeyFile);
- if (!file.open(QIODevice::Append))
- qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
- if (!file.write(debugLineClientRandom))
- qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
- file.close();
- } else {
- qCWarning(lcSsl, "could not decrypt SSL traffic");
- }
-#endif
-
- // Cache this SSL session inside the QSslContext
- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
- if (!sslContextPointer->cacheSession(ssl)) {
- sslContextPointer.clear(); // we could not cache the session
- } else {
- // Cache the session for permanent usage as well
- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
- if (!sslContextPointer->sessionASN1().isEmpty())
- configuration.sslSession = sslContextPointer->sessionASN1();
- configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
- }
- }
- }
-
-#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
-
- configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
- if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
- // we could not agree -> be conservative and use HTTP/1.1
- configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
- } else {
- const unsigned char *proto = 0;
- unsigned int proto_len = 0;
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
- if (q_SSLeay() >= 0x10002000L) {
- q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
- if (proto_len && mode == QSslSocket::SslClientMode) {
- // Client does not have a callback that sets it ...
- configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
- }
- }
-
- if (!proto_len) { // Test if NPN was more lucky ...
-#else
- {
-#endif
- q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
- }
-
- if (proto_len)
- configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len);
- else
- configuration.nextNegotiatedProtocol.clear();
- }
-#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
-
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
- if (q_SSLeay() >= 0x10002000L && mode == QSslSocket::SslClientMode) {
- EVP_PKEY *key;
- if (q_SSL_get_server_tmp_key(ssl, &key))
- configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
- }
-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
-
- connectionEncrypted = true;
- emit q->encrypted();
- if (autoStartHandshake && pendingClose) {
- pendingClose = false;
- q->disconnectFromHost();
- }
-}
-
QList<QSslCertificate> QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509)
{
ensureInitialized();
@@ -1694,12 +1396,12 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
QMutexLocker sslErrorListMutexLocker(&_q_sslErrorList()->mutex);
// Register a custom callback to get all verification errors.
- X509_STORE_set_verify_cb_func(certStore, q_X509Callback);
+ q_X509_STORE_set_verify_cb(certStore, q_X509Callback);
// Build the chain of intermediate certificates
STACK_OF(X509) *intermediates = 0;
if (certificateChain.length() > 1) {
- intermediates = (STACK_OF(X509) *) q_sk_new_null();
+ intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null();
if (!intermediates) {
q_X509_STORE_free(certStore);
@@ -1713,11 +1415,8 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
first = false;
continue;
}
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
-#else
- q_sk_push( (STACK *)intermediates, reinterpret_cast<char *>(cert.handle()));
-#endif
+
+ q_OPENSSL_sk_push((OPENSSL_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
}
}
@@ -1741,11 +1440,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
(void) q_X509_verify_cert(storeContext);
q_X509_STORE_CTX_free(storeContext);
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
- q_sk_free( (_STACK *) intermediates);
-#else
- q_sk_free( (STACK *) intermediates);
-#endif
+ q_OPENSSL_sk_free((OPENSSL_STACK *)intermediates);
// Now process the errors
const auto errorList = std::move(_q_sslErrorList()->errors);
@@ -1819,7 +1514,8 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
// Convert to Qt types
if (!key->d->fromEVP_PKEY(pkey)) {
qCWarning(lcSsl, "Unable to convert private key");
- q_sk_pop_free(reinterpret_cast<STACK *>(ca), reinterpret_cast<void(*)(void*)>(q_sk_free));
+ q_OPENSSL_sk_pop_free(reinterpret_cast<OPENSSL_STACK *>(ca),
+ reinterpret_cast<void (*)(void *)>(q_OPENSSL_sk_free));
q_X509_free(x509);
q_EVP_PKEY_free(pkey);
q_PKCS12_free(p12);
@@ -1834,7 +1530,11 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
*caCertificates = QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(ca);
// Clean up
- q_sk_pop_free(reinterpret_cast<STACK *>(ca), reinterpret_cast<void(*)(void*)>(q_sk_free));
+ // TODO: verify ASAP, in the past we had sk_pop_free with q_OPENSSL_sk_free
+ // which seems to be blatantly wrong and even crashes with 1.1.
+ q_OPENSSL_sk_pop_free(reinterpret_cast<OPENSSL_STACK *>(ca),
+ reinterpret_cast<void (*)(void *)>(q_X509_free));
+
q_X509_free(x509);
q_EVP_PKEY_free(pkey);
q_PKCS12_free(p12);
diff --git a/src/network/ssl/qsslsocket_openssl11.cpp b/src/network/ssl/qsslsocket_openssl11.cpp
new file mode 100644
index 0000000000..b6d18943a5
--- /dev/null
+++ b/src/network/ssl/qsslsocket_openssl11.cpp
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2014 Governikus GmbH & Co. KG
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** In addition, as a special exception, the copyright holders listed above give
+** permission to link the code of its release of Qt with the OpenSSL project's
+** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
+** same license as the original version), and distribute the linked executables.
+**
+** You must comply with the GNU General Public License version 2 in all
+** respects for all of the code used other than the "OpenSSL" code. If you
+** modify this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version of this file.
+**
+****************************************************************************/
+
+//#define QT_DECRYPT_SSL_TRAFFIC
+
+#include "qssl_p.h"
+#include "qsslsocket_openssl_p.h"
+#include "qsslsocket_openssl_symbols_p.h"
+#include "qsslsocket.h"
+#include "qsslkey.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qdiriterator.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qlibrary.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_opensslInitMutex, (QMutex::Recursive))
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::deinitialize()
+{
+ // This function exists only for compatibility with the pre-11 code,
+ // where deinitialize() actually does some cleanup. To be discarded
+ // once we retire < 1.1.
+}
+
+bool QSslSocketPrivate::ensureLibraryLoaded()
+{
+ if (!q_resolveOpenSslSymbols())
+ return false;
+
+ const QMutexLocker locker(qt_opensslInitMutex);
+
+ if (!s_libraryLoaded) {
+ s_libraryLoaded = true;
+
+ // Initialize OpenSSL.
+ if (q_OPENSSL_init_ssl(0, nullptr) != 1)
+ return false;
+ q_SSL_load_error_strings();
+ q_OpenSSL_add_all_algorithms();
+
+ QSslSocketBackendPrivate::s_indexForSSLExtraData
+ = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
+ nullptr, nullptr);
+
+ // Initialize OpenSSL's random seed.
+ if (!q_RAND_status()) {
+ qWarning("Random number generator not seeded, disabling SSL support");
+ return false;
+ }
+ }
+ return true;
+}
+
+void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
+{
+ const QMutexLocker locker(qt_opensslInitMutex);
+
+ if (s_loadedCiphersAndCerts)
+ return;
+ s_loadedCiphersAndCerts = true;
+
+ resetDefaultCiphers();
+ resetDefaultEllipticCurves();
+
+#if QT_CONFIG(library)
+ //load symbols needed to receive certificates from system store
+#if defined(Q_OS_WIN)
+ HINSTANCE hLib = LoadLibraryW(L"Crypt32");
+ if (hLib) {
+ ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
+ ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
+ ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
+ if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
+ qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
+ } else {
+ qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
+ }
+#elif defined(Q_OS_QNX)
+ s_loadRootCertsOnDemand = true;
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
+ // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
+ QList<QByteArray> dirs = unixRootCertDirectories();
+ QStringList symLinkFilter;
+ symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
+ for (int a = 0; a < dirs.count(); ++a) {
+ QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
+ if (iterator.hasNext()) {
+ s_loadRootCertsOnDemand = true;
+ break;
+ }
+ }
+#endif
+#endif // QT_CONFIG(library)
+ // if on-demand loading was not enabled, load the certs now
+ if (!s_loadRootCertsOnDemand)
+ setDefaultCaCertificates(systemCaCertificates());
+#ifdef Q_OS_WIN
+ //Enabled for fetching additional root certs from windows update on windows 6+
+ //This flag is set false by setDefaultCaCertificates() indicating the app uses
+ //its own cert bundle rather than the system one.
+ //Same logic that disables the unix on demand cert loading.
+ //Unlike unix, we do preload the certificates from the cert store.
+ if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
+ s_loadRootCertsOnDemand = true;
+#endif
+}
+
+long QSslSocketPrivate::sslLibraryVersionNumber()
+{
+ if (!supportsSsl())
+ return 0;
+
+ return q_OpenSSL_version_num();
+}
+
+QString QSslSocketPrivate::sslLibraryVersionString()
+{
+ if (!supportsSsl())
+ return QString();
+
+ const char *versionString = q_OpenSSL_version(OPENSSL_VERSION);
+ if (!versionString)
+ return QString();
+
+ return QString::fromLatin1(versionString);
+}
+
+void QSslSocketBackendPrivate::continueHandshake()
+{
+ Q_Q(QSslSocket);
+ // if we have a max read buffer size, reset the plain socket's to match
+ if (readBufferMaxSize)
+ plainSocket->setReadBufferSize(readBufferMaxSize);
+
+ if (q_SSL_session_reused(ssl))
+ configuration.peerSessionShared = true;
+
+#ifdef QT_DECRYPT_SSL_TRAFFIC
+ if (q_SSL_get_session(ssl)) {
+ size_t master_key_len = q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl), 0, 0);
+ size_t client_random_len = q_SSL_get_client_random(ssl, 0, 0);
+ QByteArray masterKey(int(master_key_len), 0); // Will not overflow
+ QByteArray clientRandom(int(client_random_len), 0); // Will not overflow
+
+ q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl),
+ reinterpret_cast<unsigned char*>(masterKey.data()),
+ masterKey.size());
+ q_SSL_get_client_random(ssl, reinterpret_cast<unsigned char *>(clientRandom.data()),
+ clientRandom.size());
+
+ QByteArray debugLineClientRandom("CLIENT_RANDOM ");
+ debugLineClientRandom.append(clientRandom.toHex().toUpper());
+ debugLineClientRandom.append(" ");
+ debugLineClientRandom.append(masterKey.toHex().toUpper());
+ debugLineClientRandom.append("\n");
+
+ QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
+ QFile file(sslKeyFile);
+ if (!file.open(QIODevice::Append))
+ qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
+ if (!file.write(debugLineClientRandom))
+ qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
+ file.close();
+ } else {
+ qCWarning(lcSsl, "could not decrypt SSL traffic");
+ }
+#endif
+
+ // Cache this SSL session inside the QSslContext
+ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
+ if (!sslContextPointer->cacheSession(ssl)) {
+ sslContextPointer.clear(); // we could not cache the session
+ } else {
+ // Cache the session for permanent usage as well
+ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
+ if (!sslContextPointer->sessionASN1().isEmpty())
+ configuration.sslSession = sslContextPointer->sessionASN1();
+ configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
+ }
+ }
+ }
+
+#if !defined(OPENSSL_NO_NEXTPROTONEG)
+
+ configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
+ if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
+ // we could not agree -> be conservative and use HTTP/1.1
+ configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
+ } else {
+ const unsigned char *proto = 0;
+ unsigned int proto_len = 0;
+
+ q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
+ if (proto_len && mode == QSslSocket::SslClientMode) {
+ // Client does not have a callback that sets it ...
+ configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
+ }
+
+ if (!proto_len) { // Test if NPN was more lucky ...
+ q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
+ }
+
+ if (proto_len)
+ configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len);
+ else
+ configuration.nextNegotiatedProtocol.clear();
+ }
+#endif // !defined(OPENSSL_NO_NEXTPROTONEG)
+
+ if (mode == QSslSocket::SslClientMode) {
+ EVP_PKEY *key;
+ if (q_SSL_get_server_tmp_key(ssl, &key))
+ configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
+ }
+
+ connectionEncrypted = true;
+ emit q->encrypted();
+ if (autoStartHandshake && pendingClose) {
+ pendingClose = false;
+ q->disconnectFromHost();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket_openssl11_symbols_p.h b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
new file mode 100644
index 0000000000..2980b3d23e
--- /dev/null
+++ b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** In addition, as a special exception, the copyright holders listed above give
+** permission to link the code of its release of Qt with the OpenSSL project's
+** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
+** same license as the original version), and distribute the linked executables.
+**
+** You must comply with the GNU General Public License version 2 in all
+** respects for all of the code used other than the "OpenSSL" code. If you
+** modify this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version of this file.
+**
+****************************************************************************/
+
+#ifndef QSSLSOCKET_OPENSSL11_SYMBOLS_P_H
+#define QSSLSOCKET_OPENSSL11_SYMBOLS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// Note: this file does not have QT_BEGIN_NAMESPACE/QT_END_NAMESPACE, it's done
+// in qsslsocket_openssl_symbols_p.h.
+
+#ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H
+#error "You are not supposed to use this header file, include qsslsocket_openssl_symbols_p.h instead"
+#endif
+
+const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x);
+
+Q_AUTOTEST_EXPORT BIO *q_BIO_new(const BIO_METHOD *a);
+Q_AUTOTEST_EXPORT const BIO_METHOD *q_BIO_s_mem();
+
+int q_DSA_bits(DSA *a);
+int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c);
+int q_EVP_PKEY_base_id(EVP_PKEY *a);
+int q_RSA_bits(RSA *a);
+int q_OPENSSL_sk_num(OPENSSL_STACK *a);
+void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
+OPENSSL_STACK *q_OPENSSL_sk_new_null();
+void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
+void q_OPENSSL_sk_free(OPENSSL_STACK *a);
+void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
+int q_SSL_session_reused(SSL *a);
+unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
+int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
+size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen);
+size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen);
+int q_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+const SSL_METHOD *q_TLS_method();
+const SSL_METHOD *q_TLS_client_method();
+const SSL_METHOD *q_TLS_server_method();
+ASN1_TIME *q_X509_getm_notBefore(X509 *a);
+ASN1_TIME *q_X509_getm_notAfter(X509 *a);
+
+long q_X509_get_version(X509 *a);
+EVP_PKEY *q_X509_get_pubkey(X509 *a);
+void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb);
+STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx);
+void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
+int q_DH_bits(DH *dh);
+
+# define q_SSL_load_error_strings() q_OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \
+ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
+
+#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_OPENSSL_sk_num)(st)
+#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_OPENSSL_sk_value)(st, i)
+
+#define q_OPENSSL_add_all_algorithms_conf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
+ | OPENSSL_INIT_ADD_ALL_DIGESTS \
+ | OPENSSL_INIT_LOAD_CONFIG, NULL)
+#define q_OPENSSL_add_all_algorithms_noconf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
+ | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
+
+int q_OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
+void q_CRYPTO_free(void *str, const char *file, int line);
+
+long q_OpenSSL_version_num();
+const char *q_OpenSSL_version(int type);
+
+unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session);
+
+#endif
diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
index b2adb3e547..7f9e884045 100644
--- a/src/network/ssl/qsslsocket_openssl_p.h
+++ b/src/network/ssl/qsslsocket_openssl_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -98,8 +98,8 @@
#include <openssl/crypto.h>
#include <openssl/tls1.h>
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-typedef _STACK STACK;
+#if QT_CONFIG(opensslv11)
+#include <openssl/dh.h>
#endif
QT_BEGIN_NAMESPACE
@@ -151,7 +151,7 @@ public:
#endif
Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
- static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher);
+ static QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher);
static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain, const QString &hostName);
static QString getErrorsFromOpenSsl();
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index c344a94427..0ef8bf6b5e 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -1,7 +1,8 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
@@ -136,49 +137,195 @@ void qsslSocketCannotResolveSymbolWarning(const char *functionName)
#endif // QT_LINKED_OPENSSL
+#if QT_CONFIG(opensslv11)
+
+// Below are the functions first introduced in version 1.1:
+
+DEFINEFUNC(const unsigned char *, ASN1_STRING_get0_data, const ASN1_STRING *a, a, return 0, return)
+DEFINEFUNC2(int, OPENSSL_init_ssl, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return)
+DEFINEFUNC2(int, OPENSSL_init_crypto, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return)
+DEFINEFUNC(BIO *, BIO_new, const BIO_METHOD *a, a, return 0, return)
+DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
+DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
+DEFINEFUNC(int, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX *c, c, return 0, return)
+DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return)
+DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return)
+DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return)
+DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return)
+DEFINEFUNC2(void, OPENSSL_sk_pop_free, OPENSSL_STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
+DEFINEFUNC(OPENSSL_STACK *, OPENSSL_sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMMYARG)
+DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG)
+DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return 0, return)
+DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return)
+DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return)
+DEFINEFUNC3(size_t, SSL_get_client_random, SSL *a, a, unsigned char *out, out, size_t outlen, outlen, return 0, return)
+DEFINEFUNC3(size_t, SSL_SESSION_get_master_key, const SSL_SESSION *ses, ses, unsigned char *out, out, size_t outlen, outlen, return 0, return)
+DEFINEFUNC6(int, CRYPTO_get_ex_new_index, int class_index, class_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
+
+DEFINEFUNC(const SSL_METHOD *, TLS_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLS_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return 0, return)
+DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return 0, return)
+DEFINEFUNC(long, X509_get_version, X509 *a, a, return -1, return)
+DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return 0, return)
+DEFINEFUNC2(void, X509_STORE_set_verify_cb, X509_STORE *a, a, X509_STORE_CTX_verify_cb verify_cb, verify_cb, return, DUMMYARG)
+DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return 0, return)
+DEFINEFUNC3(void, CRYPTO_free, void *str, str, const char *file, file, int line, line, return, DUMMYARG)
+DEFINEFUNC(long, OpenSSL_version_num, void, DUMMYARG, return 0, return)
+DEFINEFUNC(const char *, OpenSSL_version, int a, a, return 0, return)
+DEFINEFUNC(unsigned long, SSL_SESSION_get_ticket_lifetime_hint, const SSL_SESSION *session, session, return 0, return)
+DEFINEFUNC4(void, DH_get0_pqg, const DH *dh, dh, const BIGNUM **p, p, const BIGNUM **q, q, const BIGNUM **g, g, return, DUMMYARG)
+DEFINEFUNC(int, DH_bits, DH *dh, dh, return 0, return)
+
+#else // QT_CONFIG(opensslv11)
+
+// Functions below are either deprecated or removed in OpenSSL >= 1.1:
+
+DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
+
#ifdef SSLEAY_MACROS
DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return)
#endif
+DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return 0, return)
+DEFINEFUNC(void, ERR_clear_error, DUMMYARG, DUMMYARG, return, DUMMYARG)
+DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
+DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
+DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
+DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
+DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
+DEFINEFUNC(unsigned long, ERR_peek_last_error, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG)
+DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
+DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
+
+#ifdef SSLEAY_MACROS
+DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
+DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
+#endif // SSLEAY_MACROS
+
+DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
+DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
+DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
+DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
+#else
+DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG)
+DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
+DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
+#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L
+
+DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
+DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
+
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
+#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+#ifndef OPENSSL_NO_SSL2
+DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+#ifndef OPENSSL_NO_SSL2
+DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+#else
+#ifndef OPENSSL_NO_SSL2
+DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+#ifndef OPENSSL_NO_SSL2
+DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
+
+DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return 0, return)
+
+#ifdef SSLEAY_MACROS
+DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return)
+DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return)
+#ifndef OPENSSL_NO_EC
+DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return)
+#endif
+DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return)
+DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return)
+#ifndef OPENSSL_NO_EC
+DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return)
+#endif
+#endif
+DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
+DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
+DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
+DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
+
+#endif // QT_CONFIG(opensslv11)
+
DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return)
-DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return)
-DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return);
+DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return)
DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return)
DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return)
-DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return 0, return)
DEFINEFUNC3(int, BIO_read, BIO *a, a, void *b, b, int c, c, return -1, return)
-DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
+
DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return)
DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return)
-#if OPENSSL_VERSION_NUMBER >= 0x10100000L
-DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
-#endif
DEFINEFUNC2(BN_ULONG, BN_mod_word, const BIGNUM *a, a, BN_ULONG w, w, return static_cast<BN_ULONG>(-1), return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return 0, return)
DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return)
#endif
-DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
-DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
-DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG)
DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return 0, return)
DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return)
DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG)
-DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
-DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
-DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return);
+DEFINEFUNC(EVP_CIPHER_CTX *, EVP_CIPHER_CTX_new, void, DUMMYARG, return 0, return)
+DEFINEFUNC(void, EVP_CIPHER_CTX_free, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
+DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return)
DEFINEFUNC2(int, EVP_CIPHER_CTX_set_key_length, EVP_CIPHER_CTX *ctx, ctx, int keylen, keylen, return 0, return)
-DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *type, type, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return);
-DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return);
-DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return);
+DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *type, type, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return)
+DEFINEFUNC6(int, EVP_CipherInit_ex, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *cipher, cipher, ENGINE *impl, impl, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return)
+DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return)
+DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return)
DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return)
DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return)
DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return)
@@ -202,10 +349,8 @@ DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, retur
DEFINEFUNC4(int, OBJ_obj2txt, char *a, a, int b, b, ASN1_OBJECT *c, c, int d, d, return -1, return)
DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return)
-#ifdef SSLEAY_MACROS
-DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
-DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return)
-#else
+
+#ifndef SSLEAY_MACROS
DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
@@ -218,7 +363,7 @@ DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CI
#ifndef OPENSSL_NO_EC
DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
#endif
-#endif
+#endif // !SSLEAY_MACROS
DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
@@ -234,23 +379,10 @@ DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG)
DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return)
DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
-DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
-DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
-DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
-DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
-#else
-DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG)
-DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
-DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
-#endif
DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return)
DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return)
-DEFINEFUNC3(char *, SSL_CIPHER_description, SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
-DEFINEFUNC2(int, SSL_CIPHER_get_bits, SSL_CIPHER *a, a, int *b, b, return 0, return)
+DEFINEFUNC3(char *, SSL_CIPHER_description, const SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
+DEFINEFUNC2(int, SSL_CIPHER_get_bits, const SSL_CIPHER *a, a, int *b, b, return 0, return)
DEFINEFUNC(int, SSL_connect, SSL *a, a, return -1, return)
DEFINEFUNC(int, SSL_CTX_check_private_key, const SSL_CTX *a, a, return -1, return)
DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return)
@@ -287,8 +419,6 @@ DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return)
#else
DEFINEFUNC(long, SSL_get_verify_result, SSL *a, a, return -1, return)
#endif
-DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
-DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return 0, return)
DEFINEFUNC4(long, SSL_ctrl, SSL *a, a, int cmd, cmd, long larg, larg, void *parg, parg, return -1, return)
DEFINEFUNC3(int, SSL_read, SSL *a, a, void *b, b, int c, c, return -1, return)
@@ -301,7 +431,6 @@ DEFINEFUNC(void, SSL_SESSION_free, SSL_SESSION *ses, ses, return, DUMMYARG)
DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return 0, return)
DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return 0, return)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
DEFINEFUNC3(int, SSL_set_ex_data, SSL *ssl, ssl, int idx, idx, void *arg, arg, return 0, return)
DEFINEFUNC2(void *, SSL_get_ex_data, const SSL *ssl, ssl, int idx, idx, return NULL, return)
#endif
@@ -310,51 +439,9 @@ DEFINEFUNC2(void, SSL_set_psk_client_callback, SSL* ssl, ssl, q_psk_client_callb
DEFINEFUNC2(void, SSL_set_psk_server_callback, SSL* ssl, ssl, q_psk_server_callback_t callback, callback, return, DUMMYARG)
DEFINEFUNC2(int, SSL_CTX_use_psk_identity_hint, SSL_CTX* ctx, ctx, const char *hint, hint, return 0, return)
#endif
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
-DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
-#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
-DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
-#else
-#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
-DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
-#ifndef OPENSSL_NO_SSL2
-DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
-DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
-DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
-#endif
DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, return)
DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return)
+DEFINEFUNC4(int, X509_digest, const X509 *x509, x509, const EVP_MD *type, type, unsigned char *md, md, unsigned int *len, len, return -1, return)
#ifndef SSLEAY_MACROS
DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return 0, return)
#endif
@@ -378,6 +465,7 @@ DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, ASN1_STRING *b, b, return 0, retu
DEFINEFUNC2(int, X509_check_issued, X509 *a, a, X509 *b, b, return -1, return)
DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return 0, return)
DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return 0, return)
+DEFINEFUNC(ASN1_INTEGER *, X509_get_serialNumber, X509 *a, a, return 0, return)
DEFINEFUNC(int, X509_verify_cert, X509_STORE_CTX *a, a, return -1, return)
DEFINEFUNC(int, X509_NAME_entry_count, X509_NAME *a, a, return 0, return)
DEFINEFUNC2(X509_NAME_ENTRY *, X509_NAME_get_entry, X509_NAME *a, a, int b, b, return 0, return)
@@ -393,25 +481,8 @@ DEFINEFUNC2(int, X509_STORE_CTX_set_purpose, X509_STORE_CTX *a, a, int b, b, ret
DEFINEFUNC(int, X509_STORE_CTX_get_error, X509_STORE_CTX *a, a, return -1, return)
DEFINEFUNC(int, X509_STORE_CTX_get_error_depth, X509_STORE_CTX *a, a, return -1, return)
DEFINEFUNC(X509 *, X509_STORE_CTX_get_current_cert, X509_STORE_CTX *a, a, return 0, return)
-DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return 0, return)
DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return 0, return)
-#ifdef SSLEAY_MACROS
-DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return)
-DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return)
-#ifndef OPENSSL_NO_EC
-DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return)
-#endif
-DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return)
-DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return)
-#ifndef OPENSSL_NO_EC
-DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return)
-#endif
-#endif
-DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
-DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return)
-DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
-DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
DEFINEFUNC2(int, i2d_SSL_SESSION, SSL_SESSION *in, in, unsigned char **pp, pp, return 0, return)
DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return 0, return)
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
@@ -694,8 +765,8 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl()
#ifndef Q_OS_DARWIN
// second attempt: find the development files libssl.so and libcrypto.so
//
- // disabled on OS X/iOS:
- // OS X's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third
+ // disabled on macOS/iOS:
+ // macOS's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third
// attempt, _after_ <bundle>/Contents/Frameworks has been searched.
// iOS does not ship a system libssl.dylib, libcrypto.dylib in the first place.
libssl->setFileNameAndVersion(QLatin1String("ssl"), -1);
@@ -754,8 +825,12 @@ bool q_resolveOpenSslSymbols()
static bool symbolsResolved = false;
static bool triedToResolveSymbols = false;
#ifndef QT_NO_THREAD
+#if QT_CONFIG(opensslv11)
+ QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_OPENSSL_init_ssl));
+#else
QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_SSL_library_init));
#endif
+#endif
if (symbolsResolved)
return true;
if (triedToResolveSymbols)
@@ -771,11 +846,145 @@ bool q_resolveOpenSslSymbols()
// failed to load them
return false;
+#if QT_CONFIG(opensslv11)
+
+ RESOLVEFUNC(OPENSSL_init_ssl)
+ RESOLVEFUNC(OPENSSL_init_crypto)
+ RESOLVEFUNC(ASN1_STRING_get0_data)
+ RESOLVEFUNC(EVP_CIPHER_CTX_reset)
+ RESOLVEFUNC(EVP_PKEY_base_id)
+ RESOLVEFUNC(RSA_bits)
+ RESOLVEFUNC(OPENSSL_sk_new_null)
+ RESOLVEFUNC(OPENSSL_sk_push)
+ RESOLVEFUNC(OPENSSL_sk_free)
+ RESOLVEFUNC(OPENSSL_sk_num)
+ RESOLVEFUNC(OPENSSL_sk_pop_free)
+ RESOLVEFUNC(OPENSSL_sk_value)
+ RESOLVEFUNC(DH_get0_pqg)
+ RESOLVEFUNC(SSL_CTX_set_options)
+ RESOLVEFUNC(SSL_get_client_random)
+ RESOLVEFUNC(SSL_SESSION_get_master_key)
+ RESOLVEFUNC(SSL_session_reused)
+ RESOLVEFUNC(SSL_get_session)
+ RESOLVEFUNC(CRYPTO_get_ex_new_index)
+ RESOLVEFUNC(TLS_method)
+ RESOLVEFUNC(TLS_client_method)
+ RESOLVEFUNC(TLS_server_method)
+ RESOLVEFUNC(X509_STORE_CTX_get0_chain)
+ RESOLVEFUNC(X509_getm_notBefore)
+ RESOLVEFUNC(X509_getm_notAfter)
+ RESOLVEFUNC(X509_get_version)
+ RESOLVEFUNC(X509_get_pubkey)
+ RESOLVEFUNC(X509_STORE_set_verify_cb)
+ RESOLVEFUNC(CRYPTO_free)
+ RESOLVEFUNC(OpenSSL_version_num)
+ RESOLVEFUNC(OpenSSL_version)
+ if (!_q_OpenSSL_version) {
+ // Apparently, we were built with OpenSSL 1.1 enabled but are now using
+ // a wrong library.
+ delete libs.first;
+ delete libs.second;
+ qCWarning(lcSsl, "Incompatible version of OpenSSL");
+ return false;
+ }
+
+ RESOLVEFUNC(SSL_SESSION_get_ticket_lifetime_hint)
+ RESOLVEFUNC(DH_bits)
+ RESOLVEFUNC(DSA_bits)
+
+#else // !opensslv11
+
+ RESOLVEFUNC(ASN1_STRING_data)
+
#ifdef SSLEAY_MACROS
RESOLVEFUNC(ASN1_dup)
+#endif // SSLEAY_MACROS
+ RESOLVEFUNC(BIO_new_file)
+ RESOLVEFUNC(ERR_clear_error)
+ RESOLVEFUNC(CRYPTO_free)
+ RESOLVEFUNC(CRYPTO_num_locks)
+ RESOLVEFUNC(CRYPTO_set_id_callback)
+ RESOLVEFUNC(CRYPTO_set_locking_callback)
+ RESOLVEFUNC(ERR_peek_last_error)
+ RESOLVEFUNC(ERR_free_strings)
+ RESOLVEFUNC(EVP_CIPHER_CTX_cleanup)
+ RESOLVEFUNC(EVP_CIPHER_CTX_init)
+
+#ifdef SSLEAY_MACROS // ### verify
+ RESOLVEFUNC(PEM_ASN1_read_bio)
+#endif // SSLEAY_MACROS
+
+ RESOLVEFUNC(sk_new_null)
+ RESOLVEFUNC(sk_push)
+ RESOLVEFUNC(sk_free)
+ RESOLVEFUNC(sk_num)
+ RESOLVEFUNC(sk_pop_free)
+ RESOLVEFUNC(sk_value)
+ RESOLVEFUNC(SSL_library_init)
+ RESOLVEFUNC(SSL_load_error_strings)
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ RESOLVEFUNC(SSL_get_ex_new_index)
+#endif
+#ifndef OPENSSL_NO_SSL2
+ RESOLVEFUNC(SSLv2_client_method)
#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+ RESOLVEFUNC(SSLv3_client_method)
+#endif
+ RESOLVEFUNC(SSLv23_client_method)
+ RESOLVEFUNC(TLSv1_client_method)
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ RESOLVEFUNC(TLSv1_1_client_method)
+ RESOLVEFUNC(TLSv1_2_client_method)
+#endif
+#ifndef OPENSSL_NO_SSL2
+ RESOLVEFUNC(SSLv2_server_method)
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+ RESOLVEFUNC(SSLv3_server_method)
+#endif
+ RESOLVEFUNC(SSLv23_server_method)
+ RESOLVEFUNC(TLSv1_server_method)
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ RESOLVEFUNC(TLSv1_1_server_method)
+ RESOLVEFUNC(TLSv1_2_server_method)
+#endif
+ RESOLVEFUNC(X509_STORE_CTX_get_chain)
+#ifdef SSLEAY_MACROS
+ RESOLVEFUNC(i2d_DSAPrivateKey)
+ RESOLVEFUNC(i2d_RSAPrivateKey)
+ RESOLVEFUNC(d2i_DSAPrivateKey)
+ RESOLVEFUNC(d2i_RSAPrivateKey)
+#endif
+ RESOLVEFUNC(CONF_get1_default_config_file)
+ RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
+ RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
+ RESOLVEFUNC(SSLeay)
+
+ if (!_q_SSLeay || q_SSLeay() >= 0x10100000L) {
+ // OpenSSL 1.1 has deprecated and removed SSLeay. We consider a failure to
+ // resolve this symbol as a failure to resolve symbols.
+ // The right operand of '||' above is ... a bit of paranoia.
+ delete libs.first;
+ delete libs.second;
+ qCWarning(lcSsl, "Incompatible version of OpenSSL");
+ return false;
+ }
+
+
+ RESOLVEFUNC(SSLeay_version)
+
+#ifndef OPENSSL_NO_EC
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ if (q_SSLeay() >= 0x10002000L)
+ RESOLVEFUNC(EC_curve_nist2nid)
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
+#endif // OPENSSL_NO_EC
+
+
+#endif // !opensslv11
+
RESOLVEFUNC(ASN1_INTEGER_get)
- RESOLVEFUNC(ASN1_STRING_data)
RESOLVEFUNC(ASN1_STRING_length)
RESOLVEFUNC(ASN1_STRING_to_UTF8)
RESOLVEFUNC(BIO_ctrl)
@@ -794,25 +1003,22 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(BN_is_word)
#endif
RESOLVEFUNC(BN_mod_word)
- RESOLVEFUNC(CRYPTO_free)
- RESOLVEFUNC(CRYPTO_num_locks)
- RESOLVEFUNC(CRYPTO_set_id_callback)
- RESOLVEFUNC(CRYPTO_set_locking_callback)
RESOLVEFUNC(DSA_new)
RESOLVEFUNC(DSA_free)
RESOLVEFUNC(ERR_error_string)
RESOLVEFUNC(ERR_get_error)
- RESOLVEFUNC(ERR_free_strings)
- RESOLVEFUNC(EVP_CIPHER_CTX_cleanup)
- RESOLVEFUNC(EVP_CIPHER_CTX_init)
+ RESOLVEFUNC(EVP_CIPHER_CTX_new)
+ RESOLVEFUNC(EVP_CIPHER_CTX_free)
RESOLVEFUNC(EVP_CIPHER_CTX_ctrl)
RESOLVEFUNC(EVP_CIPHER_CTX_set_key_length)
RESOLVEFUNC(EVP_CipherInit)
+ RESOLVEFUNC(EVP_CipherInit_ex)
RESOLVEFUNC(EVP_CipherUpdate)
RESOLVEFUNC(EVP_CipherFinal)
RESOLVEFUNC(EVP_des_cbc)
RESOLVEFUNC(EVP_des_ede3_cbc)
RESOLVEFUNC(EVP_rc2_cbc)
+ RESOLVEFUNC(EVP_sha1)
RESOLVEFUNC(EVP_PKEY_assign)
RESOLVEFUNC(EVP_PKEY_set1_RSA)
RESOLVEFUNC(EVP_PKEY_set1_DSA)
@@ -834,9 +1040,8 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(i2t_ASN1_OBJECT)
RESOLVEFUNC(OBJ_obj2txt)
RESOLVEFUNC(OBJ_obj2nid)
-#ifdef SSLEAY_MACROS // ### verify
- RESOLVEFUNC(PEM_ASN1_read_bio)
-#else
+
+#ifndef SSLEAY_MACROS
RESOLVEFUNC(PEM_read_bio_PrivateKey)
RESOLVEFUNC(PEM_read_bio_DSAPrivateKey)
RESOLVEFUNC(PEM_read_bio_RSAPrivateKey)
@@ -849,7 +1054,8 @@ bool q_resolveOpenSslSymbols()
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(PEM_write_bio_ECPrivateKey)
#endif
-#endif
+#endif // !SSLEAY_MACROS
+
RESOLVEFUNC(PEM_read_bio_PUBKEY)
RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY)
RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY)
@@ -865,12 +1071,6 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(RAND_status)
RESOLVEFUNC(RSA_new)
RESOLVEFUNC(RSA_free)
- RESOLVEFUNC(sk_new_null)
- RESOLVEFUNC(sk_push)
- RESOLVEFUNC(sk_free)
- RESOLVEFUNC(sk_num)
- RESOLVEFUNC(sk_pop_free)
- RESOLVEFUNC(sk_value)
RESOLVEFUNC(SSL_CIPHER_description)
RESOLVEFUNC(SSL_CIPHER_get_bits)
RESOLVEFUNC(SSL_CTX_check_private_key)
@@ -898,8 +1098,6 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_get_peer_cert_chain)
RESOLVEFUNC(SSL_get_peer_certificate)
RESOLVEFUNC(SSL_get_verify_result)
- RESOLVEFUNC(SSL_library_init)
- RESOLVEFUNC(SSL_load_error_strings)
RESOLVEFUNC(SSL_new)
RESOLVEFUNC(SSL_ctrl)
RESOLVEFUNC(SSL_read)
@@ -912,7 +1110,6 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_get1_session)
RESOLVEFUNC(SSL_get_session)
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- RESOLVEFUNC(SSL_get_ex_new_index)
RESOLVEFUNC(SSL_set_ex_data)
RESOLVEFUNC(SSL_get_ex_data)
#endif
@@ -922,30 +1119,6 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(SSL_CTX_use_psk_identity_hint)
#endif
RESOLVEFUNC(SSL_write)
-#ifndef OPENSSL_NO_SSL2
- RESOLVEFUNC(SSLv2_client_method)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
- RESOLVEFUNC(SSLv3_client_method)
-#endif
- RESOLVEFUNC(SSLv23_client_method)
- RESOLVEFUNC(TLSv1_client_method)
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- RESOLVEFUNC(TLSv1_1_client_method)
- RESOLVEFUNC(TLSv1_2_client_method)
-#endif
-#ifndef OPENSSL_NO_SSL2
- RESOLVEFUNC(SSLv2_server_method)
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
- RESOLVEFUNC(SSLv3_server_method)
-#endif
- RESOLVEFUNC(SSLv23_server_method)
- RESOLVEFUNC(TLSv1_server_method)
-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
- RESOLVEFUNC(TLSv1_1_server_method)
- RESOLVEFUNC(TLSv1_2_server_method)
-#endif
RESOLVEFUNC(X509_NAME_entry_count)
RESOLVEFUNC(X509_NAME_get_entry)
RESOLVEFUNC(X509_NAME_ENTRY_get_data)
@@ -961,12 +1134,12 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(X509_STORE_CTX_get_error)
RESOLVEFUNC(X509_STORE_CTX_get_error_depth)
RESOLVEFUNC(X509_STORE_CTX_get_current_cert)
- RESOLVEFUNC(X509_STORE_CTX_get_chain)
RESOLVEFUNC(X509_cmp)
#ifndef SSLEAY_MACROS
RESOLVEFUNC(X509_dup)
#endif
RESOLVEFUNC(X509_print)
+ RESOLVEFUNC(X509_digest)
RESOLVEFUNC(X509_EXTENSION_get_object)
RESOLVEFUNC(X509_free)
RESOLVEFUNC(X509_get_ext)
@@ -982,20 +1155,11 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(X509_check_issued)
RESOLVEFUNC(X509_get_issuer_name)
RESOLVEFUNC(X509_get_subject_name)
+ RESOLVEFUNC(X509_get_serialNumber)
RESOLVEFUNC(X509_verify_cert)
RESOLVEFUNC(d2i_X509)
RESOLVEFUNC(i2d_X509)
-#ifdef SSLEAY_MACROS
- RESOLVEFUNC(i2d_DSAPrivateKey)
- RESOLVEFUNC(i2d_RSAPrivateKey)
- RESOLVEFUNC(d2i_DSAPrivateKey)
- RESOLVEFUNC(d2i_RSAPrivateKey)
-#endif
- RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
- RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
RESOLVEFUNC(SSL_CTX_load_verify_locations)
- RESOLVEFUNC(SSLeay)
- RESOLVEFUNC(SSLeay_version)
RESOLVEFUNC(i2d_SSL_SESSION)
RESOLVEFUNC(d2i_SSL_SESSION)
#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
@@ -1019,27 +1183,14 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(EC_KEY_new_by_curve_name)
RESOLVEFUNC(EC_KEY_free)
RESOLVEFUNC(EC_get_builtin_curves)
-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
- if (q_SSLeay() >= 0x10002000L)
- RESOLVEFUNC(EC_curve_nist2nid)
-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
#endif // OPENSSL_NO_EC
RESOLVEFUNC(PKCS12_parse)
RESOLVEFUNC(d2i_PKCS12_bio)
RESOLVEFUNC(PKCS12_free)
+ symbolsResolved = true;
delete libs.first;
delete libs.second;
- if (!_q_SSLeay || q_SSLeay() >= 0x10100000L) {
- // OpenSSL 1.1 deprecated and removed SSLeay. We consider a failure to
- // resolve this symbol as a failure to resolve symbols.
- // The right operand of '||' above ... a bit of paranoia.
- qCWarning(lcSsl, "Incompatible version of OpenSSL");
- return false;
- }
-
- symbolsResolved = true;
-
return true;
}
#endif // QT_CONFIG(library)
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index b35a895d38..796bf2d4f5 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
** Contact: https://www.qt.io/licensing/
**
@@ -56,6 +56,7 @@
#ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H
#define QSSLSOCKET_OPENSSL_SYMBOLS_P_H
+
//
// W A R N I N G
// -------------
@@ -215,17 +216,20 @@ QT_BEGIN_NAMESPACE
#endif // !defined QT_LINKED_OPENSSL
+#if QT_CONFIG(opensslv11)
+#include "qsslsocket_openssl11_symbols_p.h"
+#else
+#include "qsslsocket_opensslpre11_symbols_p.h"
+#endif // QT_CONFIG
+
bool q_resolveOpenSslSymbols();
long q_ASN1_INTEGER_get(ASN1_INTEGER *a);
-unsigned char * q_ASN1_STRING_data(ASN1_STRING *a);
int q_ASN1_STRING_length(ASN1_STRING *a);
int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b);
long q_BIO_ctrl(BIO *a, int b, long c, void *d);
Q_AUTOTEST_EXPORT int q_BIO_free(BIO *a);
-Q_AUTOTEST_EXPORT BIO *q_BIO_new(BIO_METHOD *a);
BIO *q_BIO_new_mem_buf(void *a, int b);
int q_BIO_read(BIO *a, void *b, int c);
-Q_AUTOTEST_EXPORT BIO_METHOD *q_BIO_s_mem();
Q_AUTOTEST_EXPORT int q_BIO_write(BIO *a, const void *b, int c);
int q_BN_num_bits(const BIGNUM *a);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
@@ -247,26 +251,23 @@ BN_ULONG q_BN_mod_word(const BIGNUM *a, BN_ULONG w);
const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k);
int q_EC_GROUP_get_degree(const EC_GROUP* g);
#endif
-int q_CRYPTO_num_locks();
-void q_CRYPTO_set_locking_callback(void (*a)(int, int, const char *, int));
-void q_CRYPTO_set_id_callback(unsigned long (*a)());
-void q_CRYPTO_free(void *a);
DSA *q_DSA_new();
void q_DSA_free(DSA *a);
X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c);
char *q_ERR_error_string(unsigned long a, char *b);
unsigned long q_ERR_get_error();
-void q_ERR_free_strings();
-void q_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
-void q_EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
+EVP_CIPHER_CTX *q_EVP_CIPHER_CTX_new();
+void q_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
int q_EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
int q_EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
int q_EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *key, const unsigned char *iv, int enc);
+int q_EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc);
int q_EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);
int q_EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
const EVP_CIPHER *q_EVP_des_cbc();
const EVP_CIPHER *q_EVP_des_ede3_cbc();
const EVP_CIPHER *q_EVP_rc2_cbc();
+const EVP_MD *q_EVP_sha1();
int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c);
Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b);
int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
@@ -310,7 +311,7 @@ int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned
int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigned char *d,
int e, pem_password_cb *f, void *g);
#endif
-#endif
+#endif // SSLEAY_MACROS
Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PUBKEY(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d);
DSA *q_PEM_read_bio_DSA_PUBKEY(BIO *a, DSA **b, pem_password_cb *c, void *d);
RSA *q_PEM_read_bio_RSA_PUBKEY(BIO *a, RSA **b, pem_password_cb *c, void *d);
@@ -326,23 +327,10 @@ void q_RAND_seed(const void *a, int b);
int q_RAND_status();
RSA *q_RSA_new();
void q_RSA_free(RSA *a);
-int q_sk_num(STACK *a);
-void q_sk_pop_free(STACK *a, void (*b)(void *));
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-_STACK *q_sk_new_null();
-void q_sk_push(_STACK *st, void *data);
-void q_sk_free(_STACK *a);
-void * q_sk_value(STACK *a, int b);
-#else
-STACK *q_sk_new_null();
-void q_sk_push(STACK *st, char *data);
-void q_sk_free(STACK *a);
-char * q_sk_value(STACK *a, int b);
-#endif
int q_SSL_accept(SSL *a);
int q_SSL_clear(SSL *a);
-char *q_SSL_CIPHER_description(SSL_CIPHER *a, char *b, int c);
-int q_SSL_CIPHER_get_bits(SSL_CIPHER *a, int *b);
+char *q_SSL_CIPHER_description(const SSL_CIPHER *a, char *b, int c);
+int q_SSL_CIPHER_get_bits(const SSL_CIPHER *a, int *b);
int q_SSL_connect(SSL *a);
int q_SSL_CTX_check_private_key(const SSL_CTX *a);
long q_SSL_CTX_ctrl(SSL_CTX *a, int b, long c, void *d);
@@ -374,8 +362,6 @@ int q_SSL_get_error(SSL *a, int b);
STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a);
X509 *q_SSL_get_peer_certificate(SSL *a);
long q_SSL_get_verify_result(const SSL *a);
-int q_SSL_library_init();
-void q_SSL_load_error_strings();
SSL *q_SSL_new(SSL_CTX *a);
long q_SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
int q_SSL_read(SSL *a, void *b, int c);
@@ -388,7 +374,6 @@ void q_SSL_SESSION_free(SSL_SESSION *ses);
SSL_SESSION *q_SSL_get1_session(SSL *ssl);
SSL_SESSION *q_SSL_get_session(const SSL *ssl);
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
-int q_SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
int q_SSL_set_ex_data(SSL *ssl, int idx, void *arg);
void *q_SSL_get_ex_data(const SSL *ssl, int idx);
#endif
@@ -399,49 +384,6 @@ typedef unsigned int (*q_psk_server_callback_t)(SSL *ssl, const char *identity,
void q_SSL_set_psk_server_callback(SSL *ssl, q_psk_server_callback_t callback);
int q_SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint);
#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
-#ifndef OPENSSL_NO_SSL2
-const SSL_METHOD *q_SSLv2_client_method();
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-const SSL_METHOD *q_SSLv3_client_method();
-#endif
-const SSL_METHOD *q_SSLv23_client_method();
-const SSL_METHOD *q_TLSv1_client_method();
-const SSL_METHOD *q_TLSv1_1_client_method();
-const SSL_METHOD *q_TLSv1_2_client_method();
-#ifndef OPENSSL_NO_SSL2
-const SSL_METHOD *q_SSLv2_server_method();
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-const SSL_METHOD *q_SSLv3_server_method();
-#endif
-const SSL_METHOD *q_SSLv23_server_method();
-const SSL_METHOD *q_TLSv1_server_method();
-const SSL_METHOD *q_TLSv1_1_server_method();
-const SSL_METHOD *q_TLSv1_2_server_method();
-#else
-#ifndef OPENSSL_NO_SSL2
-SSL_METHOD *q_SSLv2_client_method();
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-SSL_METHOD *q_SSLv3_client_method();
-#endif
-SSL_METHOD *q_SSLv23_client_method();
-SSL_METHOD *q_TLSv1_client_method();
-SSL_METHOD *q_TLSv1_1_client_method();
-SSL_METHOD *q_TLSv1_2_client_method();
-#ifndef OPENSSL_NO_SSL2
-SSL_METHOD *q_SSLv2_server_method();
-#endif
-#ifndef OPENSSL_NO_SSL3_METHOD
-SSL_METHOD *q_SSLv3_server_method();
-#endif
-SSL_METHOD *q_SSLv23_server_method();
-SSL_METHOD *q_TLSv1_server_method();
-SSL_METHOD *q_TLSv1_1_server_method();
-SSL_METHOD *q_TLSv1_2_server_method();
-#endif
int q_SSL_write(SSL *a, const void *b, int c);
int q_X509_cmp(X509 *a, X509 *b);
#ifdef SSLEAY_MACROS
@@ -452,6 +394,7 @@ void *q_ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
X509 *q_X509_dup(X509 *a);
#endif
void q_X509_print(BIO *a, X509*b);
+int q_X509_digest(const X509 *x509, const EVP_MD *type, unsigned char *md, unsigned int *len);
ASN1_OBJECT *q_X509_EXTENSION_get_object(X509_EXTENSION *a);
void q_X509_free(X509 *a);
X509_EXTENSION *q_X509_get_ext(X509 *a, int b);
@@ -471,6 +414,7 @@ int q_ASN1_STRING_print(BIO *a, ASN1_STRING *b);
int q_X509_check_issued(X509 *a, X509 *b);
X509_NAME *q_X509_get_issuer_name(X509 *a);
X509_NAME *q_X509_get_subject_name(X509 *a);
+ASN1_INTEGER *q_X509_get_serialNumber(X509 *a);
int q_X509_verify_cert(X509_STORE_CTX *ctx);
int q_X509_NAME_entry_count(X509_NAME *a);
X509_NAME_ENTRY *q_X509_NAME_get_entry(X509_NAME *a,int b);
@@ -488,7 +432,6 @@ int q_X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
int q_X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
int q_X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
X509 *q_X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
-STACK_OF(X509) *q_X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
// Diffie-Hellman support
DH *q_DH_new();
@@ -522,34 +465,9 @@ int q_PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
PKCS12 *q_d2i_PKCS12_bio(BIO *bio, PKCS12 **pkcs12);
void q_PKCS12_free(PKCS12 *pkcs12);
-
#define q_BIO_get_mem_data(b, pp) (int)q_BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp)
#define q_BIO_pending(b) (int)q_BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
-#ifdef SSLEAY_MACROS
-int q_i2d_DSAPrivateKey(const DSA *a, unsigned char **pp);
-int q_i2d_RSAPrivateKey(const RSA *a, unsigned char **pp);
-RSA *q_d2i_RSAPrivateKey(RSA **a, unsigned char **pp, long length);
-DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
-#define q_PEM_read_bio_RSAPrivateKey(bp, x, cb, u) \
- (RSA *)q_PEM_ASN1_read_bio( \
- (void *(*)(void**, const unsigned char**, long int))q_d2i_RSAPrivateKey, PEM_STRING_RSA, bp, (void **)x, cb, u)
-#define q_PEM_read_bio_DSAPrivateKey(bp, x, cb, u) \
- (DSA *)q_PEM_ASN1_read_bio( \
- (void *(*)(void**, const unsigned char**, long int))q_d2i_DSAPrivateKey, PEM_STRING_DSA, bp, (void **)x, cb, u)
-#define q_PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
- PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_RSAPrivateKey,PEM_STRING_RSA,\
- bp,(char *)x,enc,kstr,klen,cb,u)
-#define q_PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
- PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_DSAPrivateKey,PEM_STRING_DSA,\
- bp,(char *)x,enc,kstr,klen,cb,u)
-#define q_PEM_read_bio_DHparams(bp, dh, cb, u) \
- (DH *)q_PEM_ASN1_read_bio( \
- (void *(*)(void**, const unsigned char**, long int))q_d2i_DHparams, PEM_STRING_DHPARAMS, bp, (void **)x, cb, u)
-#endif
-#define q_SSL_CTX_set_options(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
#define q_SSL_CTX_set_mode(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)
-#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_sk_num)(st)
-#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_sk_value)(st, i)
#define q_sk_GENERAL_NAME_num(st) q_SKM_sk_num(GENERAL_NAME, (st))
#define q_sk_GENERAL_NAME_value(st, i) q_SKM_sk_value(GENERAL_NAME, (st), (i))
#define q_sk_X509_num(st) q_SKM_sk_num(X509, (st))
@@ -558,18 +476,12 @@ DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
#define q_sk_SSL_CIPHER_value(st, i) q_SKM_sk_value(SSL_CIPHER, (st), (i))
#define q_SSL_CTX_add_extra_chain_cert(ctx,x509) \
q_SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
-#define q_X509_get_notAfter(x) X509_get_notAfter(x)
-#define q_X509_get_notBefore(x) X509_get_notBefore(x)
#define q_EVP_PKEY_assign_RSA(pkey,rsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
(char *)(rsa))
#define q_EVP_PKEY_assign_DSA(pkey,dsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
(char *)(dsa))
#define q_OpenSSL_add_all_algorithms() q_OPENSSL_add_all_algorithms_conf()
-void q_OPENSSL_add_all_algorithms_noconf();
-void q_OPENSSL_add_all_algorithms_conf();
int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath);
-long q_SSLeay();
-const char *q_SSLeay_version(int type);
int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
SSL_SESSION *q_d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length);
diff --git a/src/network/ssl/qsslsocket_opensslpre11.cpp b/src/network/ssl/qsslsocket_opensslpre11.cpp
new file mode 100644
index 0000000000..e51888c5f2
--- /dev/null
+++ b/src/network/ssl/qsslsocket_opensslpre11.cpp
@@ -0,0 +1,424 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2014 Governikus GmbH & Co. KG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** In addition, as a special exception, the copyright holders listed above give
+** permission to link the code of its release of Qt with the OpenSSL project's
+** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
+** same license as the original version), and distribute the linked executables.
+**
+** You must comply with the GNU General Public License version 2 in all
+** respects for all of the code used other than the "OpenSSL" code. If you
+** modify this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version of this file.
+**
+****************************************************************************/
+
+//#define QT_DECRYPT_SSL_TRAFFIC
+
+#include "qssl_p.h"
+#include "qsslsocket_openssl_p.h"
+#include "qsslsocket_openssl_symbols_p.h"
+#include "qsslsocket.h"
+#include "qsslkey.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qdiriterator.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qlibrary.h>
+
+QT_BEGIN_NAMESPACE
+
+/* \internal
+
+ From OpenSSL's thread(3) manual page:
+
+ OpenSSL can safely be used in multi-threaded applications provided that at
+ least two callback functions are set.
+
+ locking_function(int mode, int n, const char *file, int line) is needed to
+ perform locking on shared data structures. (Note that OpenSSL uses a
+ number of global data structures that will be implicitly shared
+ whenever multiple threads use OpenSSL.) Multi-threaded
+ applications will crash at random if it is not set. ...
+ ...
+ id_function(void) is a function that returns a thread ID. It is not
+ needed on Windows nor on platforms where getpid() returns a different
+ ID for each thread (most notably Linux)
+*/
+
+class QOpenSslLocks
+{
+public:
+ QOpenSslLocks()
+ : initLocker(QMutex::Recursive),
+ locksLocker(QMutex::Recursive)
+ {
+ QMutexLocker locker(&locksLocker);
+ int numLocks = q_CRYPTO_num_locks();
+ locks = new QMutex *[numLocks];
+ memset(locks, 0, numLocks * sizeof(QMutex *));
+ }
+ ~QOpenSslLocks()
+ {
+ QMutexLocker locker(&locksLocker);
+ for (int i = 0; i < q_CRYPTO_num_locks(); ++i)
+ delete locks[i];
+ delete [] locks;
+
+ QSslSocketPrivate::deinitialize();
+ }
+ QMutex *lock(int num)
+ {
+ QMutexLocker locker(&locksLocker);
+ QMutex *tmp = locks[num];
+ if (!tmp)
+ tmp = locks[num] = new QMutex(QMutex::Recursive);
+ return tmp;
+ }
+
+ QMutex *globalLock()
+ {
+ return &locksLocker;
+ }
+
+ QMutex *initLock()
+ {
+ return &initLocker;
+ }
+
+private:
+ QMutex initLocker;
+ QMutex locksLocker;
+ QMutex **locks;
+};
+
+Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks)
+
+extern "C" {
+static void locking_function(int mode, int lockNumber, const char *, int)
+{
+ QMutex *mutex = openssl_locks()->lock(lockNumber);
+
+ // Lock or unlock it
+ if (mode & CRYPTO_LOCK)
+ mutex->lock();
+ else
+ mutex->unlock();
+}
+static unsigned long id_function()
+{
+ return (quintptr)QThread::currentThreadId();
+}
+
+} // extern "C"
+
+static void q_OpenSSL_add_all_algorithms_safe()
+{
+#ifdef Q_OS_WIN
+ // Prior to version 1.0.1m an attempt to call OpenSSL_add_all_algorithms on
+ // Windows could result in 'exit' call from OPENSSL_config (QTBUG-43843).
+ // We can predict this and avoid OPENSSL_add_all_algorithms call.
+ // From OpenSSL docs:
+ // "An application does not need to add algorithms to use them explicitly,
+ // for example by EVP_sha1(). It just needs to add them if it (or any of
+ // the functions it calls) needs to lookup algorithms.
+ // The cipher and digest lookup functions are used in many parts of the
+ // library. If the table is not initialized several functions will
+ // misbehave and complain they cannot find algorithms. This includes the
+ // PEM, PKCS#12, SSL and S/MIME libraries. This is a common query in
+ // the OpenSSL mailing lists."
+ //
+ // Anyway, as a result, we chose not to call this function if it would exit.
+
+ if (q_SSLeay() < 0x100010DFL)
+ {
+ // Now, before we try to call it, check if an attempt to open config file
+ // will result in exit:
+ if (char *confFileName = q_CONF_get1_default_config_file()) {
+ BIO *confFile = q_BIO_new_file(confFileName, "r");
+ const auto lastError = q_ERR_peek_last_error();
+ q_CRYPTO_free(confFileName);
+ if (confFile) {
+ q_BIO_free(confFile);
+ } else {
+ q_ERR_clear_error();
+ if (ERR_GET_REASON(lastError) == ERR_R_SYS_LIB) {
+ qCWarning(lcSsl, "failed to open openssl.conf file");
+ return;
+ }
+ }
+ }
+ }
+#endif // Q_OS_WIN
+
+ q_OpenSSL_add_all_algorithms();
+}
+
+
+/*!
+ \internal
+*/
+void QSslSocketPrivate::deinitialize()
+{
+ q_CRYPTO_set_id_callback(0);
+ q_CRYPTO_set_locking_callback(0);
+ q_ERR_free_strings();
+}
+
+
+bool QSslSocketPrivate::ensureLibraryLoaded()
+{
+ if (!q_resolveOpenSslSymbols())
+ return false;
+
+ // Check if the library itself needs to be initialized.
+ QMutexLocker locker(openssl_locks()->initLock());
+
+ if (!s_libraryLoaded) {
+ s_libraryLoaded = true;
+
+ // Initialize OpenSSL.
+ q_CRYPTO_set_id_callback(id_function);
+ q_CRYPTO_set_locking_callback(locking_function);
+ if (q_SSL_library_init() != 1)
+ return false;
+ q_SSL_load_error_strings();
+ q_OpenSSL_add_all_algorithms_safe();
+
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ if (q_SSLeay() >= 0x10001000L)
+ QSslSocketBackendPrivate::s_indexForSSLExtraData = q_SSL_get_ex_new_index(0L, NULL, NULL, NULL, NULL);
+#endif
+
+ // Initialize OpenSSL's random seed.
+ if (!q_RAND_status()) {
+ qWarning("Random number generator not seeded, disabling SSL support");
+ return false;
+ }
+ }
+ return true;
+}
+
+void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
+{
+ QMutexLocker locker(openssl_locks()->initLock());
+ if (s_loadedCiphersAndCerts)
+ return;
+ s_loadedCiphersAndCerts = true;
+
+ resetDefaultCiphers();
+ resetDefaultEllipticCurves();
+
+#if QT_CONFIG(library)
+ //load symbols needed to receive certificates from system store
+#if defined(Q_OS_WIN)
+ HINSTANCE hLib = LoadLibraryW(L"Crypt32");
+ if (hLib) {
+ ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
+ ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
+ ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
+ if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
+ qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
+ } else {
+ qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
+ }
+#elif defined(Q_OS_QNX)
+ s_loadRootCertsOnDemand = true;
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
+ // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
+ QList<QByteArray> dirs = unixRootCertDirectories();
+ QStringList symLinkFilter;
+ symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
+ for (int a = 0; a < dirs.count(); ++a) {
+ QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
+ if (iterator.hasNext()) {
+ s_loadRootCertsOnDemand = true;
+ break;
+ }
+ }
+#endif
+#endif // QT_CONFIG(library)
+ // if on-demand loading was not enabled, load the certs now
+ if (!s_loadRootCertsOnDemand)
+ setDefaultCaCertificates(systemCaCertificates());
+#ifdef Q_OS_WIN
+ //Enabled for fetching additional root certs from windows update on windows 6+
+ //This flag is set false by setDefaultCaCertificates() indicating the app uses
+ //its own cert bundle rather than the system one.
+ //Same logic that disables the unix on demand cert loading.
+ //Unlike unix, we do preload the certificates from the cert store.
+ if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
+ s_loadRootCertsOnDemand = true;
+#endif
+}
+
+long QSslSocketPrivate::sslLibraryVersionNumber()
+{
+ if (!supportsSsl())
+ return 0;
+
+ return q_SSLeay();
+}
+
+QString QSslSocketPrivate::sslLibraryVersionString()
+{
+ if (!supportsSsl())
+ return QString();
+
+ const char *versionString = q_SSLeay_version(SSLEAY_VERSION);
+ if (!versionString)
+ return QString();
+
+ return QString::fromLatin1(versionString);
+}
+
+void QSslSocketBackendPrivate::continueHandshake()
+{
+ Q_Q(QSslSocket);
+ // if we have a max read buffer size, reset the plain socket's to match
+ if (readBufferMaxSize)
+ plainSocket->setReadBufferSize(readBufferMaxSize);
+
+ if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL))
+ configuration.peerSessionShared = true;
+
+#ifdef QT_DECRYPT_SSL_TRAFFIC
+ if (ssl->session && ssl->s3) {
+ const char *mk = reinterpret_cast<const char *>(ssl->session->master_key);
+ QByteArray masterKey(mk, ssl->session->master_key_length);
+ const char *random = reinterpret_cast<const char *>(ssl->s3->client_random);
+ QByteArray clientRandom(random, SSL3_RANDOM_SIZE);
+
+ // different format, needed for e.g. older Wireshark versions:
+// const char *sid = reinterpret_cast<const char *>(ssl->session->session_id);
+// QByteArray sessionID(sid, ssl->session->session_id_length);
+// QByteArray debugLineRSA("RSA Session-ID:");
+// debugLineRSA.append(sessionID.toHex().toUpper());
+// debugLineRSA.append(" Master-Key:");
+// debugLineRSA.append(masterKey.toHex().toUpper());
+// debugLineRSA.append("\n");
+
+ QByteArray debugLineClientRandom("CLIENT_RANDOM ");
+ debugLineClientRandom.append(clientRandom.toHex().toUpper());
+ debugLineClientRandom.append(" ");
+ debugLineClientRandom.append(masterKey.toHex().toUpper());
+ debugLineClientRandom.append("\n");
+
+ QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
+ QFile file(sslKeyFile);
+ if (!file.open(QIODevice::Append))
+ qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
+ if (!file.write(debugLineClientRandom))
+ qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
+ file.close();
+ } else {
+ qCWarning(lcSsl, "could not decrypt SSL traffic");
+ }
+#endif
+
+ // Cache this SSL session inside the QSslContext
+ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
+ if (!sslContextPointer->cacheSession(ssl)) {
+ sslContextPointer.clear(); // we could not cache the session
+ } else {
+ // Cache the session for permanent usage as well
+ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
+ if (!sslContextPointer->sessionASN1().isEmpty())
+ configuration.sslSession = sslContextPointer->sessionASN1();
+ configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
+ }
+ }
+ }
+
+#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
+
+ configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
+ if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
+ // we could not agree -> be conservative and use HTTP/1.1
+ configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
+ } else {
+ const unsigned char *proto = 0;
+ unsigned int proto_len = 0;
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ if (q_SSLeay() >= 0x10002000L) {
+ q_SSL_get0_alpn_selected(ssl, &proto, &proto_len);
+ if (proto_len && mode == QSslSocket::SslClientMode) {
+ // Client does not have a callback that sets it ...
+ configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated;
+ }
+ }
+
+ if (!proto_len) { // Test if NPN was more lucky ...
+#else
+ {
+#endif
+ q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
+ }
+
+ if (proto_len)
+ configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len);
+ else
+ configuration.nextNegotiatedProtocol.clear();
+ }
+#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
+
+#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+ if (q_SSLeay() >= 0x10002000L && mode == QSslSocket::SslClientMode) {
+ EVP_PKEY *key;
+ if (q_SSL_get_server_tmp_key(ssl, &key))
+ configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
+ }
+#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
+
+ connectionEncrypted = true;
+ emit q->encrypted();
+ if (autoStartHandshake && pendingClose) {
+ pendingClose = false;
+ q->disconnectFromHost();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h b/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h
new file mode 100644
index 0000000000..9686d22b98
--- /dev/null
+++ b/src/network/ssl/qsslsocket_opensslpre11_symbols_p.h
@@ -0,0 +1,230 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** In addition, as a special exception, the copyright holders listed above give
+** permission to link the code of its release of Qt with the OpenSSL project's
+** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
+** same license as the original version), and distribute the linked executables.
+**
+** You must comply with the GNU General Public License version 2 in all
+** respects for all of the code used other than the "OpenSSL" code. If you
+** modify this file, you may extend this exception to your version of the file,
+** but you are not obligated to do so. If you do not wish to do so, delete
+** this exception statement from your version of this file.
+**
+****************************************************************************/
+
+
+#ifndef QSSLSOCKET_OPENSSLPRE11_SYMBOLS_P_H
+#define QSSLSOCKET_OPENSSLPRE11_SYMBOLS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+// Note: this file does not have QT_BEGIN_NAMESPACE/QT_END_NAMESPACE, it's done
+// in qsslsocket_openssl_symbols_p.h.
+
+#ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H
+#error "You are not supposed to use this header file, include qsslsocket_openssl_symbols_p.h instead"
+#endif
+
+unsigned char * q_ASN1_STRING_data(ASN1_STRING *a);
+BIO *q_BIO_new_file(const char *filename, const char *mode);
+void q_ERR_clear_error();
+Q_AUTOTEST_EXPORT BIO *q_BIO_new(BIO_METHOD *a);
+Q_AUTOTEST_EXPORT BIO_METHOD *q_BIO_s_mem();
+int q_CRYPTO_num_locks();
+void q_CRYPTO_set_locking_callback(void (*a)(int, int, const char *, int));
+void q_CRYPTO_set_id_callback(unsigned long (*a)());
+void q_CRYPTO_free(void *a);
+unsigned long q_ERR_peek_last_error();
+void q_ERR_free_strings();
+void q_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
+void q_EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+typedef _STACK STACK;
+#endif
+
+// The typedef we use to make our pre 1.1 code look more like 1.1 (less ifdefs).
+typedef STACK OPENSSL_STACK;
+
+// We resolve q_sk_ functions, but use q_OPENSSL_sk_ macros in code to reduce
+// the amount of #ifdefs.
+int q_sk_num(STACK *a);
+#define q_OPENSSL_sk_num(a) q_sk_num(a)
+void q_sk_pop_free(STACK *a, void (*b)(void *));
+#define q_OPENSSL_sk_pop_free(a, b) q_sk_pop_free(a, b)
+STACK *q_sk_new_null();
+#define q_OPENSSL_sk_new_null() q_sk_new_null()
+
+void q_sk_free(STACK *a);
+
+// Just a name alias (not a function call expression) since in code we take an
+// address of this:
+#define q_OPENSSL_sk_free q_sk_free
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+void *q_sk_value(STACK *a, int b);
+void q_sk_push(STACK *st, void *data);
+#else
+char *q_sk_value(STACK *a, int b);
+void q_sk_push(STACK *st, char *data);
+#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L
+
+#define q_OPENSSL_sk_value(a, b) q_sk_value(a, b)
+#define q_OPENSSL_sk_push(st, data) q_sk_push(st, data)
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+SSL_CTX *q_SSL_CTX_new(const SSL_METHOD *a);
+#else
+SSL_CTX *q_SSL_CTX_new(SSL_METHOD *a);
+#endif
+
+int q_SSL_library_init();
+void q_SSL_load_error_strings();
+
+#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+int q_SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+#endif
+
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+#ifndef OPENSSL_NO_SSL2
+const SSL_METHOD *q_SSLv2_client_method();
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+const SSL_METHOD *q_SSLv3_client_method();
+#endif
+const SSL_METHOD *q_SSLv23_client_method();
+const SSL_METHOD *q_TLSv1_client_method();
+const SSL_METHOD *q_TLSv1_1_client_method();
+const SSL_METHOD *q_TLSv1_2_client_method();
+#ifndef OPENSSL_NO_SSL2
+const SSL_METHOD *q_SSLv2_server_method();
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+const SSL_METHOD *q_SSLv3_server_method();
+#endif
+const SSL_METHOD *q_SSLv23_server_method();
+const SSL_METHOD *q_TLSv1_server_method();
+const SSL_METHOD *q_TLSv1_1_server_method();
+const SSL_METHOD *q_TLSv1_2_server_method();
+#else
+#ifndef OPENSSL_NO_SSL2
+SSL_METHOD *q_SSLv2_client_method();
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+SSL_METHOD *q_SSLv3_client_method();
+#endif
+SSL_METHOD *q_SSLv23_client_method();
+SSL_METHOD *q_TLSv1_client_method();
+SSL_METHOD *q_TLSv1_1_client_method();
+SSL_METHOD *q_TLSv1_2_client_method();
+#ifndef OPENSSL_NO_SSL2
+SSL_METHOD *q_SSLv2_server_method();
+#endif
+#ifndef OPENSSL_NO_SSL3_METHOD
+SSL_METHOD *q_SSLv3_server_method();
+#endif
+SSL_METHOD *q_SSLv23_server_method();
+SSL_METHOD *q_TLSv1_server_method();
+SSL_METHOD *q_TLSv1_1_server_method();
+SSL_METHOD *q_TLSv1_2_server_method();
+#endif
+
+STACK_OF(X509) *q_X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
+
+#ifdef SSLEAY_MACROS
+int q_i2d_DSAPrivateKey(const DSA *a, unsigned char **pp);
+int q_i2d_RSAPrivateKey(const RSA *a, unsigned char **pp);
+RSA *q_d2i_RSAPrivateKey(RSA **a, unsigned char **pp, long length);
+DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
+#define q_PEM_read_bio_RSAPrivateKey(bp, x, cb, u) \
+ (RSA *)q_PEM_ASN1_read_bio( \
+ (void *(*)(void**, const unsigned char**, long int))q_d2i_RSAPrivateKey, PEM_STRING_RSA, bp, (void **)x, cb, u)
+#define q_PEM_read_bio_DSAPrivateKey(bp, x, cb, u) \
+ (DSA *)q_PEM_ASN1_read_bio( \
+ (void *(*)(void**, const unsigned char**, long int))q_d2i_DSAPrivateKey, PEM_STRING_DSA, bp, (void **)x, cb, u)
+#define q_PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_RSAPrivateKey,PEM_STRING_RSA,\
+ bp,(char *)x,enc,kstr,klen,cb,u)
+#define q_PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+ PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_DSAPrivateKey,PEM_STRING_DSA,\
+ bp,(char *)x,enc,kstr,klen,cb,u)
+#define q_PEM_read_bio_DHparams(bp, dh, cb, u) \
+ (DH *)q_PEM_ASN1_read_bio( \
+ (void *(*)(void**, const unsigned char**, long int))q_d2i_DHparams, PEM_STRING_DHPARAMS, bp, (void **)x, cb, u)
+#endif // SSLEAY_MACROS
+
+#define q_SSL_CTX_set_options(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
+#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_sk_num)(st)
+#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_sk_value)(st, i)
+#define q_X509_getm_notAfter(x) X509_get_notAfter(x)
+#define q_X509_getm_notBefore(x) X509_get_notBefore(x)
+
+// "Forward compatibility" with OpenSSL 1.1 (to save on #if-ery elsewhere):
+#define q_X509_get_version(x509) q_ASN1_INTEGER_get((x509)->cert_info->version)
+#define q_ASN1_STRING_get0_data(x) q_ASN1_STRING_data(x)
+#define q_EVP_PKEY_base_id(pkey) ((pkey)->type)
+#define q_X509_get_pubkey(x509) q_X509_PUBKEY_get((x509)->cert_info->key)
+#define q_SSL_SESSION_get_ticket_lifetime_hint(s) ((s)->tlsext_tick_lifetime_hint)
+#define q_RSA_bits(rsa) q_BN_num_bits((rsa)->n)
+#define q_DSA_bits(dsa) q_BN_num_bits((dsa)->p)
+#define q_X509_STORE_set_verify_cb(s,c) X509_STORE_set_verify_cb_func((s),(c))
+
+char *q_CONF_get1_default_config_file();
+void q_OPENSSL_add_all_algorithms_noconf();
+void q_OPENSSL_add_all_algorithms_conf();
+
+long q_SSLeay();
+const char *q_SSLeay_version(int type);
+
+
+#endif // QSSLSOCKET_OPENSSL_PRE11_SYMBOLS_P_H
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index aec3437422..5e5a8d2371 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -217,6 +217,7 @@ private:
protected:
bool verifyErrorsHaveBeenIgnored();
bool paused;
+ bool flushTriggered;
};
QT_END_NAMESPACE
diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri
index 52ce2eeade..949ebc3d2a 100644
--- a/src/network/ssl/ssl.pri
+++ b/src/network/ssl/ssl.pri
@@ -60,13 +60,25 @@ qtConfig(ssl) {
HEADERS += ssl/qsslcontext_openssl_p.h \
ssl/qsslsocket_openssl_p.h \
ssl/qsslsocket_openssl_symbols_p.h
- SOURCES += ssl/qsslcertificate_openssl.cpp \
- ssl/qsslcontext_openssl.cpp \
+ SOURCES += ssl/qsslsocket_openssl_symbols.cpp \
ssl/qssldiffiehellmanparameters_openssl.cpp \
+ ssl/qsslcertificate_openssl.cpp \
ssl/qsslellipticcurve_openssl.cpp \
ssl/qsslkey_openssl.cpp \
ssl/qsslsocket_openssl.cpp \
- ssl/qsslsocket_openssl_symbols.cpp
+ ssl/qsslcontext_openssl.cpp
+
+ qtConfig(opensslv11) {
+ HEADERS += ssl/qsslsocket_openssl11_symbols_p.h
+ SOURCES += ssl/qsslsocket_openssl11.cpp \
+ ssl/qsslcontext_openssl11.cpp
+
+ QMAKE_CXXFLAGS += -DOPENSSL_API_COMPAT=0x10100000L
+ } else {
+ HEADERS += ssl/qsslsocket_opensslpre11_symbols_p.h
+ SOURCES += ssl/qsslsocket_opensslpre11.cpp \
+ ssl/qsslcontext_opensslpre11.cpp
+ }
darwin:SOURCES += ssl/qsslsocket_mac_shared.cpp
diff --git a/src/platformheaders/cocoafunctions/qcocoawindowfunctions.h b/src/platformheaders/cocoafunctions/qcocoawindowfunctions.h
index 3af3392268..248900ad2a 100644
--- a/src/platformheaders/cocoafunctions/qcocoawindowfunctions.h
+++ b/src/platformheaders/cocoafunctions/qcocoawindowfunctions.h
@@ -37,8 +37,8 @@
**
****************************************************************************/
-#ifndef QXCBWINDOWFUNCTIONS_H
-#define QXCBWINDOWFUNCTIONS_H
+#ifndef QCOCOAWINDOWFUNCTIONS_H
+#define QCOCOAWINDOWFUNCTIONS_H
#include <QtPlatformHeaders/QPlatformHeaderHelper>
@@ -60,4 +60,4 @@ public:
QT_END_NAMESPACE
-#endif // QXCBWINDOWFUNCTIONS_H
+#endif // QCOCOAWINDOWFUNCTIONS_H
diff --git a/src/platformsupport/clipboard/clipboard.pro b/src/platformsupport/clipboard/clipboard.pro
index def2a061a0..916f6b0c06 100644
--- a/src/platformsupport/clipboard/clipboard.pro
+++ b/src/platformsupport/clipboard/clipboard.pro
@@ -9,6 +9,7 @@ DEFINES += QT_NO_CAST_FROM_ASCII
HEADERS += qmacmime_p.h
SOURCES += qmacmime.mm
+LIBS += -framework ImageIO
macos: LIBS_PRIVATE += -framework AppKit
load(qt_module)
diff --git a/src/platformsupport/clipboard/qmacmime.mm b/src/platformsupport/clipboard/qmacmime.mm
index 6a6e033bec..09901ba0a5 100644
--- a/src/platformsupport/clipboard/qmacmime.mm
+++ b/src/platformsupport/clipboard/qmacmime.mm
@@ -37,10 +37,15 @@
**
****************************************************************************/
+#include <ImageIO/ImageIO.h>
+
#include <QtCore/qsystemdetection.h>
+#include <QtGui/qimage.h>
#if defined(Q_OS_OSX)
#import <AppKit/AppKit.h>
+#else
+#include <MobileCoreServices/MobileCoreServices.h>
#endif
#if defined(QT_PLATFORM_UIKIT)
@@ -779,6 +784,85 @@ QList<QByteArray> QMacPasteboardMimeVCard::convertFromMime(const QString &mime,
return ret;
}
+extern QImage qt_mac_toQImage(CGImageRef image);
+extern CGImageRef qt_mac_toCGImage(const QImage &qImage);
+
+class QMacPasteboardMimeTiff : public QMacInternalPasteboardMime {
+public:
+ QMacPasteboardMimeTiff() : QMacInternalPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeTiff::convertorName()
+{
+ return QLatin1String("Tiff");
+}
+
+QString QMacPasteboardMimeTiff::flavorFor(const QString &mime)
+{
+ if (mime.startsWith(QLatin1String("application/x-qt-image")))
+ return QLatin1String("public.tiff");
+ return QString();
+}
+
+QString QMacPasteboardMimeTiff::mimeFor(QString flav)
+{
+ if (flav == QLatin1String("public.tiff"))
+ return QLatin1String("application/x-qt-image");
+ return QString();
+}
+
+bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav)
+{
+ return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image");
+}
+
+QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if (data.count() > 1)
+ qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data");
+
+ if (!canConvert(mime, flav))
+ return QVariant();
+
+ QCFType<CFDataRef> tiffData = data.first().toRawCFData();
+ QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
+
+ if (QCFType<CGImageRef> image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0))
+ return QVariant(qt_mac_toQImage(image));
+
+ return QVariant();
+}
+
+QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav)
+{
+ if (!canConvert(mime, flav))
+ return QList<QByteArray>();
+
+ QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
+ QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0);
+
+ if (!imageDestination)
+ return QList<QByteArray>();
+
+ QImage img = qvariant_cast<QImage>(variant);
+ NSDictionary *props = @{
+ static_cast<NSString *>(kCGImagePropertyPixelWidth) : [NSNumber numberWithInt:img.width()],
+ static_cast<NSString *>(kCGImagePropertyPixelHeight) : [NSNumber numberWithInt:img.height()]
+ };
+
+ CGImageDestinationAddImage(imageDestination, qt_mac_toCGImage(img), static_cast<CFDictionaryRef>(props));
+ CGImageDestinationFinalize(imageDestination);
+
+ return QList<QByteArray>() << QByteArray::fromCFData(data);
+}
+
/*!
\internal
@@ -792,6 +876,7 @@ void QMacInternalPasteboardMime::initializeMimeTypes()
new QMacPasteboardMimeAny;
//standard types that we wrap
+ new QMacPasteboardMimeTiff;
new QMacPasteboardMimePlainTextFallback;
new QMacPasteboardMimeUnicodeText;
new QMacPasteboardMimeRtfText;
diff --git a/src/platformsupport/edid/edid.pro b/src/platformsupport/edid/edid.pro
new file mode 100644
index 0000000000..842a91170e
--- /dev/null
+++ b/src/platformsupport/edid/edid.pro
@@ -0,0 +1,13 @@
+TARGET = QtEdidSupport
+MODULE = edid_support
+
+QT = core-private
+CONFIG += static internal_module
+
+DEFINES += QT_NO_CAST_FROM_ASCII
+PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
+
+HEADERS += qedidparser_p.h
+SOURCES += qedidparser.cpp
+
+load(qt_module)
diff --git a/src/platformsupport/edid/qedidparser.cpp b/src/platformsupport/edid/qedidparser.cpp
new file mode 100644
index 0000000000..ccf12e9eb3
--- /dev/null
+++ b/src/platformsupport/edid/qedidparser.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/QFile>
+
+#include "qedidparser_p.h"
+#include "qedidvendortable_p.h"
+
+#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
+
+#define EDID_DESCRIPTOR_ALPHANUMERIC_STRING 0xfe
+#define EDID_DESCRIPTOR_PRODUCT_NAME 0xfc
+#define EDID_DESCRIPTOR_SERIAL_NUMBER 0xff
+
+#define EDID_OFFSET_DATA_BLOCKS 0x36
+#define EDID_OFFSET_LAST_BLOCK 0x6c
+#define EDID_OFFSET_PNP_ID 0x08
+#define EDID_OFFSET_SERIAL 0x0c
+#define EDID_PHYSICAL_WIDTH 0x15
+#define EDID_OFFSET_PHYSICAL_HEIGHT 0x16
+
+QT_BEGIN_NAMESPACE
+
+QEdidParser::QEdidParser()
+{
+ // Cache vendors list from pnp.ids
+ const QString fileName = QLatin1String("/usr/share/hwdata/pnp.ids");
+ if (QFile::exists(fileName)) {
+ QFile file(fileName);
+
+ if (file.open(QFile::ReadOnly)) {
+ while (!file.atEnd()) {
+ QString line = QString::fromUtf8(file.readLine()).trimmed();
+
+ if (line.startsWith(QLatin1Char('#')))
+ continue;
+
+ QStringList parts = line.split(QLatin1Char('\t'));
+ if (parts.count() > 1) {
+ QString pnpId = parts.at(0);
+ parts.removeFirst();
+ m_vendorCache[pnpId] = parts.join(QLatin1Char(' '));
+ }
+ }
+
+ file.close();
+ }
+ }
+}
+
+bool QEdidParser::parse(const QByteArray &blob)
+{
+ const quint8 *data = reinterpret_cast<const quint8 *>(blob.constData());
+ const size_t length = blob.length();
+
+ // Verify header
+ if (length < 128)
+ return false;
+ if (data[0] != 0x00 || data[1] != 0xff)
+ return false;
+
+ /* Decode the PNP ID from three 5 bit words packed into 2 bytes
+ * /--08--\/--09--\
+ * 7654321076543210
+ * |\---/\---/\---/
+ * R C1 C2 C3 */
+ char id[3];
+ id[0] = 'A' + ((data[EDID_OFFSET_PNP_ID] & 0x7c) / 4) - 1;
+ id[1] = 'A' + ((data[EDID_OFFSET_PNP_ID] & 0x3) * 8) + ((data[EDID_OFFSET_PNP_ID + 1] & 0xe0) / 32) - 1;
+ id[2] = 'A' + (data[EDID_OFFSET_PNP_ID + 1] & 0x1f) - 1;
+ identifier = QString::fromLatin1(id, 3);
+
+ // Clear manufacturer
+ manufacturer = QString();
+
+ // Serial number, will be overwritten by an ASCII descriptor
+ // when and if it will be found
+ quint32 serial = data[EDID_OFFSET_SERIAL]
+ + (data[EDID_OFFSET_SERIAL + 1] << 8)
+ + (data[EDID_OFFSET_SERIAL + 2] << 16)
+ + (data[EDID_OFFSET_SERIAL + 3] << 24);
+ if (serial > 0)
+ serialNumber = QString::number(serial);
+ else
+ serialNumber = QString();
+
+ // Parse EDID data
+ for (int i = 0; i < 5; ++i) {
+ const uint offset = EDID_OFFSET_DATA_BLOCKS + i * 18;
+
+ if (data[offset] != 0 || data[offset + 1] != 0 || data[offset + 2] != 0)
+ continue;
+
+ if (data[offset + 3] == EDID_DESCRIPTOR_PRODUCT_NAME)
+ model = parseEdidString(&data[offset + 5]);
+ else if (data[offset + 3] == EDID_DESCRIPTOR_ALPHANUMERIC_STRING)
+ identifier = parseEdidString(&data[offset + 5]);
+ else if (data[offset + 3] == EDID_DESCRIPTOR_SERIAL_NUMBER)
+ serialNumber = parseEdidString(&data[offset + 5]);
+ }
+
+ // Try to use cache first because it is potentially more updated
+ if (m_vendorCache.contains(identifier)) {
+ manufacturer = m_vendorCache[identifier];
+ } else {
+ // Find the manufacturer from the vendor lookup table
+ for (size_t i = 0; i < ARRAY_LENGTH(q_edidVendorTable); i++) {
+ if (strcmp(q_edidVendorTable[i].id, identifier.toLatin1().constData()) == 0) {
+ manufacturer = QString::fromUtf8(q_edidVendorTable[i].name);
+ break;
+ }
+ }
+ }
+
+ // If we don't know the manufacturer, fallback to PNP ID
+ if (manufacturer.isEmpty())
+ manufacturer = identifier;
+
+ // Physical size
+ physicalSize = QSizeF(data[EDID_PHYSICAL_WIDTH], data[EDID_OFFSET_PHYSICAL_HEIGHT]) * 10;
+
+ return true;
+}
+
+QString QEdidParser::parseEdidString(const quint8 *data)
+{
+ QByteArray buffer(reinterpret_cast<const char *>(data), 12);
+
+ // Erase carriage return and line feed
+ buffer = buffer.replace('\r', '\0').replace('\n', '\0');
+
+ // Replace non-printable characters with dash
+ for (int i = 0; i < buffer.count(); ++i) {
+ if (buffer[i] < '\040' && buffer[i] > '\176')
+ buffer[i] = '-';
+ }
+
+ return QString::fromLatin1(buffer.trimmed());
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/edid/qedidparser_p.h b/src/platformsupport/edid/qedidparser_p.h
new file mode 100644
index 0000000000..c5888dc5d7
--- /dev/null
+++ b/src/platformsupport/edid/qedidparser_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEDIDPARSER_P_H
+#define QEDIDPARSER_P_H
+
+#include <QtCore/QSize>
+#include <QtCore/QMap>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QEdidParser
+{
+public:
+ QEdidParser();
+
+ bool parse(const QByteArray &blob);
+
+ QString identifier;
+ QString manufacturer;
+ QString model;
+ QString serialNumber;
+ QSizeF physicalSize;
+
+private:
+ QMap<QString, QString> m_vendorCache;
+
+ QString parseEdidString(const quint8 *data);
+};
+
+QT_END_NAMESPACE
+
+#endif // QEDIDPARSER_P_H
diff --git a/src/platformsupport/edid/qedidvendortable_p.h b/src/platformsupport/edid/qedidvendortable_p.h
new file mode 100644
index 0000000000..d09642d649
--- /dev/null
+++ b/src/platformsupport/edid/qedidvendortable_p.h
@@ -0,0 +1,2296 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * This lookup table was generated from https://git.fedorahosted.org/cgit/hwdata.git/plain/pnp.ids
+ *
+ * Do not change directly this file, instead edit the
+ * qtbase/util/edid/qedidvendortable.py script and regenerate this file.
+ */
+
+#ifndef QEDIDVENDORTABLE_P_H
+#define QEDIDVENDORTABLE_P_H
+
+QT_BEGIN_NAMESPACE
+
+typedef struct VendorTable {
+ const char id[4];
+ const char name[78];
+} VendorTable;
+
+static const struct VendorTable q_edidVendorTable[] = {
+ { "LLL", "L-3 Communications" },
+ { "GMX", "GMX Inc" },
+ { "FOS", "Foss Tecator" },
+ { "PHI", "DO NOT USE - PHI" },
+ { "DNV", "DiCon" },
+ { "KZN", "K-Zone International" },
+ { "TIC", "Trigem KinfoComm" },
+ { "FNC", "Fanuc LTD" },
+ { "ESY", "E-Systems Inc" },
+ { "TGM", "TriGem Computer,Inc." },
+ { "DBN", "DB Networks Inc" },
+ { "GCS", "Grey Cell Systems Ltd" },
+ { "AVR", "AVer Information Inc." },
+ { "OKI", "OKI Electric Industrial Company Ltd" },
+ { "GDI", "G. Diehl ISDN GmbH" },
+ { "SPC", "SpinCore Technologies, Inc" },
+ { "ICV", "Inside Contactless" },
+ { "UNY", "Unicate" },
+ { "NMP", "Nokia Mobile Phones" },
+ { "HMC", "Hualon Microelectric Corporation" },
+ { "OPT", "OPTi Inc" },
+ { "TSG", "The Software Group Ltd" },
+ { "IMN", "Impossible Production" },
+ { "DHQ", "Quadram" },
+ { "UFG", "UNIGRAF-USA" },
+ { "CLA", "Clarion Company Ltd" },
+ { "IOM", "Iomega" },
+ { "MTS", "Multi-Tech Systems" },
+ { "TXN", "Texas Insturments" },
+ { "SDH", "Communications Specialies, Inc." },
+ { "DCC", "Dale Computer Corporation" },
+ { "PAK", "Many CNC System Co., Ltd." },
+ { "TDC", "Teradici" },
+ { "XAC", "XAC Automation Corp" },
+ { "DRI", "Data Race Inc" },
+ { "HAN", "Hanchang System Corporation" },
+ { "NTR", "N-trig Innovative Technologies, Inc." },
+ { "PDR", "Pure Data Inc" },
+ { "BNS", "Boulder Nonlinear Systems" },
+ { "EGO", "Ergo Electronics" },
+ { "ETS", "Electronic Trade Solutions Ltd" },
+ { "CNN", "Canon Inc" },
+ { "CSB", "Transtex SA" },
+ { "NAK", "Nakano Engineering Co.,Ltd." },
+ { "IME", "Imagraph" },
+ { "CYT", "Cytechinfo Inc" },
+ { "ADM", "Ad Lib MultiMedia Inc" },
+ { "IBC", "Integrated Business Systems" },
+ { "TMT", "T-Metrics Inc." },
+ { "ALP", "Alps Electric Company Ltd" },
+ { "TWX", "TEKWorx Limited" },
+ { "CDP", "CalComp" },
+ { "KSX", "King Tester Corporation" },
+ { "AMI", "American Megatrends Inc" },
+ { "KBI", "Kidboard Inc" },
+ { "COO", "coolux GmbH" },
+ { "CBR", "Cebra Tech A/S" },
+ { "ANA", "Anakron" },
+ { "ACT", "Applied Creative Technology" },
+ { "PGS", "Princeton Graphic Systems" },
+ { "DCL", "Dynamic Controls Ltd" },
+ { "TCH", "Interaction Systems, Inc" },
+ { "STP", "StreamPlay Ltd" },
+ { "PCG", "First Industrial Computer Inc" },
+ { "SSE", "Samsung Electronic Co." },
+ { "TXT", "Textron Defense System" },
+ { "XRO", "XORO ELECTRONICS (CHENGDU) LIMITED" },
+ { "MTU", "Mark of the Unicorn Inc" },
+ { "ERG", "Ergo System" },
+ { "GFN", "Gefen Inc." },
+ { "UNE", "Unisys Corporation" },
+ { "DDD", "Danka Data Devices" },
+ { "ZGT", "Zenith Data Systems" },
+ { "NAL", "Network Alchemy" },
+ { "FVX", "C-C-C Group Plc" },
+ { "AJA", "AJA Video Systems, Inc." },
+ { "AZT", "Aztech Systems Ltd" },
+ { "CIS", "Cisco Systems Inc" },
+ { "DUA", "Dosch & Amand GmbH & Company KG" },
+ { "INP", "Interphase Corporation" },
+ { "DMS", "DOME imaging systems" },
+ { "COW", "Polycow Productions" },
+ { "PTC", "PS Technology Corporation" },
+ { "PRD", "Praim S.R.L." },
+ { "DEC", "Digital Equipment Corporation" },
+ { "SMT", "Silcom Manufacturing Tech Inc" },
+ { "MII", "Mitec Inc" },
+ { "QLC", "Q-Logic" },
+ { "PRG", "The Phoenix Research Group Inc" },
+ { "LNV", "Lenovo" },
+ { "IND", "ILC" },
+ { "MXL", "Hitachi Maxell, Ltd." },
+ { "DAU", "Daou Tech Inc" },
+ { "SNK", "S&K Electronics" },
+ { "SYE", "SY Electronics Ltd" },
+ { "BCC", "Beaver Computer Corporaton" },
+ { "LPI", "Design Technology" },
+ { "CLO", "Clone Computers" },
+ { "CMI", "C-Media Electronics" },
+ { "ESK", "ES&S" },
+ { "HCW", "Hauppauge Computer Works Inc" },
+ { "KPC", "King Phoenix Company" },
+ { "DXS", "Signet" },
+ { "OLY", "OLYMPUS CORPORATION" },
+ { "OOS", "OSRAM" },
+ { "NOE", "NordicEye AB" },
+ { "DXP", "Data Expert Corporation" },
+ { "ITP", "IT-PRO Consulting und Systemhaus GmbH" },
+ { "MMS", "MMS Electronics" },
+ { "FDC", "Future Domain" },
+ { "ASM", "ASEM S.p.A." },
+ { "AIC", "Arnos Insturments & Computer Systems" },
+ { "ANC", "Ancot" },
+ { "SEE", "SeeColor Corporation" },
+ { "JAS", "Janz Automationssysteme AG" },
+ { "TGV", "Grass Valley Germany GmbH" },
+ { "LTI", "Jongshine Tech Inc" },
+ { "JVC", "JVC" },
+ { "TLV", "S3 Inc" },
+ { "MGC", "Mentor Graphics Corporation" },
+ { "NBS", "National Key Lab. on ISN" },
+ { "GTI", "Goldtouch" },
+ { "SPI", "SPACE-I Co., Ltd." },
+ { "ZNX", "Znyx Adv. Systems" },
+ { "EMC", "eMicro Corporation" },
+ { "WDE", "Westinghouse Digital Electronics" },
+ { "CEN", "Centurion Technologies P/L" },
+ { "BFE", "B.F. Engineering Corporation" },
+ { "DTL", "e-Net Inc" },
+ { "FTL", "FUJITSU TEN LIMITED" },
+ { "HSC", "Hagiwara Sys-Com Company Ltd" },
+ { "ECP", "Elecom Company Ltd" },
+ { "LJX", "Datalogic Corporation" },
+ { "DRC", "Data Ray Corp." },
+ { "STM", "SGS Thomson Microelectronics" },
+ { "GDT", "Vortex Computersysteme GmbH" },
+ { "JSK", "SANKEN ELECTRIC CO., LTD" },
+ { "TMC", "Techmedia Computer Systems Corporation" },
+ { "CFG", "Atlantis" },
+ { "DCO", "Dialogue Technology Corporation" },
+ { "NEC", "NEC Corporation" },
+ { "SAE", "Saab Aerotech" },
+ { "STA", "ST Electronics Systems Assembly Pte Ltd" },
+ { "GEO", "GEO Sense" },
+ { "SLH", "Silicon Library Inc." },
+ { "SAG", "Sedlbauer" },
+ { "VEK", "Vektrex" },
+ { "ADA", "Addi-Data GmbH" },
+ { "NCT", "NEC CustomTechnica, Ltd." },
+ { "STX", "ST-Ericsson" },
+ { "PRM", "Prometheus" },
+ { "DPA", "DigiTalk Pro AV" },
+ { "SLF", "StarLeaf" },
+ { "AXY", "AXYZ Automation Services, Inc" },
+ { "CPX", "Powermatic Data Systems" },
+ { "DLL", "Dell Inc" },
+ { "PLF", "Panasonic Avionics Corporation" },
+ { "FRI", "Fibernet Research Inc" },
+ { "BRM", "Braemar Inc" },
+ { "MSK", "Megasoft Inc" },
+ { "ECT", "Enciris Technologies" },
+ { "TKO", "TouchKo, Inc." },
+ { "CYC", "Cylink Corporation" },
+ { "SMR", "B.& V. s.r.l." },
+ { "SRT", "SeeReal Technologies GmbH" },
+ { "GES", "GES Singapore Pte Ltd" },
+ { "DHT", "Projectavision Inc" },
+ { "ESC", "Eden Sistemas de Computacao S/A" },
+ { "BYD", "byd:sign corporation" },
+ { "BMI", "Benson Medical Instruments Company" },
+ { "XSY", "XSYS" },
+ { "MYX", "Micronyx Inc" },
+ { "OUK", "OUK Company Ltd" },
+ { "MPI", "Mediatrix Peripherals Inc" },
+ { "BUS", "BusTek" },
+ { "LCN", "LEXICON" },
+ { "ADS", "Analog Devices Inc" },
+ { "XTL", "Crystal Computer" },
+ { "CEF", "Cefar Digital Vision" },
+ { "IPP", "IP Power Technologies GmbH" },
+ { "CDV", "Convergent Design Inc." },
+ { "OLD", "Olidata S.p.A." },
+ { "GNN", "GN Nettest Inc" },
+ { "ADH", "Aerodata Holdings Ltd" },
+ { "IMM", "Immersion Corporation" },
+ { "CBT", "Cabletime Ltd" },
+ { "RVI", "Realvision Inc" },
+ { "HNS", "Hughes Network Systems" },
+ { "HAR", "Harris Corporation" },
+ { "ACV", "ActivCard S.A" },
+ { "RUN", "RUNCO International" },
+ { "WDC", "Western Digital" },
+ { "SIG", "Sigma Designs Inc" },
+ { "PNR", "Planar Systems, Inc." },
+ { "PRS", "Leutron Vision" },
+ { "KEM", "Kontron Embedded Modules GmbH" },
+ { "LAN", "Sodeman Lancom Inc" },
+ { "CEM", "MEC Electronics GmbH" },
+ { "RHD", "RightHand Technologies" },
+ { "CHE", "Acer Inc" },
+ { "POL", "PolyComp (PTY) Ltd." },
+ { "MST", "MS Telematica" },
+ { "ALA", "Alacron Inc" },
+ { "EDI", "Edimax Tech. Company Ltd" },
+ { "EGN", "Egenera, Inc." },
+ { "PIX", "Pixie Tech Inc" },
+ { "AVN", "Advance Computer Corporation" },
+ { "CTN", "Computone Products" },
+ { "SFM", "TORNADO Company" },
+ { "ATA", "Allied Telesyn International (Asia) Pte Ltd" },
+ { "SIA", "SIEMENS AG" },
+ { "NAV", "Navigation Corporation" },
+ { "PRF", "Digital Electronics Corporation" },
+ { "HRE", "Qingdao Haier Electronics Co., Ltd." },
+ { "NAC", "Ncast Corporation" },
+ { "ELM", "Elmic Systems Inc" },
+ { "HYR", "Hypertec Pty Ltd" },
+ { "EMB", "Embedded computing inc ltd" },
+ { "MWR", "mware" },
+ { "KGL", "KEISOKU GIKEN Co.,Ltd." },
+ { "NRL", "U.S. Naval Research Lab" },
+ { "TNM", "TECNIMAGEN SA" },
+ { "GTT", "General Touch Technology Co., Ltd." },
+ { "BTE", "Brilliant Technology" },
+ { "KDS", "KDS USA" },
+ { "EEP", "E.E.P.D. GmbH" },
+ { "NCI", "NewCom Inc" },
+ { "CIP", "Ciprico Inc" },
+ { "RTL", "Realtek Semiconductor Company Ltd" },
+ { "MUK", "mainpine limited" },
+ { "SLX", "Specialix" },
+ { "HCM", "HCL Peripherals" },
+ { "CHA", "Chase Research PLC" },
+ { "VOB", "MaxData Computer AG" },
+ { "ANK", "Anko Electronic Company Ltd" },
+ { "FWR", "Flat Connections Inc" },
+ { "DXL", "Dextera Labs Inc" },
+ { "QVU", "Quartics" },
+ { "MPS", "mps Software GmbH" },
+ { "AVM", "AVM GmbH" },
+ { "TDY", "Tandy Electronics" },
+ { "MJS", "MJS Designs" },
+ { "SNC", "Sentronic International Corp." },
+ { "IPT", "International Power Technologies" },
+ { "API", "A Plus Info Corporation" },
+ { "TLT", "Dai Telecom S.p.A." },
+ { "PCC", "PowerCom Technology Company Ltd" },
+ { "TRM", "Tekram Technology Company Ltd" },
+ { "DEL", "Dell Inc." },
+ { "CYW", "Cyberware" },
+ { "TDS", "Tri-Data Systems Inc" },
+ { "FPE", "Fujitsu Peripherals Ltd" },
+ { "SPN", "Sapience Corporation" },
+ { "COX", "Comrex" },
+ { "STE", "SII Ido-Tsushin Inc" },
+ { "RVC", "RSI Systems Inc" },
+ { "HMK", "hmk Daten-System-Technik BmbH" },
+ { "TTA", "Topson Technology Co., Ltd." },
+ { "CSM", "Cosmic Engineering Inc." },
+ { "PTL", "Pantel Inc" },
+ { "EQX", "Equinox Systems Inc" },
+ { "HEL", "Hitachi Micro Systems Europe Ltd" },
+ { "TIX", "Tixi.Com GmbH" },
+ { "CMD", "Colorado MicroDisplay, Inc." },
+ { "VIS", "Visioneer" },
+ { "MTH", "Micro-Tech Hearing Instruments" },
+ { "ISR", "INSIS Co., LTD." },
+ { "EME", "EMiNE TECHNOLOGY COMPANY, LTD." },
+ { "DMT", "Distributed Management Task Force, Inc. (DMTF)" },
+ { "JFX", "Jones Futurex Inc" },
+ { "SMB", "Schlumberger" },
+ { "GTM", "Garnet System Company Ltd" },
+ { "DBK", "Databook Inc" },
+ { "IQT", "IMAGEQUEST Co., Ltd" },
+ { "DTX", "Data Translation" },
+ { "QSI", "Quantum Solutions, Inc." },
+ { "BEL", "Beltronic Industrieelektronik GmbH" },
+ { "PJT", "Pan Jit International Inc." },
+ { "WST", "Wistron Corporation" },
+ { "ASN", "Asante Tech Inc" },
+ { "ROS", "Rohde & Schwarz" },
+ { "NWP", "NovaWeb Technologies Inc" },
+ { "CLG", "CoreLogic" },
+ { "ECS", "Elitegroup Computer Systems Company Ltd" },
+ { "PER", "Perceptive Signal Technologies" },
+ { "SPR", "pmns GmbH" },
+ { "DLB", "Dolby Laboratories Inc." },
+ { "SRF", "Surf Communication Solutions Ltd" },
+ { "ATM", "ATM Ltd" },
+ { "MED", "Messeltronik Dresden GmbH" },
+ { "SGD", "Sigma Designs, Inc." },
+ { "RJA", "Roland Corporation" },
+ { "EDC", "e.Digital Corporation" },
+ { "CON", "Contec Company Ltd" },
+ { "CCJ", "CONTEC CO.,LTD." },
+ { "GVC", "GVC Corporation" },
+ { "TRI", "Tricord Systems" },
+ { "SLB", "Shlumberger Ltd" },
+ { "PRO", "Proteon" },
+ { "DSI", "Digitan Systems Inc" },
+ { "SDF", "SODIFF E&T CO., Ltd." },
+ { "VDC", "VDC Display Systems" },
+ { "PSL", "Perle Systems Limited" },
+ { "SCR", "Systran Corporation" },
+ { "DEX", "idex displays" },
+ { "CDS", "Computer Diagnostic Systems" },
+ { "RAY", "Raylar Design, Inc." },
+ { "MMF", "Minnesota Mining and Manufacturing" },
+ { "MMA", "Micromedia AG" },
+ { "FUS", "Fujitsu Siemens Computers GmbH" },
+ { "ESS", "ESS Technology Inc" },
+ { "SIX", "Zuniq Data Corporation" },
+ { "ISS", "ISS Inc" },
+ { "PFT", "Telia ProSoft AB" },
+ { "SOL", "Solitron Technologies Inc" },
+ { "ZTM", "ZT Group Int'l Inc." },
+ { "GZE", "GUNZE Limited" },
+ { "CHS", "Agentur Chairos" },
+ { "CBI", "ComputerBoards Inc" },
+ { "DTA", "DELTATEC" },
+ { "CSC", "Crystal Semiconductor" },
+ { "MPC", "M-Pact Inc" },
+ { "HHI", "Fraunhofer Heinrich-Hertz-Institute" },
+ { "BIT", "Bit 3 Computer" },
+ { "ICP", "ICP Electronics, Inc./iEi Technology Corp." },
+ { "FOA", "FOR-A Company Limited" },
+ { "NWC", "NW Computer Engineering" },
+ { "MRO", "Medikro Oy" },
+ { "IDT", "International Display Technology" },
+ { "NMV", "NEC-Mitsubishi Electric Visual Systems Corporation" },
+ { "COT", "Core Technology Inc" },
+ { "PEL", "Primax Electric Ltd" },
+ { "ZMZ", "Z Microsystems" },
+ { "TYN", "Tyan Computer Corporation" },
+ { "DIN", "Daintelecom Co., Ltd" },
+ { "QTH", "Questech Ltd" },
+ { "CYL", "Cyberlabs" },
+ { "DGC", "Data General Corporation" },
+ { "PPM", "Clinton Electronics Corp." },
+ { "ITD", "Internet Technology Corporation" },
+ { "MMM", "Electronic Measurements" },
+ { "CMM", "Comtime GmbH" },
+ { "NDC", "National DataComm Corporaiton" },
+ { "TAS", "Taskit Rechnertechnik GmbH" },
+ { "MFR", "MediaFire Corp." },
+ { "HIC", "Hitachi Information Technology Co., Ltd." },
+ { "CMC", "CMC Ltd" },
+ { "TSE", "Tottori Sanyo Electric" },
+ { "TMR", "Taicom International Inc" },
+ { "SIE", "Siemens" },
+ { "IMD", "ImasDe Canarias S.A." },
+ { "SCE", "Sun Corporation" },
+ { "PJD", "Projectiondesign AS" },
+ { "VML", "Vine Micros Limited" },
+ { "ETL", "Evertz Microsystems Ltd." },
+ { "MAZ", "MAZeT GmbH" },
+ { "UNC", "Unisys Corporation" },
+ { "MEG", "Abeam Tech Ltd" },
+ { "FCS", "Focus Enhancements, Inc." },
+ { "MDV", "MET Development Inc" },
+ { "GLD", "Goldmund - Digital Audio SA" },
+ { "MRC", "Marconi Simulation & Ty-Coch Way Training" },
+ { "FEC", "FURUNO ELECTRIC CO., LTD." },
+ { "ALR", "Advanced Logic" },
+ { "AEJ", "Alpha Electronics Company" },
+ { "QCC", "QuakeCom Company Ltd" },
+ { "TDK", "TDK USA Corporation" },
+ { "TKN", "Teknor Microsystem Inc" },
+ { "FMC", "Ford Microelectronics Inc" },
+ { "KTI", "Konica Technical Inc" },
+ { "AEI", "Actiontec Electric Inc" },
+ { "TGI", "TriGem Computer Inc" },
+ { "HIL", "Hilevel Technology" },
+ { "WNI", "WillNet Inc." },
+ { "FTI", "FastPoint Technologies, Inc." },
+ { "ASU", "Asuscom Network Inc" },
+ { "MEJ", "Mac-Eight Co., LTD." },
+ { "SLS", "Schnick-Schnack-Systems GmbH" },
+ { "SXG", "SELEX GALILEO" },
+ { "EXP", "Data Export Corporation" },
+ { "TPR", "Topro Technology Inc" },
+ { "RCE", "Parc d'Activite des Bellevues" },
+ { "VIK", "Viking Connectors" },
+ { "TGS", "Torus Systems Ltd" },
+ { "IDO", "IDEO Product Development" },
+ { "MCE", "Metz-Werke GmbH & Co KG" },
+ { "PHC", "Pijnenburg Beheer N.V." },
+ { "BTF", "Bitfield Oy" },
+ { "MCD", "McDATA Corporation" },
+ { "EXY", "Exterity Ltd" },
+ { "ZTI", "Zoom Telephonics Inc" },
+ { "MTI", "Motorola Inc." },
+ { "ONK", "ONKYO Corporation" },
+ { "SEC", "Seiko Epson Corporation" },
+ { "TTB", "National Semiconductor Japan Ltd" },
+ { "SNO", "SINOSUN TECHNOLOGY CO., LTD" },
+ { "SHG", "Soft & Hardware development Goldammer GmbH" },
+ { "GEM", "Gem Plus" },
+ { "BOS", "BOS" },
+ { "SAK", "Saitek Ltd" },
+ { "CNE", "Cine-tal" },
+ { "BOB", "Rainy Orchard" },
+ { "UNF", "Unisys Corporation" },
+ { "MCG", "Motorola Computer Group" },
+ { "RTC", "Relia Technologies" },
+ { "ASD", "USC Information Sciences Institute" },
+ { "BMS", "BIOMEDISYS" },
+ { "LPE", "El-PUSK Co., Ltd." },
+ { "CTA", "CoSystems Inc" },
+ { "SVI", "Sun Microsystems" },
+ { "PCS", "TOSHIBA PERSONAL COMPUTER SYSTEM CORPRATION" },
+ { "GEN", "Genesys ATE Inc" },
+ { "CRI", "Crio Inc." },
+ { "TOG", "The OPEN Group" },
+ { "SYT", "Seyeon Tech Company Ltd" },
+ { "CRE", "Creative Labs Inc" },
+ { "ALK", "Acrolink Inc" },
+ { "TNC", "TNC Industrial Company Ltd" },
+ { "PLV", "PLUS Vision Corp." },
+ { "CCL", "CCL/ITRI" },
+ { "PLY", "Polycom Inc." },
+ { "RMC", "Raritan Computer, Inc" },
+ { "XRC", "Xircom Inc" },
+ { "BRC", "BARC" },
+ { "CUK", "Calibre UK Ltd" },
+ { "KME", "KIMIN Electronics Co., Ltd." },
+ { "TBS", "Turtle Beach System" },
+ { "ASY", "Rockwell Collins / Airshow Systems" },
+ { "ALV", "AlphaView LCD" },
+ { "VSD", "3M" },
+ { "MTN", "Mtron Storage Technology Co., Ltd." },
+ { "LMG", "Lucent Technologies" },
+ { "HWP", "Hewlett Packard" },
+ { "UEG", "Elitegroup Computer Systems Company Ltd" },
+ { "FIC", "Formosa Industrial Computing Inc" },
+ { "CRV", "Cerevo Inc." },
+ { "AIL", "Altos India Ltd" },
+ { "EMI", "Ex Machina Inc" },
+ { "DPC", "Delta Electronics Inc" },
+ { "ADN", "Analog & Digital Devices Tel. Inc" },
+ { "LGC", "Logic Ltd" },
+ { "DMP", "D&M Holdings Inc, Professional Business Company" },
+ { "CEC", "Chicony Electronics Company Ltd" },
+ { "BTC", "Bit 3 Computer" },
+ { "IWX", "Intelliworxx, Inc." },
+ { "SML", "Sumitomo Metal Industries, Ltd." },
+ { "JWY", "Jetway Information Co., Ltd" },
+ { "OMC", "OBJIX Multimedia Corporation" },
+ { "CIT", "Citifax Limited" },
+ { "AOE", "Advanced Optics Electronics, Inc." },
+ { "SYC", "Sysmic" },
+ { "ZTT", "Z3 Technology" },
+ { "LCS", "Longshine Electronics Company" },
+ { "NXQ", "Nexiq Technologies, Inc." },
+ { "PSY", "Prodea Systems Inc." },
+ { "CUB", "Cubix Corporation" },
+ { "JWL", "Jewell Instruments, LLC" },
+ { "SUB", "Subspace Comm. Inc" },
+ { "PTG", "Cipher Systems Inc" },
+ { "TON", "TONNA" },
+ { "VBR", "VBrick Systems Inc." },
+ { "RTI", "Rancho Tech Inc" },
+ { "IMG", "IMAGENICS Co., Ltd." },
+ { "AEP", "Aetas Peripheral International" },
+ { "PTH", "Pathlight Technology Inc" },
+ { "ZYX", "Zyxel" },
+ { "NXP", "NXP Semiconductors bv." },
+ { "OYO", "Shadow Systems" },
+ { "PVM", "Penta Studiotechnik GmbH" },
+ { "AVC", "Auravision Corporation" },
+ { "SYM", "Symicron Computer Communications Ltd." },
+ { "AVI", "Nippon Avionics Co.,Ltd" },
+ { "EYE", "eyevis GmbH" },
+ { "PLM", "PROLINK Microsystems Corp." },
+ { "NFC", "BTC Korea Co., Ltd" },
+ { "PIE", "Pacific Image Electronics Company Ltd" },
+ { "SRC", "Integrated Tech Express Inc" },
+ { "CMX", "Comex Electronics AB" },
+ { "OPP", "OPPO Digital, Inc." },
+ { "GAL", "Galil Motion Control" },
+ { "YHW", "Exacom SA" },
+ { "SSD", "FlightSafety International" },
+ { "FSC", "Future Systems Consulting KK" },
+ { "HRI", "Hall Research" },
+ { "PSA", "Advanced Signal Processing Technologies" },
+ { "MSI", "Microstep" },
+ { "IMI", "International Microsystems Inc" },
+ { "IDX", "IDEXX Labs" },
+ { "SCO", "SORCUS Computer GmbH" },
+ { "DIS", "Diseda S.A." },
+ { "SVA", "SGEG" },
+ { "SMA", "SMART Modular Technologies" },
+ { "SXL", "SolutionInside" },
+ { "WRC", "WiNRADiO Communications" },
+ { "NIT", "Network Info Technology" },
+ { "EKS", "EKSEN YAZILIM" },
+ { "GEF", "GE Fanuc Embedded Systems" },
+ { "DEI", "Deico Electronics" },
+ { "DCD", "Datacast LLC" },
+ { "MEE", "Mitsubishi Electric Engineering Co., Ltd." },
+ { "LSC", "LifeSize Communications" },
+ { "PDV", "Prodrive B.V." },
+ { "HIB", "Hibino Corporation" },
+ { "SKT", "Samsung Electro-Mechanics Company Ltd" },
+ { "SAN", "Sanyo Electric Co.,Ltd." },
+ { "RCO", "Rockwell Collins" },
+ { "SNY", "Sony" },
+ { "ANR", "ANR Ltd" },
+ { "DKY", "Datakey Inc" },
+ { "OPC", "Opcode Inc" },
+ { "TBC", "Turbo Communication, Inc" },
+ { "CNT", "COINT Multimedia Systems" },
+ { "HDC", "HardCom Elektronik & Datateknik" },
+ { "UNB", "Unisys Corporation" },
+ { "IOD", "I-O Data Device Inc" },
+ { "APR", "Aprilia s.p.a." },
+ { "AXX", "Axxon Computer Corporation" },
+ { "AED", "Advanced Electronic Designs, Inc." },
+ { "MTX", "Matrox" },
+ { "TAX", "Taxan (Europe) Ltd" },
+ { "TVS", "TVS Electronics Limited" },
+ { "CZE", "Carl Zeiss AG" },
+ { "SMI", "SpaceLabs Medical Inc" },
+ { "FCB", "Furukawa Electric Company Ltd" },
+ { "AXP", "American Express" },
+ { "FST", "Modesto PC Inc" },
+ { "PSI", "PSI-Perceptive Solutions Inc" },
+ { "MCR", "Marina Communicaitons" },
+ { "JCE", "Jace Tech Inc" },
+ { "GRE", "GOLD RAIN ENTERPRISES CORP." },
+ { "SYN", "Synaptics Inc" },
+ { "MBC", "MBC" },
+ { "SIB", "Sanyo Electric Company Ltd" },
+ { "TCT", "Telecom Technology Centre Co. Ltd." },
+ { "BIC", "Big Island Communications" },
+ { "UNI", "Unisys Corporation" },
+ { "ELX", "Elonex PLC" },
+ { "ZDS", "Zenith Data Systems" },
+ { "XLX", "Xilinx, Inc." },
+ { "MIC", "Micom Communications Inc" },
+ { "SEB", "system elektronik GmbH" },
+ { "WIN", "Wintop Technology Inc" },
+ { "CDG", "Christie Digital Systems Inc" },
+ { "HUB", "GAI-Tronics, A Hubbell Company" },
+ { "CSE", "Concept Solutions & Engineering" },
+ { "SUR", "Surenam Computer Corporation" },
+ { "VTM", "Miltope Corporation" },
+ { "ATK", "Allied Telesyn Int'l" },
+ { "MGT", "Megatech R & D Company" },
+ { "SLK", "Silitek Corporation" },
+ { "DYN", "Askey Computer Corporation" },
+ { "KEY", "Key Tech Inc" },
+ { "DVD", "Dictaphone Corporation" },
+ { "OTT", "OPTO22, Inc." },
+ { "TCI", "Tulip Computers Int'l B.V." },
+ { "ACB", "Aculab Ltd" },
+ { "PAD", "Promotion and Display Technology Ltd." },
+ { "CMG", "Chenming Mold Ind. Corp." },
+ { "UJR", "Ueda Japan Radio Co., Ltd." },
+ { "LHA", "Lars Haagh ApS" },
+ { "SIM", "S3 Inc" },
+ { "TPC", "Touch Panel Systems Corporation" },
+ { "TVD", "Tecnovision" },
+ { "FZI", "FZI Forschungszentrum Informatik" },
+ { "AIW", "Aiwa Company Ltd" },
+ { "LTW", "Lightware, Inc" },
+ { "DSP", "Domain Technology Inc" },
+ { "ILS", "Innotech Corporation" },
+ { "VDM", "Vadem" },
+ { "KYK", "Samsung Electronics America Inc" },
+ { "NTW", "Networth Inc" },
+ { "SID", "Seiko Instruments Information Devices Inc" },
+ { "MRT", "Merging Technologies" },
+ { "MGL", "M-G Technology Ltd" },
+ { "UBL", "Ubinetics Ltd." },
+ { "PSM", "Prosum" },
+ { "MDR", "Medar Inc" },
+ { "STN", "Samsung Electronics America" },
+ { "NCR", "NCR Electronics" },
+ { "INU", "Inovatec S.p.A." },
+ { "WAL", "Wave Access" },
+ { "BLN", "BioLink Technologies" },
+ { "RXT", "Tectona SoftSolutions (P) Ltd.," },
+ { "MRL", "Miratel" },
+ { "ZAZ", "Zazzle Technologies" },
+ { "NIC", "National Instruments Corporation" },
+ { "FMZ", "Formoza-Altair" },
+ { "MDG", "Madge Networks" },
+ { "VIA", "VIA Tech Inc" },
+ { "KOD", "Eastman Kodak Company" },
+ { "SAI", "Sage Inc" },
+ { "FEL", "Fellowes & Questec" },
+ { "SLI", "Symbios Logic Inc" },
+ { "ELE", "Elecom Company Ltd" },
+ { "FRE", "Forvus Research Inc" },
+ { "TTL", "2-Tel B.V." },
+ { "PPX", "Perceptive Pixel Inc." },
+ { "NAT", "NaturalPoint Inc." },
+ { "SLC", "Syslogic Datentechnik AG" },
+ { "PAM", "Peter Antesberger Messtechnik" },
+ { "JPW", "Wallis Hamilton Industries" },
+ { "AVA", "Avaya Communication" },
+ { "EEH", "EEH Datalink GmbH" },
+ { "WMT", "Winmate Communication Inc" },
+ { "LWC", "Labway Corporation" },
+ { "HYO", "HYC CO., LTD." },
+ { "MCC", "Micro Industries" },
+ { "IOA", "CRE Technology Corporation" },
+ { "AGI", "Artish Graphics Inc" },
+ { "TDT", "TDT" },
+ { "UNO", "Unisys Corporation" },
+ { "LIN", "Lenovo Beijing Co. Ltd." },
+ { "MAG", "MAG InnoVision" },
+ { "HCL", "HCL America Inc" },
+ { "BWK", "Bitworks Inc." },
+ { "BSN", "BRIGHTSIGN, LLC" },
+ { "INM", "InnoMedia Inc" },
+ { "MIN", "Minicom Digital Signage" },
+ { "ARE", "ICET S.p.A." },
+ { "TPZ", "Ypoaz Systems Inc" },
+ { "BRO", "BROTHER INDUSTRIES,LTD." },
+ { "MEX", "MSC Vertriebs GmbH" },
+ { "FJC", "Fujitsu Takamisawa Component Limited" },
+ { "HRT", "HERCULES" },
+ { "MOM", "Momentum Data Systems" },
+ { "RSV", "Ross Video Ltd" },
+ { "RAN", "Rancho Tech Inc" },
+ { "HOL", "Holoeye Photonics AG" },
+ { "SOT", "Sotec Company Ltd" },
+ { "AAE", "Anatek Electronics Inc." },
+ { "ZYT", "Zytex Computers" },
+ { "APP", "Apple Computer Inc" },
+ { "MCM", "Metricom Inc" },
+ { "NXC", "NextCom K.K." },
+ { "CBX", "Cybex Computer Products Corporation" },
+ { "FJS", "Fujitsu Spain" },
+ { "SNI", "Siemens Microdesign GmbH" },
+ { "MPL", "Maple Research Inst. Company Ltd" },
+ { "PLX", "Parallax Graphics" },
+ { "EAS", "Evans and Sutherland Computer" },
+ { "ZBR", "Zebra Technologies International, LLC" },
+ { "MSL", "MicroSlate Inc." },
+ { "XOC", "DO NOT USE - XOC" },
+ { "EMG", "EMG Consultants Inc" },
+ { "SMC", "Standard Microsystems Corporation" },
+ { "RAD", "Radisys Corporation" },
+ { "NMS", "Natural Micro System" },
+ { "APT", "Audio Processing Technology Ltd" },
+ { "MLI", "McIntosh Laboratory Inc." },
+ { "ISI", "Interface Solutions" },
+ { "RAT", "Rent-A-Tech" },
+ { "BAN", "Banyan" },
+ { "PCL", "pentel.co.,ltd" },
+ { "CSI", "Cabletron System Inc" },
+ { "IVS", "Intevac Photonics Inc." },
+ { "MAT", "Matsushita Electric Ind. Company Ltd" },
+ { "LWR", "Lightware Visual Engineering" },
+ { "FWA", "Attero Tech, LLC" },
+ { "ORI", "OSR Open Systems Resources, Inc." },
+ { "ARG", "Argus Electronics Co., LTD" },
+ { "CAS", "CASIO COMPUTER CO.,LTD" },
+ { "DHP", "DH Print" },
+ { "TTS", "TechnoTrend Systemtechnik GmbH" },
+ { "HHC", "HIRAKAWA HEWTECH CORP." },
+ { "GRM", "Garmin International" },
+ { "BUL", "Bull" },
+ { "AFA", "Alfa Inc" },
+ { "OVR", "Oculus VR, Inc." },
+ { "EPI", "Envision Peripherals, Inc" },
+ { "GSC", "General Standards Corporation" },
+ { "DNG", "Apache Micro Peripherals Inc" },
+ { "VIN", "Vine Micros Ltd" },
+ { "PTW", "DO NOT USE - PTW" },
+ { "MFI", "Micro Firmware" },
+ { "SMP", "Simple Computing" },
+ { "HCA", "DAT" },
+ { "PHL", "Philips Consumer Electronics Company" },
+ { "ADC", "Acnhor Datacomm" },
+ { "VBT", "Valley Board Ltda" },
+ { "MPX", "Micropix Technologies, Ltd." },
+ { "VSP", "Vision Systems GmbH" },
+ { "PJA", "Projecta" },
+ { "AMT", "AMT International Industry" },
+ { "VCI", "VistaCom Inc" },
+ { "XIR", "Xirocm Inc" },
+ { "MBV", "Moreton Bay" },
+ { "NSC", "National Semiconductor Corporation" },
+ { "TPV", "Top Victory Electronics ( Fujian ) Company Ltd" },
+ { "HAE", "Haider electronics" },
+ { "PKA", "Acco UK ltd." },
+ { "PXC", "Phoenix Contact" },
+ { "BXE", "Buxco Electronics" },
+ { "OZC", "OZ Corporation" },
+ { "TXL", "Trixel Ltd" },
+ { "MXD", "MaxData Computer GmbH & Co.KG" },
+ { "ASK", "Ask A/S" },
+ { "KSC", "Kinetic Systems Corporation" },
+ { "XAD", "Alpha Data" },
+ { "MVI", "Media Vision Inc" },
+ { "BPU", "Best Power" },
+ { "LAF", "Microline" },
+ { "SPS", "Synopsys Inc" },
+ { "WXT", "Woxter Technology Co. Ltd" },
+ { "NIX", "Seanix Technology Inc" },
+ { "HPA", "Zytor Communications" },
+ { "SPK", "SpeakerCraft" },
+ { "CHP", "CH Products" },
+ { "SNX", "Sonix Comm. Ltd" },
+ { "LZX", "Lightwell Company Ltd" },
+ { "ART", "Corion Industrial Corporation" },
+ { "IFS", "In Focus Systems Inc" },
+ { "DAL", "Digital Audio Labs Inc" },
+ { "STR", "Starlight Networks Inc" },
+ { "PRT", "Parade Technologies, Ltd." },
+ { "VRC", "Virtual Resources Corporation" },
+ { "IIC", "ISIC Innoscan Industrial Computers A/S" },
+ { "AUR", "Aureal Semiconductor" },
+ { "ATC", "Ably-Tech Corporation" },
+ { "ODR", "Odrac" },
+ { "LIP", "Linked IP GmbH" },
+ { "FLI", "Faroudja Laboratories" },
+ { "AVV", "SBS Technologies (Canada), Inc. (was Avvida Systems, Inc.)" },
+ { "ECM", "E-Cmos Tech Corporation" },
+ { "LAG", "Laguna Systems" },
+ { "FFC", "FUJIFILM Corporation" },
+ { "MAX", "Rogen Tech Distribution Inc" },
+ { "HUM", "IMP Electronics Ltd." },
+ { "VTX", "Vestax Corporation" },
+ { "NST", "Network Security Technology Co" },
+ { "FLY", "Butterfly Communications" },
+ { "ETT", "E-Tech Inc" },
+ { "NXS", "Technology Nexus Secure Open Systems AB" },
+ { "VES", "Vestel Elektronik Sanayi ve Ticaret A. S." },
+ { "EBT", "HUALONG TECHNOLOGY CO., LTD" },
+ { "HPK", "HAMAMATSU PHOTONICS K.K." },
+ { "RGB", "RGB Spectrum" },
+ { "AUI", "Alps Electric Inc" },
+ { "ICI", "Infotek Communication Inc" },
+ { "NTS", "Nits Technology Inc." },
+ { "EVI", "eviateg GmbH" },
+ { "CRD", "Cardinal Technical Inc" },
+ { "MOD", "Modular Technology" },
+ { "CCP", "Capetronic USA Inc" },
+ { "DGS", "Diagsoft Inc" },
+ { "IFT", "Informtech" },
+ { "LWW", "Lanier Worldwide" },
+ { "SDK", "SAIT-Devlonics" },
+ { "UWC", "Uniwill Computer Corp." },
+ { "MXV", "MaxVision Corporation" },
+ { "HOE", "Hosiden Corporation" },
+ { "SGE", "Kansai Electric Company Ltd" },
+ { "URD", "Video Computer S.p.A." },
+ { "TSV", "TRANSVIDEO" },
+ { "MBM", "Marshall Electronics" },
+ { "TLA", "Ferrari Electronic GmbH" },
+ { "GLM", "Genesys Logic" },
+ { "LEN", "Lenovo Group Limited" },
+ { "SAM", "Samsung Electric Company" },
+ { "VTL", "Vivid Technology Pte Ltd" },
+ { "UTD", "Up to Date Tech" },
+ { "ITC", "Intercom Inc" },
+ { "ENI", "Efficient Networks" },
+ { "GDC", "General Datacom" },
+ { "XIT", "Xitel Pty ltd" },
+ { "CMN", "Chimei Innolux Corporation" },
+ { "AVE", "Add Value Enterpises (Asia) Pte Ltd" },
+ { "WEC", "Winbond Electronics Corporation" },
+ { "OAK", "Oak Tech Inc" },
+ { "DON", "DENON, Ltd." },
+ { "ITR", "Infotronic America, Inc." },
+ { "CAC", "CA & F Elettronica" },
+ { "VIM", "Via Mons Ltd." },
+ { "DGP", "Digicorp European sales S.A." },
+ { "HPD", "Hewlett Packard" },
+ { "USD", "U.S. Digital Corporation" },
+ { "TAM", "Tamura Seisakusyo Ltd" },
+ { "SGZ", "Systec Computer GmbH" },
+ { "NGS", "A D S Exports" },
+ { "FSI", "Fore Systems Inc" },
+ { "SIL", "Silicon Laboratories, Inc" },
+ { "QCP", "Qualcomm Inc" },
+ { "SDA", "SAT (Societe Anonyme)" },
+ { "SEI", "Seitz & Associates Inc" },
+ { "RSI", "Rampage Systems Inc" },
+ { "VIZ", "VIZIO, Inc" },
+ { "EPN", "EPiCON Inc." },
+ { "OIC", "Option Industrial Computers" },
+ { "KDE", "KDE" },
+ { "CLV", "Clevo Company" },
+ { "GRA", "Graphica Computer" },
+ { "HIK", "Hikom Co., Ltd." },
+ { "LCE", "La Commande Electronique" },
+ { "MNP", "Microcom" },
+ { "ERI", "Ericsson Mobile Communications AB" },
+ { "REX", "RATOC Systems, Inc." },
+ { "PPP", "Purup Prepress AS" },
+ { "JAT", "Jaton Corporation" },
+ { "GLE", "AD electronics" },
+ { "VAL", "Valence Computing Corporation" },
+ { "CDN", "Codenoll Technical Corporation" },
+ { "SDT", "Siemens AG" },
+ { "RSC", "PhotoTelesis" },
+ { "FFI", "Fairfield Industries" },
+ { "VPR", "Best Buy" },
+ { "IPM", "IPM Industria Politecnica Meridionale SpA" },
+ { "HSM", "AT&T Microelectronics" },
+ { "YHQ", "Yokogawa Electric Corporation" },
+ { "UEC", "Ultima Electronics Corporation" },
+ { "NME", "Navico, Inc." },
+ { "GVL", "Global Village Communication" },
+ { "TEK", "Tektronix Inc" },
+ { "SBD", "Softbed - Consulting & Development Ltd" },
+ { "PSD", "Peus-Systems GmbH" },
+ { "DCA", "Digital Communications Association" },
+ { "HWC", "DBA Hans Wedemeyer" },
+ { "DFK", "SharkTec A/S" },
+ { "DMB", "Digicom Systems Inc" },
+ { "IPW", "IPWireless, Inc" },
+ { "ACC", "Accton Technology Corporation" },
+ { "CPM", "Capella Microsystems Inc." },
+ { "AAT", "Ann Arbor Technologies" },
+ { "LAS", "LASAT Comm. A/S" },
+ { "TWI", "Easytel oy" },
+ { "HJI", "Harris & Jeffries Inc" },
+ { "SGX", "Silicon Graphics Inc" },
+ { "TSL", "Tottori SANYO Electric Co., Ltd." },
+ { "SVD", "SVD Computer" },
+ { "CLT", "automated computer control systems" },
+ { "WLD", "Wildfire Communications Inc" },
+ { "LCI", "Lite-On Communication Inc" },
+ { "AEC", "Antex Electronics Corporation" },
+ { "ACA", "Ariel Corporation" },
+ { "KML", "Kensington Microware Ltd" },
+ { "KDT", "KDDI Technology Corporation" },
+ { "BSE", "Bose Corporation" },
+ { "WSP", "Wireless And Smart Products Inc." },
+ { "GNZ", "Gunze Ltd" },
+ { "PMM", "Point Multimedia System" },
+ { "ASC", "Ascom Strategic Technology Unit" },
+ { "EVX", "Everex" },
+ { "WBN", "MicroSoftWare" },
+ { "FGL", "Fujitsu General Limited." },
+ { "JSI", "Jupiter Systems, Inc." },
+ { "SII", "Silicon Image, Inc." },
+ { "SMM", "Shark Multimedia Inc" },
+ { "XYC", "Xycotec Computer GmbH" },
+ { "PEC", "POTRANS Electrical Corp." },
+ { "TSD", "TechniSat Digital GmbH" },
+ { "ZSE", "Zenith Data Systems" },
+ { "ENC", "Eizo Nanao Corporation" },
+ { "MWY", "Microway Inc" },
+ { "OLI", "Olivetti" },
+ { "WIL", "WIPRO Information Technology Ltd" },
+ { "LKM", "Likom Technology Sdn. Bhd." },
+ { "KOU", "KOUZIRO Co.,Ltd." },
+ { "VHI", "Macrocad Development Inc." },
+ { "FIT", "Feature Integration Technology Inc." },
+ { "MXP", "Maxpeed Corporation" },
+ { "SCD", "Sanyo Electric Company Ltd" },
+ { "NBL", "N*Able Technologies Inc" },
+ { "SPT", "Sceptre Tech Inc" },
+ { "IPN", "Performance Technologies" },
+ { "BMD", "Blackmagic Design" },
+ { "MDK", "Mediatek Corporation" },
+ { "DCS", "Diamond Computer Systems Inc" },
+ { "ICE", "IC Ensemble" },
+ { "LSY", "LSI Systems Inc" },
+ { "AMC", "Attachmate Corporation" },
+ { "TCO", "Thomas-Conrad Corporation" },
+ { "NOK", "Nokia Display Products" },
+ { "VFI", "VeriFone Inc" },
+ { "OPV", "Optivision Inc" },
+ { "LCM", "Latitude Comm." },
+ { "LSL", "Logical Solutions" },
+ { "TVO", "TV One Ltd" },
+ { "KVA", "Kvaser AB" },
+ { "PMT", "Promate Electronic Co., Ltd." },
+ { "ZZZ", "Boca Research Inc" },
+ { "ELC", "Electro Scientific Ind" },
+ { "SIR", "Sirius Technologies Pty Ltd" },
+ { "DCE", "dSPACE GmbH" },
+ { "WAN", "DO NOT USE - WAN" },
+ { "PCT", "PC-Tel Inc" },
+ { "BEO", "Baug & Olufsen" },
+ { "LUM", "Lumagen, Inc." },
+ { "DNA", "DNA Enterprises, Inc." },
+ { "WEY", "WEY Design AG" },
+ { "IAF", "Institut f r angewandte Funksystemtechnik GmbH" },
+ { "QFF", "Padix Co., Inc." },
+ { "JIC", "Jaeik Information & Communication Co., Ltd." },
+ { "VIT", "Visitech AS" },
+ { "QUA", "Quatographic AG" },
+ { "BNK", "Banksia Tech Pty Ltd" },
+ { "TME", "AT&T Microelectronics" },
+ { "DRB", "Dr. Bott KG" },
+ { "NET", "Mettler Toledo" },
+ { "CDE", "Colin.de" },
+ { "ATI", "Allied Telesis KK" },
+ { "PMD", "TDK USA Corporation" },
+ { "SKY", "SKYDATA S.P.A." },
+ { "FTN", "Fountain Technologies Inc" },
+ { "DBD", "Diebold Inc." },
+ { "ECA", "Electro Cam Corp." },
+ { "TLI", "TOSHIBA TELI CORPORATION" },
+ { "CTC", "CTC Communication Development Company Ltd" },
+ { "NVT", "Navatek Engineering Corporation" },
+ { "CKC", "The Concept Keyboard Company Ltd" },
+ { "FIR", "Chaplet Systems Inc" },
+ { "HYD", "Hydis Technologies.Co.,LTD" },
+ { "TTY", "TRIDELITY Display Solutions GmbH" },
+ { "DAE", "Digatron Industrie Elektronik GmbH" },
+ { "AUT", "Autotime Corporation" },
+ { "GTC", "Graphtec Corporation" },
+ { "MYR", "Myriad Solutions Ltd" },
+ { "DLT", "Digitelec Informatique Park Cadera" },
+ { "SDR", "SDR Systems" },
+ { "ACS", "Altos Computer Systems" },
+ { "SVC", "Intellix Corp." },
+ { "ZTE", "ZTE Corporation" },
+ { "ERT", "Escort Insturments Corporation" },
+ { "WII", "Innoware Inc" },
+ { "DOL", "Dolman Technologies Group Inc" },
+ { "RLD", "MEPCO" },
+ { "HRL", "Herolab GmbH" },
+ { "IRD", "IRdata" },
+ { "IVI", "Intervoice Inc" },
+ { "ICS", "Integrated Circuit Systems" },
+ { "ASE", "AseV Display Labs" },
+ { "SYX", "Prime Systems, Inc." },
+ { "SOI", "Silicon Optix Corporation" },
+ { "OCS", "Open Connect Solutions" },
+ { "HON", "Sonitronix" },
+ { "TAG", "Teles AG" },
+ { "PEP", "Peppercon AG" },
+ { "INT", "Interphase Corporation" },
+ { "IBR", "IBR GmbH" },
+ { "WYS", "Wyse Technology" },
+ { "TRE", "Tremetrics" },
+ { "RKC", "Reakin Technolohy Corporation" },
+ { "SEG", "DO NOT USE - SEG" },
+ { "CAV", "Cavium Networks, Inc" },
+ { "ELA", "ELAD srl" },
+ { "MMD", "Micromed Biotecnologia Ltd" },
+ { "SGL", "Super Gate Technology Company Ltd" },
+ { "SIS", "Silicon Integrated Systems Corporation" },
+ { "XFO", "EXFO Electro Optical Engineering" },
+ { "ING", "Integraph Corporation" },
+ { "NEU", "NEUROTEC - EMPRESA DE PESQUISA E DESENVOLVIMENTO EM BIOMEDICINA" },
+ { "ZIC", "Nationz Technologies Inc." },
+ { "CVI", "Colorado Video, Inc." },
+ { "VCC", "Virtual Computer Corporation" },
+ { "INZ", "Best Buy" },
+ { "ELO", "Tyco Electronics" },
+ { "EPH", "Epiphan Systems Inc." },
+ { "SYL", "Sylvania Computer Products" },
+ { "MXI", "Macronix Inc" },
+ { "GEH", "GE Intelligent Platforms - Huntsville" },
+ { "BBB", "an-najah university" },
+ { "ARK", "Ark Logic Inc" },
+ { "IVM", "Iiyama North America" },
+ { "XTE", "X2E GmbH" },
+ { "DMV", "NDS Ltd" },
+ { "CPD", "CompuAdd" },
+ { "CYD", "Cyclades Corporation" },
+ { "ALX", "ALEXON Co.,Ltd." },
+ { "COB", "COBY Electronics Co., Ltd" },
+ { "HCE", "Hitachi Consumer Electronics Co., Ltd" },
+ { "EXX", "Exxact GmbH" },
+ { "TAB", "Todos Data System AB" },
+ { "MPN", "Mainpine Limited" },
+ { "ATH", "Athena Informatica S.R.L." },
+ { "AWL", "Aironet Wireless Communications, Inc" },
+ { "FNI", "Funai Electric Co., Ltd." },
+ { "PLT", "PT Hartono Istana Teknologi" },
+ { "DEN", "Densitron Computers Ltd" },
+ { "MIM", "Mimio – A Newell Rubbermaid Company" },
+ { "GER", "GERMANEERS GmbH" },
+ { "CAI", "Canon Inc." },
+ { "DNI", "Deterministic Networks Inc." },
+ { "DOT", "Dotronic Mikroelektronik GmbH" },
+ { "MVX", "COM 1" },
+ { "WTC", "ACC Microelectronics" },
+ { "HIT", "Hitachi America Ltd" },
+ { "ALM", "Acutec Ltd." },
+ { "TIP", "TIPTEL AG" },
+ { "END", "ENIDAN Technologies Ltd" },
+ { "PAR", "Parallan Comp Inc" },
+ { "DVL", "Devolo AG" },
+ { "ADV", "Advanced Micro Devices Inc" },
+ { "TKS", "TimeKeeping Systems, Inc." },
+ { "MLD", "Deep Video Imaging Ltd" },
+ { "IUC", "ICSL" },
+ { "MNL", "Monorail Inc" },
+ { "HRC", "Hercules" },
+ { "ANS", "Ansel Communication Company" },
+ { "UAS", "Ultima Associates Pte Ltd" },
+ { "SBS", "SBS-or Industrial Computers GmbH" },
+ { "DVT", "Data Video" },
+ { "PTS", "Plain Tree Systems Inc" },
+ { "CSD", "Cresta Systems Inc" },
+ { "LDT", "LogiDataTech Electronic GmbH" },
+ { "AGM", "Advan Int'l Corporation" },
+ { "TLD", "Telindus" },
+ { "SPU", "SIM2 Multimedia S.P.A." },
+ { "BCS", "Booria CAD/CAM systems" },
+ { "CRQ", "Cirque Corporation" },
+ { "MIL", "Marconi Instruments Ltd" },
+ { "FTE", "Frontline Test Equipment Inc." },
+ { "RWC", "Red Wing Corporation" },
+ { "TLS", "Teleste Educational OY" },
+ { "DAT", "Datel Inc" },
+ { "SIT", "Sitintel" },
+ { "QTI", "Quicknet Technologies Inc" },
+ { "EBH", "Data Price Informatica" },
+ { "PCK", "PCBANK21" },
+ { "VSC", "ViewSonic Corporation" },
+ { "BBL", "Brain Boxes Limited" },
+ { "UFO", "UFO Systems Inc" },
+ { "NTI", "New Tech Int'l Company" },
+ { "WAV", "Wavephore" },
+ { "NOT", "Not Limited Inc" },
+ { "GRH", "Granch Ltd" },
+ { "VTC", "VTel Corporation" },
+ { "UNA", "Unisys DSD" },
+ { "LAB", "ACT Labs Ltd" },
+ { "UIC", "Uniform Industrial Corporation" },
+ { "IDK", "IDK Corporation" },
+ { "CHI", "Chrontel Inc" },
+ { "QCH", "Metronics Inc" },
+ { "CER", "Ceronix" },
+ { "PCB", "OCTAL S.A." },
+ { "VTV", "VATIV Technologies" },
+ { "BTI", "BusTech Inc" },
+ { "RVL", "Reveal Computer Prod" },
+ { "CHC", "Chic Technology Corp." },
+ { "QDS", "Quanta Display Inc." },
+ { "DAW", "DA2 Technologies Inc" },
+ { "MTR", "Mitron computer Inc" },
+ { "PCP", "Procomp USA Inc" },
+ { "AZM", "AZ Middelheim - Radiotherapy" },
+ { "NHT", "Vinci Labs" },
+ { "ROB", "Robust Electronics GmbH" },
+ { "RIC", "RICOH COMPANY, LTD." },
+ { "PCI", "Pioneer Computer Inc" },
+ { "EKA", "MagTek Inc." },
+ { "SWL", "Sharedware Ltd" },
+ { "GSM", "Goldstar Company Ltd" },
+ { "IDP", "Integrated Device Technology, Inc." },
+ { "BPD", "Micro Solutions, Inc." },
+ { "UNS", "Unisys Corporation" },
+ { "PBN", "Packard Bell NEC" },
+ { "KRM", "Kroma Telecom" },
+ { "ENT", "Enterprise Comm. & Computing Inc" },
+ { "ATL", "Arcus Technology Ltd" },
+ { "VDT", "Viditec, Inc." },
+ { "JUK", "Janich & Klass Computertechnik GmbH" },
+ { "PVG", "Proview Global Co., Ltd" },
+ { "INX", "Communications Supply Corporation (A division of WESCO)" },
+ { "GDS", "GDS" },
+ { "UHB", "XOCECO" },
+ { "MEI", "Panasonic Industry Company" },
+ { "OXU", "Oxus Research S.A." },
+ { "SGO", "Logos Design A/S" },
+ { "STU", "Sentelic Corporation" },
+ { "PUL", "Pulse-Eight Ltd" },
+ { "BRA", "Braemac Pty Ltd" },
+ { "MBD", "Microbus PLC" },
+ { "OAS", "Oasys Technology Company" },
+ { "MDS", "Micro Display Systems Inc" },
+ { "SCS", "Nanomach Anstalt" },
+ { "DAS", "DAVIS AS" },
+ { "NLC", "Next Level Communications" },
+ { "MSU", "motorola" },
+ { "MAD", "Xedia Corporation" },
+ { "LOE", "Loewe Opta GmbH" },
+ { "EEE", "ET&T Technology Company Ltd" },
+ { "ANX", "Acer Netxus Inc" },
+ { "IEE", "IEE" },
+ { "ALL", "Alliance Semiconductor Corporation" },
+ { "DCT", "Dancall Telecom A/S" },
+ { "AII", "Amptron International Inc." },
+ { "DPT", "DPT" },
+ { "TNJ", "DO NOT USE - TNJ" },
+ { "FTC", "Futuretouch Corporation" },
+ { "ESG", "ELCON Systemtechnik GmbH" },
+ { "SYV", "SYVAX Inc" },
+ { "RAC", "Racore Computer Products Inc" },
+ { "IBM", "IBM France" },
+ { "LTV", "Leitch Technology International Inc." },
+ { "AKE", "AKAMI Electric Co.,Ltd" },
+ { "VDO", "Video & Display Oriented Corporation" },
+ { "MEN", "MEN Mikroelectronik Nueruberg GmbH" },
+ { "UNT", "Unisys Corporation" },
+ { "TTK", "Totoku Electric Company Ltd" },
+ { "DII", "Dataq Instruments Inc" },
+ { "AMO", "Amino Technologies PLC and Amino Communications Limited" },
+ { "IMC", "IMC Networks" },
+ { "STG", "StereoGraphics Corp." },
+ { "RRI", "Radicom Research Inc" },
+ { "HTI", "Hampshire Company, Inc." },
+ { "SOR", "Sorcus Computer GmbH" },
+ { "AXL", "Axel" },
+ { "SNS", "Cirtech (UK) Ltd" },
+ { "IPD", "Industrial Products Design, Inc." },
+ { "FMI", "Fujitsu Microelect Inc" },
+ { "FMA", "Fast Multimedia AG" },
+ { "MIT", "MCM Industrial Technology GmbH" },
+ { "RII", "Racal Interlan Inc" },
+ { "PDN", "AT&T Paradyne" },
+ { "TRU", "Aashima Technology B.V." },
+ { "BEI", "Beckworth Enterprises Inc" },
+ { "RSS", "Rockwell Semiconductor Systems" },
+ { "SHR", "Digital Discovery" },
+ { "CDT", "IBM Corporation" },
+ { "TKC", "Taiko Electric Works.LTD" },
+ { "ITM", "ITM inc." },
+ { "QUE", "Questra Consulting" },
+ { "CMR", "Cambridge Research Systems Ltd" },
+ { "LCC", "LCI" },
+ { "MDO", "Panasonic" },
+ { "IEC", "Interlace Engineering Corporation" },
+ { "DPL", "Digital Projection Limited" },
+ { "INV", "Inviso, Inc." },
+ { "JSD", "JS DigiTech, Inc" },
+ { "TOE", "TOEI Electronics Co., Ltd." },
+ { "HAY", "Hayes Microcomputer Products Inc" },
+ { "SSJ", "Sankyo Seiki Mfg.co., Ltd" },
+ { "NNC", "NNC" },
+ { "PHE", "Philips Medical Systems Boeblingen GmbH" },
+ { "MWI", "Multiwave Innovation Pte Ltd" },
+ { "WYT", "Wooyoung Image & Information Co.,Ltd." },
+ { "AIM", "AIMS Lab Inc" },
+ { "CSS", "CSS Laboratories" },
+ { "TRS", "Torus Systems Ltd" },
+ { "ROK", "Rockwell International" },
+ { "SXD", "Silex technology, Inc." },
+ { "PHS", "Philips Communication Systems" },
+ { "CLM", "CrystaLake Multimedia" },
+ { "ALO", "Algolith Inc." },
+ { "SIU", "Seiko Instruments USA Inc" },
+ { "TUA", "T+A elektroakustik GmbH" },
+ { "CTE", "Chunghwa Telecom Co., Ltd." },
+ { "SDD", "Intrada-SDD Ltd" },
+ { "RMT", "Roper Mobile" },
+ { "SSP", "Spectrum Signal Proecessing Inc" },
+ { "VTN", "VIDEOTRON CORP." },
+ { "VAD", "Vaddio, LLC" },
+ { "SFT", "Mikroforum Ring 3" },
+ { "DGK", "DugoTech Co., LTD" },
+ { "ACH", "Archtek Telecom Corporation" },
+ { "ABT", "Anchor Bay Technologies, Inc." },
+ { "STC", "STAC Electronics" },
+ { "DRS", "DRS Defense Solutions, LLC" },
+ { "OQI", "Oksori Company Ltd" },
+ { "IMT", "Inmax Technology Corporation" },
+ { "ENE", "ENE Technology Inc." },
+ { "WBS", "WB Systemtechnik GmbH" },
+ { "PRC", "PerComm" },
+ { "PSC", "Philips Semiconductors" },
+ { "RJS", "Advanced Engineering" },
+ { "STS", "SITECSYSTEM CO., LTD." },
+ { "LAV", "Lava Computer MFG Inc" },
+ { "RCH", "Reach Technology Inc" },
+ { "DWE", "Daewoo Electronics Company Ltd" },
+ { "KTC", "Kingston Tech Corporation" },
+ { "GLS", "Gadget Labs LLC" },
+ { "COS", "CoStar Corporation" },
+ { "SBI", "SMART Technologies Inc." },
+ { "ATP", "Alpha-Top Corporation" },
+ { "DQB", "Datacube Inc" },
+ { "INN", "Innovent Systems, Inc." },
+ { "DNT", "Dr. Neuhous Telekommunikation GmbH" },
+ { "KFX", "Kofax Image Products" },
+ { "APE", "Alpine Electronics, Inc." },
+ { "DSM", "DSM Digital Services GmbH" },
+ { "RES", "ResMed Pty Ltd" },
+ { "HMX", "HUMAX Co., Ltd." },
+ { "PCW", "Pacific CommWare Inc" },
+ { "KYC", "Kyocera Corporation" },
+ { "VSN", "Ingram Macrotron" },
+ { "SNT", "SuperNet Inc" },
+ { "TEL", "Promotion and Display Technology Ltd." },
+ { "IFX", "Infineon Technologies AG" },
+ { "PVC", "DO NOT USE - PVC" },
+ { "JKC", "JVC KENWOOD Corporation" },
+ { "MSV", "Mosgi Corporation" },
+ { "BUR", "Bernecker & Rainer Ind-Eletronik GmbH" },
+ { "PTA", "PAR Tech Inc." },
+ { "GGL", "Google Inc." },
+ { "COM", "Comtrol Corporation" },
+ { "JEN", "N-Vision" },
+ { "AMP", "AMP Inc" },
+ { "HDI", "HD-INFO d.o.o." },
+ { "BOE", "BOE" },
+ { "ICM", "Intracom SA" },
+ { "ADD", "Advanced Peripheral Devices Inc" },
+ { "PRI", "Priva Hortimation BV" },
+ { "ANL", "Analogix Semiconductor, Inc" },
+ { "AVO", "Avocent Corporation" },
+ { "LEG", "Legerity, Inc" },
+ { "DTE", "Dimension Technologies, Inc." },
+ { "WPA", "Matsushita Communication Industrial Co., Ltd." },
+ { "OLV", "Olitec S.A." },
+ { "RNB", "Rainbow Technologies" },
+ { "LVI", "LVI Low Vision International AB" },
+ { "LOC", "Locamation B.V." },
+ { "TGC", "Toshiba Global Commerce Solutions, Inc." },
+ { "STI", "Smart Tech Inc" },
+ { "TLF", "Teleforce.,co,ltd" },
+ { "PLC", "Pro-Log Corporation" },
+ { "HSD", "HannStar Display Corp" },
+ { "ONE", "Oneac Corporation" },
+ { "CLE", "Classe Audio" },
+ { "MCI", "Micronics Computers" },
+ { "VTG", "Voice Technologies Group Inc" },
+ { "VTI", "VLSI Tech Inc" },
+ { "DAI", "DAIS SET Ltd." },
+ { "UNM", "Unisys Corporation" },
+ { "MCQ", "Mat's Computers" },
+ { "IPC", "IPC Corporation" },
+ { "ADE", "Arithmos, Inc." },
+ { "PON", "Perpetual Technologies, LLC" },
+ { "EXA", "Exabyte" },
+ { "CHD", "ChangHong Electric Co.,Ltd" },
+ { "FDT", "Fujitsu Display Technologies Corp." },
+ { "DBL", "Doble Engineering Company" },
+ { "CTP", "Computer Technology Corporation" },
+ { "CLD", "COMMAT L.t.d." },
+ { "BLI", "Busicom" },
+ { "FRS", "South Mountain Technologies, LTD" },
+ { "CDD", "Convergent Data Devices" },
+ { "SHT", "Shin Ho Tech" },
+ { "EPC", "Empac" },
+ { "RDS", "Radius Inc" },
+ { "NEX", "Nexgen Mediatech Inc.," },
+ { "AGC", "Beijing Aerospace Golden Card Electronic Engineering Co.,Ltd." },
+ { "MCP", "Magni Systems Inc" },
+ { "WMO", "Westermo Teleindustri AB" },
+ { "NMX", "Neomagic" },
+ { "BDS", "Barco Display Systems" },
+ { "RIV", "Rivulet Communications" },
+ { "TRA", "TriTech Microelectronics International" },
+ { "CYX", "Cyrix Corporation" },
+ { "TCM", "3Com Corporation" },
+ { "ZYP", "Zypcom Inc" },
+ { "VIB", "Tatung UK Ltd" },
+ { "IEI", "Interlink Electronics" },
+ { "BGB", "Barco Graphics N.V" },
+ { "ISP", "IntreSource Systems Pte Ltd" },
+ { "BGT", "Budzetron Inc" },
+ { "DPS", "Digital Processing Systems" },
+ { "SSS", "S3 Inc" },
+ { "AXB", "Adrienne Electronics Corporation" },
+ { "HKA", "HONKO MFG. CO., LTD." },
+ { "TPK", "TOPRE CORPORATION" },
+ { "NPI", "Network Peripherals Inc" },
+ { "LMP", "Leda Media Products" },
+ { "MAI", "Mutoh America Inc" },
+ { "ATX", "Athenix Corporation" },
+ { "MVM", "SOBO VISION" },
+ { "ALI", "Acer Labs" },
+ { "HPR", "H.P.R. Electronics GmbH" },
+ { "BIL", "Billion Electric Company Ltd" },
+ { "CRO", "Extraordinary Technologies PTY Limited" },
+ { "KTG", "Kayser-Threde GmbH" },
+ { "SCI", "System Craft" },
+ { "MVD", "Microvitec PLC" },
+ { "IST", "Intersolve Technologies" },
+ { "ICD", "ICD Inc" },
+ { "PDS", "PD Systems International Ltd" },
+ { "CPQ", "Compaq Computer Company" },
+ { "QCL", "Quadrant Components Inc" },
+ { "PRA", "PRO/AUTOMATION" },
+ { "MAC", "MAC System Company Ltd" },
+ { "TOP", "Orion Communications Co., Ltd." },
+ { "AGT", "Agilent Technologies" },
+ { "SWI", "Sierra Wireless Inc." },
+ { "ATT", "AT&T" },
+ { "MCL", "Motorola Communications Israel" },
+ { "NCS", "Northgate Computer Systems" },
+ { "RSX", "Rapid Tech Corporation" },
+ { "ATV", "Office Depot, Inc." },
+ { "MRD", "MicroDisplay Corporation" },
+ { "SCH", "Schlumberger Cards" },
+ { "ONW", "OPEN Networks Ltd" },
+ { "DTC", "DTC Tech Corporation" },
+ { "HYV", "Hynix Semiconductor" },
+ { "WEL", "W-DEV" },
+ { "AND", "Adtran Inc" },
+ { "AMN", "Amimon LTD." },
+ { "PXL", "The Moving Pixel Company" },
+ { "ZCT", "ZeitControl cardsystems GmbH" },
+ { "ALH", "AL Systems" },
+ { "VCJ", "Victor Company of Japan, Limited" },
+ { "COD", "CODAN Pty. Ltd." },
+ { "TMM", "Time Management, Inc." },
+ { "PPR", "PicPro" },
+ { "INL", "InnoLux Display Corporation" },
+ { "LTC", "Labtec Inc" },
+ { "PNP", "Microsoft" },
+ { "FIL", "Forefront Int'l Ltd" },
+ { "OSR", "Oksori Company Ltd" },
+ { "PEI", "PEI Electronics Inc" },
+ { "EZP", "Storm Technology" },
+ { "TCE", "Century Corporation" },
+ { "KAR", "Karna" },
+ { "ALS", "Texas Advanced optoelectronics Solutions, Inc" },
+ { "COI", "Codec Inc." },
+ { "NRT", "Beijing Northern Radiantelecom Co." },
+ { "FTR", "Mediasonic" },
+ { "SUN", "Sun Electronics Corporation" },
+ { "OZO", "Tribe Computer Works Inc" },
+ { "MCO", "Motion Computing Inc." },
+ { "UBI", "Ungermann-Bass Inc" },
+ { "ZNI", "Zetinet Inc" },
+ { "FUN", "sisel muhendislik" },
+ { "RMP", "Research Machines" },
+ { "DGT", "The Dearborn Group" },
+ { "SPX", "Simplex Time Recorder Co." },
+ { "COR", "Corollary Inc" },
+ { "AMX", "AMX LLC" },
+ { "AKY", "Askey Computer Corporation" },
+ { "RAR", "Raritan, Inc." },
+ { "VDS", "Vidisys GmbH & Company" },
+ { "SCL", "Sigmacom Co., Ltd." },
+ { "KSL", "Karn Solutions Ltd." },
+ { "ACK", "Acksys" },
+ { "NWS", "Newisys, Inc." },
+ { "TRX", "Trex Enterprises" },
+ { "BOI", "NINGBO BOIGLE DIGITAL TECHNOLOGY CO.,LTD" },
+ { "NTT", "NTT Advanced Technology Corporation" },
+ { "GUZ", "Guzik Technical Enterprises" },
+ { "MDY", "Microdyne Inc" },
+ { "EDM", "EDMI" },
+ { "DTI", "Diversified Technology, Inc." },
+ { "MMI", "Multimax" },
+ { "SCB", "SeeCubic B.V." },
+ { "UPS", "Systems Enhancement" },
+ { "AKB", "Akebia Ltd" },
+ { "NBT", "NingBo Bestwinning Technology CO., Ltd" },
+ { "TCD", "Taicom Data Systems Co., Ltd." },
+ { "XMM", "C3PO S.L." },
+ { "OIM", "Option International" },
+ { "DAV", "Davicom Semiconductor Inc" },
+ { "CKJ", "Carina System Co., Ltd." },
+ { "ATD", "Alpha Telecom Inc" },
+ { "XQU", "SHANGHAI SVA-DAV ELECTRONICS CO., LTD" },
+ { "KOL", "Kollmorgen Motion Technologies Group" },
+ { "HWA", "Harris Canada Inc" },
+ { "INE", "Inventec Electronics (M) Sdn. Bhd." },
+ { "ORN", "ORION ELECTRIC CO., LTD." },
+ { "KES", "Kesa Corporation" },
+ { "CRC", "CONRAC GmbH" },
+ { "AXT", "Axtend Technologies Inc" },
+ { "NAX", "Naxos Tecnologia" },
+ { "DAN", "Danelec Marine A/S" },
+ { "ADP", "Adaptec Inc" },
+ { "ICA", "ICA Inc" },
+ { "AGL", "Argolis" },
+ { "ECC", "ESSential Comm. Corporation" },
+ { "AWS", "Wave Systems" },
+ { "APN", "Appian Tech Inc" },
+ { "DGI", "DIGI International" },
+ { "MCS", "Micro Computer Systems" },
+ { "ITA", "Itausa Export North America" },
+ { "CII", "Cromack Industries Inc" },
+ { "IPS", "IPS, Inc. (Intellectual Property Solutions, Inc.)" },
+ { "KOE", "KOLTER ELECTRONIC" },
+ { "MEP", "Meld Technology" },
+ { "IMA", "Imagraph" },
+ { "DDV", "Delta Information Systems, Inc" },
+ { "GML", "General Information Systems" },
+ { "SSC", "Sierra Semiconductor Inc" },
+ { "WNX", "Wincor Nixdorf International GmbH" },
+ { "ABD", "Allen Bradley Company" },
+ { "CMS", "CompuMaster Srl" },
+ { "INK", "Indtek Co., Ltd." },
+ { "DTT", "Design & Test Technology, Inc." },
+ { "MGA", "Mega System Technologies, Inc." },
+ { "SMO", "STMicroelectronics" },
+ { "SSI", "S-S Technology Inc" },
+ { "CIR", "Cirrus Logic Inc" },
+ { "EKC", "Eastman Kodak Company" },
+ { "LNR", "Linear Systems Ltd." },
+ { "VCM", "Vector Magnetics, LLC" },
+ { "HKG", "Josef Heim KG" },
+ { "ORG", "ORGA Kartensysteme GmbH" },
+ { "ELG", "Elmeg GmbH Kommunikationstechnik" },
+ { "NSI", "NISSEI ELECTRIC CO.,LTD" },
+ { "RDM", "Tremon Enterprises Company Ltd" },
+ { "HAI", "Haivision Systems Inc." },
+ { "CIC", "Comm. Intelligence Corporation" },
+ { "LTS", "LTS Scale LLC" },
+ { "SAS", "Stores Automated Systems Inc" },
+ { "OEC", "ORION ELECTRIC CO.,LTD" },
+ { "BRG", "Bridge Information Co., Ltd" },
+ { "SQT", "Sequent Computer Systems Inc" },
+ { "CCI", "Cache" },
+ { "PRX", "Proxima Corporation" },
+ { "ADR", "Nasa Ames Research Center" },
+ { "SNW", "Snell & Wilcox" },
+ { "CDI", "Concept Development Inc" },
+ { "SEA", "Seanix Technology Inc." },
+ { "STY", "SDS Technologies" },
+ { "PCA", "Philips BU Add On Card" },
+ { "NYC", "nakayo telecommunications,inc." },
+ { "JMT", "Micro Technical Company Ltd" },
+ { "MTD", "MindTech Display Co. Ltd" },
+ { "NSP", "Nspire System Inc." },
+ { "DSD", "DS Multimedia Pte Ltd" },
+ { "PBI", "Pitney Bowes" },
+ { "ARO", "Poso International B.V." },
+ { "TTE", "TTE, Inc." },
+ { "DDA", "DA2 Technologies Corporation" },
+ { "MAS", "Mass Inc." },
+ { "LAC", "LaCie" },
+ { "CRX", "Cyrix Corporation" },
+ { "EMO", "ELMO COMPANY, LIMITED" },
+ { "OSP", "OPTI-UPS Corporation" },
+ { "GED", "General Dynamics C4 Systems" },
+ { "PPI", "Practical Peripherals" },
+ { "VPI", "Video Products Inc" },
+ { "TOS", "Toshiba Corporation" },
+ { "ASL", "AccuScene Corporation Ltd" },
+ { "ANT", "Ace CAD Enterprise Company Ltd" },
+ { "GRV", "Advanced Gravis" },
+ { "ANO", "Anorad Corporation" },
+ { "LNK", "Link Tech Inc" },
+ { "DIG", "Digicom S.p.A." },
+ { "ALC", "Altec Corporation" },
+ { "IAI", "Integration Associates, Inc." },
+ { "APG", "Horner Electric Inc" },
+ { "TWK", "TOWITOKO electronics GmbH" },
+ { "BRI", "Boca Research Inc" },
+ { "SVS", "SVSI" },
+ { "QCI", "Quanta Computer Inc" },
+ { "MDD", "MODIS" },
+ { "PDT", "PDTS - Prozessdatentechnik und Systeme" },
+ { "IMP", "Impression Products Incorporated" },
+ { "EXI", "Exide Electronics" },
+ { "WNV", "Winnov L.P." },
+ { "ALG", "Realtek Semiconductor Corp." },
+ { "ESA", "Elbit Systems of America" },
+ { "OLC", "Olicom A/S" },
+ { "DPX", "DpiX, Inc." },
+ { "GSB", "NIPPONDENCHI CO,.LTD" },
+ { "MCA", "American Nuclear Systems Inc" },
+ { "EST", "Embedded Solution Technology" },
+ { "ADX", "Adax Inc" },
+ { "MSA", "Micro Systemation AB" },
+ { "HDV", "Holografika kft." },
+ { "GIP", "GI Provision Ltd" },
+ { "XTN", "X-10 (USA) Inc" },
+ { "VEC", "Vector Informatik GmbH" },
+ { "DTN", "Datang Telephone Co" },
+ { "CST", "CSTI Inc" },
+ { "ECO", "Echo Speech Corporation" },
+ { "TDD", "Tandberg Data Display AS" },
+ { "NVL", "Novell Inc" },
+ { "CHT", "Chunghwa Picture Tubes,LTD." },
+ { "SCP", "Scriptel Corporation" },
+ { "TMS", "Trident Microsystems Ltd" },
+ { "ABO", "D-Link Systems Inc" },
+ { "JTY", "jetway security micro,inc" },
+ { "LSD", "Intersil Corporation" },
+ { "SEP", "SEP Eletronica Ltda." },
+ { "SHI", "Jiangsu Shinco Electronic Group Co., Ltd" },
+ { "FTG", "FTG Data Systems" },
+ { "ESN", "eSATURNUS" },
+ { "DJE", "Capstone Visual Product Development" },
+ { "BEC", "Elektro Beckhoff GmbH" },
+ { "FVC", "First Virtual Corporation" },
+ { "JUP", "Jupiter Systems" },
+ { "XNT", "XN Technologies, Inc." },
+ { "RTK", "DO NOT USE - RTK" },
+ { "ACL", "Apricot Computers" },
+ { "TAA", "Tandberg" },
+ { "WIP", "Wipro Infotech" },
+ { "KRL", "Krell Industries Inc." },
+ { "INO", "Innolab Pte Ltd" },
+ { "ELT", "Element Labs, Inc." },
+ { "KTE", "K-Tech" },
+ { "CVA", "Covia Inc." },
+ { "SIC", "Sysmate Corporation" },
+ { "STH", "Semtech Corporation" },
+ { "ACD", "AWETA BV" },
+ { "EHN", "Enhansoft" },
+ { "VMI", "Vermont Microsystems" },
+ { "TTC", "Telecommunications Techniques Corporation" },
+ { "KYE", "KYE Syst Corporation" },
+ { "QDI", "Quantum Data Incorporated" },
+ { "ELL", "Electrosonic Ltd" },
+ { "FLE", "ADTI Media, Inc" },
+ { "KTD", "Takahata Electronics Co.,Ltd." },
+ { "MAL", "Meridian Audio Ltd" },
+ { "TRV", "Trivisio Prototyping GmbH" },
+ { "TWH", "Twinhead International Corporation" },
+ { "SYP", "SYPRO Co Ltd" },
+ { "GCC", "GCC Technologies Inc" },
+ { "POR", "Portalis LC" },
+ { "PIM", "Prism, LLC" },
+ { "MLX", "Mylex Corporation" },
+ { "ONL", "OnLive, Inc" },
+ { "NIS", "Nissei Electric Company" },
+ { "ISM", "Image Stream Medical" },
+ { "EPS", "KEPS" },
+ { "PAC", "Pacific Avionics Corporation" },
+ { "AXC", "AXIOMTEK CO., LTD." },
+ { "DYX", "Dynax Electronics (HK) Ltd" },
+ { "WEB", "WebGear Inc" },
+ { "RIT", "Ritech Inc" },
+ { "INI", "Initio Corporation" },
+ { "LBO", "Lubosoft" },
+ { "PGM", "Paradigm Advanced Research Centre" },
+ { "OSA", "OSAKA Micro Computer, Inc." },
+ { "SIN", "Singular Technology Co., Ltd." },
+ { "CIN", "Citron GmbH" },
+ { "OTB", "outsidetheboxstuff.com" },
+ { "ARL", "Arlotto Comnet Inc" },
+ { "HOB", "HOB Electronic GmbH" },
+ { "QQQ", "Chuomusen Co., Ltd." },
+ { "AXE", "D-Link Systems Inc" },
+ { "CCC", "C-Cube Microsystems" },
+ { "CPT", "cPATH" },
+ { "SEM", "Samsung Electronics Company Ltd" },
+ { "PVI", "Prime view international Co., Ltd" },
+ { "TAT", "Teleliaison Inc" },
+ { "SON", "Sony" },
+ { "ITT", "I&T Telecom." },
+ { "SLM", "Solomon Technology Corporation" },
+ { "MAN", "LGIC" },
+ { "AIX", "ALTINEX, INC." },
+ { "ASP", "ASP Microelectronics Ltd" },
+ { "VUT", "Vutrix (UK) Ltd" },
+ { "MTE", "MediaTec GmbH" },
+ { "UPP", "UPPI" },
+ { "DCM", "DCM Data Products" },
+ { "DYC", "Dycam Inc" },
+ { "DAK", "Daktronics" },
+ { "JAZ", "Carrera Computer Inc" },
+ { "FOX", "HON HAI PRECISON IND.CO.,LTD." },
+ { "UEI", "Universal Electronics Inc" },
+ { "OPI", "D.N.S. Corporation" },
+ { "CXT", "Conexant Systems" },
+ { "VTK", "Viewteck Co., Ltd." },
+ { "AVL", "Avalue Technology Inc." },
+ { "TSI", "TeleVideo Systems" },
+ { "PAN", "The Panda Project" },
+ { "CED", "Cambridge Electronic Design Ltd" },
+ { "RUP", "Ups Manufactoring s.r.l." },
+ { "MIP", "micronpc.com" },
+ { "REM", "SCI Systems Inc." },
+ { "NSS", "Newport Systems Solutions" },
+ { "FBI", "Interface Corporation" },
+ { "FER", "Ferranti Int'L" },
+ { "DLG", "Digital-Logic GmbH" },
+ { "TSY", "TouchSystems" },
+ { "PIO", "Pioneer Electronic Corporation" },
+ { "PNG", "P.I. Engineering Inc" },
+ { "OIN", "Option International" },
+ { "RED", "Research Electronics Development Inc" },
+ { "NOI", "North Invent A/S" },
+ { "MAY", "Maynard Electronics" },
+ { "BTO", "BioTao Ltd" },
+ { "ZYD", "Zydacron Inc" },
+ { "KCD", "Chunichi Denshi Co.,LTD." },
+ { "TTI", "Trenton Terminals Inc" },
+ { "TRD", "Trident Microsystem Inc" },
+ { "TDP", "3D Perception" },
+ { "TER", "TerraTec Electronic GmbH" },
+ { "AEM", "ASEM S.p.A." },
+ { "IBI", "INBINE.CO.LTD" },
+ { "ECK", "Eugene Chukhlomin Sole Proprietorship, d.b.a." },
+ { "AVT", "Avtek (Electronics) Pty Ltd" },
+ { "PST", "Global Data SA" },
+ { "FPS", "Deltec Corporation" },
+ { "SHP", "Sharp Corporation" },
+ { "RDN", "RADIODATA GmbH" },
+ { "TRC", "Trioc AB" },
+ { "ABE", "Alcatel Bell" },
+ { "VCX", "VCONEX" },
+ { "PBL", "Packard Bell Electronics" },
+ { "TLK", "Telelink AG" },
+ { "DMM", "Dimond Multimedia Systems Inc" },
+ { "IGM", "IGM Communi" },
+ { "KFC", "SCD Tech" },
+ { "GUD", "Guntermann & Drunck GmbH" },
+ { "MDA", "Media4 Inc" },
+ { "VWB", "Vweb Corp." },
+ { "ISG", "Insignia Solutions Inc" },
+ { "AMS", "ARMSTEL, Inc." },
+ { "NTL", "National Transcomm. Ltd" },
+ { "LSJ", "LSI Japan Company Ltd" },
+ { "NDL", "Network Designers" },
+ { "DIA", "Diadem" },
+ { "SDX", "SDX Business Systems Ltd" },
+ { "LPL", "LG Philips" },
+ { "CAG", "CalComp" },
+ { "FZC", "Founder Group Shenzhen Co." },
+ { "PCX", "PC Xperten" },
+ { "TSF", "Racal-Airtech Software Forge Ltd" },
+ { "RGL", "Robertson Geologging Ltd" },
+ { "MSD", "Datenerfassungs- und Informationssysteme" },
+ { "NVC", "NetVision Corporation" },
+ { "SKD", "Schneider & Koch" },
+ { "CRS", "Crescendo Communication Inc" },
+ { "AXI", "American Magnetics" },
+ { "HRS", "Harris Semiconductor" },
+ { "AEN", "Avencall" },
+ { "TCL", "Technical Concepts Ltd" },
+ { "SST", "SystemSoft Corporation" },
+ { "OMN", "Omnitel" },
+ { "GCI", "Gateway Comm. Inc" },
+ { "SEN", "Sencore" },
+ { "MDT", "Magus Data Tech" },
+ { "ALN", "Alana Technologies" },
+ { "AVD", "Avid Electronics Corporation" },
+ { "DOM", "Dome Imaging Systems" },
+ { "KBL", "Kobil Systems GmbH" },
+ { "ITS", "IDTECH" },
+ { "CGS", "Chyron Corp" },
+ { "CYV", "Cyviz AS" },
+ { "CSO", "California Institute of Technology" },
+ { "ADT", "Aved Display Technologies" },
+ { "ACP", "Aspen Tech Inc" },
+ { "AKI", "AKIA Corporation" },
+ { "LCT", "Labcal Technologies" },
+ { "NDS", "Nokia Data" },
+ { "WCS", "Woodwind Communications Systems Inc" },
+ { "XFG", "Jan Strapko - FOTO" },
+ { "CPI", "Computer Peripherals Inc" },
+ { "FCG", "First International Computer Ltd" },
+ { "EVE", "Advanced Micro Peripherals Ltd" },
+ { "ATO", "ASTRO DESIGN, INC." },
+ { "SGW", "Shanghai Guowei Science and Technology Co., Ltd." },
+ { "CNB", "American Power Conversion" },
+ { "TCX", "FREEMARS Heavy Industries" },
+ { "ITN", "The NTI Group" },
+ { "HWD", "Highwater Designs Ltd" },
+ { "NUG", "NU Technology, Inc." },
+ { "ISL", "Isolation Systems" },
+ { "CIL", "Citicom Infotech Private Limited" },
+ { "IOT", "I/OTech Inc" },
+ { "GET", "Getac Technology Corporation" },
+ { "ULT", "Ultra Network Tech" },
+ { "TVV", "TV1 GmbH" },
+ { "OWL", "Mediacom Technologies Pte Ltd" },
+ { "TMX", "Thermotrex Corporation" },
+ { "ARC", "Alta Research Corporation" },
+ { "SEL", "Way2Call Communications" },
+ { "ELS", "ELSA GmbH" },
+ { "STD", "STD Computer Inc" },
+ { "GST", "Graphic SystemTechnology" },
+ { "SME", "Sysmate Company" },
+ { "ARS", "Arescom Inc" },
+ { "SCN", "Scanport, Inc." },
+ { "CTX", "Creatix Polymedia GmbH" },
+ { "DIM", "dPict Imaging, Inc." },
+ { "MDI", "Micro Design Inc" },
+ { "SCM", "SCM Microsystems Inc" },
+ { "CEA", "Consumer Electronics Association" },
+ { "OTI", "Orchid Technology" },
+ { "ADK", "Adtek System Science Company Ltd" },
+ { "ETC", "Everton Technology Company Ltd" },
+ { "PCO", "Performance Concepts Inc.," },
+ { "DMC", "Dune Microsystems Corporation" },
+ { "SGM", "SAGEM" },
+ { "OBS", "Optibase Technologies" },
+ { "PMX", "Photomatrix" },
+ { "SDI", "Samtron Displays Inc" },
+ { "GMM", "GMM Research Inc" },
+ { "DUN", "NCR Corporation" },
+ { "CAL", "Acon" },
+ { "MIR", "Miro Computer Prod." },
+ { "PEN", "Interactive Computer Products Inc" },
+ { "CRL", "Creative Logic" },
+ { "SBT", "Senseboard Technologies AB" },
+ { "AST", "AST Research Inc" },
+ { "INS", "Ines GmbH" },
+ { "SGC", "Spectragraphics Corporation" },
+ { "DBI", "DigiBoard Inc" },
+ { "LEO", "First International Computer Inc" },
+ { "TSP", "U.S. Navy" },
+ { "MTK", "Microtek International Inc." },
+ { "TCN", "Tecnetics (PTY) Ltd" },
+ { "DPM", "ADPM Synthesis sas" },
+ { "LGS", "LG Semicom Company Ltd" },
+ { "LGI", "Logitech Inc" },
+ { "PBV", "Pitney Bowes" },
+ { "ELI", "Edsun Laboratories" },
+ { "HPQ", "HP" },
+ { "RPT", "R.P.T.Intergroups" },
+ { "BDO", "Brahler ICS" },
+ { "ARM", "Arima" },
+ { "JTS", "JS Motorsports" },
+ { "TNY", "Tennyson Tech Pty Ltd" },
+ { "UDN", "Uniden Corporation" },
+ { "KNC", "Konica corporation" },
+ { "GND", "Gennum Corporation" },
+ { "MSG", "MSI GmbH" },
+ { "REH", "Rehan Electronics Ltd." },
+ { "COL", "Rockwell Collins, Inc." },
+ { "MDC", "Midori Electronics" },
+ { "TRN", "Datacommunicatie Tron B.V." },
+ { "VDA", "Victor Data Systems" },
+ { "TOU", "Touchstone Technology" },
+ { "ETD", "ELAN MICROELECTRONICS CORPORATION" },
+ { "CYB", "CyberVision" },
+ { "SWC", "Software Café" },
+ { "EXN", "RGB Systems, Inc. dba Extron Electronics" },
+ { "HSP", "HannStar Display Corp" },
+ { "WTK", "Wearnes Thakral Pte" },
+ { "GFM", "GFMesstechnik GmbH" },
+ { "INC", "Home Row Inc" },
+ { "LEC", "Lectron Company Ltd" },
+ { "WTS", "Restek Electric Company Ltd" },
+ { "ACE", "Actek Engineering Pty Ltd" },
+ { "MSH", "Microsoft" },
+ { "CHL", "Chloride-R&D" },
+ { "ALT", "Altra" },
+ { "EES", "EE Solutions, Inc." },
+ { "ASX", "AudioScience" },
+ { "DAC", "Digital Acoustics Corporation" },
+ { "HAL", "Halberthal" },
+ { "HPC", "Hewlett Packard Co." },
+ { "GRY", "Robert Gray Company" },
+ { "AXO", "Axonic Labs LLC" },
+ { "ALJ", "Altec Lansing" },
+ { "SMS", "Silicom Multimedia Systems Inc" },
+ { "HPI", "Headplay, Inc." },
+ { "FRO", "FARO Technologies" },
+ { "GAU", "Gaudi Co., Ltd." },
+ { "SRS", "SR-Systems e.K." },
+ { "APL", "Aplicom Oy" },
+ { "JGD", "University College" },
+ { "NVD", "Nvidia" },
+ { "CEP", "C-DAC" },
+ { "BDR", "Blonder Tongue Labs, Inc." },
+ { "AUO", "AU Optronics" },
+ { "DCR", "Decros Ltd" },
+ { "DLK", "D-Link Systems Inc" },
+ { "SWS", "Static" },
+ { "WSC", "CIS Technology Inc" },
+ { "ESL", "Esterline Technologies" },
+ { "ISC", "Id3 Semiconductors" },
+ { "XSN", "Xscreen AS" },
+ { "FML", "Fujitsu Microelect Ltd" },
+ { "WPI", "Wearnes Peripherals International (Pte) Ltd" },
+ { "EGL", "Eagle Technology" },
+ { "EGA", "Elgato Systems LLC" },
+ { "GAG", "Gage Applied Sciences Inc" },
+ { "HCP", "Hitachi Computer Products Inc" },
+ { "UET", "Universal Empowering Technologies" },
+ { "ITL", "Inter-Tel" },
+ { "SDE", "Sherwood Digital Electronics Corporation" },
+ { "CAA", "Castles Automation Co., Ltd" },
+ { "ZRN", "Zoran Corporation" },
+ { "VLT", "VideoLan Technologies" },
+ { "EUT", "Ericsson Mobile Networks B.V." },
+ { "REA", "Real D" },
+ { "BUT", "21ST CENTURY ENTERTAINMENT" },
+ { "THN", "Thundercom Holdings Sdn. Bhd." },
+ { "CHO", "Sichuang Changhong Corporation" },
+ { "SCC", "SORD Computer Corporation" },
+ { "MSY", "MicroTouch Systems Inc" },
+ { "ERP", "Euraplan GmbH" },
+ { "CPL", "Compal Electronics Inc" },
+ { "ACM", "Acroloop Motion Control Systems Inc" },
+ { "VTS", "VTech Computers Ltd" },
+ { "ETH", "Etherboot Project" },
+ { "CGT", "congatec AG" },
+ { "FEN", "Fen Systems Ltd." },
+ { "MLN", "Mark Levinson" },
+ { "UMC", "United Microelectr Corporation" },
+ { "CAR", "Cardinal Company Ltd" },
+ { "LIT", "Lithics Silicon Technology" },
+ { "AWC", "Access Works Comm Inc" },
+ { "PPC", "Phoenixtec Power Company Ltd" },
+ { "SVT", "SEVIT Co., Ltd." },
+ { "MDX", "MicroDatec GmbH" },
+ { "XIN", "Xinex Networks Inc" },
+ { "KTN", "Katron Tech Inc" },
+ { "MJI", "MARANTZ JAPAN, INC." },
+ { "CTM", "Computerm Corporation" },
+ { "PDM", "Psion Dacom Plc." },
+ { "AKM", "Asahi Kasei Microsystems Company Ltd" },
+ { "GSY", "Grossenbacher Systeme AG" },
+ { "OMR", "Omron Corporation" },
+ { "RSH", "ADC-Centre" },
+ { "MTM", "Motium" },
+ { "XDM", "XDM Ltd." },
+ { "MSX", "Micomsoft Co., Ltd." },
+ { "VNC", "Vinca Corporation" },
+ { "STK", "SANTAK CORP." },
+ { "JET", "JET POWER TECHNOLOGY CO., LTD." },
+ { "SLR", "Schlumberger Technology Corporate" },
+ { "GWI", "GW Instruments" },
+ { "TMI", "Texas Microsystem" },
+ { "EXT", "Exatech Computadores & Servicos Ltda" },
+ { "SXB", "Syntax-Brillian" },
+ { "HYT", "Heng Yu Technology (HK) Limited" },
+ { "TST", "Transtream Inc" },
+ { "FIS", "FLY-IT Simulators" },
+ { "VMW", "VMware Inc.," },
+ { "PET", "Practical Electronic Tools" },
+ { "BLP", "Bloomberg L.P." },
+ { "MVS", "Microvision" },
+ { "ZMT", "Zalman Tech Co., Ltd." },
+ { "QTD", "Quantum 3D Inc" },
+ { "ITE", "Integrated Tech Express Inc" },
+ { "MIS", "Modular Industrial Solutions Inc" },
+ { "KOB", "Kobil Systems GmbH" },
+ { "KOW", "KOWA Company,LTD." },
+ { "SHC", "ShibaSoku Co., Ltd." },
+ { "IKS", "Ikos Systems Inc" },
+ { "PGP", "propagamma kommunikation" },
+ { "AYD", "Aydin Displays" },
+ { "MFG", "MicroField Graphics Inc" },
+ { "APS", "Autologic Inc" },
+ { "APM", "Applied Memory Tech" },
+ { "ACO", "Allion Computer Inc." },
+ { "IWR", "Icuiti Corporation" },
+ { "RCI", "RC International" },
+ { "YMH", "Yamaha Corporation" },
+ { "SPE", "SPEA Software AG" },
+ { "ADL", "ASTRA Security Products Ltd" },
+ { "QFI", "Quickflex, Inc" },
+ { "FRD", "Freedom Scientific BLV" },
+ { "PCM", "PCM Systems Corporation" },
+ { "RHM", "Rohm Company Ltd" },
+ { "EQP", "Equipe Electronics Ltd." },
+ { "UND", "Unisys Corporation" },
+ { "ITX", "integrated Technology Express Inc" },
+ { "WML", "Wolfson Microelectronics Ltd" },
+ { "IPR", "Ithaca Peripherals" },
+ { "NCE", "Norcent Technology, Inc." },
+ { "GWY", "Gateway 2000" },
+ { "DAX", "Data Apex Ltd" },
+ { "MKT", "MICROTEK Inc." },
+ { "AOL", "America OnLine" },
+ { "BIO", "BioLink Technologies International, Inc." },
+ { "DCI", "Concepts Inc" },
+ { "LOL", "Litelogic Operations Ltd" },
+ { "ADI", "ADI Systems Inc" },
+ { "TPJ", "Junnila" },
+ { "JDL", "Japan Digital Laboratory Co.,Ltd." },
+ { "MMN", "MiniMan Inc" },
+ { "MNC", "Mini Micro Methods Ltd" },
+ { "SUM", "Summagraphics Corporation" },
+ { "SXT", "SHARP TAKAYA ELECTRONIC INDUSTRY CO.,LTD." },
+ { "CAT", "Consultancy in Advanced Technology" },
+ { "MSM", "Advanced Digital Systems" },
+ { "CHY", "Cherry GmbH" },
+ { "VLB", "ValleyBoard Ltda." },
+ { "DDS", "Barco, n.v." },
+ { "STL", "SigmaTel Inc" },
+ { "AIE", "Altmann Industrieelektronik" },
+ { "CHM", "CHIC TECHNOLOGY CORP." },
+ { "KTK", "Key Tronic Corporation" },
+ { "LTN", "Litronic Inc" },
+ { "IDC", "International Datacasting Corporation" },
+ { "TWA", "Tidewater Association" },
+ { "ARI", "Argosy Research Inc" },
+ { "STT", "Star Paging Telecom Tech (Shenzhen) Co. Ltd." },
+ { "MYA", "Monydata" },
+ { "JAE", "Japan Aviation Electronics Industry, Limited" },
+ { "BBH", "B&Bh" },
+ { "GIC", "General Inst. Corporation" },
+ { "TIV", "OOO Technoinvest" },
+ { "ION", "Inside Out Networks" },
+ { "KZI", "K-Zone International co. Ltd." },
+ { "IDE", "IDE Associates" },
+ { "IQI", "IneoQuest Technologies, Inc" },
+ { "NDI", "National Display Systems" },
+ { "REL", "Reliance Electric Ind Corporation" },
+ { "SPH", "G&W Instruments GmbH" },
+ { "RPI", "RoomPro Technologies" },
+ { "LUC", "Lucent Technologies" },
+ { "CTL", "Creative Technology Ltd" },
+ { "SDS", "SunRiver Data System" },
+ { "USR", "U.S. Robotics Inc" },
+ { "GJN", "Grand Junction Networks" },
+ { "YED", "Y-E Data Inc" },
+ { "RHT", "Red Hat, Inc." },
+ { "AOT", "Alcatel" },
+ { "TCR", "Thomson Consumer Electronics" },
+ { "ILC", "Image Logic Corporation" },
+ { "IGC", "Intergate Pty Ltd" },
+ { "HYC", "Hypercope Gmbh Aachen" },
+ { "SPL", "Smart Silicon Systems Pty Ltd" },
+ { "DLC", "Diamond Lane Comm. Corporation" },
+ { "TBB", "Triple S Engineering Inc" },
+ { "MLS", "Milestone EPE" },
+ { "QDM", "Quadram" },
+ { "AIR", "Advanced Integ. Research Inc" },
+ { "SLA", "Systeme Lauer GmbH&Co KG" },
+ { "IBP", "IBP Instruments GmbH" },
+ { "DDI", "Data Display AG" },
+ { "LED", "Long Engineering Design Inc" },
+ { "MSC", "Mouse Systems Corporation" },
+ { "LXS", "ELEA CardWare" },
+ { "ATE", "Innovate Ltd" },
+ { "APV", "A+V Link" },
+ { "FRC", "Force Computers" },
+ { "ZTC", "ZyDAS Technology Corporation" },
+ { "ANP", "Andrew Network Production" },
+ { "LOG", "Logicode Technology Inc" },
+ { "RAI", "Rockwell Automation/Intecolor" },
+ { "MPJ", "Microlab" },
+ { "CMO", "Chi Mei Optoelectronics corp." },
+ { "ROH", "Rohm Co., Ltd." },
+ { "HYP", "Hyphen Ltd" },
+ { "ICO", "Intel Corp" },
+ { "ACI", "Ancor Communications Inc" },
+ { "SLT", "Salt Internatioinal Corp." },
+ { "TSC", "Sanyo Electric Company Ltd" },
+ { "APC", "American Power Conversion" },
+ { "PSE", "Practical Solutions Pte., Ltd." },
+ { "MET", "Metheus Corporation" },
+ { "SAT", "Shuttle Tech" },
+ { "SYK", "Stryker Communications" },
+ { "BCQ", "Deutsche Telekom Berkom GmbH" },
+ { "DPI", "DocuPoint" },
+ { "FAR", "Farallon Computing" },
+ { "ROP", "Roper International Ltd" },
+ { "STB", "STB Systems Inc" },
+ { "CNC", "Alvedon Computers Ltd" },
+ { "DGA", "Digiital Arts Inc" },
+ { "EDT", "Emerging Display Technologies Corp" },
+ { "IPI", "Intelligent Platform Management Interface (IPMI) forum (Intel, HP, NEC, Dell)" },
+ { "VQ@", "Vision Quest" },
+ { "EMK", "Emcore Corporation" },
+ { "XTD", "Icuiti Corporation" },
+ { "KNX", "Nutech Marketing PTL" },
+ { "WHI", "Whistle Communications" },
+ { "KDM", "Korea Data Systems Co., Ltd." },
+ { "QCK", "Quick Corporation" },
+ { "QTR", "Qtronix Corporation" },
+ { "NFS", "Number Five Software" },
+ { "HTK", "Holtek Microelectronics Inc" },
+ { "TRL", "Royal Information" },
+ { "LXN", "Luxeon" },
+ { "VLK", "Vislink International Ltd" },
+ { "TWE", "Kontron Electronik" },
+ { "DFI", "DFI" },
+ { "JWS", "JWSpencer & Co." },
+ { "FTW", "MindTribe Product Engineering, Inc." },
+ { "TDM", "Tandem Computer Europe Inc" },
+ { "RAS", "RAScom Inc" },
+ { "KVX", "KeyView" },
+ { "MOS", "Moses Corporation" },
+ { "ONX", "SOMELEC Z.I. Du Vert Galanta" },
+ { "STF", "Starflight Electronics" },
+ { "HER", "Ascom Business Systems" },
+ { "GTS", "Geotest Marvin Test Systems Inc" },
+ { "KEC", "Kyushu Electronics Systems Inc" },
+ { "MQP", "MultiQ Products AB" },
+ { "LUX", "Luxxell Research Inc" },
+ { "HEC", "Hitachi Engineering Company Ltd" },
+ { "NXG", "Nexgen" },
+ { "CNI", "Connect Int'l A/S" },
+ { "FUJ", "Fujitsu Ltd" },
+ { "APD", "AppliAdata" },
+ { "LHE", "Lung Hwa Electronics Company Ltd" },
+ { "SCT", "Smart Card Technology" },
+ { "SOY", "SOYO Group, Inc" },
+ { "ICN", "Sanyo Icon" },
+ { "TDV", "TDVision Systems, Inc." },
+ { "AHC", "Advantech Co., Ltd." },
+ { "GTK", "G-Tech Corporation" },
+ { "BII", "Boeckeler Instruments Inc" },
+ { "TCC", "Tandon Corporation" },
+ { "BUJ", "ATI Tech Inc" },
+ { "SAA", "Sanritz Automation Co.,Ltd." },
+ { "DTK", "Dynax Electronics (HK) Ltd" },
+ { "HXM", "Hexium Ltd." },
+ { "EGD", "EIZO GmbH Display Technologies" },
+ { "NDK", "Naitoh Densei CO., LTD." },
+ { "TVR", "TV Interactive Corporation" },
+ { "PNL", "Panelview, Inc." },
+ { "AET", "Aethra Telecomunicazioni S.r.l." },
+ { "REC", "ReCom" },
+ { "HET", "HETEC Datensysteme GmbH" },
+ { "ZOW", "Zowie Intertainment, Inc" },
+ { "MEQ", "Matelect Ltd." },
+ { "DRD", "DIGITAL REFLECTION INC." },
+ { "MRA", "Miranda Technologies Inc" },
+ { "QTM", "Quantum" },
+ { "REN", "Renesas Technology Corp." },
+ { "XIO", "Xiotech Corporation" },
+ { "GIS", "AT&T Global Info Solutions" },
+ { "TEA", "TEAC System Corporation" },
+ { "EMU", "Emulex Corporation" },
+ { "VIC", "Victron B.V." },
+ { "ATN", "Athena Smartcard Solutions Ltd." },
+ { "SYS", "Sysgration Ltd" },
+ { "CVS", "Clarity Visual Systems" },
+ { "CWR", "Connectware Inc" },
+ { "TVI", "Truevision" },
+ { "AMB", "Ambient Technologies, Inc." },
+ { "USA", "Utimaco Safeware AG" },
+ { "LNT", "LANETCO International" },
+ { "EDG", "Electronic-Design GmbH" },
+ { "MKV", "Trtheim Technology" },
+ { "SGT", "Stargate Technology" },
+ { "RTS", "Raintree Systems" },
+ { "PXM", "Proxim Inc" },
+ { "ACG", "A&R Cambridge Ltd" },
+ { "FJT", "F.J. Tieman BV" },
+ { "LCD", "Toshiba Matsushita Display Technology Co., Ltd" },
+ { "IDS", "Interdigital Sistemas de Informacao" },
+ { "AOA", "AOpen Inc." },
+ { "ACR", "Acer Technologies" },
+ { "AKL", "AMiT Ltd" },
+ { "IOS", "i-O Display System" },
+ { "NOR", "Norand Corporation" },
+ { "XST", "XS Technologies Inc" },
+ { "BUG", "B.U.G., Inc." },
+ { "RCN", "Radio Consult SRL" },
+ { "ESI", "Extended Systems, Inc." },
+ { "TUT", "Tut Systems" },
+ { "VAR", "Varian Australia Pty Ltd" },
+ { "DIT", "Dragon Information Technology" },
+ { "CET", "TEC CORPORATION" },
+ { "WKH", "Uni-Take Int'l Inc." },
+ { "BHZ", "BitHeadz, Inc." },
+ { "PTI", "Promise Technology Inc" },
+ { "HIQ", "Kaohsiung Opto Electronics Americas, Inc." },
+ { "SET", "SendTek Corporation" },
+ { "KCL", "Keycorp Ltd" },
+ { "EIC", "Eicon Technology Corporation" },
+ { "TRT", "Tritec Electronic AG" },
+ { "ZAN", "Zandar Technologies plc" },
+ { "NTN", "Nuvoton Technology Corporation" },
+ { "MTC", "Mars-Tech Corporation" },
+ { "JQE", "CNet Technical Inc" },
+ { "SRG", "Intuitive Surgical, Inc." },
+ { "VIR", "Visual Interface, Inc" },
+ { "HTX", "Hitex Systementwicklung GmbH" },
+ { "TLX", "Telxon Corporation" },
+ { "NGC", "Network General" },
+ { "TSB", "Toshiba America Info Systems Inc" },
+ { "SGI", "Scan Group Ltd" },
+ { "AIS", "Alien Internet Services" },
+ { "MUD", "Multi-Dimension Institute" },
+ { "PNS", "PanaScope" },
+ { "NEO", "NEO TELECOM CO.,LTD." },
+ { "IMB", "ART s.r.l." },
+ { "SRD", "Setred" },
+ { "LEX", "Lexical Ltd" },
+ { "LMI", "Lexmark Int'l Inc" },
+ { "ECL", "Excel Company Ltd" },
+ { "EXC", "Excession Audio" },
+ { "ABA", "ABBAHOME INC." },
+ { "CLI", "Cirrus Logic Inc" },
+ { "DYM", "Dymo-CoStar Corporation" },
+ { "MEL", "Mitsubishi Electric Corporation" },
+ { "ZAX", "Zefiro Acoustics" },
+ { "TEC", "Tecmar Inc" },
+ { "WTI", "WorkStation Tech" },
+ { "APX", "AP Designs Ltd" },
+ { "MLM", "Millennium Engineering Inc" },
+ { "BAC", "Biometric Access Corporation" },
+ { "DDE", "Datasat Digital Entertainment" },
+ { "GIM", "Guillemont International" },
+ { "TVM", "Taiwan Video & Monitor Corporation" },
+ { "KWD", "Kenwood Corporation" },
+ { "STW", "Starwin Inc." },
+ { "NRV", "Taugagreining hf" },
+ { "SUP", "Supra Corporation" },
+ { "MTB", "Media Technologies Ltd." },
+ { "INF", "Inframetrics Inc" },
+ { "OTM", "Optoma Corporation" },
+ { "NTX", "Netaccess Inc" },
+ { "LXC", "LXCO Technologies AG" },
+ { "CRN", "Cornerstone Imaging" },
+ { "PVP", "Klos Technologies, Inc." },
+ { "TCJ", "TEAC America Inc" },
+ { "WVM", "Wave Systems Corporation" },
+ { "ERN", "Ericsson, Inc." },
+ { "PVN", "Pixel Vision" },
+ { "LMT", "Laser Master" },
+ { "MID", "miro Displays" },
+ { "VID", "Ingram Macrotron Germany" },
+ { "IFZ", "Infinite Z" },
+ { "ODM", "ODME Inc." },
+ { "ASI", "Ahead Systems" },
+ { "ISY", "International Integrated Systems,Inc.(IISI)" },
+ { "NCL", "NetComm Ltd" },
+ { "ITK", "ITK Telekommunikation AG" },
+ { "EZE", "EzE Technologies" },
+ { "VSR", "V-Star Electronics Inc." },
+ { "CPC", "Ciprico Inc" },
+ { "JWD", "Video International Inc." },
+ { "MEC", "Mega System Technologies Inc" },
+ { "NVI", "NuVision US, Inc." },
+ { "MRK", "Maruko & Company Ltd" },
+ { "AAA", "Avolites Ltd" },
+ { "CHG", "Sichuan Changhong Electric CO, LTD." },
+ { "WWV", "World Wide Video, Inc." },
+ { "SEO", "SEOS Ltd" },
+ { "XER", "DO NOT USE - XER" },
+ { "MCN", "Micron Electronics Inc" },
+ { "DXC", "Digipronix Control Systems" },
+ { "RSN", "Radiospire Networks, Inc." },
+ { "FGD", "Lisa Draexlmaier GmbH" },
+ { "SES", "Session Control LLC" },
+ { "IIN", "IINFRA Co., Ltd" },
+ { "ETI", "Eclipse Tech Inc" },
+ { "DXD", "DECIMATOR DESIGN PTY LTD" },
+ { "BST", "BodySound Technologies, Inc." },
+ { "MTL", "Mitel Corporation" },
+ { "LGX", "Lasergraphics, Inc." },
+ { "MSP", "Mistral Solutions [P] Ltd." },
+ { "SER", "Sony Ericsson Mobile Communications Inc." },
+ { "IHE", "InHand Electronics" },
+ { "STO", "Stollmann E+V GmbH" },
+ { "RET", "Resonance Technology, Inc." },
+ { "PXE", "PIXELA CORPORATION" },
+ { "USI", "Universal Scientific Industrial Co., Ltd." },
+ { "JAC", "Astec Inc" },
+ { "WAC", "Wacom Tech" },
+ { "BUF", "Yasuhiko Shirai Melco Inc" },
+ { "LSI", "Loughborough Sound Images" },
+ { "AMA", "Asia Microelectronic Development Inc" },
+ { "DJP", "Maygay Machines, Ltd" },
+ { "CAN", "CORNEA" },
+ { "UMM", "Universal Multimedia" },
+ { "ECI", "Enciris Technologies" },
+ { "DDT", "Datadesk Technologies Inc" },
+ { "MLG", "Micrologica AG" },
+ { "NCA", "Nixdorf Company" },
+ { "ENS", "Ensoniq Corporation" },
+ { "MOT", "Motorola UDS" },
+ { "WCI", "Wisecom Inc" },
+ { "MXT", "Maxtech Corporation" },
+ { "EHJ", "Epson Research" },
+ { "KUR", "Kurta Corporation" },
+ { "DFT", "DEI Holdings dba Definitive Technology" },
+ { "NAD", "NAD Electronics" },
+ { "GMK", "GMK Electronic Design GmbH" },
+ { "TAI", "Toshiba America Info Systems Inc" },
+ { "SNP", "Siemens Nixdorf Info Systems" },
+ { "KFE", "Komatsu Forest" },
+ { "PPD", "MEPhI" },
+ { "UMG", "Umezawa Giken Co.,Ltd" },
+ { "PMC", "PMC Consumer Electronics Ltd" },
+ { "KIS", "KiSS Technology A/S" },
+ { "ABV", "Advanced Research Technology" },
+ { "ISA", "Symbol Technologies" },
+ { "GMN", "GEMINI 2000 Ltd" },
+ { "VSI", "VideoServer" },
+ { "DTO", "Deutsche Thomson OHG" },
+ { "OCN", "Olfan" },
+ { "LTK", "Lucidity Technology Company Ltd" },
+ { "CLX", "CardLogix" },
+ { "TPT", "Thruput Ltd" },
+ { "IXD", "Intertex Data AB" },
+ { "ICX", "ICCC A/S" },
+ { "REF", "Reflectivity, Inc." },
+ { "CDK", "Cray Communications" },
+ { "PNX", "Phoenix Technologies, Ltd." },
+ { "MCT", "Microtec" },
+ { "ESD", "Ensemble Designs, Inc" },
+ { "CTS", "Comtec Systems Co., Ltd." },
+ { "ADB", "Aldebbaron" },
+ { "AML", "Anderson Multimedia Communications (HK) Limited" },
+ { "FIN", "Finecom Co., Ltd." },
+ { "NCC", "NCR Corporation" },
+ { "ONS", "On Systems Inc" },
+ { "CGA", "Chunghwa Picture Tubes, LTD" },
+ { "NTC", "NeoTech S.R.L" },
+ { "AMD", "Amdek Corporation" },
+ { "WVV", "WolfVision GmbH" },
+ { "PHO", "Photonics Systems Inc." },
+ { "AVX", "AVerMedia Technologies, Inc." },
+ { "SJE", "Sejin Electron Inc" },
+ { "BCM", "Broadcom" },
+ { "RLN", "RadioLAN Inc" },
+ { "CAM", "Cambridge Audio" },
+ { "TCS", "Tatung Company of America Inc" },
+ { "RIO", "Rios Systems Company Ltd" },
+ { "SWT", "Software Technologies Group,Inc." },
+ { "BSL", "Biomedical Systems Laboratory" },
+ { "DCV", "Datatronics Technology Inc" },
+ { "JPC", "JPC Technology Limited" },
+ { "ICC", "BICC Data Networks Ltd" },
+ { "CEI", "Crestron Electronics, Inc." },
+ { "NUI", "NU Inc." },
+ { "MAE", "Maestro Pty Ltd" },
+ { "AYR", "Airlib, Inc" },
+ { "TPS", "Teleprocessing Systeme GmbH" },
+ { "SMK", "SMK CORPORATION" },
+ { "IAT", "IAT Germany GmbH" },
+ { "BNO", "Bang & Olufsen" },
+ { "KRY", "Kroy LLC" },
+ { "OLT", "Olitec S.A." },
+ { "ABC", "AboCom System Inc" },
+ { "FXX", "Fuji Xerox" },
+ { "ANI", "Anigma Inc" },
+ { "OEI", "Optum Engineering Inc." },
+ { "TPE", "Technology Power Enterprises Inc" },
+ { "RDI", "Rainbow Displays, Inc." },
+ { "KDK", "Kodiak Tech" },
+ { "LHT", "Lighthouse Technologies Limited" },
+ { "BEK", "Beko Elektronik A.S." },
+ { "LND", "Land Computer Company Ltd" },
+ { "CDC", "Core Dynamics Corporation" },
+ { "FHL", "FHLP" },
+ { "UNP", "Unitop" },
+ { "MSR", "MASPRO DENKOH Corp." },
+ { "MKC", "Media Tek Inc." },
+ { "BCD", "Barco GmbH" },
+ { "PQI", "Pixel Qi" },
+ { "ALD", "In4S Inc" },
+ { "HTC", "Hitachi Ltd" },
+ { "OCD", "Macraigor Systems Inc" },
+ { "PHY", "Phylon Communications" },
+ { "MSF", "M-Systems Flash Disk Pioneers" },
+ { "ETK", "eTEK Labs Inc." },
+ { "DVS", "Digital Video System" },
+ { "ACU", "Acculogic" },
+ { "YOW", "American Biometric Company" },
+ { "MGE", "Schneider Electric S.A." },
+ { "AKP", "Atom Komplex Prylad" },
+ { "PGI", "PACSGEAR, Inc." },
+ { "III", "Intelligent Instrumentation" },
+ { "BML", "BIOMED Lab" },
+ { "KMC", "Mitsumi Company Ltd" },
+ { "RSQ", "R Squared" },
+ { "SBC", "Shanghai Bell Telephone Equip Mfg Co" },
+ { "FPX", "Cirel Systemes" },
+ { "IDN", "Idneo Technologies" },
+ { "BNE", "Bull AB" },
+};
+
+QT_END_NAMESPACE
+
+#endif // QEDIDVENDORTABLE_P_H
diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp b/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
index dc4785071f..06f0aa6747 100644
--- a/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
+++ b/src/platformsupport/eventdispatchers/qeventdispatcher_glib.cpp
@@ -48,78 +48,26 @@
QT_BEGIN_NAMESPACE
-struct GUserEventSource
-{
- GSource source;
- QPAEventDispatcherGlib *q;
-};
-
-static gboolean userEventSourcePrepare(GSource *source, gint *timeout)
-{
- Q_UNUSED(timeout)
- GUserEventSource *userEventSource = reinterpret_cast<GUserEventSource *>(source);
- QPAEventDispatcherGlib *dispatcher = userEventSource->q;
- if (dispatcher->m_flags & QEventLoop::ExcludeUserInputEvents)
- return QWindowSystemInterface::nonUserInputEventsQueued();
- else
- return QWindowSystemInterface::windowSystemEventsQueued() > 0;
-}
-
-static gboolean userEventSourceCheck(GSource *source)
-{
- return userEventSourcePrepare(source, 0);
-}
-
-static gboolean userEventSourceDispatch(GSource *source, GSourceFunc, gpointer)
-{
- GUserEventSource *userEventSource = reinterpret_cast<GUserEventSource *>(source);
- QPAEventDispatcherGlib *dispatcher = userEventSource->q;
- QWindowSystemInterface::sendWindowSystemEvents(dispatcher->m_flags);
- return true;
-}
-
-static GSourceFuncs userEventSourceFuncs = {
- userEventSourcePrepare,
- userEventSourceCheck,
- userEventSourceDispatch,
- NULL,
- NULL,
- NULL
-};
-
QPAEventDispatcherGlibPrivate::QPAEventDispatcherGlibPrivate(GMainContext *context)
: QEventDispatcherGlibPrivate(context)
{
- Q_Q(QPAEventDispatcherGlib);
- userEventSource = reinterpret_cast<GUserEventSource *>(g_source_new(&userEventSourceFuncs,
- sizeof(GUserEventSource)));
- userEventSource->q = q;
- g_source_set_can_recurse(&userEventSource->source, true);
- g_source_attach(&userEventSource->source, mainContext);
}
-
QPAEventDispatcherGlib::QPAEventDispatcherGlib(QObject *parent)
: QEventDispatcherGlib(*new QPAEventDispatcherGlibPrivate, parent)
, m_flags(QEventLoop::AllEvents)
{
- Q_D(QPAEventDispatcherGlib);
- d->userEventSource->q = this;
}
QPAEventDispatcherGlib::~QPAEventDispatcherGlib()
{
- Q_D(QPAEventDispatcherGlib);
-
- g_source_destroy(&d->userEventSource->source);
- g_source_unref(&d->userEventSource->source);
- d->userEventSource = 0;
}
bool QPAEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags)
{
m_flags = flags;
- return QEventDispatcherGlib::processEvents(m_flags);
+ const bool didSendEvents = QEventDispatcherGlib::processEvents(m_flags);
+ return QWindowSystemInterface::sendWindowSystemEvents(m_flags) || didSendEvents;
}
QT_END_NAMESPACE
diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h b/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
index 6d148753bf..bed2532856 100644
--- a/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
+++ b/src/platformsupport/eventdispatchers/qeventdispatcher_glib_p.h
@@ -71,14 +71,11 @@ public:
QEventLoop::ProcessEventsFlags m_flags;
};
-struct GUserEventSource;
-
class QPAEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate
{
Q_DECLARE_PUBLIC(QPAEventDispatcherGlib)
public:
QPAEventDispatcherGlibPrivate(GMainContext *context = 0);
- GUserEventSource *userEventSource;
};
diff --git a/src/platformsupport/fbconvenience/qfbwindow.cpp b/src/platformsupport/fbconvenience/qfbwindow.cpp
index 7e016f2f49..36f92b8cea 100644
--- a/src/platformsupport/fbconvenience/qfbwindow.cpp
+++ b/src/platformsupport/fbconvenience/qfbwindow.cpp
@@ -106,7 +106,7 @@ void QFbWindow::setVisible(bool visible)
}
}
-void QFbWindow::setWindowState(Qt::WindowState state)
+void QFbWindow::setWindowState(Qt::WindowStates state)
{
QPlatformWindow::setWindowState(state);
mWindowState = state;
diff --git a/src/platformsupport/fbconvenience/qfbwindow_p.h b/src/platformsupport/fbconvenience/qfbwindow_p.h
index c201302a50..20bac46c69 100644
--- a/src/platformsupport/fbconvenience/qfbwindow_p.h
+++ b/src/platformsupport/fbconvenience/qfbwindow_p.h
@@ -70,7 +70,7 @@ public:
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
void setVisible(bool visible) Q_DECL_OVERRIDE;
- void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
+ void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
void setWindowFlags(Qt::WindowFlags type) Q_DECL_OVERRIDE;
Qt::WindowFlags windowFlags() const;
@@ -93,7 +93,7 @@ protected:
QFbBackingStore *mBackingStore;
QRect mOldGeometry;
Qt::WindowFlags mWindowFlags;
- Qt::WindowState mWindowState;
+ Qt::WindowStates mWindowState;
WId mWindowId;
};
diff --git a/src/platformsupport/fontdatabases/mac/coretext.pri b/src/platformsupport/fontdatabases/mac/coretext.pri
index 2a9b32f65a..af75aa3281 100644
--- a/src/platformsupport/fontdatabases/mac/coretext.pri
+++ b/src/platformsupport/fontdatabases/mac/coretext.pri
@@ -18,18 +18,4 @@ macos: \
else: \
LIBS_PRIVATE += -framework UIKit
-# CoreText is documented to be available on watchOS, but the headers aren't present
-# in the watchOS Simulator SDK like they are supposed to be. Work around the problem
-# by adding the device SDK's headers to the search path as a fallback.
-# rdar://25314492, rdar://27844864
-watchos:simulator {
- simulator_system_frameworks = $$xcodeSDKInfo(Path, $${simulator.sdk})/System/Library/Frameworks
- device_system_frameworks = $$xcodeSDKInfo(Path, $${device.sdk})/System/Library/Frameworks
- for (arch, QMAKE_APPLE_SIMULATOR_ARCHS) {
- QMAKE_CXXFLAGS += \
- -Xarch_$${arch} \
- -F$$simulator_system_frameworks \
- -Xarch_$${arch} \
- -F$$device_system_frameworks
- }
-}
+CONFIG += watchos_coretext
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
index 9612b909f1..2b4c4e3ceb 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h
@@ -57,12 +57,8 @@
#include <qpa/qplatformtheme.h>
#include <private/qcore_mac_p.h>
-#ifdef Q_OS_OSX
-#include <ApplicationServices/ApplicationServices.h>
-#else
-#include <CoreText/CoreText.h>
-#include <CoreGraphics/CoreGraphics.h>
-#endif
+Q_FORWARD_DECLARE_CF_TYPE(CTFontDescriptor);
+Q_FORWARD_DECLARE_CF_TYPE(CTFont);
Q_DECLARE_METATYPE(QCFType<CGFontRef>);
Q_DECLARE_METATYPE(QCFType<CFURLRef>);
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
index 1389b497d5..a337332b53 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine.cpp
@@ -132,20 +132,6 @@ bool QWindowsFontEngine::hasCMapTable() const
return GetFontData(hdc, MAKE_LITTLE_ENDIAN_TAG('c', 'm', 'a', 'p'), 0, 0, 0) != GDI_ERROR;
}
-bool QWindowsFontEngine::hasGlyfTable() const
-{
- HDC hdc = m_fontEngineData->hdc;
- SelectObject(hdc, hfont);
- return GetFontData(hdc, MAKE_LITTLE_ENDIAN_TAG('g', 'l', 'y', 'f'), 0, 0, 0) != GDI_ERROR;
-}
-
-bool QWindowsFontEngine::hasEbdtTable() const
-{
- HDC hdc = m_fontEngineData->hdc;
- SelectObject(hdc, hfont);
- return GetFontData(hdc, MAKE_LITTLE_ENDIAN_TAG('E', 'B', 'D', 'T'), 0, 0, 0) != GDI_ERROR;
-}
-
static inline QString stringFromOutLineTextMetric(const OUTLINETEXTMETRIC *otm, PSTR offset)
{
const uchar *p = reinterpret_cast<const uchar *>(otm) + quintptr(offset);
@@ -276,7 +262,7 @@ QWindowsFontEngine::QWindowsFontEngine(const QString &name,
userData.insert(QStringLiteral("trueType"), QVariant(bool(ttf)));
setUserData(userData);
- hasUnreliableOutline = hasGlyfTable() && hasEbdtTable();
+ hasUnreliableOutline = (tm.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) == 0;
}
QWindowsFontEngine::~QWindowsFontEngine()
diff --git a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
index 5119adc0eb..76b45d7a7b 100644
--- a/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
+++ b/src/platformsupport/fontdatabases/windows/qwindowsfontengine_p.h
@@ -138,8 +138,6 @@ private:
QImage::Format mask_format);
bool hasCFFTable() const;
bool hasCMapTable() const;
- bool hasGlyfTable() const;
- bool hasEbdtTable() const;
const QSharedPointer<QWindowsFontEngineData> m_fontEngineData;
diff --git a/src/platformsupport/glxconvenience/qglxconvenience.cpp b/src/platformsupport/glxconvenience/qglxconvenience.cpp
index 8c26550c1e..0c2b757920 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience.cpp
+++ b/src/platformsupport/glxconvenience/qglxconvenience.cpp
@@ -72,7 +72,11 @@ enum {
#undef FontChange
#endif
-QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit)
+#ifndef GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
+#define GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20B2
+#endif
+
+QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit, int flags)
{
QVector<int> spec;
@@ -116,6 +120,10 @@ QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit)
<< GLX_SAMPLES_ARB
<< format.samples();
+ if ((flags & QGLX_SUPPORTS_SRGB) && format.colorSpace() == QSurfaceFormat::sRGBColorSpace)
+ spec << GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB
+ << True;
+
spec << GLX_DRAWABLE_TYPE
<< drawableBit
@@ -175,14 +183,14 @@ template <class T>
using QXlibArrayPointer = QScopedArrayPointer<T, QXlibScopedPointerDeleter<T>>;
}
-GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format, bool highestPixelFormat, int drawableBit)
+GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format, bool highestPixelFormat, int drawableBit, int flags)
{
QXcbSoftwareOpenGLEnforcer softwareOpenGLEnforcer;
GLXFBConfig config = 0;
do {
- const QVector<int> spec = qglx_buildSpec(format, drawableBit);
+ const QVector<int> spec = qglx_buildSpec(format, drawableBit, flags);
int confcount = 0;
QXlibArrayPointer<GLXFBConfig> configs(glXChooseFBConfig(display, screen, spec.constData(), &confcount));
@@ -201,6 +209,13 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format
for (int i = 0; i < confcount; i++) {
GLXFBConfig candidate = configs[i];
+ if ((flags & QGLX_SUPPORTS_SRGB) && format.colorSpace() == QSurfaceFormat::sRGBColorSpace) {
+ int srgbCapable = 0;
+ glXGetFBConfigAttrib(display, candidate, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgbCapable);
+ if (!srgbCapable)
+ continue;
+ }
+
QXlibPointer<XVisualInfo> visual(glXGetVisualFromFBConfig(display, candidate));
const int actualRed = qPopulationCount(visual->red_mask);
@@ -224,28 +239,28 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format
return config;
}
-XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit)
+XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit, int flags)
{
Q_ASSERT(format);
XVisualInfo *visualInfo = 0;
- GLXFBConfig config = qglx_findConfig(display, screen, *format, false, drawableBit);
+ GLXFBConfig config = qglx_findConfig(display, screen, *format, false, drawableBit, flags);
if (config)
visualInfo = glXGetVisualFromFBConfig(display, config);
if (visualInfo) {
- qglx_surfaceFormatFromGLXFBConfig(format, display, config);
+ qglx_surfaceFormatFromGLXFBConfig(format, display, config, flags);
return visualInfo;
}
// attempt to fall back to glXChooseVisual
do {
- QVector<int> attribs = qglx_buildSpec(*format, drawableBit);
+ QVector<int> attribs = qglx_buildSpec(*format, drawableBit, flags);
visualInfo = glXChooseVisual(display, screen, attribs.data());
if (visualInfo) {
- qglx_surfaceFormatFromVisualInfo(format, display, visualInfo);
+ qglx_surfaceFormatFromVisualInfo(format, display, visualInfo, flags);
return visualInfo;
}
} while (qglx_reduceFormat(format));
@@ -253,7 +268,7 @@ XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *f
return visualInfo;
}
-void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config)
+void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, int flags)
{
int redSize = 0;
int greenSize = 0;
@@ -264,6 +279,7 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display,
int sampleBuffers = 0;
int sampleCount = 0;
int stereo = 0;
+ int srgbCapable = 0;
glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize);
glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize);
@@ -273,6 +289,8 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display,
glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize);
glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleBuffers);
glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo);
+ if (flags & QGLX_SUPPORTS_SRGB)
+ glXGetFBConfigAttrib(display, config, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgbCapable);
format->setRedBufferSize(redSize);
format->setGreenBufferSize(greenSize);
@@ -284,11 +302,12 @@ void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display,
glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount);
format->setSamples(sampleCount);
}
+ format->setColorSpace(srgbCapable ? QSurfaceFormat::sRGBColorSpace : QSurfaceFormat::DefaultColorSpace);
format->setStereo(stereo);
}
-void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo)
+void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo, int flags)
{
int redSize = 0;
int greenSize = 0;
@@ -299,6 +318,7 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display,
int sampleBuffers = 0;
int sampleCount = 0;
int stereo = 0;
+ int srgbCapable = 0;
glXGetConfig(display, visualInfo, GLX_RED_SIZE, &redSize);
glXGetConfig(display, visualInfo, GLX_GREEN_SIZE, &greenSize);
@@ -308,6 +328,8 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display,
glXGetConfig(display, visualInfo, GLX_STENCIL_SIZE, &stencilSize);
glXGetConfig(display, visualInfo, GLX_SAMPLES_ARB, &sampleBuffers);
glXGetConfig(display, visualInfo, GLX_STEREO, &stereo);
+ if (flags & QGLX_SUPPORTS_SRGB)
+ glXGetConfig(display, visualInfo, GLX_FRAMEBUFFER_SRGB_CAPABLE_ARB, &srgbCapable);
format->setRedBufferSize(redSize);
format->setGreenBufferSize(greenSize);
@@ -319,6 +341,7 @@ void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display,
glXGetConfig(display, visualInfo, GLX_SAMPLES_ARB, &sampleCount);
format->setSamples(sampleCount);
}
+ format->setColorSpace(srgbCapable ? QSurfaceFormat::sRGBColorSpace : QSurfaceFormat::DefaultColorSpace);
format->setStereo(stereo);
}
@@ -387,5 +410,10 @@ bool qglx_reduceFormat(QSurfaceFormat *format)
return true;
}
+ if (format->colorSpace() == QSurfaceFormat::sRGBColorSpace) {
+ format->setColorSpace(QSurfaceFormat::DefaultColorSpace);
+ return true;
+ }
+
return false;
}
diff --git a/src/platformsupport/glxconvenience/qglxconvenience_p.h b/src/platformsupport/glxconvenience/qglxconvenience_p.h
index d422668584..f9647bfd9a 100644
--- a/src/platformsupport/glxconvenience/qglxconvenience_p.h
+++ b/src/platformsupport/glxconvenience/qglxconvenience_p.h
@@ -57,11 +57,16 @@
#include <X11/Xlib.h>
#include <GL/glx.h>
-QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT);
-XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit = GLX_WINDOW_BIT);
-GLXFBConfig qglx_findConfig(Display *display, int screen, QSurfaceFormat format, bool highestPixelFormat = false, int drawableBit = GLX_WINDOW_BIT);
-void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config);
-void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo);
+enum QGlxFlags
+{
+ QGLX_SUPPORTS_SRGB = 0x01
+};
+
+QVector<int> qglx_buildSpec(const QSurfaceFormat &format, int drawableBit = GLX_WINDOW_BIT, int flags = 0);
+XVisualInfo *qglx_findVisualInfo(Display *display, int screen, QSurfaceFormat *format, int drawableBit = GLX_WINDOW_BIT, int flags = 0);
+GLXFBConfig qglx_findConfig(Display *display, int screen, QSurfaceFormat format, bool highestPixelFormat = false, int drawableBit = GLX_WINDOW_BIT, int flags = 0);
+void qglx_surfaceFormatFromGLXFBConfig(QSurfaceFormat *format, Display *display, GLXFBConfig config, int flags = 0);
+void qglx_surfaceFormatFromVisualInfo(QSurfaceFormat *format, Display *display, XVisualInfo *visualInfo, int flags = 0);
bool qglx_reduceFormat(QSurfaceFormat *format);
#endif // QGLXCONVENIENCE_H
diff --git a/src/platformsupport/graphics/qrasterbackingstore.cpp b/src/platformsupport/graphics/qrasterbackingstore.cpp
index b8d393844c..a3ffe11d19 100644
--- a/src/platformsupport/graphics/qrasterbackingstore.cpp
+++ b/src/platformsupport/graphics/qrasterbackingstore.cpp
@@ -59,20 +59,7 @@ QRasterBackingStore::~QRasterBackingStore()
void QRasterBackingStore::resize(const QSize &size, const QRegion &staticContents)
{
Q_UNUSED(staticContents);
-
- // We can't guarantee that we have a platform-window at this point, so we have
- // to pull out the DPR using QWindow and its QScreen fallback, and then remove
- // the Qt scaling factor.
- qreal nativeWindowDevicePixelRatio = window()->devicePixelRatio() / QHighDpiScaling::factor(window());
- QSize effectiveBufferSize = size * nativeWindowDevicePixelRatio;
-
- if (m_image.size() == effectiveBufferSize)
- return;
-
- m_image = QImage(effectiveBufferSize, format());
- m_image.setDevicePixelRatio(nativeWindowDevicePixelRatio);
- if (m_image.format() == QImage::Format_ARGB32_Premultiplied)
- m_image.fill(Qt::transparent);
+ m_requestedSize = size;
}
QImage::Format QRasterBackingStore::format() const
@@ -111,11 +98,13 @@ bool QRasterBackingStore::scroll(const QRegion &region, int dx, int dy)
void QRasterBackingStore::beginPaint(const QRegion &region)
{
- // Keep backing store device pixel ratio in sync with window
qreal nativeWindowDevicePixelRatio = window()->handle()->devicePixelRatio();
- if (m_image.devicePixelRatio() != nativeWindowDevicePixelRatio) {
- const QSize nativeSize = QHighDpi::toNativePixels(backingStore()->size(), window());
- resize(nativeSize, backingStore()->staticContents());
+ QSize effectiveBufferSize = m_requestedSize * nativeWindowDevicePixelRatio;
+ if (m_image.devicePixelRatio() != nativeWindowDevicePixelRatio || m_image.size() != effectiveBufferSize) {
+ m_image = QImage(effectiveBufferSize, format());
+ m_image.setDevicePixelRatio(nativeWindowDevicePixelRatio);
+ if (m_image.format() == QImage::Format_ARGB32_Premultiplied)
+ m_image.fill(Qt::transparent);
}
if (!m_image.hasAlphaChannel())
@@ -123,9 +112,8 @@ void QRasterBackingStore::beginPaint(const QRegion &region)
QPainter painter(&m_image);
painter.setCompositionMode(QPainter::CompositionMode_Source);
- const QColor blank = Qt::transparent;
for (const QRect &rect : region)
- painter.fillRect(rect, blank);
+ painter.fillRect(rect, Qt::transparent);
}
QT_END_NAMESPACE
diff --git a/src/platformsupport/graphics/qrasterbackingstore_p.h b/src/platformsupport/graphics/qrasterbackingstore_p.h
index 55976d2ceb..2764fd6432 100644
--- a/src/platformsupport/graphics/qrasterbackingstore_p.h
+++ b/src/platformsupport/graphics/qrasterbackingstore_p.h
@@ -73,6 +73,7 @@ protected:
virtual QImage::Format format() const;
QImage m_image;
+ QSize m_requestedSize;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
index 9b4bcf1575..562e7e2821 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp
@@ -236,6 +236,7 @@ void QEvdevMouseHandler::readMouseData()
posChanged = true;
}
} else if (data->type == EV_REL) {
+ QPoint delta;
if (data->code == REL_X) {
m_x += data->value;
posChanged = true;
@@ -244,12 +245,18 @@ void QEvdevMouseHandler::readMouseData()
posChanged = true;
} else if (data->code == ABS_WHEEL) { // vertical scroll
// data->value: 1 == up, -1 == down
- const int delta = 120 * data->value;
- emit handleWheelEvent(delta, Qt::Vertical);
+ if (data->value == 1)
+ delta.setY(120);
+ else
+ delta.setY(-120);
+ emit handleWheelEvent(delta);
} else if (data->code == ABS_THROTTLE) { // horizontal scroll
// data->value: 1 == right, -1 == left
- const int delta = 120 * -data->value;
- emit handleWheelEvent(delta, Qt::Horizontal);
+ if (data->value == 1)
+ delta.setX(-120);
+ else
+ delta.setX(120);
+ emit handleWheelEvent(delta);
}
} else if (data->type == EV_KEY && data->code == BTN_TOUCH) {
// We care about touchpads only, not touchscreens -> don't map to button press.
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
index eb34334b12..79156645da 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler_p.h
@@ -53,6 +53,7 @@
#include <QObject>
#include <QString>
+#include <QPoint>
QT_BEGIN_NAMESPACE
@@ -67,7 +68,7 @@ public:
signals:
void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons);
- void handleWheelEvent(int delta, Qt::Orientation orientation);
+ void handleWheelEvent(QPoint delta);
private slots:
void readMouseData();
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
index b2f3fe5787..6264e4ada2 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp
@@ -144,10 +144,10 @@ void QEvdevMouseManager::handleMouseEvent(int x, int y, bool abs, Qt::MouseButto
QWindowSystemInterface::handleMouseEvent(0, pos, pos, buttons, QGuiApplication::keyboardModifiers());
}
-void QEvdevMouseManager::handleWheelEvent(int delta, Qt::Orientation orientation)
+void QEvdevMouseManager::handleWheelEvent(QPoint delta)
{
QPoint pos(m_x + m_xoffset, m_y + m_yoffset);
- QWindowSystemInterface::handleWheelEvent(0, pos, pos, delta, orientation, QGuiApplication::keyboardModifiers());
+ QWindowSystemInterface::handleWheelEvent(0, pos, pos, QPoint(), delta, QGuiApplication::keyboardModifiers());
}
void QEvdevMouseManager::addMouse(const QString &deviceNode)
@@ -157,7 +157,7 @@ void QEvdevMouseManager::addMouse(const QString &deviceNode)
handler = QEvdevMouseHandler::create(deviceNode, m_spec);
if (handler) {
connect(handler, SIGNAL(handleMouseEvent(int,int,bool,Qt::MouseButtons)), this, SLOT(handleMouseEvent(int,int,bool,Qt::MouseButtons)));
- connect(handler, SIGNAL(handleWheelEvent(int,Qt::Orientation)), this, SLOT(handleWheelEvent(int,Qt::Orientation)));
+ connect(handler, SIGNAL(handleWheelEvent(QPoint)), this, SLOT(handleWheelEvent(QPoint)));
m_mice.insert(deviceNode, handler);
QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
QInputDeviceManager::DeviceTypePointer, m_mice.count());
diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
index 08b5409d31..7cabfac0d8 100644
--- a/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
+++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager_p.h
@@ -56,6 +56,7 @@
#include <QObject>
#include <QHash>
#include <QSocketNotifier>
+#include <QPoint>
QT_BEGIN_NAMESPACE
@@ -70,7 +71,7 @@ public:
public slots:
void handleMouseEvent(int x, int y, bool abs, Qt::MouseButtons buttons);
- void handleWheelEvent(int delta, Qt::Orientation orientation);
+ void handleWheelEvent(QPoint delta);
private slots:
void addMouse(const QString &deviceNode = QString());
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
index 11f7311bb7..8cce403b31 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
@@ -883,7 +883,7 @@ void QEvdevTouchScreenHandlerThread::filterAndSendTouchPoints()
}
QList<QWindowSystemInterface::TouchPoint> points = m_handler->d->m_touchPoints;
- const QList<QWindowSystemInterface::TouchPoint> &lastPoints = m_handler->d->m_lastTouchPoints;
+ QList<QWindowSystemInterface::TouchPoint> lastPoints = m_handler->d->m_lastTouchPoints;
m_handler->d->m_mutex.unlock();
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
index 669abab331..71b7633e6c 100644
--- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp
+++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -330,11 +330,13 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
crtc_id,
physSize,
selected_mode,
+ selected_mode,
false,
drmModeGetCrtc(m_dri_fd, crtc_id),
modes,
connector->subpixel,
connectorProperty(connector, QByteArrayLiteral("DPMS")),
+ connectorPropertyBlob(connector, QByteArrayLiteral("EDID")),
false,
0,
false
@@ -382,6 +384,23 @@ drmModePropertyPtr QKmsDevice::connectorProperty(drmModeConnectorPtr connector,
return Q_NULLPTR;
}
+drmModePropertyBlobPtr QKmsDevice::connectorPropertyBlob(drmModeConnectorPtr connector, const QByteArray &name)
+{
+ drmModePropertyPtr prop;
+ drmModePropertyBlobPtr blob = nullptr;
+
+ for (int i = 0; i < connector->count_props && !blob; i++) {
+ prop = drmModeGetProperty(m_dri_fd, connector->props[i]);
+ if (!prop)
+ continue;
+ if ((prop->flags & DRM_MODE_PROP_BLOB) && (strcmp(prop->name, name.constData()) == 0))
+ blob = drmModeGetPropertyBlob(m_dri_fd, connector->prop_values[i]);
+ drmModeFreeProperty(prop);
+ }
+
+ return blob;
+}
+
QKmsDevice::QKmsDevice(QKmsScreenConfig *screenConfig, const QString &path)
: m_screenConfig(screenConfig)
, m_path(path)
@@ -626,6 +645,11 @@ void QKmsOutput::cleanup(QKmsDevice *device)
dpms_prop = nullptr;
}
+ if (edid_blob) {
+ drmModeFreePropertyBlob(edid_blob);
+ edid_blob = nullptr;
+ }
+
restoreMode(device);
if (saved_crtc) {
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice_p.h b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
index 35a51c18b1..964a0b1775 100644
--- a/src/platformsupport/kmsconvenience/qkmsdevice_p.h
+++ b/src/platformsupport/kmsconvenience/qkmsdevice_p.h
@@ -100,12 +100,14 @@ struct QKmsOutput
uint32_t connector_id;
uint32_t crtc_id;
QSizeF physical_size;
+ int preferred_mode; // index of preferred mode in list below
int mode; // index of selected mode in list below
bool mode_set;
drmModeCrtcPtr saved_crtc;
QList<drmModeModeInfo> modes;
int subpixel;
drmModePropertyPtr dpms_prop;
+ drmModePropertyBlobPtr edid_blob;
bool wants_plane;
uint32_t plane_id;
bool plane_set;
@@ -153,6 +155,7 @@ protected:
drmModeConnectorPtr connector,
VirtualDesktopInfo *vinfo);
drmModePropertyPtr connectorProperty(drmModeConnectorPtr connector, const QByteArray &name);
+ drmModePropertyBlobPtr connectorPropertyBlob(drmModeConnectorPtr connector, const QByteArray &name);
QKmsScreenConfig *m_screenConfig;
QString m_path;
diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
index 6561e95a0d..a936ec7aad 100644
--- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
+++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp
@@ -45,7 +45,7 @@
#include <qdbusreply.h>
#include <qclipboard.h>
-#include <qdebug.h>
+#include <QtCore/qloggingcategory.h>
#ifndef QT_NO_ACCESSIBILITY
#include "socket_interface.h"
@@ -65,8 +65,8 @@
QT_BEGIN_NAMESPACE
-static bool isDebugging = false;
-#define qAtspiDebug if (!::isDebugging); else qDebug
+Q_LOGGING_CATEGORY(lcAccessibilityAtspi, "qt.accessibility.atspi")
+Q_LOGGING_CATEGORY(lcAccessibilityAtspiCreation, "qt.accessibility.atspi.creation")
AtSpiAdaptor::AtSpiAdaptor(DBusConnection *connection, QObject *parent)
: QDBusVirtualObject(parent), m_dbus(connection)
@@ -128,8 +128,6 @@ AtSpiAdaptor::AtSpiAdaptor(DBusConnection *connection, QObject *parent)
, sendWindow_shade(0)
, sendWindow_unshade(0)
{
- ::isDebugging = qEnvironmentVariableIsSet("QT_DEBUG_ACCESSIBILITY");
-
m_applicationAdaptor = new QSpiApplicationAdaptor(m_dbus->connection(), this);
connect(m_applicationAdaptor, SIGNAL(windowActivated(QObject*,bool)), this, SLOT(windowActivated(QObject*,bool)));
@@ -140,9 +138,6 @@ AtSpiAdaptor::AtSpiAdaptor(DBusConnection *connection, QObject *parent)
success = success && m_dbus->connection().connect(QLatin1String("org.a11y.atspi.Registry"), QLatin1String("/org/a11y/atspi/registry"),
QLatin1String("org.a11y.atspi.Registry"), QLatin1String("EventListenerDeregistered"), this,
SLOT(eventListenerDeregistered(QString,QString)));
-#ifdef QT_ATSPI_DEBUG
- qAtspiDebug() << "Registered event listener change listener: " << success;
-#endif
}
AtSpiAdaptor::~AtSpiAdaptor()
@@ -589,7 +584,7 @@ QString AtSpiAdaptor::introspect(const QString &path) const
QAccessibleInterface * interface = interfaceFromPath(path);
if (!interface) {
- qAtspiDebug() << "WARNING Qt AtSpiAdaptor: Could not find accessible on path: " << path;
+ qCDebug(lcAccessibilityAtspi) << "WARNING Qt AtSpiAdaptor: Could not find accessible on path: " << path;
return QString();
}
@@ -698,7 +693,7 @@ void AtSpiAdaptor::setBitFlag(const QString &flag)
|| right.startsWith(QLatin1String("VisibledataChanged"))) { // typo in libatspi
sendObject_visible_data_changed = 1;
} else {
- qAtspiDebug() << "WARNING: subscription string not handled:" << flag;
+ qCDebug(lcAccessibilityAtspi) << "WARNING: subscription string not handled:" << flag;
}
}
break;
@@ -744,7 +739,7 @@ void AtSpiAdaptor::setBitFlag(const QString &flag)
} else if (right.startsWith(QLatin1String("DesktopDestroy"))) {
// ignore this one
} else {
- qAtspiDebug() << "WARNING: subscription string not handled:" << flag;
+ qCDebug(lcAccessibilityAtspi) << "WARNING: subscription string not handled:" << flag;
}
}
break;
@@ -763,7 +758,7 @@ void AtSpiAdaptor::setBitFlag(const QString &flag)
break;
}
default:
- qAtspiDebug() << "WARNING: subscription string not handled:" << flag;
+ qCDebug(lcAccessibilityAtspi) << "WARNING: subscription string not handled:" << flag;
}
}
@@ -782,19 +777,19 @@ void AtSpiAdaptor::updateEventListeners()
setBitFlag(ev.eventName);
m_applicationAdaptor->sendEvents(!evList.isEmpty());
} else {
- qAtspiDebug("Could not query active accessibility event listeners.");
+ qCDebug(lcAccessibilityAtspi) << "Could not query active accessibility event listeners.";
}
}
void AtSpiAdaptor::eventListenerDeregistered(const QString &/*bus*/, const QString &/*path*/)
{
-// qAtspiDebug() << "AtSpiAdaptor::eventListenerDeregistered: " << bus << path;
+// qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::eventListenerDeregistered: " << bus << path;
updateEventListeners();
}
void AtSpiAdaptor::eventListenerRegistered(const QString &/*bus*/, const QString &/*path*/)
{
-// qAtspiDebug() << "AtSpiAdaptor::eventListenerRegistered: " << bus << path;
+// qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::eventListenerRegistered: " << bus << path;
updateEventListeners();
}
@@ -859,7 +854,7 @@ QAccessibleInterface *AtSpiAdaptor::interfaceFromPath(const QString& dbusPath) c
QStringList parts = dbusPath.split(QLatin1Char('/'));
if (parts.size() != 6) {
- qAtspiDebug() << "invalid path: " << dbusPath;
+ qCDebug(lcAccessibilityAtspi) << "invalid path: " << dbusPath;
return 0;
}
@@ -868,7 +863,7 @@ QAccessibleInterface *AtSpiAdaptor::interfaceFromPath(const QString& dbusPath) c
// The id is always in the range [INT_MAX+1, UINT_MAX]
if ((int)id >= 0)
- qWarning() << "No accessible object found for id: " << id;
+ qCWarning(lcAccessibilityAtspi) << "No accessible object found for id: " << id;
return QAccessible::accessibleInterface(id);
}
@@ -943,7 +938,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
if (sendObject || sendObject_text_changed) {
QAccessibleInterface * iface = event->accessibleInterface();
if (!iface || !iface->textInterface()) {
- qAtspiDebug("Received text event for invalid interface.");
+ qCDebug(lcAccessibilityAtspi) << "Received text event for invalid interface.";
return;
}
QString path = pathForInterface(iface);
@@ -1001,7 +996,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
if (sendObject || sendObject_text_caret_moved) {
QAccessibleInterface * iface = event->accessibleInterface();
if (!iface || !iface->textInterface()) {
- qWarning() << "Sending TextCaretMoved from object that does not implement text interface: " << iface;
+ qCWarning(lcAccessibilityAtspi) << "Sending TextCaretMoved from object that does not implement text interface: " << iface;
return;
}
@@ -1029,7 +1024,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
if (sendObject || sendObject_value_changed || sendObject_property_change_accessible_value) {
QAccessibleInterface * iface = event->accessibleInterface();
if (!iface) {
- qWarning("ValueChanged event from invalid accessible.");
+ qCWarning(lcAccessibilityAtspi) << "ValueChanged event from invalid accessible.";
return;
}
if (iface->valueInterface()) {
@@ -1048,7 +1043,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
sendDBusSignal(path, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT),
QLatin1String("SelectionChanged"), args2);
} else {
- qWarning() << "ValueChanged event and no ValueInterface or ComboBox: " << iface;
+ qCWarning(lcAccessibilityAtspi) << "ValueChanged event and no ValueInterface or ComboBox: " << iface;
}
}
break;
@@ -1058,7 +1053,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
case QAccessible::Selection: {
QAccessibleInterface * iface = event->accessibleInterface();
if (!iface) {
- qWarning("Selection event from invalid accessible.");
+ qCWarning(lcAccessibilityAtspi) << "Selection event from invalid accessible.";
return;
}
QString path = pathForInterface(iface);
@@ -1075,7 +1070,7 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
if (stateChange.checked) {
QAccessibleInterface * iface = event->accessibleInterface();
if (!iface) {
- qWarning("StateChanged event from invalid accessible.");
+ qCWarning(lcAccessibilityAtspi) << "StateChanged event from invalid accessible.";
return;
}
int checked = iface->state().checked;
@@ -1206,7 +1201,7 @@ void AtSpiAdaptor::notifyAboutCreation(QAccessibleInterface *interface) const
// notify about the new child of our parent
QAccessibleInterface * parent = interface->parent();
if (!parent) {
- qAtspiDebug() << "AtSpiAdaptor::notifyAboutCreation: Could not find parent for " << interface->object();
+ qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::notifyAboutCreation: Could not find parent for " << interface->object();
return;
}
QString path = pathForInterface(interface);
@@ -1223,7 +1218,7 @@ void AtSpiAdaptor::notifyAboutDestruction(QAccessibleInterface *interface) const
QAccessibleInterface * parent = interface->parent();
if (!parent) {
- qAtspiDebug() << "AtSpiAdaptor::notifyAboutDestruction: Could not find parent for " << interface->object();
+ qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::notifyAboutDestruction: Could not find parent for " << interface->object();
return;
}
QString path = pathForInterface(interface);
@@ -1251,18 +1246,18 @@ bool AtSpiAdaptor::handleMessage(const QDBusMessage &message, const QDBusConnect
// get accessible interface
QAccessibleInterface * accessible = interfaceFromPath(message.path());
if (!accessible) {
- qAtspiDebug() << "WARNING Qt AtSpiAdaptor: Could not find accessible on path: " << message.path();
+ qCDebug(lcAccessibilityAtspi) << "WARNING Qt AtSpiAdaptor: Could not find accessible on path: " << message.path();
return false;
}
if (!accessible->isValid()) {
- qWarning() << "WARNING Qt AtSpiAdaptor: Accessible invalid: " << accessible << message.path();
+ qCWarning(lcAccessibilityAtspi) << "WARNING Qt AtSpiAdaptor: Accessible invalid: " << accessible << message.path();
return false;
}
QString interface = message.interface();
QString function = message.member();
- // qAtspiDebug() << "AtSpiAdaptor::handleMessage: " << interface << function;
+ // qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::handleMessage: " << interface << function;
if (function == QLatin1String("Introspect")) {
//introspect(message.path());
@@ -1294,7 +1289,7 @@ bool AtSpiAdaptor::handleMessage(const QDBusMessage &message, const QDBusConnect
if (interface == QLatin1String(ATSPI_DBUS_INTERFACE_TABLE))
return tableInterface(accessible, function, message, connection);
- qAtspiDebug() << "AtSpiAdaptor::handleMessage with unknown interface: " << message.path() << interface << function;
+ qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::handleMessage with unknown interface: " << message.path() << interface << function;
return false;
}
@@ -1302,7 +1297,7 @@ bool AtSpiAdaptor::handleMessage(const QDBusMessage &message, const QDBusConnect
bool AtSpiAdaptor::applicationInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
{
if (message.path() != QLatin1String(ATSPI_DBUS_PATH_ROOT)) {
- qAtspiDebug() << "WARNING Qt AtSpiAdaptor: Could not find application interface for: " << message.path() << interface;
+ qCDebug(lcAccessibilityAtspi) << "WARNING Qt AtSpiAdaptor: Could not find application interface for: " << message.path() << interface;
return false;
}
@@ -1333,7 +1328,7 @@ bool AtSpiAdaptor::applicationInterface(QAccessibleInterface *interface, const Q
QDBusMessage reply = message.createReply(QVariant::fromValue(QLocale().name()));
return connection.send(reply);
}
- qAtspiDebug() << "AtSpiAdaptor::applicationInterface " << message.path() << interface << function;
+ qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::applicationInterface " << message.path() << interface << function;
return false;
}
@@ -1354,7 +1349,7 @@ void AtSpiAdaptor::registerApplication()
const QSpiObjectReference &socket = reply.value();
accessibilityRegistry = QSpiObjectReference(socket);
} else {
- qAtspiDebug() << "Error in contacting registry: "
+ qCDebug(lcAccessibilityAtspi) << "Error in contacting registry: "
<< reply.error().name()
<< reply.error().message();
}
@@ -1380,7 +1375,7 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
if (parent) {
childIndex = parent->indexOfChild(interface);
if (childIndex < 0) {
- qAtspiDebug() << "GetIndexInParent get invalid index: " << childIndex << interface;
+ qCDebug(lcAccessibilityAtspi) << "GetIndexInParent get invalid index: " << childIndex << interface;
}
}
sendReply(connection, message, childIndex);
@@ -1445,7 +1440,7 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
}
connection.send(message.createReply(QVariant::fromValue(children)));
} else {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::accessibleInterface does not implement " << function << message.path();
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::accessibleInterface does not implement " << function << message.path();
return false;
}
return true;
@@ -1458,14 +1453,10 @@ AtspiRole AtSpiAdaptor::getRole(QAccessibleInterface *interface) const
return qSpiRoleMapping[interface->role()].spiRole();
}
-//#define ACCESSIBLE_CREATION_DEBUG
-
QStringList AtSpiAdaptor::accessibleInterfaces(QAccessibleInterface *interface) const
{
QStringList ifaces;
-#ifdef ACCESSIBLE_CREATION_DEBUG
- qAtspiDebug() << "AtSpiAdaptor::accessibleInterfaces create: " << interface->object();
-#endif
+ qCDebug(lcAccessibilityAtspiCreation) << "AtSpiAdaptor::accessibleInterfaces create: " << interface->object();
ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_ACCESSIBLE);
if ( (!interface->rect().isEmpty()) ||
@@ -1477,12 +1468,9 @@ QStringList AtSpiAdaptor::accessibleInterfaces(QAccessibleInterface *interface)
(interface->object() && interface->object()->inherits("QSGItem"))
) {
ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_COMPONENT);
- }
-#ifdef ACCESSIBLE_CREATION_DEBUG
- else {
- qAtspiDebug(" IS NOT a component");
+ } else {
+ qCDebug(lcAccessibilityAtspiCreation) << " IS NOT a component";
}
-#endif
if (interface->role() == QAccessible::Application)
ifaces << QLatin1String(ATSPI_DBUS_INTERFACE_APPLICATION);
@@ -1536,7 +1524,7 @@ QString AtSpiAdaptor::pathForObject(QObject *object) const
Q_ASSERT(object);
if (inheritsQAction(object)) {
- qAtspiDebug("AtSpiAdaptor::pathForObject: warning: creating path with QAction as object.");
+ qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::pathForObject: warning: creating path with QAction as object.";
}
QAccessibleInterface *iface = QAccessible::queryAccessibleInterface(object);
@@ -1667,21 +1655,21 @@ bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QSt
// int width = message.arguments().at(2).toInt();
// int height = message.arguments().at(3).toInt();
// uint coordinateType = message.arguments().at(4).toUInt();
- qAtspiDebug("SetExtents is not implemented.");
+ qCDebug(lcAccessibilityAtspi) << "SetExtents is not implemented.";
sendReply(connection, message, false);
} else if (function == QLatin1String("SetPosition")) {
// int x = message.arguments().at(0).toInt();
// int y = message.arguments().at(1).toInt();
// uint coordinateType = message.arguments().at(2).toUInt();
- qAtspiDebug("SetPosition is not implemented.");
+ qCDebug(lcAccessibilityAtspi) << "SetPosition is not implemented.";
sendReply(connection, message, false);
} else if (function == QLatin1String("SetSize")) {
// int width = message.arguments().at(0).toInt();
// int height = message.arguments().at(1).toInt();
- qAtspiDebug("SetSize is not implemented.");
+ qCDebug(lcAccessibilityAtspi) << "SetSize is not implemented.";
sendReply(connection, message, false);
} else {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::componentInterface does not implement " << function << message.path();
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::componentInterface does not implement " << function << message.path();
return false;
}
return true;
@@ -1743,7 +1731,7 @@ bool AtSpiAdaptor::actionInterface(QAccessibleInterface *interface, const QStrin
else
sendReply(connection, message, QString());
} else {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::actionInterface does not implement " << function << message.path();
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::actionInterface does not implement " << function << message.path();
return false;
}
return true;
@@ -1815,7 +1803,7 @@ bool AtSpiAdaptor::textInterface(QAccessibleInterface *interface, const QString
Q_UNUSED(x) Q_UNUSED (y) Q_UNUSED(width)
Q_UNUSED(height) Q_UNUSED(coordType)
Q_UNUSED(xClipType) Q_UNUSED(yClipType)
- qAtspiDebug("Not implemented: QSpiAdaptor::GetBoundedRanges");
+ qCDebug(lcAccessibilityAtspi) << "Not implemented: QSpiAdaptor::GetBoundedRanges";
sendReply(connection, message, QVariant::fromValue(QSpiTextRangeList()));
} else if (function == QLatin1String("GetCharacterAtOffset")) {
int offset = message.arguments().at(0).toInt();
@@ -1834,7 +1822,7 @@ bool AtSpiAdaptor::textInterface(QAccessibleInterface *interface, const QString
} else if (function == QLatin1String("GetNSelections")) {
sendReply(connection, message, interface->textInterface()->selectionCount());
} else if (function == QLatin1String("GetOffsetAtPoint")) {
- qAtspiDebug() << message.signature();
+ qCDebug(lcAccessibilityAtspi) << message.signature();
Q_ASSERT(!message.signature().isEmpty());
QPoint point(message.arguments().at(0).toInt(), message.arguments().at(1).toInt());
uint coordType = message.arguments().at(2).toUInt();
@@ -1903,7 +1891,7 @@ bool AtSpiAdaptor::textInterface(QAccessibleInterface *interface, const QString
interface->textInterface()->setSelection(selectionNum, startOffset, endOffset);
sendReply(connection, message, true);
} else {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::textInterface does not implement " << function << message.path();
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::textInterface does not implement " << function << message.path();
return false;
}
return true;
@@ -1979,7 +1967,7 @@ namespace
value != QLatin1String("center")
) {
value = QString();
- qAtspiDebug() << "Unknown text-align attribute value \"" << value << "\" cannot be translated to AT-SPI.";
+ qCDebug(lcAccessibilityAtspi) << "Unknown text-align attribute value \"" << value << "\" cannot be translated to AT-SPI.";
}
}
} else if (ia2Name == QLatin1String("font-size")) {
@@ -1992,7 +1980,7 @@ namespace
value != QLatin1String("oblique")
) {
value = QString();
- qAtspiDebug() << "Unknown font-style attribute value \"" << value << "\" cannot be translated to AT-SPI.";
+ qCDebug(lcAccessibilityAtspi) << "Unknown font-style attribute value \"" << value << "\" cannot be translated to AT-SPI.";
}
} else if (ia2Name == QLatin1String("text-underline-type")) {
name = QStringLiteral("underline");
@@ -2001,7 +1989,7 @@ namespace
value != QLatin1String("double")
) {
value = QString();
- qAtspiDebug() << "Unknown text-underline-type attribute value \"" << value << "\" cannot be translated to AT-SPI.";
+ qCDebug(lcAccessibilityAtspi) << "Unknown text-underline-type attribute value \"" << value << "\" cannot be translated to AT-SPI.";
}
} else if (ia2Name == QLatin1String("font-weight")) {
name = QStringLiteral("weight");
@@ -2017,7 +2005,7 @@ namespace
value != QLatin1String("sub")
) {
value = QString();
- qAtspiDebug() << "Unknown text-position attribute value \"" << value << "\" cannot be translated to AT-SPI.";
+ qCDebug(lcAccessibilityAtspi) << "Unknown text-position attribute value \"" << value << "\" cannot be translated to AT-SPI.";
}
} else if (ia2Name == QLatin1String("writing-mode")) {
name = QStringLiteral("direction");
@@ -2028,10 +2016,10 @@ namespace
else if (value == QLatin1String("tb")) {
// IAccessible2 docs refer to XSL, which specifies "tb" is shorthand for "tb-rl"; so at least give a hint about the horizontal direction (ATK does not support vertical direction in this attribute (yet))
value = QStringLiteral("rtl");
- qAtspiDebug() << "writing-mode attribute value \"tb\" translated only w.r.t. horizontal direction; vertical direction ignored";
+ qCDebug(lcAccessibilityAtspi) << "writing-mode attribute value \"tb\" translated only w.r.t. horizontal direction; vertical direction ignored";
} else {
value = QString();
- qAtspiDebug() << "Unknown writing-mode attribute value \"" << value << "\" cannot be translated to AT-SPI.";
+ qCDebug(lcAccessibilityAtspi) << "Unknown writing-mode attribute value \"" << value << "\" cannot be translated to AT-SPI.";
}
} else if (ia2Name == QLatin1String("language")) {
// OK - ATK has no docs on the format of the value, IAccessible2 has reasonable format - leave it at that now
@@ -2223,7 +2211,7 @@ bool AtSpiAdaptor::editableTextInterface(QAccessibleInterface *interface, const
} else if (function == QLatin1String("")) {
connection.send(message.createReply());
} else {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::editableTextInterface does not implement " << function << message.path();
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::editableTextInterface does not implement " << function << message.path();
return false;
}
return true;
@@ -2254,11 +2242,11 @@ bool AtSpiAdaptor::valueInterface(QAccessibleInterface *interface, const QString
else if (function == QLatin1String("GetMinimumValue"))
value = valueIface->minimumValue();
else {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::valueInterface does not implement " << function << message.path();
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::valueInterface does not implement " << function << message.path();
return false;
}
if (!value.canConvert(QVariant::Double)) {
- qAtspiDebug() << "AtSpiAdaptor::valueInterface: Could not convert to double: " << function;
+ qCDebug(lcAccessibilityAtspi) << "AtSpiAdaptor::valueInterface: Could not convert to double: " << function;
}
// explicitly convert to dbus-variant containing one double since atspi expects that
@@ -2273,7 +2261,7 @@ bool AtSpiAdaptor::valueInterface(QAccessibleInterface *interface, const QString
bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
{
if (!(interface->tableInterface() || interface->tableCellInterface())) {
- qAtspiDebug() << "WARNING Qt AtSpiAdaptor: Could not find table interface for: " << message.path() << interface;
+ qCDebug(lcAccessibilityAtspi) << "WARNING Qt AtSpiAdaptor: Could not find table interface for: " << message.path() << interface;
return false;
}
@@ -2311,7 +2299,7 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
(column < 0) ||
(row >= interface->tableInterface()->rowCount()) ||
(column >= interface->tableInterface()->columnCount())) {
- qAtspiDebug() << "WARNING: invalid index for tableInterface GetAccessibleAt (" << row << ", " << column << ')';
+ qCDebug(lcAccessibilityAtspi) << "WARNING: invalid index for tableInterface GetAccessibleAt (" << row << ", " << column << ')';
return false;
}
@@ -2320,7 +2308,7 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
if (cell) {
ref = QSpiObjectReference(connection, QDBusObjectPath(pathForInterface(cell)));
} else {
- qAtspiDebug() << "WARNING: no cell interface returned for " << interface->object() << row << column;
+ qCDebug(lcAccessibilityAtspi) << "WARNING: no cell interface returned for " << interface->object() << row << column;
ref = QSpiObjectReference();
}
connection.send(message.createReply(QVariant::fromValue(ref)));
@@ -2330,11 +2318,11 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
int column = message.arguments().at(1).toInt();
QAccessibleInterface *cell = interface->tableInterface()->cellAt(row, column);
if (!cell) {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::GetIndexAt(" << row << ',' << column << ") did not find a cell. " << interface;
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::GetIndexAt(" << row << ',' << column << ") did not find a cell. " << interface;
return false;
}
int index = interface->indexOfChild(cell);
- qAtspiDebug() << "QSpiAdaptor::GetIndexAt row:" << row << " col:" << column << " logical index:" << index;
+ qCDebug(lcAccessibilityAtspi) << "QSpiAdaptor::GetIndexAt row:" << row << " col:" << column << " logical index:" << index;
Q_ASSERT(index > 0);
connection.send(message.createReply(index));
} else if ((function == QLatin1String("GetColumnAtIndex")) || (function == QLatin1String("GetRowAtIndex"))) {
@@ -2350,7 +2338,7 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
ret = -1;
} else {
if (!cell->tableCellInterface()) {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::" << function << " No table cell interface: " << cell;
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::" << function << " No table cell interface: " << cell;
return false;
}
ret = cell->tableCellInterface()->columnIndex();
@@ -2362,14 +2350,14 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
ret = index % interface->tableInterface()->columnCount();
} else {
if (!cell->tableCellInterface()) {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::" << function << " No table cell interface: " << cell;
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::" << function << " No table cell interface: " << cell;
return false;
}
ret = cell->tableCellInterface()->rowIndex();
}
}
} else {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::" << function << " No cell at index: " << index << interface;
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::" << function << " No cell at index: " << index << interface;
return false;
}
}
@@ -2475,7 +2463,7 @@ bool AtSpiAdaptor::tableInterface(QAccessibleInterface *interface, const QString
int row = message.arguments().at(0).toInt();
connection.send(message.createReply(interface->tableInterface()->unselectRow(row)));
} else {
- qAtspiDebug() << "WARNING: AtSpiAdaptor::tableInterface does not implement " << function << message.path();
+ qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::tableInterface does not implement " << function << message.path();
return false;
}
return true;
diff --git a/src/platformsupport/platformsupport.pro b/src/platformsupport/platformsupport.pro
index 7db6de78b4..248c1ae667 100644
--- a/src/platformsupport/platformsupport.pro
+++ b/src/platformsupport/platformsupport.pro
@@ -2,6 +2,7 @@ TEMPLATE = subdirs
QT_FOR_CONFIG += gui-private
SUBDIRS = \
+ edid \
eventdispatchers \
devicediscovery \
fbconvenience \
@@ -42,3 +43,6 @@ darwin {
macos: \
SUBDIRS += cglconvenience
}
+
+qtConfig(vulkan): \
+ SUBDIRS += vkconvenience
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu.cpp b/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu.cpp
index 4b099e5c0e..51c690d43a 100644
--- a/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu.cpp
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu.cpp
@@ -50,9 +50,8 @@ Q_LOGGING_CATEGORY(qLcMenu, "qt.qpa.menu")
static int nextDBusID = 1;
QHash<int, QDBusPlatformMenuItem *> menuItemsByID;
-QDBusPlatformMenuItem::QDBusPlatformMenuItem(quintptr tag)
- : m_tag(tag ? tag : reinterpret_cast<quintptr>(this)) // QMenu will overwrite this later
- , m_subMenu(Q_NULLPTR)
+QDBusPlatformMenuItem::QDBusPlatformMenuItem()
+ : m_subMenu(nullptr)
, m_role(NoRole)
, m_isEnabled(true)
, m_isVisible(true)
@@ -72,11 +71,6 @@ QDBusPlatformMenuItem::~QDBusPlatformMenuItem()
static_cast<QDBusPlatformMenu *>(m_subMenu)->setContainingMenuItem(Q_NULLPTR);
}
-void QDBusPlatformMenuItem::setTag(quintptr tag)
-{
- m_tag = tag;
-}
-
void QDBusPlatformMenuItem::setText(const QString &text)
{
qCDebug(qLcMenu) << m_dbusID << text;
@@ -167,9 +161,8 @@ QList<const QDBusPlatformMenuItem *> QDBusPlatformMenuItem::byIds(const QList<in
}
-QDBusPlatformMenu::QDBusPlatformMenu(quintptr tag)
- : m_tag(tag ? tag : reinterpret_cast<quintptr>(this))
- , m_isEnabled(true)
+QDBusPlatformMenu::QDBusPlatformMenu()
+ : m_isEnabled(true)
, m_isVisible(true)
, m_revision(1)
, m_containingMenuItem(Q_NULLPTR)
@@ -252,11 +245,6 @@ void QDBusPlatformMenu::emitUpdated()
emit updated(++m_revision, 0);
}
-void QDBusPlatformMenu::setTag(quintptr tag)
-{
- m_tag = tag;
-}
-
void QDBusPlatformMenu::setText(const QString &text)
{
m_text = text;
diff --git a/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h b/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h
index 49b7316d11..5458e2fdd5 100644
--- a/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h
+++ b/src/platformsupport/themes/genericunix/dbusmenu/qdbusplatformmenu_p.h
@@ -73,12 +73,9 @@ class QDBusPlatformMenuItem : public QPlatformMenuItem
Q_OBJECT
public:
- QDBusPlatformMenuItem(quintptr tag = 0LL);
+ QDBusPlatformMenuItem();
~QDBusPlatformMenuItem();
- quintptr tag()const Q_DECL_OVERRIDE { return m_tag; }
- void setTag(quintptr tag) Q_DECL_OVERRIDE;
-
const QString text() const { return m_text; }
void setText(const QString &text) Q_DECL_OVERRIDE;
QIcon icon() const { return m_icon; }
@@ -110,13 +107,10 @@ public:
void trigger();
- bool operator==(const QDBusPlatformMenuItem& other) { return m_tag == other.m_tag; }
-
static QDBusPlatformMenuItem *byId(int id);
static QList<const QDBusPlatformMenuItem *> byIds(const QList<int> &ids);
private:
- quintptr m_tag;
QString m_text;
QIcon m_icon;
QPlatformMenu *m_subMenu;
@@ -137,7 +131,7 @@ class QDBusPlatformMenu : public QPlatformMenu
Q_OBJECT
public:
- QDBusPlatformMenu(quintptr tag = 0LL);
+ QDBusPlatformMenu();
~QDBusPlatformMenu();
void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE;
void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
@@ -145,9 +139,6 @@ public:
void syncMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
void syncSeparatorsCollapsible(bool enable) Q_DECL_OVERRIDE { Q_UNUSED(enable); }
- quintptr tag()const Q_DECL_OVERRIDE { return m_tag; }
- void setTag(quintptr tag) Q_DECL_OVERRIDE;
-
const QString text() const { return m_text; }
void setText(const QString &text) Q_DECL_OVERRIDE;
QIcon icon() const { return m_icon; }
@@ -172,8 +163,6 @@ public:
QPlatformMenuItem *createMenuItem() const Q_DECL_OVERRIDE;
QPlatformMenu *createSubMenu() const Q_DECL_OVERRIDE;
- bool operator==(const QDBusPlatformMenu& other) { return m_tag == other.m_tag; }
-
uint revision() const { return m_revision; }
void emitUpdated();
@@ -184,7 +173,6 @@ signals:
void popupRequested(int id, uint timestamp);
private:
- quintptr m_tag;
QString m_text;
QIcon m_icon;
bool m_isEnabled;
diff --git a/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp b/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp
index fc0fa00655..fc49fcbea9 100644
--- a/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp
+++ b/src/platformsupport/themes/genericunix/dbustray/qdbustraytypes.cpp
@@ -104,7 +104,7 @@ QXdgDBusImageVector iconToQXdgDBusImageVector(const QIcon &icon)
}
// copy and endian-convert
QXdgDBusImageStruct kim(im.width(), im.height());
- const uchar *end = im.constBits() + im.byteCount();
+ const uchar *end = im.constBits() + im.sizeInBytes();
uchar *dest = reinterpret_cast<uchar *>(kim.data.data());
for (const uchar *src = im.constBits(); src < end; src += 4, dest += 4)
qToUnaligned(qToBigEndian<quint32>(qFromUnaligned<quint32>(src)), dest);
diff --git a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
index 323e8fd13b..be0fac4b55 100644
--- a/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
+++ b/src/platformsupport/themes/genericunix/qgenericunixthemes.cpp
@@ -87,14 +87,6 @@ void ResourceHelper::clear()
std::fill(fonts, fonts + QPlatformTheme::NFonts, static_cast<QFont *>(0));
}
-/*!
- \class QGenericX11ThemeQKdeTheme
- \brief QGenericX11Theme is a generic theme implementation for X11.
- \since 5.0
- \internal
- \ingroup qpa
-*/
-
const char *QGenericUnixTheme::name = "generic";
// Default system font, corresponding to the value returned by 4.8 for
diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
new file mode 100644
index 0000000000..1a2a07260a
--- /dev/null
+++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance.cpp
@@ -0,0 +1,357 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbasicvulkanplatforminstance_p.h"
+#include <QLibrary>
+#include <QCoreApplication>
+#include <QVector>
+#include <QLoggingCategory>
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcVk, "qt.vulkan")
+
+/*!
+ \class QBasicPlatformVulkanInstance
+ \brief A generic platform Vulkan instance implementation.
+ \since 5.10
+ \internal
+ \ingroup qpa
+
+ Implements QPlatformVulkanInstance, serving as a base for platform-specific
+ implementations. The library loading and any WSI-specifics are excluded.
+
+ Subclasses are expected to call init() from their constructor and
+ initInstance() from their createOrAdoptInstance() implementation.
+ */
+
+QBasicPlatformVulkanInstance::QBasicPlatformVulkanInstance()
+ : m_vkInst(VK_NULL_HANDLE),
+ m_vkGetInstanceProcAddr(nullptr),
+ m_ownsVkInst(false),
+ m_errorCode(VK_SUCCESS),
+ m_debugCallback(0)
+{
+}
+
+QBasicPlatformVulkanInstance::~QBasicPlatformVulkanInstance()
+{
+ if (!m_vkInst)
+ return;
+
+ if (m_debugCallback && m_vkDestroyDebugReportCallbackEXT)
+ m_vkDestroyDebugReportCallbackEXT(m_vkInst, m_debugCallback, nullptr);
+
+ if (m_ownsVkInst)
+ m_vkDestroyInstance(m_vkInst, nullptr);
+}
+
+void QBasicPlatformVulkanInstance::init(QLibrary *lib)
+{
+ if (m_vkGetInstanceProcAddr)
+ return;
+
+ qCDebug(lcVk, "Vulkan init (%s)", qPrintable(lib->fileName()));
+
+ // While not strictly required with every implementation, try to follow the spec
+ // and do not rely on core functions being exported.
+ //
+ // 1. dlsym vkGetInstanceProcAddr
+ // 2. with a special null instance resolve vkCreateInstance and vkEnumerateInstance*
+ // 3. all other core functions are resolved with the created instance
+
+ m_vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(lib->resolve("vkGetInstanceProcAddr"));
+ if (!m_vkGetInstanceProcAddr) {
+ qWarning("Failed to find vkGetInstanceProcAddr");
+ return;
+ }
+
+ m_vkCreateInstance = reinterpret_cast<PFN_vkCreateInstance>(m_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateInstance"));
+ if (!m_vkCreateInstance) {
+ qWarning("Failed to find vkCreateInstance");
+ return;
+ }
+ m_vkEnumerateInstanceLayerProperties = reinterpret_cast<PFN_vkEnumerateInstanceLayerProperties>(
+ m_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceLayerProperties"));
+ if (!m_vkEnumerateInstanceLayerProperties) {
+ qWarning("Failed to find vkEnumerateInstanceLayerProperties");
+ return;
+ }
+ m_vkEnumerateInstanceExtensionProperties = reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>(
+ m_vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties"));
+ if (!m_vkEnumerateInstanceExtensionProperties) {
+ qWarning("Failed to find vkEnumerateInstanceExtensionProperties");
+ return;
+ }
+
+ uint32_t layerCount = 0;
+ m_vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
+ if (layerCount) {
+ QVector<VkLayerProperties> layerProps(layerCount);
+ m_vkEnumerateInstanceLayerProperties(&layerCount, layerProps.data());
+ m_supportedLayers.reserve(layerCount);
+ for (const VkLayerProperties &p : qAsConst(layerProps)) {
+ QVulkanLayer layer;
+ layer.name = p.layerName;
+ layer.version = p.implementationVersion;
+ layer.specVersion = QVersionNumber(VK_VERSION_MAJOR(p.specVersion),
+ VK_VERSION_MINOR(p.specVersion),
+ VK_VERSION_PATCH(p.specVersion));
+ layer.description = p.description;
+ m_supportedLayers.append(layer);
+ }
+ }
+ qCDebug(lcVk) << "Supported Vulkan instance layers:" << m_supportedLayers;
+
+ uint32_t extCount = 0;
+ m_vkEnumerateInstanceExtensionProperties(nullptr, &extCount, nullptr);
+ if (extCount) {
+ QVector<VkExtensionProperties> extProps(extCount);
+ m_vkEnumerateInstanceExtensionProperties(nullptr, &extCount, extProps.data());
+ m_supportedExtensions.reserve(extCount);
+ for (const VkExtensionProperties &p : qAsConst(extProps)) {
+ QVulkanExtension ext;
+ ext.name = p.extensionName;
+ ext.version = p.specVersion;
+ m_supportedExtensions.append(ext);
+ }
+ }
+ qDebug(lcVk) << "Supported Vulkan instance extensions:" << m_supportedExtensions;
+}
+
+QVulkanInfoVector<QVulkanLayer> QBasicPlatformVulkanInstance::supportedLayers() const
+{
+ return m_supportedLayers;
+}
+
+QVulkanInfoVector<QVulkanExtension> QBasicPlatformVulkanInstance::supportedExtensions() const
+{
+ return m_supportedExtensions;
+}
+
+void QBasicPlatformVulkanInstance::initInstance(QVulkanInstance *instance, const QByteArrayList &extraExts)
+{
+ if (!m_vkGetInstanceProcAddr) {
+ qWarning("initInstance: No Vulkan library available");
+ return;
+ }
+
+ m_vkInst = instance->vkInstance(); // when non-null we are adopting an existing instance
+
+ QVulkanInstance::Flags flags = instance->flags();
+ m_enabledLayers = instance->layers();
+ m_enabledExtensions = instance->extensions();
+
+ if (!m_vkInst) {
+ VkApplicationInfo appInfo;
+ memset(&appInfo, 0, sizeof(appInfo));
+ appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
+ QByteArray appName = QCoreApplication::applicationName().toUtf8();
+ appInfo.pApplicationName = appName.constData();
+ const QVersionNumber apiVersion = instance->apiVersion();
+ if (!apiVersion.isNull()) {
+ appInfo.apiVersion = VK_MAKE_VERSION(apiVersion.majorVersion(),
+ apiVersion.minorVersion(),
+ apiVersion.microVersion());
+ }
+
+ if (!flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))
+ m_enabledExtensions.append("VK_EXT_debug_report");
+
+ m_enabledExtensions.append("VK_KHR_surface");
+
+ for (const QByteArray &ext : extraExts)
+ m_enabledExtensions.append(ext);
+
+ // No clever stuff with QSet and friends: the order for layers matters
+ // and the user-provided order must be kept.
+ for (int i = 0; i < m_enabledLayers.count(); ++i) {
+ const QByteArray &layerName(m_enabledLayers[i]);
+ if (!m_supportedLayers.contains(layerName))
+ m_enabledLayers.removeAt(i--);
+ }
+ qDebug(lcVk) << "Enabling Vulkan instance layers:" << m_enabledLayers;
+ for (int i = 0; i < m_enabledExtensions.count(); ++i) {
+ const QByteArray &extName(m_enabledExtensions[i]);
+ if (!m_supportedExtensions.contains(extName))
+ m_enabledExtensions.removeAt(i--);
+ }
+ qDebug(lcVk) << "Enabling Vulkan instance extensions:" << m_enabledExtensions;
+
+ VkInstanceCreateInfo instInfo;
+ memset(&instInfo, 0, sizeof(instInfo));
+ instInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
+ instInfo.pApplicationInfo = &appInfo;
+
+ QVector<const char *> layerNameVec;
+ for (const QByteArray &ba : qAsConst(m_enabledLayers))
+ layerNameVec.append(ba.constData());
+ if (!layerNameVec.isEmpty()) {
+ instInfo.enabledLayerCount = layerNameVec.count();
+ instInfo.ppEnabledLayerNames = layerNameVec.constData();
+ }
+
+ QVector<const char *> extNameVec;
+ for (const QByteArray &ba : qAsConst(m_enabledExtensions))
+ extNameVec.append(ba.constData());
+ if (!extNameVec.isEmpty()) {
+ instInfo.enabledExtensionCount = extNameVec.count();
+ instInfo.ppEnabledExtensionNames = extNameVec.constData();
+ }
+
+ m_errorCode = m_vkCreateInstance(&instInfo, nullptr, &m_vkInst);
+ if (m_errorCode != VK_SUCCESS || !m_vkInst) {
+ qWarning("Failed to create Vulkan instance: %d", m_errorCode);
+ return;
+ }
+
+ m_vkDestroyInstance = reinterpret_cast<PFN_vkDestroyInstance>(m_vkGetInstanceProcAddr(m_vkInst, "vkDestroyInstance"));
+ if (!m_vkDestroyInstance) {
+ qWarning("Failed to find vkDestroyInstance");
+ m_vkInst = VK_NULL_HANDLE;
+ return;
+ }
+
+ m_ownsVkInst = true;
+ }
+
+ m_getPhysDevSurfaceSupport = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceSurfaceSupportKHR"));
+ if (!m_getPhysDevSurfaceSupport)
+ qWarning("Failed to find vkGetPhysicalDeviceSurfaceSupportKHR");
+
+ if (!flags.testFlag(QVulkanInstance::NoDebugOutputRedirect))
+ setupDebugOutput();
+}
+
+bool QBasicPlatformVulkanInstance::isValid() const
+{
+ return m_vkInst != VK_NULL_HANDLE;
+}
+
+VkResult QBasicPlatformVulkanInstance::errorCode() const
+{
+ return m_errorCode;
+}
+
+VkInstance QBasicPlatformVulkanInstance::vkInstance() const
+{
+ return m_vkInst;
+}
+
+QByteArrayList QBasicPlatformVulkanInstance::enabledLayers() const
+{
+ return m_enabledLayers;
+}
+
+QByteArrayList QBasicPlatformVulkanInstance::enabledExtensions() const
+{
+ return m_enabledExtensions;
+}
+
+PFN_vkVoidFunction QBasicPlatformVulkanInstance::getInstanceProcAddr(const char *name)
+{
+ if (!name)
+ return nullptr;
+
+ const bool needsNullInstance = !strcmp(name, "vkEnumerateInstanceLayerProperties")
+ || !strcmp(name, "vkEnumerateInstanceExtensionProperties");
+
+ return m_vkGetInstanceProcAddr(needsNullInstance ? 0 : m_vkInst, name);
+}
+
+bool QBasicPlatformVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ QWindow *window)
+{
+ if (!m_getPhysDevSurfaceSupport)
+ return true;
+
+ VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(window);
+ VkBool32 supported = false;
+ m_getPhysDevSurfaceSupport(physicalDevice, queueFamilyIndex, surface, &supported);
+
+ return supported;
+}
+
+static VKAPI_ATTR VkBool32 VKAPI_CALL defaultDebugCallbackFunc(VkDebugReportFlagsEXT flags,
+ VkDebugReportObjectTypeEXT objectType,
+ uint64_t object,
+ size_t location,
+ int32_t messageCode,
+ const char *pLayerPrefix,
+ const char *pMessage,
+ void *pUserData)
+{
+ Q_UNUSED(flags);
+ Q_UNUSED(objectType);
+ Q_UNUSED(object);
+ Q_UNUSED(location);
+ Q_UNUSED(pUserData);
+
+ // not categorized, just route to plain old qDebug
+ qDebug("vkDebug: %s: %d: %s", pLayerPrefix, messageCode, pMessage);
+
+ return VK_FALSE;
+}
+
+void QBasicPlatformVulkanInstance::setupDebugOutput()
+{
+ if (!m_enabledExtensions.contains("VK_EXT_debug_report"))
+ return;
+
+ PFN_vkCreateDebugReportCallbackEXT createDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkCreateDebugReportCallbackEXT"));
+ m_vkDestroyDebugReportCallbackEXT = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkDestroyDebugReportCallbackEXT"));
+
+ VkDebugReportCallbackCreateInfoEXT dbgCallbackInfo;
+ memset(&dbgCallbackInfo, 0, sizeof(dbgCallbackInfo));
+ dbgCallbackInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
+ dbgCallbackInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT
+ | VK_DEBUG_REPORT_WARNING_BIT_EXT
+ | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
+ dbgCallbackInfo.pfnCallback = defaultDebugCallbackFunc;
+
+ VkResult err = createDebugReportCallback(m_vkInst, &dbgCallbackInfo, nullptr, &m_debugCallback);
+ if (err != VK_SUCCESS)
+ qWarning("Failed to create debug report callback: %d", err);
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
new file mode 100644
index 0000000000..748b138f01
--- /dev/null
+++ b/src/platformsupport/vkconvenience/qbasicvulkanplatforminstance_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBASICVULKANPLATFORMINSTANCE_P_H
+#define QBASICVULKANPLATFORMINSTANCE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qpa/qplatformvulkaninstance.h>
+
+QT_BEGIN_NAMESPACE
+
+class QLibrary;
+
+class QBasicPlatformVulkanInstance : public QPlatformVulkanInstance
+{
+public:
+ QBasicPlatformVulkanInstance();
+ ~QBasicPlatformVulkanInstance();
+
+ QVulkanInfoVector<QVulkanLayer> supportedLayers() const override;
+ QVulkanInfoVector<QVulkanExtension> supportedExtensions() const override;
+ bool isValid() const override;
+ VkResult errorCode() const override;
+ VkInstance vkInstance() const override;
+ QByteArrayList enabledLayers() const override;
+ QByteArrayList enabledExtensions() const override;
+ PFN_vkVoidFunction getInstanceProcAddr(const char *name) override;
+ bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override;
+
+protected:
+ void init(QLibrary *lib);
+ void initInstance(QVulkanInstance *instance, const QByteArrayList &extraExts);
+
+ VkInstance m_vkInst;
+ PFN_vkGetInstanceProcAddr m_vkGetInstanceProcAddr;
+ PFN_vkGetPhysicalDeviceSurfaceSupportKHR m_getPhysDevSurfaceSupport;
+
+private:
+ void setupDebugOutput();
+
+ bool m_ownsVkInst;
+ VkResult m_errorCode;
+ QVulkanInfoVector<QVulkanLayer> m_supportedLayers;
+ QVulkanInfoVector<QVulkanExtension> m_supportedExtensions;
+ QByteArrayList m_enabledLayers;
+ QByteArrayList m_enabledExtensions;
+
+ PFN_vkCreateInstance m_vkCreateInstance;
+ PFN_vkEnumerateInstanceLayerProperties m_vkEnumerateInstanceLayerProperties;
+ PFN_vkEnumerateInstanceExtensionProperties m_vkEnumerateInstanceExtensionProperties;
+
+ PFN_vkDestroyInstance m_vkDestroyInstance;
+
+ VkDebugReportCallbackEXT m_debugCallback;
+ PFN_vkDestroyDebugReportCallbackEXT m_vkDestroyDebugReportCallbackEXT;
+};
+
+QT_END_NAMESPACE
+
+#endif // QBASICVULKANPLATFORMINSTANCE_P_H
diff --git a/src/platformsupport/vkconvenience/vkconvenience.pro b/src/platformsupport/vkconvenience/vkconvenience.pro
new file mode 100644
index 0000000000..7a4cdb041d
--- /dev/null
+++ b/src/platformsupport/vkconvenience/vkconvenience.pro
@@ -0,0 +1,16 @@
+TARGET = QtVulkanSupport
+MODULE = vulkan_support
+
+QT = core-private gui-private
+CONFIG += static internal_module
+
+DEFINES += QT_NO_CAST_FROM_ASCII
+PRECOMPILED_HEADER = ../../corelib/global/qt_pch.h
+
+SOURCES += \
+ qbasicvulkanplatforminstance.cpp
+
+HEADERS += \
+ qbasicvulkanplatforminstance_p.h
+
+load(qt_module)
diff --git a/src/plugins/bearer/linux_common/qofonoservice_linux.cpp b/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
index adf7feef2e..897ee953c0 100644
--- a/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
+++ b/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
@@ -118,7 +118,7 @@ QString QOfonoManagerInterface::currentModem()
for (const QString &modem : modems) {
QOfonoModemInterface device(modem);
if (device.isPowered() && device.isOnline()
- && device.interfaces().contains(QStringLiteral("org.ofono.NetworkRegistration")))
+ && device.interfaces().contains(QLatin1String("org.ofono.NetworkRegistration")))
return modem;
}
return QString();
diff --git a/src/plugins/generic/tuiotouch/qoscbundle.cpp b/src/plugins/generic/tuiotouch/qoscbundle.cpp
index b84ae39aca..e9166922a1 100644
--- a/src/plugins/generic/tuiotouch/qoscbundle.cpp
+++ b/src/plugins/generic/tuiotouch/qoscbundle.cpp
@@ -125,7 +125,7 @@ QOscBundle::QOscBundle(const QByteArray &data)
if (size == 0) {
// empty bundle; these are valid, but should they be allowed? the
// spec is unclear on this...
- qWarning("Empty bundle?");
+ qCWarning(lcTuioBundle, "Empty bundle?");
m_isValid = true;
m_immediate = isImmediate;
m_timeEpoch = oscTimeEpoch;
@@ -155,7 +155,7 @@ QOscBundle::QOscBundle(const QByteArray &data)
m_timePico = oscTimePico;
m_messages.append(subMessage);
} else {
- qWarning("Invalid sub-message");
+ qCWarning(lcTuioBundle, "Invalid sub-message");
return;
}
} else if (subdata.startsWith(bundleIdentifier)) {
@@ -169,7 +169,7 @@ QOscBundle::QOscBundle(const QByteArray &data)
m_bundles.append(subBundle);
}
} else {
- qWarning("Malformed sub-data!");
+ qCWarning(lcTuioBundle, "Malformed sub-data!");
return;
}
}
diff --git a/src/plugins/generic/tuiotouch/qoscmessage.cpp b/src/plugins/generic/tuiotouch/qoscmessage.cpp
index b2004903bd..3c30caa923 100644
--- a/src/plugins/generic/tuiotouch/qoscmessage.cpp
+++ b/src/plugins/generic/tuiotouch/qoscmessage.cpp
@@ -113,7 +113,7 @@ QOscMessage::QOscMessage(const QByteArray &data)
parsedBytes += sizeof(quint32);
arguments.append(value.f);
} else {
- qWarning() << "Reading argument of unknown type " << typeTag;
+ qCWarning(lcTuioMessage) << "Reading argument of unknown type " << typeTag;
return;
}
}
diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp
index eb646644ec..bb18ba5085 100644
--- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp
+++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp
@@ -57,6 +57,7 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcTuioHandler, "qt.qpa.tuio.handler")
Q_LOGGING_CATEGORY(lcTuioSource, "qt.qpa.tuio.source")
Q_LOGGING_CATEGORY(lcTuioSet, "qt.qpa.tuio.set")
@@ -82,7 +83,7 @@ QTuioHandler::QTuioHandler(const QString &specification)
} else if (args.at(i).startsWith("tcp=")) {
QString portString = args.at(i).section('=', 1, 1);
portNumber = portString.toInt();
- qWarning() << "TCP is not yet supported. Falling back to UDP on " << portNumber;
+ qCWarning(lcTuioHandler) << "TCP is not yet supported. Falling back to UDP on " << portNumber;
} else if (args.at(i) == "invertx") {
invertx = true;
} else if (args.at(i) == "inverty") {
@@ -119,7 +120,7 @@ QTuioHandler::QTuioHandler(const QString &specification)
QWindowSystemInterface::registerTouchDevice(m_device);
if (!m_socket.bind(QHostAddress::Any, portNumber)) {
- qWarning() << "Failed to bind TUIO socket: " << m_socket.errorString();
+ qCWarning(lcTuioHandler) << "Failed to bind TUIO socket: " << m_socket.errorString();
return;
}
@@ -172,7 +173,7 @@ void QTuioHandler::processPackets()
if (message.addressPattern() == "/tuio/2Dcur") {
QList<QVariant> arguments = message.arguments();
if (arguments.count() == 0) {
- qWarning("Ignoring TUIO message with no arguments");
+ qCWarning(lcTuioHandler, "Ignoring TUIO message with no arguments");
continue;
}
@@ -186,13 +187,13 @@ void QTuioHandler::processPackets()
} else if (messageType == "fseq") {
process2DCurFseq(message);
} else {
- qWarning() << "Ignoring unknown TUIO message type: " << messageType;
+ qCWarning(lcTuioHandler) << "Ignoring unknown TUIO message type: " << messageType;
continue;
}
} else if (message.addressPattern() == "/tuio/2Dobj") {
QList<QVariant> arguments = message.arguments();
if (arguments.count() == 0) {
- qWarning("Ignoring TUIO message with no arguments");
+ qCWarning(lcTuioHandler, "Ignoring TUIO message with no arguments");
continue;
}
@@ -206,11 +207,11 @@ void QTuioHandler::processPackets()
} else if (messageType == "fseq") {
process2DObjFseq(message);
} else {
- qWarning() << "Ignoring unknown TUIO message type: " << messageType;
+ qCWarning(lcTuioHandler) << "Ignoring unknown TUIO message type: " << messageType;
continue;
}
} else {
- qWarning() << "Ignoring unknown address pattern " << message.addressPattern();
+ qCWarning(lcTuioHandler) << "Ignoring unknown address pattern " << message.addressPattern();
continue;
}
}
@@ -221,12 +222,12 @@ void QTuioHandler::process2DCurSource(const QOscMessage &message)
{
QList<QVariant> arguments = message.arguments();
if (arguments.count() != 2) {
- qWarning() << "Ignoring malformed TUIO source message: " << arguments.count();
+ qCWarning(lcTuioSource) << "Ignoring malformed TUIO source message: " << arguments.count();
return;
}
if (QMetaType::Type(arguments.at(1).type()) != QMetaType::QByteArray) {
- qWarning("Ignoring malformed TUIO source message (bad argument type)");
+ qCWarning(lcTuioSource, "Ignoring malformed TUIO source message (bad argument type)");
return;
}
@@ -248,7 +249,7 @@ void QTuioHandler::process2DCurAlive(const QOscMessage &message)
for (int i = 1; i < arguments.count(); ++i) {
if (QMetaType::Type(arguments.at(i).type()) != QMetaType::Int) {
- qWarning() << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ')';
+ qCWarning(lcTuioHandler) << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ')';
return;
}
@@ -288,7 +289,7 @@ void QTuioHandler::process2DCurSet(const QOscMessage &message)
{
QList<QVariant> arguments = message.arguments();
if (arguments.count() < 7) {
- qWarning() << "Ignoring malformed TUIO set message with too few arguments: " << arguments.count();
+ qCWarning(lcTuioSet) << "Ignoring malformed TUIO set message with too few arguments: " << arguments.count();
return;
}
@@ -299,7 +300,7 @@ void QTuioHandler::process2DCurSet(const QOscMessage &message)
QMetaType::Type(arguments.at(5).type()) != QMetaType::Float ||
QMetaType::Type(arguments.at(6).type()) != QMetaType::Float
) {
- qWarning() << "Ignoring malformed TUIO set message with bad types: " << arguments;
+ qCWarning(lcTuioSet) << "Ignoring malformed TUIO set message with bad types: " << arguments;
return;
}
@@ -312,7 +313,7 @@ void QTuioHandler::process2DCurSet(const QOscMessage &message)
QMap<int, QTuioCursor>::Iterator it = m_activeCursors.find(cursorId);
if (it == m_activeCursors.end()) {
- qWarning() << "Ignoring malformed TUIO set for nonexistent cursor " << cursorId;
+ qCWarning(lcTuioSet) << "Ignoring malformed TUIO set for nonexistent cursor " << cursorId;
return;
}
@@ -386,12 +387,12 @@ void QTuioHandler::process2DObjSource(const QOscMessage &message)
{
QList<QVariant> arguments = message.arguments();
if (arguments.count() != 2) {
- qWarning() << "Ignoring malformed TUIO source message: " << arguments.count();
+ qCWarning(lcTuioSource, ) << "Ignoring malformed TUIO source message: " << arguments.count();
return;
}
if (QMetaType::Type(arguments.at(1).type()) != QMetaType::QByteArray) {
- qWarning("Ignoring malformed TUIO source message (bad argument type)");
+ qCWarning(lcTuioSource, "Ignoring malformed TUIO source message (bad argument type)");
return;
}
@@ -413,7 +414,7 @@ void QTuioHandler::process2DObjAlive(const QOscMessage &message)
for (int i = 1; i < arguments.count(); ++i) {
if (QMetaType::Type(arguments.at(i).type()) != QMetaType::Int) {
- qWarning() << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ')';
+ qCWarning(lcTuioHandler) << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ')';
return;
}
@@ -453,7 +454,7 @@ void QTuioHandler::process2DObjSet(const QOscMessage &message)
{
QList<QVariant> arguments = message.arguments();
if (arguments.count() < 7) {
- qWarning() << "Ignoring malformed TUIO set message with too few arguments: " << arguments.count();
+ qCWarning(lcTuioSet) << "Ignoring malformed TUIO set message with too few arguments: " << arguments.count();
return;
}
@@ -467,7 +468,7 @@ void QTuioHandler::process2DObjSet(const QOscMessage &message)
QMetaType::Type(arguments.at(8).type()) != QMetaType::Float ||
QMetaType::Type(arguments.at(9).type()) != QMetaType::Float ||
QMetaType::Type(arguments.at(10).type()) != QMetaType::Float) {
- qWarning() << "Ignoring malformed TUIO set message with bad types: " << arguments;
+ qCWarning(lcTuioSet) << "Ignoring malformed TUIO set message with bad types: " << arguments;
return;
}
@@ -484,7 +485,7 @@ void QTuioHandler::process2DObjSet(const QOscMessage &message)
QMap<int, QTuioToken>::Iterator it = m_activeTokens.find(id);
if (it == m_activeTokens.end()) {
- qWarning() << "Ignoring malformed TUIO set for nonexistent token " << classId;
+ qCWarning(lcTuioSet) << "Ignoring malformed TUIO set for nonexistent token " << classId;
return;
}
@@ -522,7 +523,7 @@ QWindowSystemInterface::TouchPoint QTuioHandler::tokenToTouchPoint(const QTuioTo
QPointF delta = relPos - relPos.toPoint();
tp.area.moveCenter(win->mapToGlobal(relPos.toPoint()) + delta);
tp.velocity = QVector2D(win->size().width() * tc.vx(), win->size().height() * tc.vy());
- tp.rotation = tc.angle() * 180.0 / M_PI; // convert radians to degrees
+ tp.rotation = qRadiansToDegrees(tc.angle());
return tp;
}
diff --git a/src/plugins/imageformats/gif/main.h b/src/plugins/imageformats/gif/main.h
index 4287a8a39c..84913a31d7 100644
--- a/src/plugins/imageformats/gif/main.h
+++ b/src/plugins/imageformats/gif/main.h
@@ -55,8 +55,8 @@ public:
QGifPlugin();
~QGifPlugin();
- Capabilities capabilities(QIODevice *device, const QByteArray &format) const Q_DECL_OVERRIDE;
- QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const Q_DECL_OVERRIDE;
+ Capabilities capabilities(QIODevice *device, const QByteArray &format) const override;
+ QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp
index bae74bf9a1..e0f7f44701 100644
--- a/src/plugins/imageformats/gif/qgifhandler.cpp
+++ b/src/plugins/imageformats/gif/qgifhandler.cpp
@@ -354,7 +354,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
(*image) = QImage(swidth, sheight, format);
bpl = image->bytesPerLine();
bits = image->bits();
- memset(bits, 0, image->byteCount());
+ memset(bits, 0, image->sizeInBytes());
}
// Check if the previous attempt to create the image failed. If it
@@ -415,7 +415,7 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
backingstore = QImage(qMax(backingstore.width(), w),
qMax(backingstore.height(), h),
QImage::Format_RGB32);
- memset(backingstore.bits(), 0, backingstore.byteCount());
+ memset(backingstore.bits(), 0, backingstore.sizeInBytes());
}
const int dest_bpl = backingstore.bytesPerLine();
unsigned char *dest_data = backingstore.bits();
diff --git a/src/plugins/imageformats/gif/qgifhandler_p.h b/src/plugins/imageformats/gif/qgifhandler_p.h
index bc3debe83c..b004ee610d 100644
--- a/src/plugins/imageformats/gif/qgifhandler_p.h
+++ b/src/plugins/imageformats/gif/qgifhandler_p.h
@@ -69,22 +69,22 @@ public:
QGifHandler();
~QGifHandler();
- bool canRead() const Q_DECL_OVERRIDE;
- bool read(QImage *image) Q_DECL_OVERRIDE;
- bool write(const QImage &image) Q_DECL_OVERRIDE;
+ bool canRead() const override;
+ bool read(QImage *image) override;
+ bool write(const QImage &image) override;
- QByteArray name() const Q_DECL_OVERRIDE;
+ QByteArray name() const override;
static bool canRead(QIODevice *device);
- QVariant option(ImageOption option) const Q_DECL_OVERRIDE;
- void setOption(ImageOption option, const QVariant &value) Q_DECL_OVERRIDE;
- bool supportsOption(ImageOption option) const Q_DECL_OVERRIDE;
+ QVariant option(ImageOption option) const override;
+ void setOption(ImageOption option, const QVariant &value) override;
+ bool supportsOption(ImageOption option) const override;
- int imageCount() const Q_DECL_OVERRIDE;
- int loopCount() const Q_DECL_OVERRIDE;
- int nextImageDelay() const Q_DECL_OVERRIDE;
- int currentImageNumber() const Q_DECL_OVERRIDE;
+ int imageCount() const override;
+ int loopCount() const override;
+ int nextImageDelay() const override;
+ int currentImageNumber() const override;
private:
bool imageIsComing() const;
diff --git a/src/plugins/imageformats/ico/ico.pro b/src/plugins/imageformats/ico/ico.pro
index 7ca1f18cb1..c8bb37eff2 100644
--- a/src/plugins/imageformats/ico/ico.pro
+++ b/src/plugins/imageformats/ico/ico.pro
@@ -3,6 +3,7 @@ TARGET = qico
HEADERS += main.h qicohandler.h
SOURCES += main.cpp qicohandler.cpp
OTHER_FILES += ico.json
+QT += core-private
PLUGIN_TYPE = imageformats
PLUGIN_CLASS_NAME = QICOPlugin
diff --git a/src/plugins/imageformats/ico/main.h b/src/plugins/imageformats/ico/main.h
index 8e54d7c643..b5875183c1 100644
--- a/src/plugins/imageformats/ico/main.h
+++ b/src/plugins/imageformats/ico/main.h
@@ -52,8 +52,8 @@ class QICOPlugin : public QImageIOPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "ico.json")
public:
- Capabilities capabilities(QIODevice *device, const QByteArray &format) const Q_DECL_OVERRIDE;
- QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const Q_DECL_OVERRIDE;
+ Capabilities capabilities(QIODevice *device, const QByteArray &format) const override;
+ QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index 17d1aeeb5d..e61173db30 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -48,6 +48,7 @@
#include "qicohandler.h"
#include <QtCore/qendian.h>
+#include <private/qendian_p.h>
#include <QtGui/QImage>
#include <QtCore/QFile>
#include <QtCore/QBuffer>
@@ -63,34 +64,34 @@ typedef struct
quint8 bHeight; // Height of the image (actual height, not times 2)
quint8 bColorCount; // Number of colors in image (0 if >=8bpp) [ not ture ]
quint8 bReserved; // Reserved
- quint16 wPlanes; // Color Planes
- quint16 wBitCount; // Bits per pixel
- quint32 dwBytesInRes; // how many bytes in this resource?
- quint32 dwImageOffset; // where in the file is this image
+ quint16_le wPlanes; // Color Planes
+ quint16_le wBitCount; // Bits per pixel
+ quint32_le dwBytesInRes; // how many bytes in this resource?
+ quint32_le dwImageOffset; // where in the file is this image
} ICONDIRENTRY, *LPICONDIRENTRY;
#define ICONDIRENTRY_SIZE 16
typedef struct
{
- quint16 idReserved; // Reserved
- quint16 idType; // resource type (1 for icons, 2 for cursors)
- quint16 idCount; // how many images?
+ quint16_le idReserved; // Reserved
+ quint16_le idType; // resource type (1 for icons, 2 for cursors)
+ quint16_le idCount; // how many images?
ICONDIRENTRY idEntries[1]; // the entries for each image
} ICONDIR, *LPICONDIR;
#define ICONDIR_SIZE 6 // Exclude the idEntries field
typedef struct { // BMP information header
- quint32 biSize; // size of this struct
- quint32 biWidth; // pixmap width
- quint32 biHeight; // pixmap height (specifies the combined height of the XOR and AND masks)
- quint16 biPlanes; // should be 1
- quint16 biBitCount; // number of bits per pixel
- quint32 biCompression; // compression method
- quint32 biSizeImage; // size of image
- quint32 biXPelsPerMeter; // horizontal resolution
- quint32 biYPelsPerMeter; // vertical resolution
- quint32 biClrUsed; // number of colors used
- quint32 biClrImportant; // number of important colors
+ quint32_le biSize; // size of this struct
+ quint32_le biWidth; // pixmap width
+ quint32_le biHeight; // pixmap height (specifies the combined height of the XOR and AND masks)
+ quint16_le biPlanes; // should be 1
+ quint16_le biBitCount; // number of bits per pixel
+ quint32_le biCompression; // compression method
+ quint32_le biSizeImage; // size of image
+ quint32_le biXPelsPerMeter; // horizontal resolution
+ quint32_le biYPelsPerMeter; // vertical resolution
+ quint32_le biClrUsed; // number of colors used
+ quint32_le biClrImportant; // number of important colors
} BMP_INFOHDR ,*LPBMP_INFOHDR;
#define BMP_INFOHDR_SIZE 40
@@ -140,108 +141,43 @@ private:
// Data readers and writers that takes care of alignment and endian stuff.
static bool readIconDirEntry(QIODevice *iodev, ICONDIRENTRY *iconDirEntry)
{
- if (iodev) {
- uchar tmp[ICONDIRENTRY_SIZE];
- if (iodev->read((char*)tmp, ICONDIRENTRY_SIZE) == ICONDIRENTRY_SIZE) {
- iconDirEntry->bWidth = tmp[0];
- iconDirEntry->bHeight = tmp[1];
- iconDirEntry->bColorCount = tmp[2];
- iconDirEntry->bReserved = tmp[3];
-
- iconDirEntry->wPlanes = qFromLittleEndian<quint16>(&tmp[4]);
- iconDirEntry->wBitCount = qFromLittleEndian<quint16>(&tmp[6]);
- iconDirEntry->dwBytesInRes = qFromLittleEndian<quint32>(&tmp[8]);
- iconDirEntry->dwImageOffset = qFromLittleEndian<quint32>(&tmp[12]);
- return true;
- }
- }
+ if (iodev)
+ return (iodev->read((char*)iconDirEntry, ICONDIRENTRY_SIZE) == ICONDIRENTRY_SIZE);
return false;
}
static bool writeIconDirEntry(QIODevice *iodev, const ICONDIRENTRY &iconEntry)
{
- if (iodev) {
- uchar tmp[ICONDIRENTRY_SIZE];
- tmp[0] = iconEntry.bWidth;
- tmp[1] = iconEntry.bHeight;
- tmp[2] = iconEntry.bColorCount;
- tmp[3] = iconEntry.bReserved;
- qToLittleEndian<quint16>(iconEntry.wPlanes, &tmp[4]);
- qToLittleEndian<quint16>(iconEntry.wBitCount, &tmp[6]);
- qToLittleEndian<quint32>(iconEntry.dwBytesInRes, &tmp[8]);
- qToLittleEndian<quint32>(iconEntry.dwImageOffset, &tmp[12]);
- return iodev->write((char*)tmp, ICONDIRENTRY_SIZE) == ICONDIRENTRY_SIZE;
- }
-
+ if (iodev)
+ return iodev->write((char*)&iconEntry, ICONDIRENTRY_SIZE) == ICONDIRENTRY_SIZE;
return false;
}
static bool readIconDir(QIODevice *iodev, ICONDIR *iconDir)
{
- if (iodev) {
- uchar tmp[ICONDIR_SIZE];
- if (iodev->read((char*)tmp, ICONDIR_SIZE) == ICONDIR_SIZE) {
- iconDir->idReserved = qFromLittleEndian<quint16>(&tmp[0]);
- iconDir->idType = qFromLittleEndian<quint16>(&tmp[2]);
- iconDir->idCount = qFromLittleEndian<quint16>(&tmp[4]);
- return true;
- }
- }
+ if (iodev)
+ return (iodev->read((char*)iconDir, ICONDIR_SIZE) == ICONDIR_SIZE);
return false;
}
static bool writeIconDir(QIODevice *iodev, const ICONDIR &iconDir)
{
- if (iodev) {
- uchar tmp[6];
- qToLittleEndian(iconDir.idReserved, tmp);
- qToLittleEndian(iconDir.idType, &tmp[2]);
- qToLittleEndian(iconDir.idCount, &tmp[4]);
- return iodev->write((char*)tmp, 6) == 6;
- }
+ if (iodev)
+ return iodev->write((char*)&iconDir, 6) == 6;
return false;
}
static bool readBMPInfoHeader(QIODevice *iodev, BMP_INFOHDR *pHeader)
{
- if (iodev) {
- uchar header[BMP_INFOHDR_SIZE];
- if (iodev->read((char*)header, BMP_INFOHDR_SIZE) == BMP_INFOHDR_SIZE) {
- pHeader->biSize = qFromLittleEndian<quint32>(&header[0]);
- pHeader->biWidth = qFromLittleEndian<quint32>(&header[4]);
- pHeader->biHeight = qFromLittleEndian<quint32>(&header[8]);
- pHeader->biPlanes = qFromLittleEndian<quint16>(&header[12]);
- pHeader->biBitCount = qFromLittleEndian<quint16>(&header[14]);
- pHeader->biCompression = qFromLittleEndian<quint32>(&header[16]);
- pHeader->biSizeImage = qFromLittleEndian<quint32>(&header[20]);
- pHeader->biXPelsPerMeter = qFromLittleEndian<quint32>(&header[24]);
- pHeader->biYPelsPerMeter = qFromLittleEndian<quint32>(&header[28]);
- pHeader->biClrUsed = qFromLittleEndian<quint32>(&header[32]);
- pHeader->biClrImportant = qFromLittleEndian<quint32>(&header[36]);
- return true;
- }
- }
+ if (iodev)
+ return (iodev->read((char*)pHeader, BMP_INFOHDR_SIZE) == BMP_INFOHDR_SIZE);
return false;
}
static bool writeBMPInfoHeader(QIODevice *iodev, const BMP_INFOHDR &header)
{
- if (iodev) {
- uchar tmp[BMP_INFOHDR_SIZE];
- qToLittleEndian<quint32>(header.biSize, &tmp[0]);
- qToLittleEndian<quint32>(header.biWidth, &tmp[4]);
- qToLittleEndian<quint32>(header.biHeight, &tmp[8]);
- qToLittleEndian<quint16>(header.biPlanes, &tmp[12]);
- qToLittleEndian<quint16>(header.biBitCount, &tmp[14]);
- qToLittleEndian<quint32>(header.biCompression, &tmp[16]);
- qToLittleEndian<quint32>(header.biSizeImage, &tmp[20]);
- qToLittleEndian<quint32>(header.biXPelsPerMeter, &tmp[24]);
- qToLittleEndian<quint32>(header.biYPelsPerMeter, &tmp[28]);
- qToLittleEndian<quint32>(header.biClrUsed, &tmp[32]);
- qToLittleEndian<quint32>(header.biClrImportant, &tmp[36]);
-
- return iodev->write((char*)tmp, BMP_INFOHDR_SIZE) == BMP_INFOHDR_SIZE;
- }
+ if (iodev)
+ return iodev->write((char*)&header, BMP_INFOHDR_SIZE) == BMP_INFOHDR_SIZE;
return false;
}
@@ -561,7 +497,7 @@ QImage ICOReader::iconAt(int index)
if (icoAttrib.depth == 32) // there's no colormap
icoAttrib.ncolors = 0;
else // # colors used
- icoAttrib.ncolors = header.biClrUsed ? header.biClrUsed : 1 << icoAttrib.nbits;
+ icoAttrib.ncolors = header.biClrUsed ? uint(header.biClrUsed) : 1 << icoAttrib.nbits;
if (icoAttrib.ncolors > 256) //color table can't be more than 256
return img;
icoAttrib.w = iconEntry.bWidth;
diff --git a/src/plugins/imageformats/ico/qicohandler.h b/src/plugins/imageformats/ico/qicohandler.h
index eea894a950..435f036113 100644
--- a/src/plugins/imageformats/ico/qicohandler.h
+++ b/src/plugins/imageformats/ico/qicohandler.h
@@ -50,20 +50,20 @@ public:
QtIcoHandler(QIODevice *device);
virtual ~QtIcoHandler();
- bool canRead() const Q_DECL_OVERRIDE;
- bool read(QImage *image) Q_DECL_OVERRIDE;
- bool write(const QImage &image) Q_DECL_OVERRIDE;
+ bool canRead() const override;
+ bool read(QImage *image) override;
+ bool write(const QImage &image) override;
- QByteArray name() const Q_DECL_OVERRIDE;
+ QByteArray name() const override;
- int imageCount() const Q_DECL_OVERRIDE;
- bool jumpToImage(int imageNumber) Q_DECL_OVERRIDE;
- bool jumpToNextImage() Q_DECL_OVERRIDE;
+ int imageCount() const override;
+ bool jumpToImage(int imageNumber) override;
+ bool jumpToNextImage() override;
static bool canRead(QIODevice *device);
- bool supportsOption(ImageOption option) const Q_DECL_OVERRIDE;
- QVariant option(ImageOption option) const Q_DECL_OVERRIDE;
+ bool supportsOption(ImageOption option) const override;
+ QVariant option(ImageOption option) const override;
private:
int m_currentIconIndex;
diff --git a/src/plugins/imageformats/jpeg/main.h b/src/plugins/imageformats/jpeg/main.h
index 10619757c4..1845c8c124 100644
--- a/src/plugins/imageformats/jpeg/main.h
+++ b/src/plugins/imageformats/jpeg/main.h
@@ -51,8 +51,8 @@ class QJpegPlugin : public QImageIOPlugin
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "jpeg.json")
public:
- Capabilities capabilities(QIODevice *device, const QByteArray &format) const Q_DECL_OVERRIDE;
- QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const Q_DECL_OVERRIDE;
+ Capabilities capabilities(QIODevice *device, const QByteArray &format) const override;
+ QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
};
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler_p.h b/src/plugins/imageformats/jpeg/qjpeghandler_p.h
index 534ce12115..d832bf82f3 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler_p.h
+++ b/src/plugins/imageformats/jpeg/qjpeghandler_p.h
@@ -64,17 +64,17 @@ public:
QJpegHandler();
~QJpegHandler();
- bool canRead() const Q_DECL_OVERRIDE;
- bool read(QImage *image) Q_DECL_OVERRIDE;
- bool write(const QImage &image) Q_DECL_OVERRIDE;
+ bool canRead() const override;
+ bool read(QImage *image) override;
+ bool write(const QImage &image) override;
- QByteArray name() const Q_DECL_OVERRIDE;
+ QByteArray name() const override;
static bool canRead(QIODevice *device);
- QVariant option(ImageOption option) const Q_DECL_OVERRIDE;
- void setOption(ImageOption option, const QVariant &value) Q_DECL_OVERRIDE;
- bool supportsOption(ImageOption option) const Q_DECL_OVERRIDE;
+ QVariant option(ImageOption option) const override;
+ void setOption(ImageOption option, const QVariant &value) override;
+ bool supportsOption(ImageOption option) const override;
private:
QJpegHandlerPrivate *d;
diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro
index 03592bfa7d..73db9e93a3 100644
--- a/src/plugins/platforms/android/android.pro
+++ b/src/plugins/platforms/android/android.pro
@@ -11,6 +11,8 @@ QT += \
eventdispatcher_support-private accessibility_support-private \
fontdatabase_support-private egl_support-private
+qtConfig(vulkan): QT += vulkan_support-private
+
OTHER_FILES += $$PWD/android.json
INCLUDEPATH += \
@@ -78,6 +80,13 @@ HEADERS += $$PWD/qandroidplatformintegration.h \
qtConfig(android-style-assets): SOURCES += $$PWD/extract.cpp
else: SOURCES += $$PWD/extract-dummy.cpp
+qtConfig(vulkan) {
+ SOURCES += $$PWD/qandroidplatformvulkaninstance.cpp \
+ $$PWD/qandroidplatformvulkanwindow.cpp
+ HEADERS += $$PWD/qandroidplatformvulkaninstance.h \
+ $$PWD/qandroidplatformvulkanwindow.h
+}
+
PLUGIN_TYPE = platforms
load(qt_plugin)
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index f19b7d5484..dabab553c2 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -50,6 +50,7 @@
#include <QGuiApplication>
#include <QDebug>
+#include <QtMath>
QT_BEGIN_NAMESPACE
@@ -251,7 +252,7 @@ namespace QtAndroidInput
QWindowSystemInterface::TouchPoint touchPoint;
touchPoint.id = id;
touchPoint.pressure = pressure;
- touchPoint.rotation = rotation * 180 / M_PI;
+ touchPoint.rotation = qRadiansToDegrees(rotation);
touchPoint.normalPosition = QPointF(double(x / dw), double(y / dh));
touchPoint.state = state;
touchPoint.area = QRectF(x - double(minor),
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index ad2fef7070..8b0b18a846 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -529,7 +529,14 @@ static jboolean startQtApplication(JNIEnv *env, jobject /*object*/, jstring para
if (sem_init(&m_terminateSemaphore, 0, 0) == -1)
return false;
- return pthread_create(&m_qtAppThread, nullptr, startMainMethod, nullptr) == 0;
+ jboolean res = pthread_create(&m_qtAppThread, nullptr, startMainMethod, nullptr) == 0;
+
+ // The service must wait until the QCoreApplication starts otherwise onBind will be
+ // called too early
+ if (m_serviceObject)
+ QtAndroidPrivate::waitForServiceSetup();
+
+ return res;
}
static void quitQtCoreApplication(JNIEnv *env, jclass /*clazz*/)
@@ -734,6 +741,11 @@ static void onNewIntent(JNIEnv *env, jclass /*cls*/, jobject data)
QtAndroidPrivate::handleNewIntent(env, data);
}
+static jobject onBind(JNIEnv */*env*/, jclass /*cls*/, jobject intent)
+{
+ return QtAndroidPrivate::callOnBindListener(intent);
+}
+
static JNINativeMethod methods[] = {
{"startQtAndroidPlugin", "()Z", (void *)startQtAndroidPlugin},
{"startQtApplication", "(Ljava/lang/String;Ljava/lang/String;)V", (void *)startQtApplication},
@@ -746,7 +758,8 @@ static JNINativeMethod methods[] = {
{"updateApplicationState", "(I)V", (void *)updateApplicationState},
{"handleOrientationChanged", "(II)V", (void *)handleOrientationChanged},
{"onActivityResult", "(IILandroid/content/Intent;)V", (void *)onActivityResult},
- {"onNewIntent", "(Landroid/content/Intent;)V", (void *)onNewIntent}
+ {"onNewIntent", "(Landroid/content/Intent;)V", (void *)onNewIntent},
+ {"onBind", "(Landroid/content/Intent;)Landroid/os/IBinder;", (void *)onBind}
};
#define FIND_AND_CHECK_CLASS(CLASS_NAME) \
diff --git a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp
index 08498d0582..ced35c4cfa 100644
--- a/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp
+++ b/src/plugins/platforms/android/qandroidplatformdialoghelpers.cpp
@@ -103,11 +103,7 @@ bool QAndroidPlatformMessageDialogHelper::show(Qt::WindowFlags windowFlags
if (!str.isEmpty())
m_javaMessageDialog.callMethod<void>("setDetailedText", "(Ljava/lang/String;)V", QJNIObjectPrivate::fromString(str).object());
- // http://developer.android.com/design/building-blocks/dialogs.html
- // dismissive action on the left, affirmative on the right
- // There don't seem to be more fine-grained rules, but the OS X layout
- // at least conforms to this one rule and makes the rest deterministic.
- const int * currentLayout = buttonLayout(Qt::Horizontal, MacLayout);
+ const int * currentLayout = buttonLayout(Qt::Horizontal, AndroidLayout);
while (*currentLayout != QPlatformDialogHelper::EOL) {
int role = (*currentLayout & ~QPlatformDialogHelper::Reverse);
addButtons(opt, static_cast<ButtonRole>(role));
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index 7185b573cd..763b294660 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -69,6 +69,11 @@
#include <QtPlatformHeaders/QEGLNativeContext>
+#if QT_CONFIG(vulkan)
+#include "qandroidplatformvulkanwindow.h"
+#include "qandroidplatformvulkaninstance.h"
+#endif
+
QT_BEGIN_NAMESPACE
int QAndroidPlatformIntegration::m_defaultGeometryWidth = 320;
@@ -119,6 +124,23 @@ void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteA
return 0;
}
+void *QAndroidPlatformNativeInterface::nativeResourceForWindow(const QByteArray &resource, QWindow *window)
+{
+#if QT_CONFIG(vulkan)
+ if (resource == "vkSurface") {
+ if (window->surfaceType() == QSurface::VulkanSurface) {
+ QAndroidPlatformVulkanWindow *w = static_cast<QAndroidPlatformVulkanWindow *>(window->handle());
+ // return a pointer to the VkSurfaceKHR, not the value
+ return w ? w->vkSurface() : nullptr;
+ }
+ }
+#else
+ Q_UNUSED(resource);
+ Q_UNUSED(window);
+#endif
+ return nullptr;
+}
+
void QAndroidPlatformNativeInterface::customEvent(QEvent *event)
{
if (event->type() != QEvent::User)
@@ -243,6 +265,7 @@ bool QAndroidPlatformIntegration::hasCapability(Capability cap) const
case ForeignWindows: return QtAndroid::activity();
case ThreadedOpenGL: return !needsBasicRenderloopWorkaround() && QtAndroid::activity();
case RasterGLSurface: return QtAndroid::activity();
+ case TopStackedNativeChildWindows: return false;
default:
return QPlatformIntegration::hasCapability(cap);
}
@@ -295,6 +318,11 @@ QPlatformWindow *QAndroidPlatformIntegration::createPlatformWindow(QWindow *wind
if (!QtAndroid::activity())
return nullptr;
+#if QT_CONFIG(vulkan)
+ if (window->surfaceType() == QSurface::VulkanSurface)
+ return new QAndroidPlatformVulkanWindow(window);
+#endif
+
return new QAndroidPlatformOpenGLWindow(window, m_eglDisplay);
}
@@ -443,4 +471,13 @@ void QAndroidPlatformIntegration::setScreenSize(int width, int height)
QMetaObject::invokeMethod(m_primaryScreen, "setSize", Qt::AutoConnection, Q_ARG(QSize, QSize(width, height)));
}
+#if QT_CONFIG(vulkan)
+
+QPlatformVulkanInstance *QAndroidPlatformIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
+{
+ return new QAndroidPlatformVulkanInstance(instance);
+}
+
+#endif // QT_CONFIG(vulkan)
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h
index 337f4a9279..c795c499bc 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.h
+++ b/src/plugins/platforms/android/qandroidplatformintegration.h
@@ -40,6 +40,8 @@
#ifndef QANDROIDPLATFORMINTERATION_H
#define QANDROIDPLATFORMINTERATION_H
+#include <QtGui/qtguiglobal.h>
+
#include <qpa/qplatformintegration.h>
#include <qpa/qplatformmenu.h>
#include <qpa/qplatformnativeinterface.h>
@@ -64,6 +66,7 @@ class QAndroidPlatformNativeInterface: public QPlatformNativeInterface
{
public:
void *nativeResourceForIntegration(const QByteArray &resource) override;
+ void *nativeResourceForWindow(const QByteArray &resource, QWindow *window) override;
std::shared_ptr<AndroidStyle> m_androidStyle;
protected:
@@ -128,6 +131,10 @@ public:
void flushPendingUpdates();
+#if QT_CONFIG(vulkan)
+ QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override;
+#endif
+
private:
EGLDisplay m_eglDisplay;
QTouchDevice *m_touchDevice;
diff --git a/src/plugins/platforms/android/qandroidplatformmenu.cpp b/src/plugins/platforms/android/qandroidplatformmenu.cpp
index 06b297a1ad..d9cecebf2c 100644
--- a/src/plugins/platforms/android/qandroidplatformmenu.cpp
+++ b/src/plugins/platforms/android/qandroidplatformmenu.cpp
@@ -46,7 +46,6 @@ QT_BEGIN_NAMESPACE
QAndroidPlatformMenu::QAndroidPlatformMenu()
{
- m_tag = reinterpret_cast<quintptr>(this); // QMenu will overwrite this later, but we need a unique ID for QtQuick
m_enabled = true;
m_isVisible = true;
}
@@ -92,16 +91,6 @@ void QAndroidPlatformMenu::syncSeparatorsCollapsible(bool enable)
Q_UNUSED(enable)
}
-void QAndroidPlatformMenu::setTag(quintptr tag)
-{
- m_tag = tag;
-}
-
-quintptr QAndroidPlatformMenu::tag() const
-{
- return m_tag;
-}
-
void QAndroidPlatformMenu::setText(const QString &text)
{
m_text = text;
diff --git a/src/plugins/platforms/android/qandroidplatformmenu.h b/src/plugins/platforms/android/qandroidplatformmenu.h
index 00968672c5..47e650f2d7 100644
--- a/src/plugins/platforms/android/qandroidplatformmenu.h
+++ b/src/plugins/platforms/android/qandroidplatformmenu.h
@@ -61,8 +61,6 @@ public:
void syncMenuItem(QPlatformMenuItem *menuItem) override;
void syncSeparatorsCollapsible(bool enable) override;
- void setTag(quintptr tag) override;
- quintptr tag() const override;
void setText(const QString &text) override;
QString text() const;
void setIcon(const QIcon &icon) override;
@@ -81,7 +79,6 @@ public:
private:
PlatformMenuItemsType m_menuItems;
- quintptr m_tag;
QString m_text;
QIcon m_icon;
bool m_enabled;
diff --git a/src/plugins/platforms/android/qandroidplatformmenuitem.cpp b/src/plugins/platforms/android/qandroidplatformmenuitem.cpp
index 0591522e55..e24c5f974e 100644
--- a/src/plugins/platforms/android/qandroidplatformmenuitem.cpp
+++ b/src/plugins/platforms/android/qandroidplatformmenuitem.cpp
@@ -44,7 +44,6 @@ QT_BEGIN_NAMESPACE
QAndroidPlatformMenuItem::QAndroidPlatformMenuItem()
{
- m_tag = reinterpret_cast<quintptr>(this); // QMenu will overwrite this later, but we need a unique ID for QtQuick
m_menu = 0;
m_isVisible = true;
m_isSeparator = false;
@@ -54,16 +53,6 @@ QAndroidPlatformMenuItem::QAndroidPlatformMenuItem()
m_isEnabled = true;
}
-void QAndroidPlatformMenuItem::setTag(quintptr tag)
-{
- m_tag = tag;
-}
-
-quintptr QAndroidPlatformMenuItem::tag() const
-{
- return m_tag;
-}
-
void QAndroidPlatformMenuItem::setText(const QString &text)
{
m_text = text;
diff --git a/src/plugins/platforms/android/qandroidplatformmenuitem.h b/src/plugins/platforms/android/qandroidplatformmenuitem.h
index be5240cfa6..b8782f995d 100644
--- a/src/plugins/platforms/android/qandroidplatformmenuitem.h
+++ b/src/plugins/platforms/android/qandroidplatformmenuitem.h
@@ -49,8 +49,6 @@ class QAndroidPlatformMenuItem: public QPlatformMenuItem
{
public:
QAndroidPlatformMenuItem();
- void setTag(quintptr tag) override;
- quintptr tag() const override;
void setText(const QString &text) override;
QString text() const;
@@ -86,7 +84,6 @@ public:
void setIconSize(int size) override;
private:
- quintptr m_tag;
QString m_text;
QIcon m_icon;
QAndroidPlatformMenu *m_menu;
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 3b59b293a5..3a79e32abe 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -85,7 +85,8 @@ private:
# define PROFILE_SCOPE
#endif
-QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen()
+QAndroidPlatformScreen::QAndroidPlatformScreen()
+ : QObject(), QPlatformScreen()
{
m_availableGeometry = QRect(0, 0, QAndroidPlatformIntegration::m_defaultGeometryWidth, QAndroidPlatformIntegration::m_defaultGeometryHeight);
m_size = QSize(QAndroidPlatformIntegration::m_defaultScreenWidth, QAndroidPlatformIntegration::m_defaultScreenHeight);
@@ -100,9 +101,6 @@ QAndroidPlatformScreen::QAndroidPlatformScreen():QObject(),QPlatformScreen()
}
m_physicalSize.setHeight(QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight);
m_physicalSize.setWidth(QAndroidPlatformIntegration::m_defaultPhysicalSizeWidth);
- m_redrawTimer.setSingleShot(true);
- m_redrawTimer.setInterval(0);
- connect(&m_redrawTimer, SIGNAL(timeout()), this, SLOT(doRedraw()));
connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QAndroidPlatformScreen::applicationStateChanged);
}
@@ -136,6 +134,16 @@ QWindow *QAndroidPlatformScreen::topLevelAt(const QPoint &p) const
return 0;
}
+bool QAndroidPlatformScreen::event(QEvent *event)
+{
+ if (event->type() == QEvent::UpdateRequest) {
+ doRedraw();
+ m_updatePending = false;
+ return true;
+ }
+ return QObject::event(event);
+}
+
void QAndroidPlatformScreen::addWindow(QAndroidPlatformWindow *window)
{
if (window->parent() && window->isRaster())
@@ -209,8 +217,10 @@ void QAndroidPlatformScreen::lower(QAndroidPlatformWindow *window)
void QAndroidPlatformScreen::scheduleUpdate()
{
- if (!m_redrawTimer.isActive())
- m_redrawTimer.start();
+ if (!m_updatePending) {
+ m_updatePending = true;
+ QCoreApplication::postEvent(this, new QEvent(QEvent::UpdateRequest));
+ }
}
void QAndroidPlatformScreen::setDirty(const QRect &rect)
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h
index 923c9e8832..f15aeae3fd 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.h
+++ b/src/plugins/platforms/android/qandroidplatformscreen.h
@@ -89,10 +89,12 @@ public slots:
void setSize(const QSize &size);
protected:
+ bool event(QEvent *event) override;
+
typedef QList<QAndroidPlatformWindow *> WindowStackType;
WindowStackType m_windowStack;
QRect m_dirtyRect;
- QTimer m_redrawTimer;
+ bool m_updatePending = false;
QRect m_availableGeometry;
int m_depth;
diff --git a/src/plugins/platforms/android/qandroidplatformvulkaninstance.cpp b/src/plugins/platforms/android/qandroidplatformvulkaninstance.cpp
new file mode 100644
index 0000000000..a411d0f007
--- /dev/null
+++ b/src/plugins/platforms/android/qandroidplatformvulkaninstance.cpp
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidplatformvulkaninstance.h"
+
+QT_BEGIN_NAMESPACE
+
+QAndroidPlatformVulkanInstance::QAndroidPlatformVulkanInstance(QVulkanInstance *instance)
+ : m_instance(instance)
+{
+ m_lib.setFileName(QStringLiteral("vulkan"));
+
+ if (!m_lib.load()) {
+ qWarning("Failed to load %s", qPrintable(m_lib.fileName()));
+ return;
+ }
+
+ init(&m_lib);
+}
+
+void QAndroidPlatformVulkanInstance::createOrAdoptInstance()
+{
+ initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_KHR_android_surface"));
+}
+
+QAndroidPlatformVulkanInstance::~QAndroidPlatformVulkanInstance()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformvulkaninstance.h b/src/plugins/platforms/android/qandroidplatformvulkaninstance.h
new file mode 100644
index 0000000000..67edcceed9
--- /dev/null
+++ b/src/plugins/platforms/android/qandroidplatformvulkaninstance.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDPLATFORMVULKANINSTANCE_H
+#define QANDROIDPLATFORMVULKANINSTANCE_H
+
+#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h>
+#include <QLibrary>
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidPlatformVulkanInstance : public QBasicPlatformVulkanInstance
+{
+public:
+ QAndroidPlatformVulkanInstance(QVulkanInstance *instance);
+ ~QAndroidPlatformVulkanInstance();
+
+ void createOrAdoptInstance() override;
+
+private:
+ QVulkanInstance *m_instance;
+ QLibrary m_lib;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDPLATFORMVULKANINSTANCE_H
diff --git a/src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp b/src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp
new file mode 100644
index 0000000000..cc41a871f3
--- /dev/null
+++ b/src/plugins/platforms/android/qandroidplatformvulkanwindow.cpp
@@ -0,0 +1,210 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qandroidplatformvulkanwindow.h"
+#include "qandroidplatformscreen.h"
+#include "androidjnimain.h"
+#include "qandroideventdispatcher.h"
+#include "androiddeadlockprotector.h"
+
+#include <QSurfaceFormat>
+#include <qpa/qwindowsysteminterface.h>
+#include <qpa/qplatformscreen.h>
+
+#include <android/native_window.h>
+#include <android/native_window_jni.h>
+
+QT_BEGIN_NAMESPACE
+
+QAndroidPlatformVulkanWindow::QAndroidPlatformVulkanWindow(QWindow *window)
+ : QAndroidPlatformWindow(window),
+ m_nativeSurfaceId(-1),
+ m_nativeWindow(nullptr),
+ m_vkSurface(0),
+ m_createVkSurface(nullptr),
+ m_destroyVkSurface(nullptr)
+{
+}
+
+QAndroidPlatformVulkanWindow::~QAndroidPlatformVulkanWindow()
+{
+ m_surfaceWaitCondition.wakeOne();
+ lockSurface();
+ if (m_nativeSurfaceId != -1)
+ QtAndroid::destroySurface(m_nativeSurfaceId);
+ clearSurface();
+ unlockSurface();
+}
+
+void QAndroidPlatformVulkanWindow::setGeometry(const QRect &rect)
+{
+ if (rect == geometry())
+ return;
+
+ m_oldGeometry = geometry();
+
+ QAndroidPlatformWindow::setGeometry(rect);
+ if (m_nativeSurfaceId != -1)
+ QtAndroid::setSurfaceGeometry(m_nativeSurfaceId, rect);
+
+ QRect availableGeometry = screen()->availableGeometry();
+ if (m_oldGeometry.width() == 0
+ && m_oldGeometry.height() == 0
+ && rect.width() > 0
+ && rect.height() > 0
+ && availableGeometry.width() > 0
+ && availableGeometry.height() > 0) {
+ QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size()));
+ }
+
+ if (rect.topLeft() != m_oldGeometry.topLeft())
+ repaint(QRegion(rect));
+}
+
+void QAndroidPlatformVulkanWindow::applicationStateChanged(Qt::ApplicationState state)
+{
+ QAndroidPlatformWindow::applicationStateChanged(state);
+ if (state <= Qt::ApplicationHidden) {
+ lockSurface();
+ if (m_nativeSurfaceId != -1) {
+ QtAndroid::destroySurface(m_nativeSurfaceId);
+ m_nativeSurfaceId = -1;
+ }
+ clearSurface();
+ unlockSurface();
+ }
+}
+
+QSurfaceFormat QAndroidPlatformVulkanWindow::format() const
+{
+ return window()->requestedFormat();
+}
+
+void QAndroidPlatformVulkanWindow::clearSurface()
+{
+ if (m_vkSurface && m_destroyVkSurface) {
+ m_destroyVkSurface(window()->vulkanInstance()->vkInstance(), m_vkSurface, nullptr);
+ m_vkSurface = 0;
+ }
+
+ if (m_nativeWindow) {
+ ANativeWindow_release(m_nativeWindow);
+ m_nativeWindow = nullptr;
+ }
+}
+
+void QAndroidPlatformVulkanWindow::sendExpose()
+{
+ QRect availableGeometry = screen()->availableGeometry();
+ if (geometry().width() > 0 && geometry().height() > 0 && availableGeometry.width() > 0 && availableGeometry.height() > 0)
+ QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(), geometry().size())));
+}
+
+void QAndroidPlatformVulkanWindow::surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h)
+{
+ Q_UNUSED(jniEnv);
+ Q_UNUSED(w);
+ Q_UNUSED(h);
+
+ lockSurface();
+ m_androidSurfaceObject = surface;
+ if (surface)
+ m_surfaceWaitCondition.wakeOne();
+ unlockSurface();
+
+ if (surface)
+ sendExpose();
+}
+
+VkSurfaceKHR *QAndroidPlatformVulkanWindow::vkSurface()
+{
+ if (QAndroidEventDispatcherStopper::stopped())
+ return &m_vkSurface;
+
+ bool needsExpose = false;
+ if (!m_vkSurface) {
+ clearSurface();
+
+ QMutexLocker lock(&m_surfaceMutex);
+ if (m_nativeSurfaceId == -1) {
+ AndroidDeadlockProtector protector;
+ if (!protector.acquire())
+ return &m_vkSurface;
+ const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
+ m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32);
+ m_surfaceWaitCondition.wait(&m_surfaceMutex);
+ }
+
+ if (m_nativeSurfaceId == -1 || !m_androidSurfaceObject.isValid())
+ return &m_vkSurface;
+
+ QJNIEnvironmentPrivate env;
+ m_nativeWindow = ANativeWindow_fromSurface(env, m_androidSurfaceObject.object());
+
+ VkAndroidSurfaceCreateInfoKHR surfaceInfo;
+ memset(&surfaceInfo, 0, sizeof(surfaceInfo));
+ surfaceInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
+ surfaceInfo.window = m_nativeWindow;
+ QVulkanInstance *inst = window()->vulkanInstance();
+ if (!inst) {
+ qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?");
+ return &m_vkSurface;
+ }
+ if (!m_createVkSurface) {
+ m_createVkSurface = reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(
+ inst->getInstanceProcAddr("vkCreateAndroidSurfaceKHR"));
+ }
+ if (!m_destroyVkSurface) {
+ m_destroyVkSurface = reinterpret_cast<PFN_vkDestroySurfaceKHR>(
+ inst->getInstanceProcAddr("vkDestroySurfaceKHR"));
+ }
+ VkResult err = m_createVkSurface(inst->vkInstance(), &surfaceInfo, nullptr, &m_vkSurface);
+ if (err != VK_SUCCESS)
+ qWarning("Failed to create Android VkSurface: %d", err);
+
+ needsExpose = true;
+ }
+
+ if (needsExpose)
+ sendExpose();
+
+ return &m_vkSurface;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidplatformvulkanwindow.h b/src/plugins/platforms/android/qandroidplatformvulkanwindow.h
new file mode 100644
index 0000000000..19eca98720
--- /dev/null
+++ b/src/plugins/platforms/android/qandroidplatformvulkanwindow.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANDROIDPLATFORMVULKANWINDOW_H
+#define QANDROIDPLATFORMVULKANWINDOW_H
+
+#if defined(VULKAN_H_) && !defined(VK_USE_PLATFORM_ANDROID_KHR)
+#error "vulkan.h included without Android WSI"
+#endif
+
+#define VK_USE_PLATFORM_ANDROID_KHR
+
+#include <QWaitCondition>
+#include <QtCore/private/qjni_p.h>
+
+#include "androidsurfaceclient.h"
+#include "qandroidplatformwindow.h"
+
+#include "qandroidplatformvulkaninstance.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidPlatformVulkanWindow : public QAndroidPlatformWindow, public AndroidSurfaceClient
+{
+public:
+ explicit QAndroidPlatformVulkanWindow(QWindow *window);
+ ~QAndroidPlatformVulkanWindow();
+
+ void setGeometry(const QRect &rect) override;
+ QSurfaceFormat format() const override;
+ void applicationStateChanged(Qt::ApplicationState) override;
+
+ VkSurfaceKHR *vkSurface();
+
+protected:
+ void surfaceChanged(JNIEnv *jniEnv, jobject surface, int w, int h) override;
+
+private:
+ void sendExpose();
+ void clearSurface();
+
+ int m_nativeSurfaceId;
+ ANativeWindow *m_nativeWindow;
+ QJNIObjectPrivate m_androidSurfaceObject;
+ QWaitCondition m_surfaceWaitCondition;
+ QSurfaceFormat m_format;
+ QRect m_oldGeometry;
+ VkSurfaceKHR m_vkSurface;
+ PFN_vkCreateAndroidSurfaceKHR m_createVkSurface;
+ PFN_vkDestroySurfaceKHR m_destroyVkSurface;
+};
+
+QT_END_NAMESPACE
+
+#endif // QANDROIDPLATFORMVULKANWINDOW_H
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.cpp b/src/plugins/platforms/android/qandroidplatformwindow.cpp
index 424cfefc6c..c095f51fa3 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformwindow.cpp
@@ -56,7 +56,7 @@ QAndroidPlatformWindow::QAndroidPlatformWindow(QWindow *window)
m_windowState = Qt::WindowNoState;
static QAtomicInt winIdGenerator(1);
m_windowId = winIdGenerator.fetchAndAddRelaxed(1);
- setWindowState(window->windowState());
+ setWindowState(window->windowStates());
}
void QAndroidPlatformWindow::lower()
@@ -73,7 +73,6 @@ void QAndroidPlatformWindow::raise()
void QAndroidPlatformWindow::setGeometry(const QRect &rect)
{
QWindowSystemInterface::handleGeometryChange(window(), rect);
- QPlatformWindow::setGeometry(rect);
}
void QAndroidPlatformWindow::setVisible(bool visible)
@@ -98,7 +97,7 @@ void QAndroidPlatformWindow::setVisible(bool visible)
QPlatformWindow::setVisible(visible);
}
-void QAndroidPlatformWindow::setWindowState(Qt::WindowState state)
+void QAndroidPlatformWindow::setWindowState(Qt::WindowStates state)
{
if (m_windowState == state)
return;
diff --git a/src/plugins/platforms/android/qandroidplatformwindow.h b/src/plugins/platforms/android/qandroidplatformwindow.h
index 91cb1e76e6..f2e51bd3df 100644
--- a/src/plugins/platforms/android/qandroidplatformwindow.h
+++ b/src/plugins/platforms/android/qandroidplatformwindow.h
@@ -59,7 +59,7 @@ public:
void setVisible(bool visible) override;
- void setWindowState(Qt::WindowState state) override;
+ void setWindowState(Qt::WindowStates state) override;
void setWindowFlags(Qt::WindowFlags flags) override;
Qt::WindowFlags windowFlags() const;
void setParent(const QPlatformWindow *window) override;
@@ -91,7 +91,7 @@ protected:
protected:
Qt::WindowFlags m_windowFlags;
- Qt::WindowState m_windowState;
+ Qt::WindowStates m_windowState;
WId m_windowId;
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index 13e59906ca..1e6ea70161 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -6,6 +6,7 @@ OBJECTIVE_SOURCES += main.mm \
qcocoabackingstore.mm \
qcocoawindow.mm \
qnsview.mm \
+ qnswindow.mm \
qnsviewaccessibility.mm \
qnswindowdelegate.mm \
qcocoanativeinterface.mm \
@@ -39,6 +40,7 @@ HEADERS += qcocoaintegration.h \
qcocoabackingstore.h \
qcocoawindow.h \
qnsview.h \
+ qnswindow.h \
qnswindowdelegate.h \
qcocoanativeinterface.h \
qcocoaeventdispatcher.h \
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index b15c486e9d..8b6dcb35a6 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -41,8 +41,6 @@
#include <QtGui/qaccessible.h>
#include <private/qcore_mac_p.h>
-#include <Carbon/Carbon.h>
-
QT_BEGIN_NAMESPACE
#ifndef QT_NO_ACCESSIBILITY
@@ -369,7 +367,7 @@ id getValueAttribute(QAccessibleInterface *interface)
QString text;
if (interface->state().passwordEdit) {
// return round password replacement chars
- text = QString(end, QChar(kBulletUnicode));
+ text = QString(end, QChar(0x2022));
} else {
// VoiceOver will read out the entire text string at once when returning
// text as a value. For large text edits the size of the returned string
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index 5ed455fd71..bf6766beaa 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -53,6 +53,7 @@ public:
void flush(QWindow *, const QRegion &, const QPoint &) Q_DECL_OVERRIDE;
private:
+ bool windowHasUnifiedToolbar() const;
QImage::Format format() const Q_DECL_OVERRIDE;
};
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 1d7ad772dc..e0f7f7f57a 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -44,6 +44,8 @@
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcCocoaBackingStore, "qt.qpa.cocoa.backingstore");
+
QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
: QRasterBackingStore(window)
{
@@ -51,26 +53,157 @@ QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
QCocoaBackingStore::~QCocoaBackingStore()
{
- if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle()))
- [qnsview_cast(cocoaWindow->view()) clearBackingStore:this];
+}
+
+bool QCocoaBackingStore::windowHasUnifiedToolbar() const
+{
+ Q_ASSERT(window()->handle());
+ return static_cast<QCocoaWindow *>(window()->handle())->m_drawContentBorderGradient;
}
QImage::Format QCocoaBackingStore::format() const
{
- QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window()->handle());
- if (cocoaWindow && cocoaWindow->m_drawContentBorderGradient)
+ if (windowHasUnifiedToolbar())
return QImage::Format_ARGB32_Premultiplied;
return QRasterBackingStore::format();
}
+#if !QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
+static const NSCompositingOperation NSCompositingOperationCopy = NSCompositeCopy;
+static const NSCompositingOperation NSCompositingOperationSourceOver = NSCompositeSourceOver;
+#endif
+
+/*!
+ Flushes the given \a region from the specified \a window onto the
+ screen.
+
+ The \a window is the top level window represented by this backingstore,
+ or a non-transient child of that window.
+
+ If the \a window is a child window, the \a region will be in child window
+ coordinates, and the \a offset will be the child window's offset in relation
+ to the backingstore's top level window.
+*/
void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
if (m_image.isNull())
return;
- if (QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle()))
- [qnsview_cast(cocoaWindow->view()) flushBackingStore:this region:region offset:offset];
+ const QWindow *topLevelWindow = this->window();
+
+ Q_ASSERT(topLevelWindow->handle() && window->handle());
+ Q_ASSERT(!topLevelWindow->handle()->isForeignWindow() && !window->handle()->isForeignWindow());
+
+ QNSView *topLevelView = qnsview_cast(static_cast<QCocoaWindow *>(topLevelWindow->handle())->view());
+ QNSView *view = qnsview_cast(static_cast<QCocoaWindow *>(window->handle())->view());
+
+ if (lcCocoaBackingStore().isDebugEnabled()) {
+ QString targetViewDescription;
+ if (view != topLevelView) {
+ QDebug targetDebug(&targetViewDescription);
+ targetDebug << "onto" << topLevelView << "at" << offset;
+ }
+ qCDebug(lcCocoaBackingStore) << "Flushing" << region << "of" << view << targetViewDescription;
+ }
+
+ // Normally a NSView is drawn via drawRect, as part of the display cycle in the
+ // main runloop, via setNeedsDisplay and friends. AppKit will lock focus on each
+ // individual view, starting with the top level and then traversing any subviews,
+ // calling drawRect for each of them. This pull model results in expose events
+ // sent to Qt, which result in drawing to the backingstore and flushing it.
+ // Qt may also decide to paint and flush the backingstore via e.g. timers,
+ // or other events such as mouse events, in which case we're in a push model.
+ // If there is no focused view, it means we're in the latter case, and need
+ // to manually flush the NSWindow after drawing to its graphic context.
+ const bool drawingOutsideOfDisplayCycle = ![NSView focusView];
+
+ // We also need to ensure the flushed view has focus, so that the graphics
+ // context is set up correctly (coordinate system, clipping, etc). Outside
+ // of the normal display cycle there is no focused view, as explained above,
+ // so we have to handle it manually. There's also a corner case inside the
+ // normal display cycle due to way QWidgetBackingStore composits native child
+ // widgets, where we'll get a flush of a native child during the drawRect of
+ // its parent/ancestor, and the parent/ancestor being the one locked by AppKit.
+ // In this case we also need to lock and unlock focus manually.
+ const bool shouldHandleViewLockManually = [NSView focusView] != view;
+ if (shouldHandleViewLockManually && ![view lockFocusIfCanDraw]) {
+ qWarning() << "failed to lock focus of" << view;
+ return;
+ }
+
+ const qreal devicePixelRatio = m_image.devicePixelRatio();
+
+ // If the flushed window is a content view, and not in unified toolbar mode,
+ // we can get away with copying the backingstore instead of blending.
+ const NSCompositingOperation compositingOperation = static_cast<QCocoaWindow *>(
+ window->handle())->isContentView() && !windowHasUnifiedToolbar() ?
+ NSCompositingOperationCopy : NSCompositingOperationSourceOver;
+
+#ifdef QT_DEBUG
+ static bool debugBackingStoreFlush = [[NSUserDefaults standardUserDefaults]
+ boolForKey:@"QtCocoaDebugBackingStoreFlush"];
+#endif
+
+ // -------------------------------------------------------------------------
+
+ // The current contexts is typically a NSWindowGraphicsContext, but can be
+ // NSBitmapGraphicsContext e.g. when debugging the view hierarchy in Xcode.
+ // If we need to distinguish things here in the future, we can use e.g.
+ // [NSGraphicsContext drawingToScreen], or the attributes of the context.
+ NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
+ Q_ASSERT_X(graphicsContext, "QCocoaBackingStore",
+ "Focusing the view should give us a current graphics context");
+
+ // Create temporary image to use for blitting, without copying image data
+ NSImage *backingStoreImage = [[[NSImage alloc]
+ initWithCGImage:QCFType<CGImageRef>(m_image.toCGImage()) size:NSZeroSize] autorelease];
+
+ if ([topLevelView hasMask]) {
+ // FIXME: Implement via NSBezierPath and addClip
+ CGRect boundingRect = region.boundingRect().toCGRect();
+ QCFType<CGImageRef> subMask = CGImageCreateWithImageInRect([topLevelView maskImage], boundingRect);
+ CGContextClipToMask(graphicsContext.CGContext, boundingRect, subMask);
+ }
+
+ for (const QRect &viewLocalRect : region) {
+ QPoint backingStoreOffset = viewLocalRect.topLeft() + offset;
+ QRect backingStoreRect(backingStoreOffset * devicePixelRatio, viewLocalRect.size() * devicePixelRatio);
+ if (graphicsContext.flipped) // Flip backingStoreRect to match graphics context
+ backingStoreRect.moveTop(m_image.height() - (backingStoreRect.y() + backingStoreRect.height()));
+
+ CGRect viewRect = viewLocalRect.toCGRect();
+
+ if (windowHasUnifiedToolbar())
+ NSDrawWindowBackground(viewRect);
+
+ [backingStoreImage drawInRect:viewRect fromRect:backingStoreRect.toCGRect()
+ operation:compositingOperation fraction:1.0 respectFlipped:YES hints:nil];
+
+#ifdef QT_DEBUG
+ if (Q_UNLIKELY(debugBackingStoreFlush)) {
+ [[NSColor colorWithCalibratedRed:drand48() green:drand48() blue:drand48() alpha:0.3] set];
+ [NSBezierPath fillRect:viewRect];
+
+ if (drawingOutsideOfDisplayCycle) {
+ [[[NSColor magentaColor] colorWithAlphaComponent:0.5] set];
+ [NSBezierPath strokeLineFromPoint:viewLocalRect.topLeft().toCGPoint()
+ toPoint:viewLocalRect.bottomRight().toCGPoint()];
+ }
+ }
+#endif
+ }
+
+ // -------------------------------------------------------------------------
+
+ if (shouldHandleViewLockManually)
+ [view unlockFocus];
+
+ if (drawingOutsideOfDisplayCycle)
+ [view.window flushWindow];
+
+ // FIXME: Tie to changing window flags and/or mask instead
+ [view invalidateWindowShadowIfNeeded];
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h
index 9ebb090989..c7277a47bf 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.h
+++ b/src/plugins/platforms/cocoa/qcocoadrag.h
@@ -55,7 +55,7 @@ public:
QCocoaDrag();
~QCocoaDrag();
- QMimeData *platformDropData() Q_DECL_OVERRIDE;
+ QMimeData *dragMimeData();
Qt::DropAction drag(QDrag *m_drag) Q_DECL_OVERRIDE;
Qt::DropAction defaultAction(Qt::DropActions possibleActions,
diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm
index c71e80d191..3bd0b05725 100644
--- a/src/plugins/platforms/cocoa/qcocoadrag.mm
+++ b/src/plugins/platforms/cocoa/qcocoadrag.mm
@@ -68,7 +68,7 @@ void QCocoaDrag::setLastMouseEvent(NSEvent *event, NSView *view)
m_lastView = view;
}
-QMimeData *QCocoaDrag::platformDropData()
+QMimeData *QCocoaDrag::dragMimeData()
{
if (m_drag)
return m_drag->mimeData();
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index 70887c41c9..2ffc1395ba 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -177,8 +177,6 @@ public:
void maybeCancelWaitForMoreEvents();
void ensureNSAppInitialized();
- void removeQueuedUserInputEvents(int nsWinNumber);
-
QCFSocketNotifier cfSocketNotifier;
QList<void *> queuedUserInputEvents; // NSEvent *
CFRunLoopSourceRef postedEventsSource;
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index d2f985ec87..874d3fc24b 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -86,7 +86,6 @@
#include <qdebug.h>
#include <AppKit/AppKit.h>
-#include <Carbon/Carbon.h>
QT_BEGIN_NAMESPACE
@@ -285,7 +284,7 @@ bool QCocoaEventDispatcher::hasPendingEvents()
{
extern uint qGlobalPostedEventsCount();
extern bool qt_is_gui_used; //qapplication.cpp
- return qGlobalPostedEventsCount() || (qt_is_gui_used && GetNumEventsInQueue(GetMainEventQueue()));
+ return qGlobalPostedEventsCount() || (qt_is_gui_used && !CFRunLoopIsWaiting(CFRunLoopGetMain()));
}
static bool IsMouseOrKeyEvent( NSEvent* event )
@@ -890,21 +889,6 @@ void QCocoaEventDispatcherPrivate::processPostedEvents()
}
}
-void QCocoaEventDispatcherPrivate::removeQueuedUserInputEvents(int nsWinNumber)
-{
- if (nsWinNumber) {
- int eventIndex = queuedUserInputEvents.size();
-
- while (--eventIndex >= 0) {
- NSEvent * nsevent = static_cast<NSEvent *>(queuedUserInputEvents.at(eventIndex));
- if ([nsevent windowNumber] == nsWinNumber) {
- queuedUserInputEvents.removeAt(eventIndex);
- [nsevent release];
- }
- }
- }
-}
-
void QCocoaEventDispatcherPrivate::firstLoopEntry(CFRunLoopObserverRef ref,
CFRunLoopActivity activity,
void *info)
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index 74148b7cbf..9a00eb89b7 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -231,7 +231,7 @@ static QString strippedText(QString s)
[mOpenPanel beginWithCompletionHandler:^(NSInteger result){
mReturnCode = result;
if (mHelper)
- mHelper->QNSOpenSavePanelDelegate_panelClosed(result == NSOKButton);
+ mHelper->QNSOpenSavePanelDelegate_panelClosed(result == NSModalResponseOK);
}];
}
}
@@ -260,12 +260,12 @@ static QString strippedText(QString s)
QCocoaMenuBar::resetKnownMenuItemsToQt();
QAbstractEventDispatcher::instance()->interrupt();
- return (mReturnCode == NSOKButton);
+ return (mReturnCode == NSModalResponseOK);
}
- (QPlatformDialogHelper::DialogCode)dialogResultCode
{
- return (mReturnCode == NSOKButton) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
+ return (mReturnCode == NSModalResponseOK) ? QPlatformDialogHelper::Accepted : QPlatformDialogHelper::Rejected;
}
- (void)showWindowModalSheet:(QWindow *)parent
@@ -286,7 +286,7 @@ static QString strippedText(QString s)
[mSavePanel beginSheetModalForWindow:nsparent completionHandler:^(NSInteger result){
mReturnCode = result;
if (mHelper)
- mHelper->QNSOpenSavePanelDelegate_panelClosed(result == NSOKButton);
+ mHelper->QNSOpenSavePanelDelegate_panelClosed(result == NSModalResponseOK);
}];
}
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm
index 5d0f13c5a9..9f9618177d 100644
--- a/src/plugins/platforms/cocoa/qcocoahelpers.mm
+++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm
@@ -55,8 +55,6 @@
#include <algorithm>
-#include <Carbon/Carbon.h>
-
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaCocoaWindow, "qt.qpa.cocoa.window");
@@ -407,6 +405,7 @@ QT_END_NAMESPACE
self.panelContents.needsDisplay = YES;
self.needsDisplay = YES;
+ [super layout];
}
@end
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index ecdd20c4dc..d3f2079042 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -92,6 +92,8 @@ public:
QPointF mapFromNative(const QPointF &pos) const { return flipCoordinate(pos); }
QRectF mapFromNative(const QRectF &rect) const { return flipCoordinate(rect); }
+ static QCocoaScreen *primaryScreen();
+
private:
QPointF flipCoordinate(const QPointF &pos) const;
QRectF flipCoordinate(const QRectF &rect) const;
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index bac49cfad9..1df74c986a 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -145,7 +145,7 @@ void QCocoaScreen::updateGeometry()
// we may be in the process of creating and registering the primary screen, we
// must special-case that and assign it direcly.
QCocoaScreen *primaryScreen = (nsScreen == [[NSScreen screens] firstObject]) ?
- this : static_cast<QCocoaScreen*>(QGuiApplication::primaryScreen()->handle());
+ this : QCocoaScreen::primaryScreen();
m_geometry = primaryScreen->mapFromNative(m_geometry).toRect();
m_availableGeometry = primaryScreen->mapFromNative(m_availableGeometry).toRect();
@@ -293,6 +293,14 @@ QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height
return windowPixmap;
}
+/*!
+ The screen used as a reference for global window geometry
+*/
+QCocoaScreen *QCocoaScreen::primaryScreen()
+{
+ return static_cast<QCocoaScreen *>(QGuiApplication::primaryScreen()->handle());
+}
+
static QCocoaIntegration::Options parseOptions(const QStringList &paramList)
{
QCocoaIntegration::Options options;
diff --git a/src/plugins/platforms/cocoa/qcocoakeymapper.mm b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
index 1ef7f11011..5fa062bbe0 100644
--- a/src/plugins/platforms/cocoa/qcocoakeymapper.mm
+++ b/src/plugins/platforms/cocoa/qcocoakeymapper.mm
@@ -72,14 +72,6 @@ static const Qt::KeyboardModifiers ModsTbl[] = {
bool qt_mac_eat_unicode_key = false;
-Q_GUI_EXPORT void qt_mac_secure_keyboard(bool b)
-{
- static bool secure = false;
- if (b != secure){
- b ? EnableSecureEventInput() : DisableSecureEventInput();
- secure = b;
- }
-}
/* key maps */
struct qt_mac_enum_mapper
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h
index b77071536b..903d41220a 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.h
+++ b/src/plugins/platforms/cocoa/qcocoamenu.h
@@ -55,11 +55,6 @@ public:
QCocoaMenu();
~QCocoaMenu();
- void setTag(quintptr tag) Q_DECL_OVERRIDE
- { m_tag = tag; }
- quintptr tag() const Q_DECL_OVERRIDE
- { return m_tag; }
-
void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE;
void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
void syncMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE;
@@ -103,7 +98,6 @@ private:
QList<QCocoaMenuItem *> m_menuItems;
NSMenu *m_nativeMenu;
NSMenuItem *m_attachedItem;
- quintptr m_tag;
bool m_enabled:1;
bool m_parentEnabled:1;
bool m_visible:1;
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 8e47974d12..ada6334cf4 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -259,7 +259,6 @@ QT_BEGIN_NAMESPACE
QCocoaMenu::QCocoaMenu() :
m_attachedItem(0),
- m_tag(0),
m_enabled(true),
m_parentEnabled(true),
m_visible(true),
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h
index 23f788687c..53862d0484 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.h
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h
@@ -78,11 +78,6 @@ public:
QCocoaMenuItem();
~QCocoaMenuItem();
- void setTag(quintptr tag) Q_DECL_OVERRIDE
- { m_tag = tag; }
- quintptr tag() const Q_DECL_OVERRIDE
- { return m_tag; }
-
void setText(const QString &text) Q_DECL_OVERRIDE;
void setIcon(const QIcon &icon) Q_DECL_OVERRIDE;
void setMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE;
@@ -129,7 +124,6 @@ private:
#ifndef QT_NO_SHORTCUT
QKeySequence m_shortcut;
#endif
- quintptr m_tag;
int m_iconSize;
bool m_textSynced:1;
bool m_isVisible:1;
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index 21f2b4de85..d135b244e0 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -95,7 +95,6 @@ QCocoaMenuItem::QCocoaMenuItem() :
m_itemView(nil),
m_menu(NULL),
m_role(NoRole),
- m_tag(0),
m_iconSize(16),
m_textSynced(false),
m_isVisible(true),
diff --git a/src/plugins/platforms/cocoa/qcocoamimetypes.mm b/src/plugins/platforms/cocoa/qcocoamimetypes.mm
index 093f86da6e..f7662a92a4 100644
--- a/src/plugins/platforms/cocoa/qcocoamimetypes.mm
+++ b/src/plugins/platforms/cocoa/qcocoamimetypes.mm
@@ -105,101 +105,9 @@ QList<QByteArray> QMacPasteboardMimeTraditionalMacPlainText::convertFromMime(con
return ret;
}
-class QMacPasteboardMimeTiff : public QMacInternalPasteboardMime {
-public:
- QMacPasteboardMimeTiff() : QMacInternalPasteboardMime(MIME_ALL) { }
- QString convertorName();
-
- QString flavorFor(const QString &mime);
- QString mimeFor(QString flav);
- bool canConvert(const QString &mime, QString flav);
- QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
- QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
-};
-
-QString QMacPasteboardMimeTiff::convertorName()
-{
- return QLatin1String("Tiff");
-}
-
-QString QMacPasteboardMimeTiff::flavorFor(const QString &mime)
-{
- if (mime.startsWith(QLatin1String("application/x-qt-image")))
- return QLatin1String("public.tiff");
- return QString();
-}
-
-QString QMacPasteboardMimeTiff::mimeFor(QString flav)
-{
- if (flav == QLatin1String("public.tiff"))
- return QLatin1String("application/x-qt-image");
- return QString();
-}
-
-bool QMacPasteboardMimeTiff::canConvert(const QString &mime, QString flav)
-{
- return flav == QLatin1String("public.tiff") && mime == QLatin1String("application/x-qt-image");
-}
-
-QVariant QMacPasteboardMimeTiff::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
-{
- if (data.count() > 1)
- qWarning("QMacPasteboardMimeTiff: Cannot handle multiple member data");
- QVariant ret;
- if (!canConvert(mime, flav))
- return ret;
- const QByteArray &a = data.first();
- QCFType<CGImageRef> image;
- QCFType<CFDataRef> tiffData = CFDataCreateWithBytesNoCopy(0,
- reinterpret_cast<const UInt8 *>(a.constData()),
- a.size(), kCFAllocatorNull);
- QCFType<CGImageSourceRef> imageSource = CGImageSourceCreateWithData(tiffData, 0);
- image = CGImageSourceCreateImageAtIndex(imageSource, 0, 0);
- if (image != 0)
- ret = QVariant(qt_mac_toQImage(image));
- return ret;
-}
-
-QList<QByteArray> QMacPasteboardMimeTiff::convertFromMime(const QString &mime, QVariant variant, QString flav)
-{
- QList<QByteArray> ret;
- if (!canConvert(mime, flav))
- return ret;
-
- QImage img = qvariant_cast<QImage>(variant);
- QCFType<CGImageRef> cgimage = qt_mac_toCGImage(img);
-
- QCFType<CFMutableDataRef> data = CFDataCreateMutable(0, 0);
- QCFType<CGImageDestinationRef> imageDestination = CGImageDestinationCreateWithData(data, kUTTypeTIFF, 1, 0);
- if (imageDestination != 0) {
- CFTypeRef keys[2];
- QCFType<CFTypeRef> values[2];
- QCFType<CFDictionaryRef> options;
- keys[0] = kCGImagePropertyPixelWidth;
- keys[1] = kCGImagePropertyPixelHeight;
- int width = img.width();
- int height = img.height();
- values[0] = CFNumberCreate(0, kCFNumberIntType, &width);
- values[1] = CFNumberCreate(0, kCFNumberIntType, &height);
- options = CFDictionaryCreate(0, reinterpret_cast<const void **>(keys),
- reinterpret_cast<const void **>(values), 2,
- &kCFTypeDictionaryKeyCallBacks,
- &kCFTypeDictionaryValueCallBacks);
- CGImageDestinationAddImage(imageDestination, cgimage, options);
- CGImageDestinationFinalize(imageDestination);
- }
- QByteArray ar(CFDataGetLength(data), 0);
- CFDataGetBytes(data,
- CFRangeMake(0, ar.size()),
- reinterpret_cast<UInt8 *>(ar.data()));
- ret.append(ar);
- return ret;
-}
-
void QCocoaMimeTypes::initializeMimeTypes()
{
new QMacPasteboardMimeTraditionalMacPlainText;
- new QMacPasteboardMimeTiff;
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
index 26ab07ffaf..8943cb6cd5 100644
--- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
+++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm
@@ -103,7 +103,7 @@ void *QCocoaNativeInterface::nativeResourceForWindow(const QByteArray &resourceS
return static_cast<QCocoaWindow *>(window->handle())->currentContext()->nsOpenGLContext();
#endif
} else if (resourceString == "nswindow") {
- return static_cast<QCocoaWindow *>(window->handle())->m_nsWindow;
+ return static_cast<QCocoaWindow *>(window->handle())->nativeWindow();
}
return 0;
}
diff --git a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
index 9ddad7fc7a..91fb6e973d 100644
--- a/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
+++ b/src/plugins/platforms/cocoa/qcocoasystemsettings.mm
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins of the Qt Toolkit.
@@ -45,49 +45,8 @@
#include <QtGui/qfont.h>
#include <QtGui/private/qcoregraphics_p.h>
-#include <Carbon/Carbon.h>
-
QT_BEGIN_NAMESPACE
-QBrush qt_mac_brushForTheme(ThemeBrush brush)
-{
- QMacAutoReleasePool pool;
-
- QCFType<CGColorRef> cgClr = 0;
- HIThemeBrushCreateCGColor(brush, &cgClr);
- return qt_mac_toQBrush(cgClr);
-}
-
-QColor qt_mac_colorForThemeTextColor(ThemeTextColor themeColor)
-{
- // No GetThemeTextColor in 64-bit mode, use hardcoded values:
- switch (themeColor) {
- case kThemeTextColorAlertActive:
- case kThemeTextColorTabFrontActive:
- case kThemeTextColorBevelButtonActive:
- case kThemeTextColorListView:
- case kThemeTextColorPlacardActive:
- case kThemeTextColorPopupButtonActive:
- case kThemeTextColorPopupLabelActive:
- case kThemeTextColorPushButtonActive:
- return Qt::black;
- case kThemeTextColorAlertInactive:
- case kThemeTextColorDialogInactive:
- case kThemeTextColorPlacardInactive:
- case kThemeTextColorPopupButtonInactive:
- case kThemeTextColorPopupLabelInactive:
- case kThemeTextColorPushButtonInactive:
- case kThemeTextColorTabFrontInactive:
- case kThemeTextColorBevelButtonInactive:
- case kThemeTextColorMenuItemDisabled:
- return QColor(127, 127, 127, 255);
- case kThemeTextColorMenuItemSelected:
- return Qt::white;
- default:
- return QColor(0, 0, 0, 255); // ### TODO: Sample color like Qt 4.
- }
-}
-
QPalette * qt_mac_createSystemPalette()
{
QColor qc;
@@ -119,7 +78,7 @@ QPalette * qt_mac_createSystemPalette()
palette->setBrush(QPalette::Shadow, background.darker(170));
- qc = qt_mac_colorForThemeTextColor(kThemeTextColorDialogActive);
+ qc = qt_mac_toQColor([NSColor controlTextColor]);
palette->setColor(QPalette::Active, QPalette::Text, qc);
palette->setColor(QPalette::Active, QPalette::WindowText, qc);
palette->setColor(QPalette::Active, QPalette::HighlightedText, qc);
@@ -127,7 +86,7 @@ QPalette * qt_mac_createSystemPalette()
palette->setColor(QPalette::Inactive, QPalette::WindowText, qc);
palette->setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
- qc = qt_mac_colorForThemeTextColor(kThemeTextColorDialogInactive);
+ qc = qt_mac_toQColor([NSColor disabledControlTextColor]);
palette->setColor(QPalette::Disabled, QPalette::Text, qc);
palette->setColor(QPalette::Disabled, QPalette::WindowText, qc);
palette->setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
@@ -136,60 +95,67 @@ QPalette * qt_mac_createSystemPalette()
}
struct QMacPaletteMap {
- inline QMacPaletteMap(QPlatformTheme::Palette p, ThemeBrush a, ThemeBrush i) :
+ inline QMacPaletteMap(QPlatformTheme::Palette p, NSColor *a, NSColor *i) :
paletteRole(p), active(a), inactive(i) { }
QPlatformTheme::Palette paletteRole;
- ThemeBrush active, inactive;
+ NSColor *active, *inactive;
};
+#define MAC_PALETTE_ENTRY(pal, active, inactive) \
+ QMacPaletteMap(pal, [NSColor active], [NSColor inactive])
static QMacPaletteMap mac_widget_colors[] = {
- QMacPaletteMap(QPlatformTheme::ToolButtonPalette, kThemeTextColorBevelButtonActive, kThemeTextColorBevelButtonInactive),
- QMacPaletteMap(QPlatformTheme::ButtonPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
- QMacPaletteMap(QPlatformTheme::HeaderPalette, kThemeTextColorPushButtonActive, kThemeTextColorPushButtonInactive),
- QMacPaletteMap(QPlatformTheme::ComboBoxPalette, kThemeTextColorPopupButtonActive, kThemeTextColorPopupButtonInactive),
- QMacPaletteMap(QPlatformTheme::ItemViewPalette, kThemeTextColorListView, kThemeTextColorDialogInactive),
- QMacPaletteMap(QPlatformTheme::MessageBoxLabelPalette, kThemeTextColorAlertActive, kThemeTextColorAlertInactive),
- QMacPaletteMap(QPlatformTheme::TabBarPalette, kThemeTextColorTabFrontActive, kThemeTextColorTabFrontInactive),
- QMacPaletteMap(QPlatformTheme::LabelPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
- QMacPaletteMap(QPlatformTheme::GroupBoxPalette, kThemeTextColorPlacardActive, kThemeTextColorPlacardInactive),
- QMacPaletteMap(QPlatformTheme::MenuPalette, kThemeTextColorMenuItemActive, kThemeTextColorMenuItemDisabled),
- QMacPaletteMap(QPlatformTheme::MenuBarPalette, kThemeTextColorMenuItemActive, kThemeTextColorMenuItemDisabled),
- //### TODO: The zeros below gives white-on-black text.
- QMacPaletteMap(QPlatformTheme::TextEditPalette, 0, 0),
- QMacPaletteMap(QPlatformTheme::TextLineEditPalette, 0, 0),
- QMacPaletteMap(QPlatformTheme::NPalettes, 0, 0) };
+ MAC_PALETTE_ENTRY(QPlatformTheme::ToolButtonPalette, controlTextColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::ButtonPalette, controlTextColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::HeaderPalette, headerTextColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::ComboBoxPalette, controlTextColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::ItemViewPalette, textColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::MessageBoxLabelPalette, textColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::TabBarPalette, controlTextColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::LabelPalette, textColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::GroupBoxPalette, textColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::MenuPalette, controlTextColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::MenuBarPalette, controlTextColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::TextEditPalette, textColor, disabledControlTextColor),
+ MAC_PALETTE_ENTRY(QPlatformTheme::TextLineEditPalette, textColor, disabledControlTextColor)
+};
+#undef MAC_PALETTE_ENTRY
+
+static const int mac_widget_colors_count = sizeof(mac_widget_colors) / sizeof(mac_widget_colors[0]);
QHash<QPlatformTheme::Palette, QPalette*> qt_mac_createRolePalettes()
{
QHash<QPlatformTheme::Palette, QPalette*> palettes;
QColor qc;
- for (int i = 0; mac_widget_colors[i].paletteRole != QPlatformTheme::NPalettes; i++) {
+ for (int i = 0; i < mac_widget_colors_count; i++) {
QPalette &pal = *qt_mac_createSystemPalette();
if (mac_widget_colors[i].active != 0) {
- qc = qt_mac_colorForThemeTextColor(mac_widget_colors[i].active);
+ qc = qt_mac_toQColor(mac_widget_colors[i].active);
pal.setColor(QPalette::Active, QPalette::Text, qc);
pal.setColor(QPalette::Inactive, QPalette::Text, qc);
pal.setColor(QPalette::Active, QPalette::WindowText, qc);
pal.setColor(QPalette::Inactive, QPalette::WindowText, qc);
pal.setColor(QPalette::Active, QPalette::HighlightedText, qc);
pal.setColor(QPalette::Inactive, QPalette::HighlightedText, qc);
- qc = qt_mac_colorForThemeTextColor(mac_widget_colors[i].inactive);
+ qc = qt_mac_toQColor(mac_widget_colors[i].inactive);
pal.setColor(QPalette::Disabled, QPalette::Text, qc);
pal.setColor(QPalette::Disabled, QPalette::WindowText, qc);
pal.setColor(QPalette::Disabled, QPalette::HighlightedText, qc);
}
if (mac_widget_colors[i].paletteRole == QPlatformTheme::MenuPalette
|| mac_widget_colors[i].paletteRole == QPlatformTheme::MenuBarPalette) {
- pal.setBrush(QPalette::Background, qt_mac_brushForTheme(kThemeBrushMenuBackground));
- qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemActive);
+ pal.setBrush(QPalette::Background, qt_mac_toQColor([NSColor windowBackgroundColor]));
+ pal.setBrush(QPalette::Highlight, qt_mac_toQColor([NSColor selectedMenuItemColor]));
+ qc = qt_mac_toQColor([NSColor labelColor]);
pal.setBrush(QPalette::ButtonText, qc);
- qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemSelected);
+ pal.setBrush(QPalette::Text, qc);
+ qc = qt_mac_toQColor([NSColor selectedMenuItemTextColor]);
pal.setBrush(QPalette::HighlightedText, qc);
- qc = qt_mac_colorForThemeTextColor(kThemeTextColorMenuItemDisabled);
+ qc = qt_mac_toQColor([NSColor disabledControlTextColor]);
pal.setBrush(QPalette::Disabled, QPalette::Text, qc);
} else if ((mac_widget_colors[i].paletteRole == QPlatformTheme::ButtonPalette)
- || (mac_widget_colors[i].paletteRole == QPlatformTheme::HeaderPalette)) {
+ || (mac_widget_colors[i].paletteRole == QPlatformTheme::HeaderPalette)
+ || (mac_widget_colors[i].paletteRole == QPlatformTheme::TabBarPalette)) {
pal.setColor(QPalette::Disabled, QPalette::ButtonText,
pal.color(QPalette::Disabled, QPalette::Text));
pal.setColor(QPalette::Inactive, QPalette::ButtonText,
diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm
index a1c1b379f7..04dce802f3 100644
--- a/src/plugins/platforms/cocoa/qcocoatheme.mm
+++ b/src/plugins/platforms/cocoa/qcocoatheme.mm
@@ -341,7 +341,7 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const
case IconPixmapSizes:
return QVariant::fromValue(QCocoaFileIconEngine::availableIconSizes());
case QPlatformTheme::PasswordMaskCharacter:
- return QVariant(QChar(kBulletUnicode));
+ return QVariant(QChar(0x2022));
case QPlatformTheme::UiEffects:
return QVariant(int(HoverEffect));
default:
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h
index deba861fcc..e20f033a43 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.h
+++ b/src/plugins/platforms/cocoa/qcocoawindow.h
@@ -50,79 +50,15 @@
#include "qcocoaglcontext.h"
#endif
#include "qnsview.h"
+#include "qnswindow.h"
#include "qt_mac_p.h"
-QT_FORWARD_DECLARE_CLASS(QCocoaWindow)
-
-@class QT_MANGLE_NAMESPACE(QNSWindowHelper);
-
-@protocol QNSWindowProtocol
-
-@property (nonatomic, readonly) QT_MANGLE_NAMESPACE(QNSWindowHelper) *helper;
-
-- (void)superSendEvent:(NSEvent *)theEvent;
-- (void)closeAndRelease;
-
-@end
-
-typedef NSWindow<QNSWindowProtocol> QCocoaNSWindow;
-
-@interface QT_MANGLE_NAMESPACE(QNSWindowHelper) : NSObject
-{
- QCocoaNSWindow *_window;
- QPointer<QCocoaWindow> _platformWindow;
- BOOL _grabbingMouse;
- BOOL _releaseOnMouseUp;
-}
-
-@property (nonatomic, readonly) QCocoaNSWindow *window;
-@property (nonatomic, readonly) QCocoaWindow *platformWindow;
-@property (nonatomic) BOOL grabbingMouse;
-@property (nonatomic) BOOL releaseOnMouseUp;
-
-- (id)initWithNSWindow:(QCocoaNSWindow *)window platformWindow:(QCocoaWindow *)platformWindow;
-- (void)handleWindowEvent:(NSEvent *)theEvent;
-- (void) clearWindow;
-
-@end
-
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindowHelper);
-
-@interface QT_MANGLE_NAMESPACE(QNSWindow) : NSWindow<QNSWindowProtocol>
-{
- QNSWindowHelper *_helper;
-}
-
-@property (nonatomic, readonly) QNSWindowHelper *helper;
-
-- (id)initWithContentRect:(NSRect)contentRect
- screen:(NSScreen*)screen
- styleMask:(NSUInteger)windowStyle
- qPlatformWindow:(QCocoaWindow *)qpw;
-
-@end
-
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindow);
-
-@interface QT_MANGLE_NAMESPACE(QNSPanel) : NSPanel<QNSWindowProtocol>
-{
- QNSWindowHelper *_helper;
-}
-
-@property (nonatomic, readonly) QNSWindowHelper *helper;
-
-- (id)initWithContentRect:(NSRect)contentRect
- screen:(NSScreen*)screen
- styleMask:(NSUInteger)windowStyle
- qPlatformWindow:(QCocoaWindow *)qpw;
-
-@end
-
-QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSPanel);
+QT_BEGIN_NAMESPACE
-@class QT_MANGLE_NAMESPACE(QNSWindowDelegate);
+#ifndef QT_NO_DEBUG_STREAM
+class QDebug;
+#endif
-QT_BEGIN_NAMESPACE
// QCocoaWindow
//
// QCocoaWindow is an NSView (not an NSWindow!) in the sense
@@ -159,16 +95,15 @@ public:
QCocoaWindow(QWindow *tlw, WId nativeHandle = 0);
~QCocoaWindow();
+ void initialize() override;
+
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
QRect geometry() const Q_DECL_OVERRIDE;
void setCocoaGeometry(const QRect &rect);
- void clipChildWindows();
- void clipWindow(const NSRect &clipRect);
- void show(bool becauseOfAncestor = false);
- void hide(bool becauseOfAncestor = false);
+
void setVisible(bool visible) Q_DECL_OVERRIDE;
void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
- void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
+ void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
void setWindowFilePath(const QString &filePath) Q_DECL_OVERRIDE;
void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE;
@@ -221,11 +156,8 @@ public:
bool windowShouldClose();
bool windowIsPopupType(Qt::WindowType type = Qt::Widget) const;
- void reportCurrentWindowState(bool unconditionally = false);
-
NSInteger windowLevel(Qt::WindowFlags flags);
NSUInteger windowStyleMask(Qt::WindowFlags flags);
- void setWindowShadow(Qt::WindowFlags flags);
void setWindowZoomButton(Qt::WindowFlags flags);
#ifndef QT_NO_OPENGL
@@ -252,14 +184,10 @@ public:
void setContentBorderAreaEnabled(quintptr identifier, bool enable);
void setContentBorderEnabled(bool enable);
bool testContentBorderAreaPosition(int position) const;
- void applyContentBorderThickness(NSWindow *window);
+ void applyContentBorderThickness(NSWindow *window = nullptr);
void updateNSToolbar();
qreal devicePixelRatio() const Q_DECL_OVERRIDE;
- bool isWindowExposable();
- void exposeWindow();
- void obscureWindow();
- void updateExposedGeometry();
QWindow *childWindowAt(QPoint windowPoint);
bool shouldRefuseKeyWindowAndFirstResponder();
@@ -271,7 +199,6 @@ public:
ParentChanged = 0x1,
MissingWindow = 0x2,
WindowModalityChanged = 0x4,
- ChildNSWindowChanged = 0x8,
ContentViewChanged = 0x10,
PanelChanged = 0x20,
};
@@ -279,20 +206,13 @@ public:
Q_FLAG(RecreationReasons)
protected:
- bool isChildNSWindow() const;
- bool isContentView() const;
-
- void foreachChildNSWindow(void (^block)(QCocoaWindow *));
-
void recreateWindowIfNeeded();
- QCocoaNSWindow *createNSWindow(bool shouldBeChildNSWindow, bool shouldBePanel);
+ QCocoaNSWindow *createNSWindow(bool shouldBePanel);
QRect nativeWindowGeometry() const;
- void reinsertChildWindow(QCocoaWindow *child);
- void removeChildWindow(QCocoaWindow *child);
Qt::WindowState windowState() const;
- void applyWindowState(Qt::WindowState newState);
+ void applyWindowState(Qt::WindowStates newState);
void toggleMaximized();
void toggleFullScreen();
bool isTransitioningToFullScreen() const;
@@ -302,24 +222,34 @@ public: // for QNSView
friend class QCocoaBackingStore;
friend class QCocoaNativeInterface;
+ bool isContentView() const;
+
bool alwaysShowToolWindow() const;
void removeMonitor();
+ enum HandleFlags {
+ NoHandleFlags = 0,
+ HandleUnconditionally = 1
+ };
+
+ void handleGeometryChange();
+ void handleWindowStateChanged(HandleFlags flags = NoHandleFlags);
+ void handleExposeEvent(const QRegion &region);
+
NSView *m_view;
QCocoaNSWindow *m_nsWindow;
- QPointer<QCocoaWindow> m_forwardWindow;
// TODO merge to one variable if possible
bool m_viewIsEmbedded; // true if the m_view is actually embedded in a "foreign" NSView hiearchy
bool m_viewIsToBeEmbedded; // true if the m_view is intended to be embedded in a "foreign" NSView hiearchy
Qt::WindowFlags m_windowFlags;
- Qt::WindowState m_lastReportedWindowState;
+ Qt::WindowStates m_lastReportedWindowState;
Qt::WindowModality m_windowModality;
QPointer<QWindow> m_enterLeaveTargetWindow;
bool m_windowUnderMouse;
- bool m_inConstructor;
+ bool m_initialized;
bool m_inSetVisible;
bool m_inSetGeometry;
bool m_inSetStyleMask;
@@ -331,14 +261,9 @@ public: // for QNSView
bool m_hasModalSession;
bool m_frameStrutEventsEnabled;
- bool m_geometryUpdateExposeAllowed;
bool m_isExposed;
- QRect m_exposedGeometry;
- qreal m_exposedDevicePixelRatio;
int m_registerTouchCount;
bool m_resizableTransientParent;
- bool m_hiddenByClipping;
- bool m_hiddenByAncestor;
static const int NoAlertRequest;
NSInteger m_alertRequest;
@@ -363,6 +288,10 @@ public: // for QNSView
bool m_hasWindowFilePath;
};
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QCocoaWindow *window);
+#endif
+
QT_END_NAMESPACE
#endif // QCOCOAWINDOW_H
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index 59b76370ae..9f98ad56de 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -46,6 +46,7 @@
#include "qcocoahelpers.h"
#include "qcocoanativeinterface.h"
#include "qnsview.h"
+#include "qnswindow.h"
#include <QtCore/qfileinfo.h>
#include <QtCore/private/qcore_mac_p.h>
#include <qwindow.h>
@@ -53,6 +54,7 @@
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformscreen.h>
#include <QtGui/private/qcoregraphics_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
#include <AppKit/AppKit.h>
@@ -60,27 +62,13 @@
#include <vector>
+QT_BEGIN_NAMESPACE
+
enum {
defaultWindowWidth = 160,
defaultWindowHeight = 160
};
-static bool isMouseEvent(NSEvent *ev)
-{
- switch ([ev type]) {
- case NSLeftMouseDown:
- case NSLeftMouseUp:
- case NSRightMouseDown:
- case NSRightMouseUp:
- case NSMouseMoved:
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- return true;
- default:
- return false;
- }
-}
-
static void qt_closePopups()
{
while (QCocoaWindow *popup = QCocoaIntegration::instance()->popPopupWindow()) {
@@ -89,373 +77,6 @@ static void qt_closePopups()
}
}
-@interface NSWindow (FullScreenProperty)
-@property(readonly) BOOL qt_fullScreen;
-@end
-
-@implementation NSWindow (FullScreenProperty)
-
-+ (void)load
-{
- NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
- [center addObserverForName:NSWindowDidEnterFullScreenNotification object:nil queue:nil
- usingBlock:^(NSNotification *notification) {
- objc_setAssociatedObject(notification.object, @selector(qt_fullScreen),
- [NSNumber numberWithBool:YES], OBJC_ASSOCIATION_RETAIN);
- }
- ];
- [center addObserverForName:NSWindowDidExitFullScreenNotification object:nil queue:nil
- usingBlock:^(NSNotification *notification) {
- objc_setAssociatedObject(notification.object, @selector(qt_fullScreen),
- nil, OBJC_ASSOCIATION_RETAIN);
- }
- ];
-}
-
-- (BOOL)qt_fullScreen
-{
- NSNumber *number = objc_getAssociatedObject(self, @selector(qt_fullScreen));
- return [number boolValue];
-}
-@end
-
-@implementation QNSWindowHelper
-
-@synthesize window = _window;
-@synthesize grabbingMouse = _grabbingMouse;
-@synthesize releaseOnMouseUp = _releaseOnMouseUp;
-
-- (QCocoaWindow *)platformWindow
-{
- return _platformWindow.data();
-}
-
-- (id)initWithNSWindow:(QCocoaNSWindow *)window platformWindow:(QCocoaWindow *)platformWindow
-{
- self = [super init];
- if (self) {
- _window = window;
- _platformWindow = platformWindow;
-
- _window.delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:_platformWindow];
-
- // Prevent Cocoa from releasing the window on close. Qt
- // handles the close event asynchronously and we want to
- // make sure that m_nsWindow stays valid until the
- // QCocoaWindow is deleted by Qt.
- [_window setReleasedWhenClosed:NO];
- }
-
- return self;
-}
-
-- (void)handleWindowEvent:(NSEvent *)theEvent
-{
- QCocoaWindow *pw = self.platformWindow;
- if (pw && pw->m_forwardWindow) {
- if (theEvent.type == NSLeftMouseUp || theEvent.type == NSLeftMouseDragged) {
- QNSView *forwardView = qnsview_cast(pw->view());
- if (theEvent.type == NSLeftMouseUp) {
- [forwardView mouseUp:theEvent];
- pw->m_forwardWindow.clear();
- } else {
- [forwardView mouseDragged:theEvent];
- }
- }
- if (pw->window()->isTopLevel() && theEvent.type == NSLeftMouseDown) {
- pw->m_forwardWindow.clear();
- }
- }
-
- if (theEvent.type == NSLeftMouseDown) {
- self.grabbingMouse = YES;
- } else if (theEvent.type == NSLeftMouseUp) {
- self.grabbingMouse = NO;
- if (self.releaseOnMouseUp) {
- [self detachFromPlatformWindow];
- [self.window release];
- return;
- }
- }
-
- // The call to -[NSWindow sendEvent] may result in the window being deleted
- // (e.g., when closing the window by pressing the title bar close button).
- [self retain];
- [self.window superSendEvent:theEvent];
- bool windowStillAlive = self.window != nil; // We need to read before releasing
- [self release];
- if (!windowStillAlive)
- return;
-
- if (!self.window.delegate)
- return; // Already detached, pending NSAppKitDefined event
-
- if (pw && pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
- NSPoint loc = [theEvent locationInWindow];
- NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]];
- NSRect contentFrame = [[self.window contentView] frame];
- if (NSMouseInRect(loc, windowFrame, NO) && !NSMouseInRect(loc, contentFrame, NO))
- [qnsview_cast(pw->view()) handleFrameStrutMouseEvent:theEvent];
- }
-}
-
-- (void)detachFromPlatformWindow
-{
- _platformWindow.clear();
- [self.window.delegate release];
- self.window.delegate = nil;
-}
-
-- (void)clearWindow
-{
- if (_window) {
- QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
- if (cocoaEventDispatcher) {
- QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
- cocoaEventDispatcherPrivate->removeQueuedUserInputEvents([_window windowNumber]);
- }
-
- _window = nil;
- }
-}
-
-- (void)dealloc
-{
- _window = nil;
- _platformWindow.clear();
- [super dealloc];
-}
-
-@end
-
-@implementation QNSWindow
-
-@synthesize helper = _helper;
-
-- (id)initWithContentRect:(NSRect)contentRect
- screen:(NSScreen*)screen
- styleMask:(NSUInteger)windowStyle
- qPlatformWindow:(QCocoaWindow *)qpw
-{
- self = [super initWithContentRect:contentRect
- styleMask:windowStyle
- backing:NSBackingStoreBuffered
- defer:NO screen:screen]; // Deferring window creation breaks OpenGL (the GL context is
- // set up before the window is shown and needs a proper window)
-
- if (self) {
- _helper = [[QNSWindowHelper alloc] initWithNSWindow:self platformWindow:qpw];
- }
- return self;
-}
-
-- (BOOL)canBecomeKeyWindow
-{
- // Prevent child NSWindows from becoming the key window in
- // order keep the active apperance of the top-level window.
- QCocoaWindow *pw = self.helper.platformWindow;
- if (!pw || !pw->window()->isTopLevel())
- return NO;
-
- if (pw->shouldRefuseKeyWindowAndFirstResponder())
- return NO;
-
- // The default implementation returns NO for title-bar less windows,
- // override and return yes here to make sure popup windows such as
- // the combobox popup can become the key window.
- return YES;
-}
-
-- (BOOL)canBecomeMainWindow
-{
- BOOL canBecomeMain = YES; // By default, windows can become the main window
-
- // Windows with a transient parent (such as combobox popup windows)
- // cannot become the main window:
- QCocoaWindow *pw = self.helper.platformWindow;
- if (!pw || !pw->window()->isTopLevel() || pw->window()->transientParent())
- canBecomeMain = NO;
-
- return canBecomeMain;
-}
-
-- (void) sendEvent: (NSEvent*) theEvent
-{
- [self.helper handleWindowEvent:theEvent];
-}
-
-- (void)superSendEvent:(NSEvent *)theEvent
-{
- [super sendEvent:theEvent];
-}
-
-- (void)closeAndRelease
-{
- qCDebug(lcQpaCocoaWindow) << "closeAndRelease" << self;
-
- [self close];
-
- if (self.helper.grabbingMouse) {
- self.helper.releaseOnMouseUp = YES;
- } else {
- [self.helper detachFromPlatformWindow];
- [self release];
- }
-}
-
-- (void)dealloc
-{
- [_helper clearWindow];
- [_helper release];
- _helper = nil;
- [super dealloc];
-}
-
-@end
-
-@implementation QNSPanel
-
-@synthesize helper = _helper;
-
-+ (void)applicationActivationChanged:(NSNotification*)notification
-{
- const id sender = self;
- NSEnumerator<NSWindow*> *windowEnumerator = nullptr;
- NSApplication *application = [NSApplication sharedApplication];
-
-#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
- if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra) {
- // Unfortunately there's no NSWindowListOrderedBackToFront,
- // so we have to manually reverse the order using an array.
- NSMutableArray *windows = [[[NSMutableArray alloc] init] autorelease];
- [application enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
- usingBlock:^(NSWindow *window, BOOL *) {
- // For some reason AppKit will give us nil-windows, skip those
- if (!window)
- return;
-
- [(NSMutableArray*)windows addObject:window];
- }
- ];
-
- windowEnumerator = windows.reverseObjectEnumerator;
- } else
-#endif
- {
- // No way to get ordered list of windows, so fall back to unordered,
- // list, which typically corresponds to window creation order.
- windowEnumerator = application.windows.objectEnumerator;
- }
-
- for (NSWindow *window in windowEnumerator) {
- // We're meddling with normal and floating windows, so leave others alone
- if (!(window.level == NSNormalWindowLevel || window.level == NSFloatingWindowLevel))
- continue;
-
- // Windows that hide automatically will keep their NSFloatingWindowLevel,
- // and hence be on top of the window stack. We don't want to affect these
- // windows, as otherwise we might end up with key windows being ordered
- // behind these auto-hidden windows when activating the application by
- // clicking on a new tool window.
- if (window.hidesOnDeactivate)
- continue;
-
- if ([window conformsToProtocol:@protocol(QNSWindowProtocol)]) {
- QCocoaWindow *cocoaWindow = static_cast<id<QNSWindowProtocol>>(window).helper.platformWindow;
- window.level = notification.name == NSApplicationWillResignActiveNotification ?
- NSNormalWindowLevel : cocoaWindow->windowLevel(cocoaWindow->window()->flags());
- }
-
- // The documentation says that "when a window enters a new level, it’s ordered
- // in front of all its peers in that level", but that doesn't seem to be the
- // case in practice. To keep the order correct after meddling with the window
- // levels, we explicitly order each window to the front. Since we are iterating
- // the windows in back-to-front order, this is okey. The call also triggers AppKit
- // to re-evaluate the level in relation to windows from other applications,
- // working around an issue where our tool windows would stay on top of other
- // application windows if activation was transferred to another application by
- // clicking on it instead of via the application switcher or Dock. Finally, we
- // do this re-ordering for all windows (except auto-hiding ones), otherwise we would
- // end up triggering a bug in AppKit where the tool windows would disappear behind
- // the application window.
- [window orderFront:sender];
- }
-}
-
-- (id)initWithContentRect:(NSRect)contentRect
- screen:(NSScreen*)screen
- styleMask:(NSUInteger)windowStyle
- qPlatformWindow:(QCocoaWindow *)qpw
-{
- self = [super initWithContentRect:contentRect
- styleMask:windowStyle
- backing:NSBackingStoreBuffered
- defer:NO screen:screen]; // Deferring window creation breaks OpenGL (the GL context is
- // set up before the window is shown and needs a proper window)
-
- if (self) {
- _helper = [[QNSWindowHelper alloc] initWithNSWindow:self platformWindow:qpw];
-
- if (qpw->alwaysShowToolWindow()) {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
- [center addObserver:[self class] selector:@selector(applicationActivationChanged:)
- name:NSApplicationWillResignActiveNotification object:nil];
- [center addObserver:[self class] selector:@selector(applicationActivationChanged:)
- name:NSApplicationWillBecomeActiveNotification object:nil];
- });
- }
- }
- return self;
-}
-
-- (BOOL)canBecomeKeyWindow
-{
- QCocoaWindow *pw = self.helper.platformWindow;
- if (!pw)
- return NO;
-
- if (pw->shouldRefuseKeyWindowAndFirstResponder())
- return NO;
-
- // Only tool or dialog windows should become key:
- Qt::WindowType type = pw->window()->type();
- if (type == Qt::Tool || type == Qt::Dialog)
- return YES;
-
- return NO;
-}
-
-- (void) sendEvent: (NSEvent*) theEvent
-{
- [self.helper handleWindowEvent:theEvent];
-}
-
-- (void)superSendEvent:(NSEvent *)theEvent
-{
- [super sendEvent:theEvent];
-}
-
-- (void)closeAndRelease
-{
- qCDebug(lcQpaCocoaWindow) << "closeAndRelease" << self;
-
- [self.helper detachFromPlatformWindow];
- [self close];
- [self release];
-}
-
-- (void)dealloc
-{
- [_helper clearWindow];
- [_helper release];
- _helper = nil;
- [super dealloc];
-}
-
-@end
-
static void qRegisterNotificationCallbacks()
{
static const QLatin1String notificationHandlerPrefix(Q_NOTIFICATION_PREFIX);
@@ -478,10 +99,6 @@ static void qRegisterNotificationCallbacks()
NSView *view = nullptr;
if ([notification.object isKindOfClass:[NSWindow class]]) {
NSWindow *window = notification.object;
- // Only top level NSWindows should notify their QNSViews
- if (window.parentWindow)
- return;
-
if (!window.contentView)
return;
@@ -515,8 +132,8 @@ Q_CONSTRUCTOR_FUNCTION(qRegisterNotificationCallbacks)
const int QCocoaWindow::NoAlertRequest = -1;
-QCocoaWindow::QCocoaWindow(QWindow *tlw, WId nativeHandle)
- : QPlatformWindow(tlw)
+QCocoaWindow::QCocoaWindow(QWindow *win, WId nativeHandle)
+ : QPlatformWindow(win)
, m_view(nil)
, m_nsWindow(0)
, m_viewIsEmbedded(false)
@@ -524,7 +141,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw, WId nativeHandle)
, m_lastReportedWindowState(Qt::WindowNoState)
, m_windowModality(Qt::NonModal)
, m_windowUnderMouse(false)
- , m_inConstructor(true)
+ , m_initialized(false)
, m_inSetVisible(false)
, m_inSetGeometry(false)
, m_inSetStyleMask(false)
@@ -535,12 +152,9 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw, WId nativeHandle)
, m_windowCursor(0)
, m_hasModalSession(false)
, m_frameStrutEventsEnabled(false)
- , m_geometryUpdateExposeAllowed(false)
, m_isExposed(false)
, m_registerTouchCount(0)
, m_resizableTransientParent(false)
- , m_hiddenByClipping(false)
- , m_hiddenByAncestor(false)
, m_alertRequest(NoAlertRequest)
, monitor(nil)
, m_drawContentBorderGradient(false)
@@ -550,24 +164,31 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw, WId nativeHandle)
{
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::QCocoaWindow" << window();
- QMacAutoReleasePool pool;
-
if (nativeHandle) {
m_view = reinterpret_cast<NSView *>(nativeHandle);
[m_view retain];
- } else {
+ }
+}
+
+void QCocoaWindow::initialize()
+{
+ qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::initialize" << window();
+
+ QMacAutoReleasePool pool;
+
+ if (!m_view) {
m_view = [[QNSView alloc] initWithCocoaWindow:this];
// Enable high-dpi OpenGL for retina displays. Enabling has the side
// effect that Cocoa will start calling glViewport(0, 0, width, height),
// overriding any glViewport calls in application code. This is usually not a
// problem, except if the appilcation wants to have a "custom" viewport.
// (like the hellogl example)
- if (tlw->supportsOpenGL()) {
- BOOL enable = qt_mac_resolveOption(YES, tlw, "_q_mac_wantsBestResolutionOpenGLSurface",
+ if (window()->supportsOpenGL()) {
+ BOOL enable = qt_mac_resolveOption(YES, window(), "_q_mac_wantsBestResolutionOpenGLSurface",
"QT_MAC_WANTS_BEST_RESOLUTION_OPENGL_SURFACE");
[m_view setWantsBestResolutionOpenGLSurface:enable];
}
- BOOL enable = qt_mac_resolveOption(NO, tlw, "_q_mac_wantsLayer",
+ BOOL enable = qt_mac_resolveOption(NO, window(), "_q_mac_wantsLayer",
"QT_MAC_WANTS_LAYER");
[m_view setWantsLayer:enable];
}
@@ -575,10 +196,11 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw, WId nativeHandle)
setGeometry(initialGeometry(window(), windowGeometry(), defaultWindowWidth, defaultWindowHeight));
recreateWindowIfNeeded();
- tlw->setGeometry(geometry());
- if (tlw->isTopLevel())
- setWindowIcon(tlw->icon());
- m_inConstructor = false;
+ window()->setGeometry(geometry());
+ if (window()->isTopLevel())
+ setWindowIcon(window()->icon());
+
+ m_initialized = true;
}
QCocoaWindow::~QCocoaWindow()
@@ -589,9 +211,7 @@ QCocoaWindow::~QCocoaWindow()
[m_nsWindow makeFirstResponder:nil];
[m_nsWindow setContentView:nil];
[m_nsWindow.helper detachFromPlatformWindow];
- if (m_view.window.parentWindow)
- [m_view.window.parentWindow removeChildWindow:m_view.window];
- else if ([m_view superview])
+ if ([m_view superview])
[m_view removeFromSuperview];
removeMonitor();
@@ -607,10 +227,6 @@ QCocoaWindow::~QCocoaWindow()
QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
}
- foreachChildNSWindow(^(QCocoaWindow *childWindow) {
- [m_nsWindow removeChildWindow:childWindow->m_nsWindow];
- });
-
[m_view release];
[m_nsWindow release];
[m_windowCursor release];
@@ -674,134 +290,29 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect)
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setCocoaGeometry" << window() << rect;
QMacAutoReleasePool pool;
+ QPlatformWindow::setGeometry(rect);
+
if (m_viewIsEmbedded) {
if (!isForeignWindow()) {
[m_view setFrame:NSMakeRect(0, 0, rect.width(), rect.height())];
- } else {
- QPlatformWindow::setGeometry(rect);
}
return;
}
- if (isChildNSWindow()) {
- QPlatformWindow::setGeometry(rect);
- NSWindow *parentNSWindow = m_view.window.parentWindow;
- NSRect parentWindowFrame = [parentNSWindow contentRectForFrameRect:parentNSWindow.frame];
- clipWindow(parentWindowFrame);
-
- // call this here: updateGeometry in qnsview.mm is a no-op for this case
- QWindowSystemInterface::handleGeometryChange(window(), rect);
- QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size()));
- } else if (m_nsWindow) {
+ if (isContentView()) {
NSRect bounds = qt_mac_flipRect(rect);
- [m_nsWindow setFrame:[m_nsWindow frameRectForContentRect:bounds] display:YES animate:NO];
+ [m_view.window setFrame:[m_view.window frameRectForContentRect:bounds] display:YES animate:NO];
} else {
[m_view setFrame:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
}
- if (isForeignWindow())
- QPlatformWindow::setGeometry(rect);
-
// will call QPlatformWindow::setGeometry(rect) during resize confirmation (see qnsview.mm)
}
-void QCocoaWindow::clipChildWindows()
-{
- foreachChildNSWindow(^(QCocoaWindow *childWindow) {
- childWindow->clipWindow(m_nsWindow.frame);
- });
-}
-
-void QCocoaWindow::clipWindow(const NSRect &clipRect)
-{
- if (!isChildNSWindow())
- return;
-
- NSRect clippedWindowRect = NSZeroRect;
- if (!NSIsEmptyRect(clipRect)) {
- NSRect windowFrame = qt_mac_flipRect(QRect(window()->mapToGlobal(QPoint(0, 0)), geometry().size()));
- clippedWindowRect = NSIntersectionRect(windowFrame, clipRect);
- // Clipping top/left offsets the content. Move it back.
- NSPoint contentViewOffset = NSMakePoint(qMax(CGFloat(0), NSMinX(clippedWindowRect) - NSMinX(windowFrame)),
- qMax(CGFloat(0), NSMaxY(windowFrame) - NSMaxY(clippedWindowRect)));
- [m_view setBoundsOrigin:contentViewOffset];
- }
-
- if (NSIsEmptyRect(clippedWindowRect)) {
- if (!m_hiddenByClipping) {
- // We dont call hide() here as we will recurse further down
- [m_nsWindow orderOut:nil];
- m_hiddenByClipping = true;
- }
- } else {
- [m_nsWindow setFrame:clippedWindowRect display:YES animate:NO];
- if (m_hiddenByClipping) {
- m_hiddenByClipping = false;
- if (!m_hiddenByAncestor) {
- [m_nsWindow orderFront:nil];
- static_cast<QCocoaWindow *>(QPlatformWindow::parent())->reinsertChildWindow(this);
- }
- }
- }
-
- // recurse
- foreachChildNSWindow(^(QCocoaWindow *childWindow) {
- childWindow->clipWindow(clippedWindowRect);
- });
-}
-
-void QCocoaWindow::hide(bool becauseOfAncestor)
-{
- bool visible = [m_nsWindow isVisible];
-
- if (!m_hiddenByAncestor && !visible) // Already explicitly hidden
- return;
- if (m_hiddenByAncestor && becauseOfAncestor) // Trying to hide some child again
- return;
-
- m_hiddenByAncestor = becauseOfAncestor;
-
- if (!visible) // Could have been clipped before
- return;
-
- foreachChildNSWindow(^(QCocoaWindow *childWindow) {
- childWindow->hide(true);
- });
-
- [m_nsWindow orderOut:nil];
-}
-
-void QCocoaWindow::show(bool becauseOfAncestor)
-{
- if ([m_nsWindow isVisible])
- return;
-
- if (m_view.window.parentWindow && !m_view.window.parentWindow.visible) {
- m_hiddenByAncestor = true; // Parent still hidden, don't show now
- } else if ((becauseOfAncestor == m_hiddenByAncestor) // Was NEITHER explicitly hidden
- && !m_hiddenByClipping) { // ... NOR clipped
- if (isChildNSWindow()) {
- m_hiddenByAncestor = false;
- setCocoaGeometry(windowGeometry());
- }
- if (!m_hiddenByClipping) { // setCocoaGeometry() can change the clipping status
- [m_nsWindow orderFront:nil];
- if (isChildNSWindow())
- static_cast<QCocoaWindow *>(QPlatformWindow::parent())->reinsertChildWindow(this);
- foreachChildNSWindow(^(QCocoaWindow *childWindow) {
- childWindow->show(true);
- });
- }
- }
-}
-
void QCocoaWindow::setVisible(bool visible)
{
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setVisible" << window() << visible;
- if (isChildNSWindow() && m_hiddenByClipping)
- return;
-
m_inSetVisible = true;
QMacAutoReleasePool pool;
@@ -826,34 +337,28 @@ void QCocoaWindow::setVisible(bool visible)
if (window()->type() == Qt::Popup) {
// QTBUG-30266: a window should not be resizable while a transient popup is open
// Since this isn't a native popup, the window manager doesn't close the popup when you click outside
- NSUInteger parentStyleMask = [parentCocoaWindow->m_nsWindow styleMask];
+ NSWindow *nativeParentWindow = parentCocoaWindow->nativeWindow();
+ NSUInteger parentStyleMask = nativeParentWindow.styleMask;
if ((m_resizableTransientParent = (parentStyleMask & NSResizableWindowMask))
- && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask))
- [parentCocoaWindow->m_nsWindow setStyleMask:parentStyleMask & ~NSResizableWindowMask];
+ && !(nativeParentWindow.styleMask & NSFullScreenWindowMask))
+ nativeParentWindow.styleMask &= ~NSResizableWindowMask;
}
}
- // This call is here to handle initial window show correctly:
- // - top-level windows need to have backing store content ready when the
- // window is shown, sendin the expose event here makes that more likely.
- // - QNSViews for child windows are initialy not hidden and won't get the
- // viewDidUnhide message.
- exposeWindow();
-
- if (m_nsWindow) {
+ if (isContentView()) {
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
// setWindowState might have been called while the window was hidden and
// will not change the NSWindow state in that case. Sync up here:
- applyWindowState(window()->windowState());
+ applyWindowState(window()->windowStates());
if (window()->windowState() != Qt::WindowMinimized) {
if ((window()->modality() == Qt::WindowModal
|| window()->type() == Qt::Sheet)
&& parentCocoaWindow) {
// show the window as a sheet
- [parentCocoaWindow->m_nsWindow beginSheet:m_nsWindow completionHandler:nil];
+ [parentCocoaWindow->nativeWindow() beginSheet:m_view.window completionHandler:nil];
} else if (window()->modality() != Qt::NonModal) {
// show the window as application modal
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
@@ -861,28 +366,24 @@ void QCocoaWindow::setVisible(bool visible)
QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
cocoaEventDispatcherPrivate->beginModalSession(window());
m_hasModalSession = true;
- } else if ([m_nsWindow canBecomeKeyWindow]) {
+ } else if ([m_view.window canBecomeKeyWindow]) {
QCocoaEventDispatcher *cocoaEventDispatcher = qobject_cast<QCocoaEventDispatcher *>(QGuiApplication::instance()->eventDispatcher());
QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0;
if (cocoaEventDispatcher)
cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
if (cocoaEventDispatcherPrivate && cocoaEventDispatcherPrivate->cocoaModalSessionStack.isEmpty())
- [m_nsWindow makeKeyAndOrderFront:nil];
+ [m_view.window makeKeyAndOrderFront:nil];
else
- [m_nsWindow orderFront:nil];
-
- foreachChildNSWindow(^(QCocoaWindow *childWindow) {
- childWindow->show(true);
- });
+ [m_view.window orderFront:nil];
} else {
- show();
+ [m_view.window orderFront:nil];
}
// We want the events to properly reach the popup, dialog, and tool
if ((window()->type() == Qt::Popup || window()->type() == Qt::Dialog || window()->type() == Qt::Tool)
- && [m_nsWindow isKindOfClass:[NSPanel class]]) {
- [(NSPanel *)m_nsWindow setWorksWhenModal:YES];
+ && [m_view.window isKindOfClass:[NSPanel class]]) {
+ ((NSPanel *)m_view.window).worksWhenModal = YES;
if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) {
removeMonitor();
monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) {
@@ -909,20 +410,21 @@ void QCocoaWindow::setVisible(bool visible)
QCocoaEventDispatcherPrivate *cocoaEventDispatcherPrivate = 0;
if (cocoaEventDispatcher)
cocoaEventDispatcherPrivate = static_cast<QCocoaEventDispatcherPrivate *>(QObjectPrivate::get(cocoaEventDispatcher));
- if (m_nsWindow) {
+ if (isContentView()) {
if (m_hasModalSession) {
if (cocoaEventDispatcherPrivate)
cocoaEventDispatcherPrivate->endModalSession(window());
m_hasModalSession = false;
} else {
- if ([m_nsWindow isSheet]) {
+ if ([m_view.window isSheet]) {
Q_ASSERT_X(parentCocoaWindow, "QCocoaWindow", "Window modal dialog has no transient parent.");
- [parentCocoaWindow->m_nsWindow endSheet:m_nsWindow];
+ [parentCocoaWindow->nativeWindow() endSheet:m_view.window];
}
}
- hide();
- if (m_nsWindow == [NSApp keyWindow]
+ [m_view.window orderOut:nil];
+
+ if (m_view.window == [NSApp keyWindow]
&& !(cocoaEventDispatcherPrivate && cocoaEventDispatcherPrivate->currentModalSession())) {
// Probably because we call runModalSession: outside [NSApp run] in QCocoaEventDispatcher
// (e.g., when show()-ing a modal QDialog instead of exec()-ing it), it can happen that
@@ -941,10 +443,11 @@ void QCocoaWindow::setVisible(bool visible)
QCocoaIntegration::instance()->popupWindowStack()->removeAll(this);
if (parentCocoaWindow && window()->type() == Qt::Popup) {
+ NSWindow *nativeParentWindow = parentCocoaWindow->nativeWindow();
if (m_resizableTransientParent
- && !([parentCocoaWindow->m_nsWindow styleMask] & NSFullScreenWindowMask))
- // QTBUG-30266: a window should not be resizable while a transient popup is open
- [parentCocoaWindow->m_nsWindow setStyleMask:[parentCocoaWindow->m_nsWindow styleMask] | NSResizableWindowMask];
+ && !(nativeParentWindow.styleMask & NSFullScreenWindowMask))
+ // A window should not be resizable while a transient popup is open
+ nativeParentWindow.styleMask |= NSResizableWindowMask;
}
}
@@ -974,7 +477,7 @@ NSInteger QCocoaWindow::windowLevel(Qt::WindowFlags flags)
const QWindow * const transientParent = window()->transientParent();
const QCocoaWindow * const transientParentWindow = transientParent ? static_cast<QCocoaWindow *>(transientParent->handle()) : 0;
if (transientParentWindow)
- windowLevel = qMax([transientParentWindow->m_nsWindow level], windowLevel);
+ windowLevel = qMax([transientParentWindow->nativeWindow() level], windowLevel);
}
return windowLevel;
@@ -1032,20 +535,17 @@ NSUInteger QCocoaWindow::windowStyleMask(Qt::WindowFlags flags)
styleMask |= NSTexturedBackgroundWindowMask;
// Don't wipe fullscreen state
- if (m_nsWindow.styleMask & NSFullScreenWindowMask)
+ if (m_view.window.styleMask & NSFullScreenWindowMask)
styleMask |= NSFullScreenWindowMask;
return styleMask;
}
-void QCocoaWindow::setWindowShadow(Qt::WindowFlags flags)
-{
- bool keepShadow = !(flags & Qt::NoDropShadowWindowHint);
- [m_nsWindow setHasShadow:(keepShadow ? YES : NO)];
-}
-
void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags)
{
+ if (!isContentView())
+ return;
+
// Disable the zoom (maximize) button for fixed-sized windows and customized
// no-WindowMaximizeButtonHint windows. From a Qt perspective it migth be expected
// that the button would be removed in the latter case, but disabling it is more
@@ -1054,28 +554,27 @@ void QCocoaWindow::setWindowZoomButton(Qt::WindowFlags flags)
&& windowMinimumSize() == windowMaximumSize());
bool customizeNoZoom = ((flags & Qt::CustomizeWindowHint)
&& !(flags & (Qt::WindowMaximizeButtonHint | Qt::WindowFullscreenButtonHint)));
- [[m_nsWindow standardWindowButton:NSWindowZoomButton] setEnabled:!(fixedSizeNoZoom || customizeNoZoom)];
+ [[m_view.window standardWindowButton:NSWindowZoomButton] setEnabled:!(fixedSizeNoZoom || customizeNoZoom)];
}
void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
{
- if (m_nsWindow && !isChildNSWindow()) {
- NSUInteger styleMask = windowStyleMask(flags);
- NSInteger level = this->windowLevel(flags);
- // While setting style mask we can have -updateGeometry calls on a content
+ if (isContentView()) {
+ // While setting style mask we can have handleGeometryChange calls on a content
// view with null geometry, reporting an invalid coordinates as a result.
m_inSetStyleMask = true;
- [m_nsWindow setStyleMask:styleMask];
+ m_view.window.styleMask = windowStyleMask(flags);
m_inSetStyleMask = false;
- [m_nsWindow setLevel:level];
- setWindowShadow(flags);
- if (!(flags & Qt::FramelessWindowHint)) {
+ m_view.window.level = this->windowLevel(flags);
+
+ m_view.window.hasShadow = !(flags & Qt::NoDropShadowWindowHint);
+
+ if (!(flags & Qt::FramelessWindowHint))
setWindowTitle(window()->title());
- }
Qt::WindowType type = window()->type();
if ((type & Qt::Popup) != Qt::Popup && (type & Qt::Dialog) != Qt::Dialog) {
- NSWindowCollectionBehavior behavior = [m_nsWindow collectionBehavior];
+ NSWindowCollectionBehavior behavior = m_view.window.collectionBehavior;
if (flags & Qt::WindowFullscreenButtonHint) {
behavior |= NSWindowCollectionBehaviorFullScreenPrimary;
behavior &= ~NSWindowCollectionBehaviorFullScreenAuxiliary;
@@ -1083,18 +582,17 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags)
behavior |= NSWindowCollectionBehaviorFullScreenAuxiliary;
behavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
}
- [m_nsWindow setCollectionBehavior:behavior];
+ m_view.window.collectionBehavior = behavior;
}
setWindowZoomButton(flags);
- }
- if (m_nsWindow)
- m_nsWindow.ignoresMouseEvents = flags & Qt::WindowTransparentForInput;
+ m_view.window.ignoresMouseEvents = flags & Qt::WindowTransparentForInput;
+ }
m_windowFlags = flags;
}
-void QCocoaWindow::setWindowState(Qt::WindowState state)
+void QCocoaWindow::setWindowState(Qt::WindowStates state)
{
if (window()->isVisible())
applyWindowState(state); // Window state set for hidden windows take effect when show() is called
@@ -1102,37 +600,38 @@ void QCocoaWindow::setWindowState(Qt::WindowState state)
void QCocoaWindow::setWindowTitle(const QString &title)
{
- QMacAutoReleasePool pool;
- if (!m_nsWindow)
+ if (!isContentView())
return;
- CFStringRef windowTitle = title.toCFString();
- [m_nsWindow setTitle: const_cast<NSString *>(reinterpret_cast<const NSString *>(windowTitle))];
- CFRelease(windowTitle);
+ QMacAutoReleasePool pool;
+ m_view.window.title = title.toNSString();
}
void QCocoaWindow::setWindowFilePath(const QString &filePath)
{
- QMacAutoReleasePool pool;
- if (!m_nsWindow)
+ if (!isContentView())
return;
+ QMacAutoReleasePool pool;
QFileInfo fi(filePath);
- [m_nsWindow setRepresentedFilename:fi.exists() ? filePath.toNSString() : @""];
+ [m_view.window setRepresentedFilename:fi.exists() ? filePath.toNSString() : @""];
m_hasWindowFilePath = fi.exists();
}
void QCocoaWindow::setWindowIcon(const QIcon &icon)
{
+ if (!isContentView())
+ return;
+
QMacAutoReleasePool pool;
- NSButton *iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton];
+ NSButton *iconButton = [m_view.window standardWindowButton:NSWindowDocumentIconButton];
if (iconButton == nil) {
if (icon.isNull())
return;
NSString *title = window()->title().toNSString();
- [m_nsWindow setRepresentedURL:[NSURL fileURLWithPath:title]];
- iconButton = [m_nsWindow standardWindowButton:NSWindowDocumentIconButton];
+ [m_view.window setRepresentedURL:[NSURL fileURLWithPath:title]];
+ iconButton = [m_view.window standardWindowButton:NSWindowDocumentIconButton];
}
if (icon.isNull()) {
[iconButton setImage:nil];
@@ -1164,34 +663,22 @@ void QCocoaWindow::raise()
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::raise" << window();
// ### handle spaces (see Qt 4 raise_sys in qwidget_mac.mm)
- if (!m_nsWindow)
+ if (!isContentView())
return;
- if (isChildNSWindow()) {
- if (m_hiddenByClipping)
- return;
- }
- if ([m_nsWindow isVisible]) {
- if (isChildNSWindow()) {
- // -[NSWindow orderFront:] doesn't work with attached windows.
- // The only solution is to remove and add the child window.
- // This will place it on top of all the other NSWindows.
- NSWindow *parentNSWindow = m_view.window.parentWindow;
- [parentNSWindow removeChildWindow:m_nsWindow];
- [parentNSWindow addChildWindow:m_nsWindow ordered:NSWindowAbove];
- } else {
- {
- // Clean up autoreleased temp objects from orderFront immediately.
- // Failure to do so has been observed to cause leaks also beyond any outer
- // autorelease pool (for example around a complete QWindow
- // construct-show-raise-hide-delete cyle), counter to expected autoreleasepool
- // behavior.
- QMacAutoReleasePool pool;
- [m_nsWindow orderFront: m_nsWindow];
- }
- static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS");
- if (raiseProcess) {
- [NSApp activateIgnoringOtherApps:YES];
- }
+
+ if (m_view.window.visible) {
+ {
+ // Clean up autoreleased temp objects from orderFront immediately.
+ // Failure to do so has been observed to cause leaks also beyond any outer
+ // autorelease pool (for example around a complete QWindow
+ // construct-show-raise-hide-delete cyle), counter to expected autoreleasepool
+ // behavior.
+ QMacAutoReleasePool pool;
+ [m_view.window orderFront:m_view.window];
+ }
+ static bool raiseProcess = qt_mac_resolveOption(true, "QT_MAC_SET_RAISE_PROCESS");
+ if (raiseProcess) {
+ [NSApp activateIgnoringOtherApps:YES];
}
}
}
@@ -1199,29 +686,11 @@ void QCocoaWindow::raise()
void QCocoaWindow::lower()
{
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::lower" << window();
- if (!m_nsWindow)
+ if (!isContentView())
return;
- if (isChildNSWindow()) {
- if (m_hiddenByClipping)
- return;
- }
- if ([m_nsWindow isVisible]) {
- if (isChildNSWindow()) {
- // -[NSWindow orderBack:] doesn't work with attached windows.
- // The only solution is to remove and add all the child windows except this one.
- // This will keep the current window at the bottom while adding the others on top of it,
- // hopefully in the same order (this is not documented anywhere in the Cocoa documentation).
- NSWindow *parentNSWindow = m_view.window.parentWindow;
- NSArray *children = [parentNSWindow.childWindows copy];
- for (NSWindow *child in children)
- if (m_nsWindow != child) {
- [parentNSWindow removeChildWindow:child];
- [parentNSWindow addChildWindow:child ordered:NSWindowAbove];
- }
- } else {
- [m_nsWindow orderBack: m_nsWindow];
- }
- }
+
+ if (m_view.window.visible)
+ [m_view.window orderBack:m_view.window];
}
bool QCocoaWindow::isExposed() const
@@ -1245,24 +714,24 @@ bool QCocoaWindow::isOpaque() const
void QCocoaWindow::propagateSizeHints()
{
QMacAutoReleasePool pool;
- if (!m_nsWindow)
+ if (!isContentView())
return;
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::propagateSizeHints" << window() << "\n"
- << " min/max" << windowMinimumSize() << windowMaximumSize()
- << "size increment" << windowSizeIncrement()
- << " basesize" << windowBaseSize()
- << " geometry" << windowGeometry();
+ qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::propagateSizeHints" << window()
+ << "min:" << windowMinimumSize() << "max:" << windowMaximumSize()
+ << "increment:" << windowSizeIncrement()
+ << "base:" << windowBaseSize();
+
+ const NSWindow *window = m_view.window;
// Set the minimum content size.
- const QSize minimumSize = windowMinimumSize();
+ QSize minimumSize = windowMinimumSize();
if (!minimumSize.isValid()) // minimumSize is (-1, -1) when not set. Make that (0, 0) for Cocoa.
- [m_nsWindow setContentMinSize : NSMakeSize(0.0, 0.0)];
- [m_nsWindow setContentMinSize : NSMakeSize(minimumSize.width(), minimumSize.height())];
+ minimumSize = QSize(0, 0);
+ window.contentMinSize = NSSizeFromCGSize(minimumSize.toCGSize());
// Set the maximum content size.
- const QSize maximumSize = windowMaximumSize();
- [m_nsWindow setContentMaxSize : NSMakeSize(maximumSize.width(), maximumSize.height())];
+ window.contentMaxSize = NSSizeFromCGSize(windowMaximumSize().toCGSize());
// The window may end up with a fixed size; in this case the zoom button should be disabled.
setWindowZoomButton(m_windowFlags);
@@ -1272,42 +741,42 @@ void QCocoaWindow::propagateSizeHints()
QSize sizeIncrement = windowSizeIncrement();
if (sizeIncrement.isEmpty())
sizeIncrement = QSize(1, 1);
- [m_nsWindow setResizeIncrements:NSSizeFromCGSize(sizeIncrement.toCGSize())];
+ window.resizeIncrements = NSSizeFromCGSize(sizeIncrement.toCGSize());
QRect rect = geometry();
QSize baseSize = windowBaseSize();
- if (!baseSize.isNull() && baseSize.isValid()) {
- [m_nsWindow setFrame:NSMakeRect(rect.x(), rect.y(), baseSize.width(), baseSize.height()) display:YES];
- }
+ if (!baseSize.isNull() && baseSize.isValid())
+ [window setFrame:NSMakeRect(rect.x(), rect.y(), baseSize.width(), baseSize.height()) display:YES];
}
void QCocoaWindow::setOpacity(qreal level)
{
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setOpacity" << level;
- if (m_nsWindow) {
- [m_nsWindow setAlphaValue:level];
- [m_nsWindow setOpaque: isOpaque()];
- }
+ if (!isContentView())
+ return;
+
+ m_view.window.alphaValue = level;
+ m_view.window.opaque = isOpaque();
}
void QCocoaWindow::setMask(const QRegion &region)
{
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setMask" << window() << region;
- if (m_nsWindow)
- [m_nsWindow setBackgroundColor:[NSColor clearColor]];
+ if (isContentView())
+ m_view.window.backgroundColor = !region.isEmpty() ? [NSColor clearColor] : nil;
[qnsview_cast(m_view) setMaskRegion:&region];
- [m_nsWindow setOpaque:isOpaque()];
+ m_view.window.opaque = isOpaque();
}
bool QCocoaWindow::setKeyboardGrabEnabled(bool grab)
{
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setKeyboardGrabEnabled" << window() << grab;
- if (!m_nsWindow)
+ if (!isContentView())
return false;
- if (grab && ![m_nsWindow isKeyWindow])
- [m_nsWindow makeKeyWindow];
+ if (grab && ![m_view.window isKeyWindow])
+ [m_view.window makeKeyWindow];
return true;
}
@@ -1315,11 +784,11 @@ bool QCocoaWindow::setKeyboardGrabEnabled(bool grab)
bool QCocoaWindow::setMouseGrabEnabled(bool grab)
{
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::setMouseGrabEnabled" << window() << grab;
- if (!m_nsWindow)
+ if (!isContentView())
return false;
- if (grab && ![m_nsWindow isKeyWindow])
- [m_nsWindow makeKeyWindow];
+ if (grab && ![m_view.window isKeyWindow])
+ [m_view.window makeKeyWindow];
return true;
}
@@ -1348,7 +817,7 @@ NSView *QCocoaWindow::view() const
NSWindow *QCocoaWindow::nativeWindow() const
{
- return m_nsWindow;
+ return m_view.window;
}
void QCocoaWindow::setEmbeddedInForeignView(bool embedded)
@@ -1369,33 +838,26 @@ void QCocoaWindow::windowWillMove()
void QCocoaWindow::windowDidMove()
{
- if (isChildNSWindow())
- return;
-
- [qnsview_cast(m_view) updateGeometry];
+ handleGeometryChange();
// Moving a window might bring it out of maximized state
- reportCurrentWindowState();
+ handleWindowStateChanged();
}
void QCocoaWindow::windowDidResize()
{
- if (!m_nsWindow)
- return;
-
- if (isChildNSWindow())
+ if (!isContentView())
return;
- clipChildWindows();
- [qnsview_cast(m_view) updateGeometry];
+ handleGeometryChange();
if (!m_view.inLiveResize)
- reportCurrentWindowState();
+ handleWindowStateChanged();
}
void QCocoaWindow::viewDidChangeFrame()
{
- [qnsview_cast(m_view) updateGeometry];
+ handleGeometryChange();
}
/*!
@@ -1407,12 +869,12 @@ void QCocoaWindow::viewDidChangeFrame()
*/
void QCocoaWindow::viewDidChangeGlobalFrame()
{
- updateExposedGeometry();
+ [m_view setNeedsDisplay:YES];
}
void QCocoaWindow::windowDidEndLiveResize()
{
- reportCurrentWindowState();
+ handleWindowStateChanged();
}
void QCocoaWindow::windowDidBecomeKey()
@@ -1449,12 +911,12 @@ void QCocoaWindow::windowDidResignKey()
void QCocoaWindow::windowDidMiniaturize()
{
- reportCurrentWindowState();
+ handleWindowStateChanged();
}
void QCocoaWindow::windowDidDeminiaturize()
{
- reportCurrentWindowState();
+ handleWindowStateChanged();
}
void QCocoaWindow::windowWillEnterFullScreen()
@@ -1462,30 +924,30 @@ void QCocoaWindow::windowWillEnterFullScreen()
// The NSWindow needs to be resizable, otherwise we'll end up with
// the normal window geometry, centered in the middle of the screen
// on a black background. The styleMask will be reset below.
- m_nsWindow.styleMask |= NSResizableWindowMask;
+ m_view.window.styleMask |= NSResizableWindowMask;
}
void QCocoaWindow::windowDidEnterFullScreen()
{
- Q_ASSERT_X(m_nsWindow.qt_fullScreen, "QCocoaWindow",
+ Q_ASSERT_X(m_view.window.qt_fullScreen, "QCocoaWindow",
"FullScreen category processes window notifications first");
// Reset to original styleMask
setWindowFlags(m_windowFlags);
- reportCurrentWindowState();
+ handleWindowStateChanged();
}
void QCocoaWindow::windowWillExitFullScreen()
{
// The NSWindow needs to be resizable, otherwise we'll end up with
// a weird zoom animation. The styleMask will be reset below.
- m_nsWindow.styleMask |= NSResizableWindowMask;
+ m_view.window.styleMask |= NSResizableWindowMask;
}
void QCocoaWindow::windowDidExitFullScreen()
{
- Q_ASSERT_X(!m_nsWindow.qt_fullScreen, "QCocoaWindow",
+ Q_ASSERT_X(!m_view.window.qt_fullScreen, "QCocoaWindow",
"FullScreen category processes window notifications first");
// Reset to original styleMask
@@ -1494,7 +956,7 @@ void QCocoaWindow::windowDidExitFullScreen()
Qt::WindowState requestedState = window()->windowState();
// Deliver update of QWindow state
- reportCurrentWindowState();
+ handleWindowStateChanged();
if (requestedState != windowState() && requestedState != Qt::WindowFullScreen) {
// We were only going out of full screen as an intermediate step before
@@ -1505,28 +967,20 @@ void QCocoaWindow::windowDidExitFullScreen()
void QCocoaWindow::windowDidOrderOffScreen()
{
- obscureWindow();
+ handleExposeEvent(QRegion());
}
void QCocoaWindow::windowDidOrderOnScreen()
{
- exposeWindow();
+ [m_view setNeedsDisplay:YES];
}
void QCocoaWindow::windowDidChangeOcclusionState()
{
- // Several unit tests expect paint and/or expose events for windows that are
- // sometimes (unpredictably) occluded and some unit tests depend on QWindow::isExposed.
- // Don't send Expose/Obscure events when running under QTestLib.
- static const bool onTestLib = qt_mac_resolveOption(false, "QT_QTESTLIB_RUNNING");
- if (!onTestLib) {
- if ((NSUInteger)[m_view.window occlusionState] & NSWindowOcclusionStateVisible) {
- exposeWindow();
- } else {
- // Send Obscure events on window occlusion to stop animations.
- obscureWindow();
- }
- }
+ if (m_view.window.occlusionState & NSWindowOcclusionStateVisible)
+ [m_view setNeedsDisplay:YES];
+ else
+ handleExposeEvent(QRegion());
}
void QCocoaWindow::windowDidChangeScreen()
@@ -1536,8 +990,6 @@ void QCocoaWindow::windowDidChangeScreen()
if (QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenForNSScreen(m_view.window.screen))
QWindowSystemInterface::handleWindowScreenChanged(window(), cocoaScreen->screen());
-
- updateExposedGeometry();
}
void QCocoaWindow::windowWillClose()
@@ -1562,6 +1014,90 @@ bool QCocoaWindow::windowShouldClose()
return accepted;
}
+// ----------------------------- QPA forwarding -----------------------------
+
+void QCocoaWindow::handleGeometryChange()
+{
+ // Prevent geometry change during initialization, as that will result
+ // in a resize event, and Qt expects those to come after the show event.
+ // FIXME: Remove once we've clarified the Qt behavior for this.
+ if (!m_initialized)
+ return;
+
+ // Don't send the geometry change if the QWindow is designated to be
+ // embedded in a foreign view hierarchy but has not actually been
+ // embedded yet - it's too early.
+ if (m_viewIsToBeEmbedded && !m_viewIsEmbedded)
+ return;
+
+ // It can happen that the current NSWindow is nil (if we are changing styleMask
+ // from/to borderless, and the content view is being re-parented), which results
+ // in invalid coordinates.
+ if (m_inSetStyleMask && !m_view.window)
+ return;
+
+ const bool isEmbedded = m_viewIsToBeEmbedded || m_viewIsEmbedded;
+
+ QRect newGeometry;
+ if (isContentView() && !isEmbedded) {
+ // Content views are positioned at (0, 0) in the window, so we resolve via the window
+ CGRect contentRect = [m_view.window contentRectForFrameRect:m_view.window.frame];
+
+ // The result above is in native screen coordinates, so remap to the Qt coordinate system
+ newGeometry = QCocoaScreen::primaryScreen()->mapFromNative(QRectF::fromCGRect(contentRect)).toRect();
+ } else {
+ // QNSView has isFlipped set, so no need to remap the geometry
+ newGeometry = QRectF::fromCGRect(m_view.frame).toRect();
+ }
+
+ qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleGeometryChange" << window()
+ << "current" << geometry() << "new" << newGeometry;
+
+ QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
+
+ // Guard against processing window system events during QWindow::setGeometry
+ // calls, which Qt and Qt applications do not expect.
+ if (!m_inSetGeometry)
+ QWindowSystemInterface::flushWindowSystemEvents();
+}
+
+void QCocoaWindow::handleExposeEvent(const QRegion &region)
+{
+ // Ideally we'd implement isExposed() in terms of these properties,
+ // plus the occlusionState of the NSWindow, and let the expose event
+ // pull the exposed state out when needed. However, when the window
+ // is first shown we receive a drawRect call where the occlusionState
+ // of the window is still hidden, but we still want to prepare the
+ // window for display by issuing an expose event to Qt. To work around
+ // this we don't use the occlusionState directly, but instead base
+ // the exposed state on the region we get in, which in the case of
+ // a window being obscured is an empty region, and in the case of
+ // a drawRect call is a non-null region, even if occlusionState
+ // is still hidden. This ensures the window is prepared for display.
+ m_isExposed = m_view.window.visible
+ && m_view.window.screen
+ && !geometry().size().isEmpty()
+ && !region.isEmpty()
+ && !m_view.hiddenOrHasHiddenAncestor;
+
+ qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleExposeEvent" << window() << region << "isExposed" << isExposed();
+ QWindowSystemInterface::handleExposeEvent<QWindowSystemInterface::SynchronousDelivery>(window(), region);
+}
+
+void QCocoaWindow::handleWindowStateChanged(HandleFlags flags)
+{
+ Qt::WindowState currentState = windowState();
+ if (!(flags & HandleUnconditionally) && currentState == m_lastReportedWindowState)
+ return;
+
+ qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::handleWindowStateChanged" <<
+ m_lastReportedWindowState << "-->" << currentState;
+
+ QWindowSystemInterface::handleWindowStateChanged<QWindowSystemInterface::SynchronousDelivery>(
+ window(), currentState, m_lastReportedWindowState);
+ m_lastReportedWindowState = currentState;
+}
+
// --------------------------------------------------------------------------
bool QCocoaWindow::windowIsPopupType(Qt::WindowType type) const
@@ -1587,26 +1123,13 @@ QCocoaGLContext *QCocoaWindow::currentContext() const
#endif
/*!
- Checks if the window is a non-top level QWindow with a NSWindow.
-
- \sa _q_platform_MacUseNSWindow, QT_MAC_USE_NSWINDOW
-*/
-bool QCocoaWindow::isChildNSWindow() const
-{
- return m_view.window.parentWindow != nil;
-}
-
-/*!
Checks if the window is the content view of its immediate NSWindow.
Being the content view of a NSWindow means the QWindow is
the highest accessible NSView object in the window's view
hierarchy.
- This can only happen in two cases, either if the QWindow is
- itself a top level window, or if it's a child NSWindow.
-
- \sa isChildNSWindow
+ This is the case if the QWindow is a top level window.
*/
bool QCocoaWindow::isContentView() const
{
@@ -1614,33 +1137,16 @@ bool QCocoaWindow::isContentView() const
}
/*!
- Iterates child NSWindows that have a corresponding QCocoaWindow.
-*/
-void QCocoaWindow::foreachChildNSWindow(void (^block)(QCocoaWindow *))
-{
- NSArray *windows = m_view.window.childWindows;
- [windows enumerateObjectsUsingBlock:^(NSWindow *window, NSUInteger index, BOOL *stop) {
- Q_UNUSED(index);
- Q_UNUSED(stop);
- if (QNSView *view = qnsview_cast(window.contentView))
- block(view.platformWindow);
- }];
-}
-
-/*!
Recreates (or removes) the NSWindow for this QWindow, if needed.
- A QWindow may need a corresponding NSWindow, depending on whether
- or not it's a top level or not (or explicitly set to be a child
- NSWindow), whether it is a NSPanel or not, etc.
+ A QWindow may need a corresponding NSWindow/NSPanel, depending on
+ whether or not it's a top level or not, window flags, etc.
*/
void QCocoaWindow::recreateWindowIfNeeded()
{
QMacAutoReleasePool pool;
QPlatformWindow *parentWindow = QPlatformWindow::parent();
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::recreateWindowIfNeeded" << window()
- << "parent" << (parentWindow ? parentWindow->window() : 0);
RecreationReasons recreateReason = RecreationNotNeeded;
@@ -1658,79 +1164,56 @@ void QCocoaWindow::recreateWindowIfNeeded()
if (m_windowModality != window()->modality())
recreateReason |= WindowModalityChanged;
- const bool shouldBeChildNSWindow = parentWindow && qt_mac_resolveOption(NO,
- window(), "_q_platform_MacUseNSWindow", "QT_MAC_USE_NSWINDOW");
-
- if (isChildNSWindow() != shouldBeChildNSWindow)
- recreateReason |= ChildNSWindowChanged;
-
- const bool shouldBeContentView = (!parentWindow && !m_viewIsEmbedded) || shouldBeChildNSWindow;
+ const bool shouldBeContentView = !parentWindow && !m_viewIsEmbedded;
if (isContentView() != shouldBeContentView)
recreateReason |= ContentViewChanged;
Qt::WindowType type = window()->type();
const bool isPanel = isContentView() && [m_view.window isKindOfClass:[QNSPanel class]];
- const bool shouldBePanel = shouldBeContentView && !shouldBeChildNSWindow &&
+ const bool shouldBePanel = shouldBeContentView &&
((type & Qt::Popup) == Qt::Popup || (type & Qt::Dialog) == Qt::Dialog);
if (isPanel != shouldBePanel)
recreateReason |= PanelChanged;
- if (recreateReason == RecreationNotNeeded) {
- qCDebug(lcQpaCocoaWindow) << "No need to recreate NSWindow";
- return;
- }
+ qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::recreateWindowIfNeeded" << window() << recreateReason;
- qCDebug(lcQpaCocoaWindow) << "Reconfiguring NSWindow due to" << recreateReason;
+ if (recreateReason == RecreationNotNeeded)
+ return;
QCocoaWindow *parentCocoaWindow = static_cast<QCocoaWindow *>(parentWindow);
- if (shouldBeChildNSWindow) {
- QWindow *parentQWindow = parentWindow->window();
- // Ensure that all parents in the hierarchy are also child NSWindows
- if (!parentQWindow->property("_q_platform_MacUseNSWindow").toBool()) {
- parentQWindow->setProperty("_q_platform_MacUseNSWindow", QVariant(true));
- parentCocoaWindow->recreateWindowIfNeeded();
- }
- }
-
// Remove current window (if any)
if ((isContentView() && !shouldBeContentView) || (recreateReason & PanelChanged)) {
- qCDebug(lcQpaCocoaWindow) << "Getting rid of existing window" << m_nsWindow;
- [m_nsWindow closeAndRelease];
- if (isChildNSWindow())
- [m_view.window.parentWindow removeChildWindow:m_view.window];
- if (isContentView()) {
- // We explicitly disassociate m_view from the window's contentView,
- // as AppKit does not automatically do this in response to removing
- // the view from the NSThemeFrame subview list, so we might end up
- // with a NSWindow contentView pointing to a deallocated NSView.
- m_view.window.contentView = nil;
+ if (m_nsWindow) {
+ qCDebug(lcQpaCocoaWindow) << "Getting rid of existing window" << m_nsWindow;
+ [m_nsWindow closeAndRelease];
+ if (isContentView()) {
+ // We explicitly disassociate m_view from the window's contentView,
+ // as AppKit does not automatically do this in response to removing
+ // the view from the NSThemeFrame subview list, so we might end up
+ // with a NSWindow contentView pointing to a deallocated NSView.
+ m_view.window.contentView = nil;
+ }
+ m_nsWindow = 0;
}
- m_nsWindow = 0;
}
if (shouldBeContentView) {
bool noPreviousWindow = m_nsWindow == 0;
+ QCocoaNSWindow *newWindow = nullptr;
if (noPreviousWindow)
- m_nsWindow = createNSWindow(shouldBeChildNSWindow, shouldBePanel);
-
- if (m_view.window.parentWindow) {
- if (!shouldBeChildNSWindow || (recreateReason & ParentChanged))
- [m_view.window.parentWindow removeChildWindow:m_view.window];
- m_forwardWindow = oldParentCocoaWindow;
- }
+ newWindow = createNSWindow(shouldBePanel);
// Move view to new NSWindow if needed
- if (m_nsWindow.contentView != m_view) {
- qCDebug(lcQpaCocoaWindow) << "Ensuring that view is content view for" << m_nsWindow;
+ if (newWindow) {
+ qCDebug(lcQpaCocoaWindow) << "Ensuring that" << m_view << "is content view for" << newWindow;
[m_view setPostsFrameChangedNotifications:NO];
- [m_view retain];
- if (m_view.superview) // m_view comes from another NSWindow
- [m_view removeFromSuperview];
- [m_nsWindow setContentView:m_view];
- [m_view release];
+ [newWindow setContentView:m_view];
[m_view setPostsFrameChangedNotifications:YES];
+
+ m_nsWindow = newWindow;
+ Q_ASSERT(m_view.window == m_nsWindow);
}
}
@@ -1742,20 +1225,8 @@ void QCocoaWindow::recreateWindowIfNeeded()
setWindowFlags(window()->flags());
setWindowTitle(window()->title());
setWindowState(window()->windowState());
- } else if (shouldBeChildNSWindow) {
- if (!m_hiddenByClipping) {
- [parentCocoaWindow->m_nsWindow addChildWindow:m_nsWindow ordered:NSWindowAbove];
- parentCocoaWindow->reinsertChildWindow(this);
- }
-
- // Set properties after the window has been made a child NSWindow
- setCocoaGeometry(windowGeometry());
- setWindowFlags(window()->flags());
} else {
// Child windows have no NSWindow, link the NSViews instead.
- if ([m_view superview])
- [m_view removeFromSuperview];
-
[parentCocoaWindow->m_view addSubview:m_view];
QRect rect = windowGeometry();
// Prevent setting a (0,0) window size; causes opengl context
@@ -1771,31 +1242,14 @@ void QCocoaWindow::recreateWindowIfNeeded()
if (!qFuzzyCompare(opacity, qreal(1.0)))
setOpacity(opacity);
+ setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
+
// top-level QWindows may have an attached NSToolBar, call
// update function which will attach to the NSWindow.
if (!parentWindow)
updateNSToolbar();
}
-void QCocoaWindow::reinsertChildWindow(QCocoaWindow *child)
-{
- const QObjectList &childWindows = window()->children();
- int childIndex = childWindows.indexOf(child->window());
- Q_ASSERT(childIndex != -1);
-
- for (int i = childIndex; i < childWindows.size(); ++i) {
- QWindow *window = static_cast<QWindow *>(childWindows.at(i));
- QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
- if (!cocoaWindow)
- continue;
-
- NSWindow *nsChild = cocoaWindow->m_nsWindow;
- if (i != childIndex)
- [m_nsWindow removeChildWindow:nsChild];
- [m_nsWindow addChildWindow:nsChild ordered:NSWindowAbove];
- }
-}
-
void QCocoaWindow::requestActivateWindow()
{
NSWindow *window = [m_view window];
@@ -1803,10 +1257,8 @@ void QCocoaWindow::requestActivateWindow()
[window makeKeyWindow];
}
-QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool shouldBePanel)
+QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
{
- qCDebug(lcQpaCocoaWindow) << "createNSWindow" << shouldBeChildNSWindow << shouldBePanel;
-
QMacAutoReleasePool pool;
QRect rect = geometry();
@@ -1838,46 +1290,41 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBeChildNSWindow, bool sh
// Create NSWindow
Class windowClass = shouldBePanel ? [QNSPanel class] : [QNSWindow class];
- NSUInteger styleMask = shouldBeChildNSWindow ? NSBorderlessWindowMask : windowStyleMask(flags);
- QCocoaNSWindow *window = [[windowClass alloc] initWithContentRect:frame
- screen:cocoaScreen->nativeScreen() styleMask:styleMask qPlatformWindow:this];
+ QCocoaNSWindow *nsWindow = [[windowClass alloc] initWithContentRect:frame
+ screen:cocoaScreen->nativeScreen() styleMask:windowStyleMask(flags) qPlatformWindow:this];
+ Q_ASSERT_X(nsWindow.screen == cocoaScreen->nativeScreen(), "QCocoaWindow",
+ "Resulting NSScreen should match the requested NSScreen");
- window.restorable = NO;
- window.level = shouldBeChildNSWindow ? NSNormalWindowLevel : windowLevel(flags);
+ if (targetScreen != window()->screen())
+ QWindowSystemInterface::handleWindowScreenChanged(window(), targetScreen);
+
+ nsWindow.restorable = NO;
+ nsWindow.level = windowLevel(flags);
if (!isOpaque()) {
- window.backgroundColor = [NSColor clearColor];
- window.opaque = NO;
+ nsWindow.backgroundColor = [NSColor clearColor];
+ nsWindow.opaque = NO;
}
- Q_ASSERT(!(shouldBePanel && shouldBeChildNSWindow));
-
if (shouldBePanel) {
// Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set
- window.hidesOnDeactivate = ((type & Qt::Tool) == Qt::Tool) && !alwaysShowToolWindow();
+ nsWindow.hidesOnDeactivate = ((type & Qt::Tool) == Qt::Tool) && !alwaysShowToolWindow();
// Make popup windows show on the same desktop as the parent full-screen window
- window.collectionBehavior = NSWindowCollectionBehaviorFullScreenAuxiliary;
+ nsWindow.collectionBehavior = NSWindowCollectionBehaviorFullScreenAuxiliary;
if ((type & Qt::Popup) == Qt::Popup) {
- window.hasShadow = YES;
- window.animationBehavior = NSWindowAnimationBehaviorUtilityWindow;
+ nsWindow.hasShadow = YES;
+ nsWindow.animationBehavior = NSWindowAnimationBehaviorUtilityWindow;
}
- } else if (shouldBeChildNSWindow) {
- window.collectionBehavior =
- NSWindowCollectionBehaviorManaged
- | NSWindowCollectionBehaviorIgnoresCycle
- | NSWindowCollectionBehaviorFullScreenAuxiliary;
- window.hasShadow = NO;
- window.animationBehavior = NSWindowAnimationBehaviorNone;
}
// Persist modality so we can detect changes later on
m_windowModality = QPlatformWindow::window()->modality();
- applyContentBorderThickness(window);
+ applyContentBorderThickness(nsWindow);
- return window;
+ return nsWindow;
}
bool QCocoaWindow::alwaysShowToolWindow() const
@@ -1896,10 +1343,10 @@ void QCocoaWindow::removeMonitor()
// Returns the current global screen geometry for the nswindow associated with this window.
QRect QCocoaWindow::nativeWindowGeometry() const
{
- if (!m_nsWindow || isChildNSWindow())
+ if (!isContentView())
return geometry();
- NSRect rect = [m_nsWindow frame];
+ NSRect rect = m_view.window.frame;
QPlatformScreen *onScreen = QPlatformScreen::platformScreenForWindow(window());
int flippedY = onScreen->geometry().height() - rect.origin.y - rect.size.height; // account for nswindow inverted y.
QRect qRect = QRect(rect.origin.x, flippedY, rect.size.width, rect.size.height);
@@ -1913,13 +1360,15 @@ QRect QCocoaWindow::nativeWindowGeometry() const
updated yet, so window()->windowState() will reflect the previous state that was
reported to QtGui.
*/
-void QCocoaWindow::applyWindowState(Qt::WindowState newState)
+void QCocoaWindow::applyWindowState(Qt::WindowStates requestedState)
{
const Qt::WindowState currentState = windowState();
+ const Qt::WindowState newState = QWindowPrivate::effectiveState(requestedState);
+
if (newState == currentState)
return;
- if (!m_nsWindow)
+ if (!isContentView())
return;
const NSSize contentSize = m_view.frame.size;
@@ -1927,23 +1376,25 @@ void QCocoaWindow::applyWindowState(Qt::WindowState newState)
// If content view width or height is 0 then the window animations will crash so
// do nothing. We report the current state back to reflect the failed operation.
qWarning("invalid window content view size, check your window geometry");
- reportCurrentWindowState(true);
+ handleWindowStateChanged(HandleUnconditionally);
return;
}
- if (m_nsWindow.styleMask & NSUtilityWindowMask) {
- // Utility panels cannot be fullscreen
- qWarning() << window()->type() << "windows can not be made full screen";
- reportCurrentWindowState(true);
+ const NSWindow *nsWindow = m_view.window;
+
+ if (nsWindow.styleMask & NSUtilityWindowMask
+ && newState & (Qt::WindowMinimized | Qt::WindowFullScreen)) {
+ qWarning() << window()->type() << "windows can not be made" << newState;
+ handleWindowStateChanged(HandleUnconditionally);
return;
}
- const id sender = m_nsWindow;
+ const id sender = nsWindow;
// First we need to exit states that can't transition directly to other states
switch (currentState) {
case Qt::WindowMinimized:
- [m_nsWindow deminiaturize:sender];
+ [nsWindow deminiaturize:sender];
Q_ASSERT_X(windowState() != Qt::WindowMinimized, "QCocoaWindow",
"[NSWindow deminiaturize:] is synchronous");
break;
@@ -1969,7 +1420,7 @@ void QCocoaWindow::applyWindowState(Qt::WindowState newState)
toggleMaximized();
break;
case Qt::WindowMinimized:
- [m_nsWindow miniaturize:sender];
+ [nsWindow miniaturize:sender];
break;
case Qt::WindowNoState:
if (windowState() == Qt::WindowMaximized)
@@ -1982,27 +1433,31 @@ void QCocoaWindow::applyWindowState(Qt::WindowState newState)
void QCocoaWindow::toggleMaximized()
{
+ const NSWindow *window = m_view.window;
+
// The NSWindow needs to be resizable, otherwise the window will
// not be possible to zoom back to non-zoomed state.
- const bool wasResizable = m_nsWindow.styleMask & NSResizableWindowMask;
- m_nsWindow.styleMask |= NSResizableWindowMask;
+ const bool wasResizable = window.styleMask & NSResizableWindowMask;
+ window.styleMask |= NSResizableWindowMask;
- const id sender = m_nsWindow;
- [m_nsWindow zoom:sender];
+ const id sender = window;
+ [window zoom:sender];
if (!wasResizable)
- m_nsWindow.styleMask &= ~NSResizableWindowMask;
+ window.styleMask &= ~NSResizableWindowMask;
}
void QCocoaWindow::toggleFullScreen()
{
+ const NSWindow *window = m_view.window;
+
// The window needs to have the correct collection behavior for the
// toggleFullScreen call to have an effect. The collection behavior
// will be reset in windowDidEnterFullScreen/windowDidLeaveFullScreen.
- m_nsWindow.collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
+ window.collectionBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
- const id sender = m_nsWindow;
- [m_nsWindow toggleFullScreen:sender];
+ const id sender = window;
+ [window toggleFullScreen:sender];
}
bool QCocoaWindow::isTransitioningToFullScreen() const
@@ -2030,22 +1485,12 @@ Qt::WindowState QCocoaWindow::windowState() const
return Qt::WindowNoState;
}
-void QCocoaWindow::reportCurrentWindowState(bool unconditionally)
-{
- Qt::WindowState currentState = windowState();
- if (!unconditionally && currentState == m_lastReportedWindowState)
- return;
-
- QWindowSystemInterface::handleWindowStateChanged<QWindowSystemInterface::SynchronousDelivery>(
- window(), currentState, m_lastReportedWindowState);
- m_lastReportedWindowState = currentState;
-}
-
bool QCocoaWindow::setWindowModified(bool modified)
{
- if (!m_nsWindow)
+ if (!isContentView())
return false;
- [m_nsWindow setDocumentEdited:(modified?YES:NO)];
+
+ m_view.window.documentEdited = modified;
return true;
}
@@ -2122,35 +1567,38 @@ void QCocoaWindow::setContentBorderThickness(int topThickness, int bottomThickne
bool enable = (topThickness > 0 || bottomThickness > 0);
m_drawContentBorderGradient = enable;
- applyContentBorderThickness(m_nsWindow);
+ applyContentBorderThickness();
}
void QCocoaWindow::registerContentBorderArea(quintptr identifier, int upper, int lower)
{
m_contentBorderAreas.insert(identifier, BorderRange(identifier, upper, lower));
- applyContentBorderThickness(m_nsWindow);
+ applyContentBorderThickness();
}
void QCocoaWindow::setContentBorderAreaEnabled(quintptr identifier, bool enable)
{
m_enabledContentBorderAreas.insert(identifier, enable);
- applyContentBorderThickness(m_nsWindow);
+ applyContentBorderThickness();
}
void QCocoaWindow::setContentBorderEnabled(bool enable)
{
m_drawContentBorderGradient = enable;
- applyContentBorderThickness(m_nsWindow);
+ applyContentBorderThickness();
}
void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
{
+ if (!window && isContentView())
+ window = m_view.window;
+
if (!window)
return;
if (!m_drawContentBorderGradient) {
- [window setStyleMask:[window styleMask] & ~NSTexturedBackgroundWindowMask];
- [[[window contentView] superview] setNeedsDisplay:YES];
+ window.styleMask = window.styleMask & ~NSTexturedBackgroundWindowMask;
+ [window.contentView.superview setNeedsDisplay:YES];
return;
}
@@ -2187,22 +1635,23 @@ void QCocoaWindow::applyContentBorderThickness(NSWindow *window)
void QCocoaWindow::updateNSToolbar()
{
- if (!m_nsWindow)
+ if (!isContentView())
return;
NSToolbar *toolbar = QCocoaIntegration::instance()->toolbar(window());
+ const NSWindow *window = m_view.window;
- if ([m_nsWindow toolbar] == toolbar)
+ if (window.toolbar == toolbar)
return;
- [m_nsWindow setToolbar: toolbar];
- [m_nsWindow setShowsToolbarButton:YES];
+ window.toolbar = toolbar;
+ window.showsToolbarButton = YES;
}
bool QCocoaWindow::testContentBorderAreaPosition(int position) const
{
- return m_nsWindow && m_drawContentBorderGradient &&
- 0 <= position && position < [m_nsWindow contentBorderThicknessForEdge: NSMaxYEdge];
+ return isContentView() && m_drawContentBorderGradient &&
+ 0 <= position && position < [m_view.window contentBorderThicknessForEdge:NSMaxYEdge];
}
qreal QCocoaWindow::devicePixelRatio() const
@@ -2216,85 +1665,6 @@ qreal QCocoaWindow::devicePixelRatio() const
return backingSize.height;
}
-// Returns whether the window can be expose, which it can
-// if it is on screen and has a valid geometry.
-bool QCocoaWindow::isWindowExposable()
-{
- QSize size = geometry().size();
- bool validGeometry = (size.width() > 0 && size.height() > 0);
- bool validScreen = ([[m_view window] screen] != 0);
- bool nonHiddenSuperView = ![[m_view superview] isHidden];
- return (validGeometry && validScreen && nonHiddenSuperView);
-}
-
-// Exposes the window by posting an expose event to QWindowSystemInterface
-void QCocoaWindow::exposeWindow()
-{
- m_geometryUpdateExposeAllowed = true;
-
- if (!isWindowExposable())
- return;
-
- if (window()->isTopLevel()) {
- // Update the QWindow's screen property. This property is set
- // to QGuiApplication::primaryScreen() at QWindow construciton
- // time, and we won't get a NSWindowDidChangeScreenNotification
- // on show. The case where the window is initially displayed
- // on a non-primary screen needs special handling here.
- if (QCocoaScreen *cocoaScreen = QCocoaIntegration::instance()->screenForNSScreen(m_nsWindow.screen))
- window()->setScreen(cocoaScreen->screen());
- }
-
- if (!m_isExposed) {
- m_isExposed = true;
- m_exposedGeometry = geometry();
- m_exposedDevicePixelRatio = devicePixelRatio();
- QRect geometry(QPoint(0, 0), m_exposedGeometry.size());
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow: exposeWindow" << window() << geometry;
- QWindowSystemInterface::handleExposeEvent(window(), geometry);
- }
-}
-
-// Obscures the window by posting an empty expose event to QWindowSystemInterface
-void QCocoaWindow::obscureWindow()
-{
- if (m_isExposed) {
- m_geometryUpdateExposeAllowed = false;
- m_isExposed = false;
-
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::obscureWindow" << window();
- QWindowSystemInterface::handleExposeEvent(window(), QRegion());
- }
-}
-
-// Updates window geometry by posting an expose event to QWindowSystemInterface
-void QCocoaWindow::updateExposedGeometry()
-{
- // updateExposedGeometry is not allowed to send the initial expose. If you want
- // that call exposeWindow();
- if (!m_geometryUpdateExposeAllowed)
- return;
-
- // Do not send incorrect exposes in case the window is not even visible yet.
- // We might get here as a result of a resize() from QWidget's show(), for instance.
- if (!window()->isVisible())
- return;
-
- if (!isWindowExposable())
- return;
-
- if (m_exposedGeometry.size() == geometry().size() && m_exposedDevicePixelRatio == devicePixelRatio())
- return;
-
- m_isExposed = true;
- m_exposedGeometry = geometry();
- m_exposedDevicePixelRatio = devicePixelRatio();
-
- QRect geometry(QPoint(0, 0), m_exposedGeometry.size());
- qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::updateExposedGeometry" << window() << geometry;
- QWindowSystemInterface::handleExposeEvent(window(), geometry);
-}
-
QWindow *QCocoaWindow::childWindowAt(QPoint windowPoint)
{
QWindow *targetWindow = window();
@@ -2344,8 +1714,11 @@ QPoint QCocoaWindow::bottomLeftClippedByNSWindowOffset() const
QMargins QCocoaWindow::frameMargins() const
{
- NSRect frameW = [m_nsWindow frame];
- NSRect frameC = [m_nsWindow contentRectForFrameRect:frameW];
+ if (!isContentView())
+ return QMargins();
+
+ NSRect frameW = m_view.window.frame;
+ NSRect frameC = [m_view.window contentRectForFrameRect:frameW];
return QMargins(frameW.origin.x - frameC.origin.x,
(frameW.origin.y + frameW.size.height) - (frameC.origin.y + frameC.size.height),
@@ -2358,4 +1731,19 @@ void QCocoaWindow::setFrameStrutEventsEnabled(bool enabled)
m_frameStrutEventsEnabled = enabled;
}
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QCocoaWindow *window)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << "QCocoaWindow(" << (const void *)window;
+ if (window)
+ debug << ", window=" << window->window();
+ debug << ')';
+ return debug;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
#include "moc_qcocoawindow.cpp"
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index a78151ebbe..414c6b7fe7 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -51,18 +51,14 @@
QT_BEGIN_NAMESPACE
class QCocoaWindow;
-class QCocoaBackingStore;
class QCocoaGLContext;
QT_END_NAMESPACE
Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
@interface QT_MANGLE_NAMESPACE(QNSView) : NSView <NSTextInputClient> {
- QCocoaBackingStore* m_backingStore;
- QPoint m_backingStoreOffset;
QRegion m_maskRegion;
CGImageRef m_maskImage;
- uchar *m_maskData;
bool m_shouldInvalidateWindowShadow;
QPointer<QCocoaWindow> m_platformWindow;
NSTrackingArea *m_trackingArea;
@@ -72,6 +68,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
QString m_composingText;
bool m_sendKeyEvent;
QStringList *currentCustomDragTypes;
+ bool m_dontOverrideCtrlLMB;
bool m_sendUpAsRightButton;
Qt::KeyboardModifiers currentWheelModifiers;
#ifndef QT_NO_OPENGL
@@ -93,16 +90,12 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
#ifndef QT_NO_OPENGL
- (void)setQCocoaGLContext:(QCocoaGLContext *)context;
#endif
-- (void)flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset;
-- (void)clearBackingStore:(QCocoaBackingStore *)backingStore;
- (void)setMaskRegion:(const QRegion *)region;
+- (CGImageRef)maskImage;
- (void)invalidateWindowShadowIfNeeded;
- (void)drawRect:(NSRect)dirtyRect;
-- (void)drawBackingStoreUsingCoreGraphics:(NSRect)dirtyRect;
-- (void)updateGeometry;
- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification;
- (void)viewDidHide;
-- (void)viewDidUnhide;
- (void)removeFromSuperview;
- (BOOL)isFlipped;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index e6d513bb89..e531e79c8f 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -71,8 +71,6 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
static QTouchDevice *touchDevice = 0;
-static bool _q_dontOverrideCtrlLMB = false;
-
@interface NSEvent (Qt_Compile_Leopard_DeviceDelta)
- (CGFloat)deviceDeltaX;
- (CGFloat)deviceDeltaY;
@@ -133,15 +131,9 @@ static bool _q_dontOverrideCtrlLMB = false;
@implementation QT_MANGLE_NAMESPACE(QNSView)
-+ (void)initialize
-{
- _q_dontOverrideCtrlLMB = qt_mac_resolveOption(false, "QT_MAC_DONT_OVERRIDE_CTRL_LMB");
-}
-
- (id) init
{
if (self = [super initWithFrame:NSZeroRect]) {
- m_backingStore = 0;
m_maskImage = 0;
m_shouldInvalidateWindowShadow = false;
m_buttons = Qt::NoButton;
@@ -153,6 +145,7 @@ static bool _q_dontOverrideCtrlLMB = false;
m_shouldSetGLContextinDrawRect = false;
#endif
currentCustomDragTypes = 0;
+ m_dontOverrideCtrlLMB = false;
m_sendUpAsRightButton = false;
m_inputSource = 0;
m_mouseMoveHelper = [[QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper) alloc] initWithView:self];
@@ -199,6 +192,7 @@ static bool _q_dontOverrideCtrlLMB = false;
m_platformWindow = platformWindow;
m_sendKeyEvent = false;
+ m_dontOverrideCtrlLMB = qt_mac_resolveOption(false, platformWindow->window(), "_q_platform_MacDontOverrideCtrlLMB", "QT_MAC_DONT_OVERRIDE_CTRL_LMB");
m_trackingArea = nil;
#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
@@ -226,6 +220,22 @@ static bool _q_dontOverrideCtrlLMB = false;
return self;
}
+- (NSString *)description
+{
+ NSMutableString *description = [NSMutableString stringWithString:[super description]];
+
+#ifndef QT_NO_DEBUG_STREAM
+ QString platformWindowDescription;
+ QDebug debug(&platformWindowDescription);
+ debug.nospace() << "; " << m_platformWindow << ">";
+
+ NSRange lastCharacter = [description rangeOfComposedCharacterSequenceAtIndex:description.length - 1];
+ [description replaceCharactersInRange:lastCharacter withString:platformWindowDescription.toNSString()];
+#endif
+
+ return description;
+}
+
#ifndef QT_NO_OPENGL
- (void) setQCocoaGLContext:(QCocoaGLContext *)context
{
@@ -249,18 +259,13 @@ static bool _q_dontOverrideCtrlLMB = false;
if ([self superview]) {
m_platformWindow->m_viewIsEmbedded = true;
QWindowSystemInterface::handleGeometryChange(m_platformWindow->window(), m_platformWindow->geometry());
- m_platformWindow->updateExposedGeometry();
+ [self setNeedsDisplay:YES];
QWindowSystemInterface::flushWindowSystemEvents();
} else {
m_platformWindow->m_viewIsEmbedded = false;
}
}
-- (void)viewDidMoveToWindow
-{
- m_backingStore = Q_NULLPTR;
-}
-
- (QWindow *)topLevelWindow
{
if (!m_platformWindow)
@@ -279,77 +284,6 @@ static bool _q_dontOverrideCtrlLMB = false;
return focusWindow;
}
-- (void)updateGeometry
-{
- if (!m_platformWindow)
- return;
-
- QRect geometry;
-
- if (self.window.parentWindow) {
- return;
-#if 0
- //geometry = QRectF::fromCGRect([self frame]).toRect();
- qDebug() << "nsview updateGeometry" << m_platformWindow->window();
- QRect screenRect = QRectF::fromCGRect([m_platformWindow->m_nsWindow convertRectToScreen:[self frame]]).toRect();
- qDebug() << "screenRect" << screenRect;
-
- screenRect.moveTop(qt_mac_flipYCoordinate(screenRect.y() + screenRect.height()));
- geometry = QRect(m_platformWindow->window()->parent()->mapFromGlobal(screenRect.topLeft()), screenRect.size());
- qDebug() << "geometry" << geometry;
-#endif
- //geometry = QRect(screenRect.origin.x, qt_mac_flipYCoordinate(screenRect.origin.y + screenRect.size.height), screenRect.size.width, screenRect.size.height);
- } else if (m_platformWindow->m_nsWindow) {
- // top level window, get window rect and flip y.
- NSRect rect = [self frame];
- NSRect windowRect = [[self window] frame];
- geometry = QRect(windowRect.origin.x, qt_mac_flipYCoordinate(windowRect.origin.y + rect.size.height), rect.size.width, rect.size.height);
- } else if (m_platformWindow->m_viewIsToBeEmbedded) {
- // embedded child window, use the frame rect ### merge with case below
- geometry = QRectF::fromCGRect(NSRectToCGRect([self bounds])).toRect();
- } else {
- // child window, use the frame rect
- geometry = QRectF::fromCGRect(NSRectToCGRect([self frame])).toRect();
- }
-
- if (m_platformWindow->m_nsWindow && geometry == m_platformWindow->geometry())
- return;
-
- const bool isResize = geometry.size() != m_platformWindow->geometry().size();
-
- // It can happen that self.window is nil (if we are changing
- // styleMask from/to borderless and content view is being re-parented)
- // - this results in an invalid coordinates.
- if (m_platformWindow->m_inSetStyleMask && !self.window)
- return;
-
- qCDebug(lcQpaCocoaWindow) << "[QNSView udpateGeometry:]" << m_platformWindow->window()
- << "current" << m_platformWindow->geometry() << "new" << geometry;
-
- // Call setGeometry on QPlatformWindow. (not on QCocoaWindow,
- // doing that will initiate a geometry change it and possibly create
- // an infinite loop when this notification is triggered again.)
- m_platformWindow->QPlatformWindow::setGeometry(geometry);
-
- // Don't send the geometry change if the QWindow is designated to be
- // embedded in a foreign view hiearchy but has not actually been
- // embedded yet - it's too early.
- if (m_platformWindow->m_viewIsToBeEmbedded && !m_platformWindow->m_viewIsEmbedded)
- return;
-
- // Send a geometry change event to Qt, if it's ready to handle events
- if (!m_platformWindow->m_inConstructor) {
- QWindowSystemInterface::handleGeometryChange(m_platformWindow->window(), geometry);
- m_platformWindow->updateExposedGeometry();
- // Guard against processing window system events during QWindow::setGeometry
- // calles, which Qt and Qt applications do not excpect.
- if (!m_platformWindow->m_inSetGeometry)
- QWindowSystemInterface::flushWindowSystemEvents();
- else if (isResize)
- m_backingStore = 0;
- }
-}
-
- (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification
{
Q_UNUSED(textInputContextKeyboardSelectionDidChangeNotification)
@@ -361,12 +295,13 @@ static bool _q_dontOverrideCtrlLMB = false;
- (void)viewDidHide
{
- m_platformWindow->obscureWindow();
-}
+ if (!m_platformWindow->isExposed())
+ return;
-- (void)viewDidUnhide
-{
- m_platformWindow->exposeWindow();
+ m_platformWindow->handleExposeEvent(QRegion());
+
+ // Note: setNeedsDisplay is automatically called for
+ // viewDidUnhide so no reason to override it here.
}
- (void)removeFromSuperview
@@ -375,30 +310,6 @@ static bool _q_dontOverrideCtrlLMB = false;
[super removeFromSuperview];
}
-- (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset
-{
- qCDebug(lcQpaCocoaWindow) << "[QNSView flushBackingStore:]" << m_platformWindow->window() << region.rectCount() << region.boundingRect() << offset;
-
- m_backingStore = backingStore;
- m_backingStoreOffset = offset * m_backingStore->paintDevice()->devicePixelRatio();
-
- // Prevent buildup of NSDisplayCycle objects during setNeedsDisplayInRect, which
- // would normally be released as part of the root runloop's autorelease pool, but
- // can be kept alive during repeated painting which starve the root runloop.
- // FIXME: Move this to the event dispatcher, to cover more cases of starvation.
- // FIXME: Figure out if there's a way to detect and/or prevent runloop starvation.
- QMacAutoReleasePool pool;
-
- for (const QRect &rect : region)
- [self setNeedsDisplayInRect:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())];
-}
-
-- (void)clearBackingStore:(QCocoaBackingStore *)backingStore
-{
- if (backingStore == m_backingStore)
- m_backingStore = 0;
-}
-
- (BOOL) hasMask
{
return !m_maskRegion.isEmpty();
@@ -440,20 +351,34 @@ static bool _q_dontOverrideCtrlLMB = false;
m_maskImage = qt_mac_toCGImageMask(maskImage);
}
+- (CGImageRef)maskImage
+{
+ return m_maskImage;
+}
+
- (void)invalidateWindowShadowIfNeeded
{
- if (m_shouldInvalidateWindowShadow && m_platformWindow->m_nsWindow) {
- [m_platformWindow->m_nsWindow invalidateShadow];
+ if (m_shouldInvalidateWindowShadow && m_platformWindow->isContentView()) {
+ [m_platformWindow->nativeWindow() invalidateShadow];
m_shouldInvalidateWindowShadow = false;
}
}
- (void)drawRect:(NSRect)dirtyRect
{
+ Q_UNUSED(dirtyRect);
+
if (!m_platformWindow)
return;
- qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:]" << m_platformWindow->window() << QRectF::fromCGRect(NSRectToCGRect(dirtyRect));
+ QRegion exposedRegion;
+ const NSRect *dirtyRects;
+ NSInteger numDirtyRects;
+ [self getRectsBeingDrawn:&dirtyRects count:&numDirtyRects];
+ for (int i = 0; i < numDirtyRects; ++i)
+ exposedRegion += QRectF::fromCGRect(dirtyRects[i]).toRect();
+
+ qCDebug(lcQpaCocoaWindow) << "[QNSView drawRect:]" << m_platformWindow->window() << exposedRegion;
#ifndef QT_NO_OPENGL
if (m_glContext && m_shouldSetGLContextinDrawRect) {
@@ -462,78 +387,10 @@ static bool _q_dontOverrideCtrlLMB = false;
}
#endif
- if (m_platformWindow->m_drawContentBorderGradient)
- NSDrawWindowBackground(dirtyRect);
-
- if (m_backingStore)
- [self drawBackingStoreUsingCoreGraphics:dirtyRect];
-
- [self invalidateWindowShadowIfNeeded];
-}
-
-// Draws the backing store content to the QNSView using Core Graphics.
-// This function assumes that the QNSView is in a configuration that
-// supports Core Graphics, such as "classic" mode or layer mode with
-// the default layer.
-- (void)drawBackingStoreUsingCoreGraphics:(NSRect)dirtyRect
-{
- if (!m_backingStore)
- return;
-
- // Calculate source and target rects. The target rect is the dirtyRect:
- CGRect dirtyWindowRect = NSRectToCGRect(dirtyRect);
-
- // The backing store source rect will be larger on retina displays.
- // Scale dirtyRect by the device pixel ratio:
- const qreal devicePixelRatio = m_backingStore->paintDevice()->devicePixelRatio();
- CGRect dirtyBackingRect = CGRectMake(dirtyRect.origin.x * devicePixelRatio,
- dirtyRect.origin.y * devicePixelRatio,
- dirtyRect.size.width * devicePixelRatio,
- dirtyRect.size.height * devicePixelRatio);
-
- NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext];
- CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort];
-
- // Translate coordiate system from CoreGraphics (bottom-left) to NSView (top-left):
- CGContextSaveGState(cgContext);
- int dy = dirtyWindowRect.origin.y + CGRectGetMaxY(dirtyWindowRect);
-
- CGContextTranslateCTM(cgContext, 0, dy);
- CGContextScaleCTM(cgContext, 1, -1);
-
- // If a mask is set, modify the sub image accordingly:
- CGImageRef subMask = 0;
- if (m_maskImage) {
- subMask = CGImageCreateWithImageInRect(m_maskImage, dirtyWindowRect);
- CGContextClipToMask(cgContext, dirtyWindowRect, subMask);
- }
-
- // Clip out and draw the correct sub image from the (shared) backingstore:
- CGRect backingStoreRect = CGRectMake(
- dirtyBackingRect.origin.x + m_backingStoreOffset.x(),
- dirtyBackingRect.origin.y + m_backingStoreOffset.y(),
- dirtyBackingRect.size.width,
- dirtyBackingRect.size.height
- );
- CGImageRef bsCGImage = qt_mac_toCGImage(m_backingStore->toImage());
- CGImageRef cleanImg = CGImageCreateWithImageInRect(bsCGImage, backingStoreRect);
-
- // Optimization: Copy frame buffer content instead of blending for
- // top-level windows where Qt fills the entire window content area.
- // (But don't overpaint the title-bar gradient)
- if (m_platformWindow->m_nsWindow && !m_platformWindow->m_drawContentBorderGradient)
- CGContextSetBlendMode(cgContext, kCGBlendModeCopy);
-
- CGContextDrawImage(cgContext, dirtyWindowRect, cleanImg);
-
- // Clean-up:
- CGContextRestoreGState(cgContext);
- CGImageRelease(cleanImg);
- CGImageRelease(subMask);
- CGImageRelease(bsCGImage);
+ m_platformWindow->handleExposeEvent(exposedRegion);
}
-- (BOOL) isFlipped
+- (BOOL)isFlipped
{
return YES;
}
@@ -652,12 +509,6 @@ static bool _q_dontOverrideCtrlLMB = false;
QPointF qtWindowPoint;
QPointF qtScreenPoint;
QNSView *targetView = self;
- if (m_platformWindow && m_platformWindow->m_forwardWindow) {
- if (theEvent.type == NSLeftMouseDragged || theEvent.type == NSLeftMouseUp)
- targetView = qnsview_cast(m_platformWindow->m_forwardWindow->view());
- else
- m_platformWindow->m_forwardWindow.clear();
- }
if (!targetView.platformWindow)
return;
@@ -866,7 +717,7 @@ static bool _q_dontOverrideCtrlLMB = false;
if ([self hasMarkedText]) {
[[NSTextInputContext currentInputContext] handleEvent:theEvent];
} else {
- if (!_q_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) {
+ if (!m_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) {
m_buttons |= Qt::RightButton;
m_sendUpAsRightButton = true;
} else {
@@ -985,7 +836,7 @@ static bool _q_dontOverrideCtrlLMB = false;
// the time of the leave. This is dificult to accomplish by
// handling mouseEnter and mouseLeave envents, since they are sent
// individually to different views.
- if (m_platformWindow->m_nsWindow && childWindow) {
+ if (m_platformWindow->isContentView() && childWindow) {
if (childWindow != m_platformWindow->m_enterLeaveTargetWindow) {
QWindowSystemInterface::handleEnterLeaveEvent(childWindow, m_platformWindow->m_enterLeaveTargetWindow, windowPoint, screenPoint);
m_platformWindow->m_enterLeaveTargetWindow = childWindow;
@@ -1012,7 +863,7 @@ static bool _q_dontOverrideCtrlLMB = false;
return;
// Top-level windows generate enter events for sub-windows.
- if (!m_platformWindow->m_nsWindow)
+ if (!m_platformWindow->isContentView())
return;
QPointF windowPoint;
@@ -1034,7 +885,7 @@ static bool _q_dontOverrideCtrlLMB = false;
return;
// Top-level windows generate leave events for sub-windows.
- if (!m_platformWindow->m_nsWindow)
+ if (!m_platformWindow->isContentView())
return;
QWindowSystemInterface::handleLeaveEvent(m_platformWindow->m_enterLeaveTargetWindow);
@@ -2082,7 +1933,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
if (nativeDrag->currentDrag()) {
// The drag was started from within the application
- response = QWindowSystemInterface::handleDrag(target, nativeDrag->platformDropData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
+ response = QWindowSystemInterface::handleDrag(target, nativeDrag->dragMimeData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
[self updateCursorFromDragResponse:response drag:nativeDrag];
} else {
QCocoaDropData mimeData([sender draggingPasteboard]);
@@ -2126,7 +1977,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
if (nativeDrag->currentDrag()) {
// The drag was started from within the application
- response = QWindowSystemInterface::handleDrop(target, nativeDrag->platformDropData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
+ response = QWindowSystemInterface::handleDrop(target, nativeDrag->dragMimeData(), mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
} else {
QCocoaDropData mimeData([sender draggingPasteboard]);
response = QWindowSystemInterface::handleDrop(target, &mimeData, mapWindowCoordinates(m_platformWindow->window(), target, qt_windowPoint), qtAllowed);
diff --git a/src/plugins/platforms/cocoa/qnswindow.h b/src/plugins/platforms/cocoa/qnswindow.h
new file mode 100644
index 0000000000..b13b6d42a9
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnswindow.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNSWINDOW_H
+#define QNSWINDOW_H
+
+#include <qglobal.h>
+#include <QPointer>
+#include "qt_mac_p.h"
+
+#include <AppKit/AppKit.h>
+
+QT_FORWARD_DECLARE_CLASS(QCocoaWindow)
+Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSWindowHelper));
+
+// -------------------------------------------------------------------------
+
+@interface NSWindow (FullScreenProperty)
+@property(readonly) BOOL qt_fullScreen;
+@end
+
+// -------------------------------------------------------------------------
+
+@protocol QNSWindowProtocol
+
+@property (nonatomic, readonly) QT_MANGLE_NAMESPACE(QNSWindowHelper) *helper;
+
+- (id)initWithContentRect:(NSRect)contentRect screen:(NSScreen*)screen
+ styleMask:(NSUInteger)windowStyle qPlatformWindow:(QCocoaWindow *)qpw;
+
+- (void)superSendEvent:(NSEvent *)theEvent;
+- (void)closeAndRelease;
+
+@end
+
+typedef NSWindow<QNSWindowProtocol> QCocoaNSWindow;
+
+// -------------------------------------------------------------------------
+
+@interface QT_MANGLE_NAMESPACE(QNSWindowHelper) : NSObject
+{
+ QPointer<QCocoaWindow> _platformWindow;
+}
+
+@property (nonatomic, readonly) QCocoaNSWindow *window;
+@property (nonatomic, readonly) QCocoaWindow *platformWindow;
+
+- (id)initWithNSWindow:(QCocoaNSWindow *)window platformWindow:(QCocoaWindow *)platformWindow;
+- (void)handleWindowEvent:(NSEvent *)theEvent;
+- (void)detachFromPlatformWindow;
+
+@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindowHelper);
+
+// -------------------------------------------------------------------------
+
+@interface QT_MANGLE_NAMESPACE(QNSWindow) : NSWindow<QNSWindowProtocol>
+@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindow);
+
+// -------------------------------------------------------------------------
+
+@interface QT_MANGLE_NAMESPACE(QNSPanel) : NSPanel<QNSWindowProtocol>
+@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSPanel);
+
+// -------------------------------------------------------------------------
+
+#endif // QNSWINDOW_H
diff --git a/src/plugins/platforms/cocoa/qnswindow.mm b/src/plugins/platforms/cocoa/qnswindow.mm
new file mode 100644
index 0000000000..e44db3ff3b
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qnswindow.mm
@@ -0,0 +1,374 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnswindow.h"
+#include "qnswindowdelegate.h"
+#include "qcocoawindow.h"
+#include "qcocoahelpers.h"
+#include "qcocoaeventdispatcher.h"
+
+#include <qpa/qwindowsysteminterface.h>
+#include <qoperatingsystemversion.h>
+
+static bool isMouseEvent(NSEvent *ev)
+{
+ switch ([ev type]) {
+ case NSLeftMouseDown:
+ case NSLeftMouseUp:
+ case NSRightMouseDown:
+ case NSRightMouseUp:
+ case NSMouseMoved:
+ case NSLeftMouseDragged:
+ case NSRightMouseDragged:
+ return true;
+ default:
+ return false;
+ }
+}
+
+@implementation NSWindow (FullScreenProperty)
+
++ (void)load
+{
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+ [center addObserverForName:NSWindowDidEnterFullScreenNotification object:nil queue:nil
+ usingBlock:^(NSNotification *notification) {
+ objc_setAssociatedObject(notification.object, @selector(qt_fullScreen),
+ [NSNumber numberWithBool:YES], OBJC_ASSOCIATION_RETAIN);
+ }
+ ];
+ [center addObserverForName:NSWindowDidExitFullScreenNotification object:nil queue:nil
+ usingBlock:^(NSNotification *notification) {
+ objc_setAssociatedObject(notification.object, @selector(qt_fullScreen),
+ nil, OBJC_ASSOCIATION_RETAIN);
+ }
+ ];
+}
+
+- (BOOL)qt_fullScreen
+{
+ NSNumber *number = objc_getAssociatedObject(self, @selector(qt_fullScreen));
+ return [number boolValue];
+}
+@end
+
+@implementation QNSWindowHelper
+
+- (QCocoaWindow *)platformWindow
+{
+ return _platformWindow.data();
+}
+
+- (id)initWithNSWindow:(QCocoaNSWindow *)window platformWindow:(QCocoaWindow *)platformWindow
+{
+ if (self = [super init]) {
+ _window = window;
+ _platformWindow = platformWindow;
+
+ _window.delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:_platformWindow];
+
+ // Prevent Cocoa from releasing the window on close. Qt
+ // handles the close event asynchronously and we want to
+ // make sure that NSWindow stays valid until the
+ // QCocoaWindow is deleted by Qt.
+ [_window setReleasedWhenClosed:NO];
+ }
+
+ return self;
+}
+
+- (void)handleWindowEvent:(NSEvent *)theEvent
+{
+ // We might get events for a NSWindow after the corresponding platform
+ // window has been deleted, as the NSWindow can outlive the QCocoaWindow
+ // e.g. if being retained by other parts of AppKit, or in an auto-release
+ // pool. We guard against this in QNSView as well, as not all callbacks
+ // come via events, but if they do there's no point in propagating them.
+ if (!self.platformWindow)
+ return;
+
+ const char *eventType = object_getClassName(theEvent);
+ if (QWindowSystemInterface::handleNativeEvent(self.platformWindow->window(),
+ QByteArray::fromRawData(eventType, qstrlen(eventType)), theEvent, nullptr)) {
+ return;
+ }
+
+ [self.window superSendEvent:theEvent];
+
+ if (!self.platformWindow)
+ return; // Platform window went away while processing event
+
+ QCocoaWindow *pw = self.platformWindow;
+ if (pw->frameStrutEventsEnabled() && isMouseEvent(theEvent)) {
+ NSPoint loc = [theEvent locationInWindow];
+ NSRect windowFrame = [self.window convertRectFromScreen:[self.window frame]];
+ NSRect contentFrame = [[self.window contentView] frame];
+ if (NSMouseInRect(loc, windowFrame, NO) && !NSMouseInRect(loc, contentFrame, NO))
+ [qnsview_cast(pw->view()) handleFrameStrutMouseEvent:theEvent];
+ }
+}
+
+- (void)detachFromPlatformWindow
+{
+ _platformWindow.clear();
+ [self.window.delegate release];
+ self.window.delegate = nil;
+}
+
+- (void)dealloc
+{
+ _window = nil;
+ _platformWindow.clear();
+ [super dealloc];
+}
+
+@end
+
+// Deferring window creation breaks OpenGL (the GL context is
+// set up before the window is shown and needs a proper window)
+static const bool kNoDefer = NO;
+
+@implementation QNSWindow
+
+@synthesize helper = _helper;
+
+- (id)initWithContentRect:(NSRect)contentRect
+ screen:(NSScreen*)screen
+ styleMask:(NSUInteger)windowStyle
+ qPlatformWindow:(QCocoaWindow *)qpw
+{
+ if (self = [super initWithContentRect:contentRect styleMask:windowStyle
+ backing:NSBackingStoreBuffered defer:kNoDefer screen:screen]) {
+ _helper = [[QNSWindowHelper alloc] initWithNSWindow:self platformWindow:qpw];
+ }
+ return self;
+}
+
+- (BOOL)canBecomeKeyWindow
+{
+ QCocoaWindow *pw = self.helper.platformWindow;
+ if (!pw)
+ return NO;
+
+ if (pw->shouldRefuseKeyWindowAndFirstResponder())
+ return NO;
+
+ // The default implementation returns NO for title-bar less windows,
+ // override and return yes here to make sure popup windows such as
+ // the combobox popup can become the key window.
+ return YES;
+}
+
+- (BOOL)canBecomeMainWindow
+{
+ BOOL canBecomeMain = YES; // By default, windows can become the main window
+
+ // Windows with a transient parent (such as combobox popup windows)
+ // cannot become the main window:
+ QCocoaWindow *pw = self.helper.platformWindow;
+ if (!pw || pw->window()->transientParent())
+ canBecomeMain = NO;
+
+ return canBecomeMain;
+}
+
+- (void)sendEvent:(NSEvent*)theEvent
+{
+ [self.helper handleWindowEvent:theEvent];
+}
+
+- (void)superSendEvent:(NSEvent *)theEvent
+{
+ [super sendEvent:theEvent];
+}
+
+- (void)closeAndRelease
+{
+ qCDebug(lcQpaCocoaWindow) << "closeAndRelease" << self;
+
+ [self.helper detachFromPlatformWindow];
+ [self close];
+ [self release];
+}
+
+- (void)dealloc
+{
+ [_helper release];
+ _helper = nil;
+ [super dealloc];
+}
+
+@end
+
+@implementation QNSPanel
+
+@synthesize helper = _helper;
+
++ (void)applicationActivationChanged:(NSNotification*)notification
+{
+ const id sender = self;
+ NSEnumerator<NSWindow*> *windowEnumerator = nullptr;
+ NSApplication *application = [NSApplication sharedApplication];
+
+#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_12)
+ if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra) {
+ // Unfortunately there's no NSWindowListOrderedBackToFront,
+ // so we have to manually reverse the order using an array.
+ NSMutableArray *windows = [[[NSMutableArray alloc] init] autorelease];
+ [application enumerateWindowsWithOptions:NSWindowListOrderedFrontToBack
+ usingBlock:^(NSWindow *window, BOOL *) {
+ // For some reason AppKit will give us nil-windows, skip those
+ if (!window)
+ return;
+
+ [(NSMutableArray*)windows addObject:window];
+ }
+ ];
+
+ windowEnumerator = windows.reverseObjectEnumerator;
+ } else
+#endif
+ {
+ // No way to get ordered list of windows, so fall back to unordered,
+ // list, which typically corresponds to window creation order.
+ windowEnumerator = application.windows.objectEnumerator;
+ }
+
+ for (NSWindow *window in windowEnumerator) {
+ // We're meddling with normal and floating windows, so leave others alone
+ if (!(window.level == NSNormalWindowLevel || window.level == NSFloatingWindowLevel))
+ continue;
+
+ // Windows that hide automatically will keep their NSFloatingWindowLevel,
+ // and hence be on top of the window stack. We don't want to affect these
+ // windows, as otherwise we might end up with key windows being ordered
+ // behind these auto-hidden windows when activating the application by
+ // clicking on a new tool window.
+ if (window.hidesOnDeactivate)
+ continue;
+
+ if ([window conformsToProtocol:@protocol(QNSWindowProtocol)]) {
+ QCocoaWindow *cocoaWindow = static_cast<id<QNSWindowProtocol>>(window).helper.platformWindow;
+ window.level = notification.name == NSApplicationWillResignActiveNotification ?
+ NSNormalWindowLevel : cocoaWindow->windowLevel(cocoaWindow->window()->flags());
+ }
+
+ // The documentation says that "when a window enters a new level, it’s ordered
+ // in front of all its peers in that level", but that doesn't seem to be the
+ // case in practice. To keep the order correct after meddling with the window
+ // levels, we explicitly order each window to the front. Since we are iterating
+ // the windows in back-to-front order, this is okey. The call also triggers AppKit
+ // to re-evaluate the level in relation to windows from other applications,
+ // working around an issue where our tool windows would stay on top of other
+ // application windows if activation was transferred to another application by
+ // clicking on it instead of via the application switcher or Dock. Finally, we
+ // do this re-ordering for all windows (except auto-hiding ones), otherwise we would
+ // end up triggering a bug in AppKit where the tool windows would disappear behind
+ // the application window.
+ [window orderFront:sender];
+ }
+}
+
+- (id)initWithContentRect:(NSRect)contentRect
+ screen:(NSScreen*)screen
+ styleMask:(NSUInteger)windowStyle
+ qPlatformWindow:(QCocoaWindow *)qpw
+{
+ if (self = [super initWithContentRect:contentRect styleMask:windowStyle
+ backing:NSBackingStoreBuffered defer:kNoDefer screen:screen]) {
+ _helper = [[QNSWindowHelper alloc] initWithNSWindow:self platformWindow:qpw];
+
+ if (qpw->alwaysShowToolWindow()) {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
+ [center addObserver:[self class] selector:@selector(applicationActivationChanged:)
+ name:NSApplicationWillResignActiveNotification object:nil];
+ [center addObserver:[self class] selector:@selector(applicationActivationChanged:)
+ name:NSApplicationWillBecomeActiveNotification object:nil];
+ });
+ }
+ }
+ return self;
+}
+
+- (BOOL)canBecomeKeyWindow
+{
+ QCocoaWindow *pw = self.helper.platformWindow;
+ if (!pw)
+ return NO;
+
+ if (pw->shouldRefuseKeyWindowAndFirstResponder())
+ return NO;
+
+ // Only tool or dialog windows should become key:
+ Qt::WindowType type = pw->window()->type();
+ if (type == Qt::Tool || type == Qt::Dialog)
+ return YES;
+
+ return NO;
+}
+
+- (void)sendEvent:(NSEvent*)theEvent
+{
+ [self.helper handleWindowEvent:theEvent];
+}
+
+- (void)superSendEvent:(NSEvent *)theEvent
+{
+ [super sendEvent:theEvent];
+}
+
+- (void)closeAndRelease
+{
+ qCDebug(lcQpaCocoaWindow) << "closeAndRelease" << self;
+
+ [self.helper detachFromPlatformWindow];
+ [self close];
+ [self release];
+}
+
+- (void)dealloc
+{
+ [_helper release];
+ _helper = nil;
+ [super dealloc];
+}
+
+@end
diff --git a/src/plugins/platforms/direct2d/direct2d.pro b/src/plugins/platforms/direct2d/direct2d.pro
index 224f122fc4..87405ae19f 100644
--- a/src/plugins/platforms/direct2d/direct2d.pro
+++ b/src/plugins/platforms/direct2d/direct2d.pro
@@ -5,6 +5,8 @@ QT += \
eventdispatcher_support-private accessibility_support-private \
fontdatabase_support-private theme_support-private
+qtConfig(vulkan): QT += vulkan_support-private
+
LIBS += -ldwmapi -ld2d1 -ld3d11 -ldwrite -lVersion -lgdi32
include(../windows/windows.pri)
diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
index 9b4732eab4..f3efbea60b 100644
--- a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
@@ -41,6 +41,7 @@
#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformintegration.h>
#include <private/qguiapplication_p.h>
+#include <private/qwindow_p.h>
#ifndef QT_NO_OPENGL
# include <QtGui/private/qopenglcontext_p.h>
# include <QtGui/QOpenGLContext>
@@ -99,7 +100,6 @@ void QEglFSWindow::create()
if (window()->type() == Qt::Desktop) {
QRect fullscreenRect(QPoint(), screen()->availableGeometry().size());
- QPlatformWindow::setGeometry(fullscreenRect);
QWindowSystemInterface::handleGeometryChange(window(), fullscreenRect);
return;
}
@@ -235,21 +235,16 @@ void QEglFSWindow::setVisible(bool visible)
void QEglFSWindow::setGeometry(const QRect &r)
{
- QRect rect;
- bool forceFullscreen = m_flags.testFlag(HasNativeWindow);
- if (forceFullscreen)
+ QRect rect = r;
+ if (m_flags.testFlag(HasNativeWindow))
rect = screen()->availableGeometry();
- else
- rect = r;
- const bool changed = rect != QPlatformWindow::geometry();
QPlatformWindow::setGeometry(rect);
- // if we corrected the size, trigger a resize event
- if (rect != r)
- QWindowSystemInterface::handleGeometryChange(window(), rect, r);
+ QWindowSystemInterface::handleGeometryChange(window(), rect);
- if (changed)
+ const QRect lastReportedGeometry = qt_window_private(window())->geometry;
+ if (rect != lastReportedGeometry)
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), rect.size()));
}
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h
index 513a5063fb..be5524cba3 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.h
@@ -45,7 +45,7 @@
#include <QtCore/QLoggingCategory>
#include <QtCore/QFunctionPointer>
-typedef const char *(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC) ();
+typedef QByteArray (EGLAPIENTRYP PFNQGSGETDISPLAYSPROC) ();
typedef void (EGLAPIENTRYP PFNQGSSETDISPLAYPROC) (uint screen);
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp
index 4546088327..7654034f85 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.cpp
@@ -110,6 +110,11 @@ uint QEglFSEmulatorScreen::id() const
return m_id;
}
+QString QEglFSEmulatorScreen::name() const
+{
+ return m_description;
+}
+
void QEglFSEmulatorScreen::initFromJsonObject(const QJsonObject &description)
{
QJsonValue value;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h
index 3e5113c9c2..c4994720fa 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorscreen.h
@@ -62,6 +62,7 @@ public:
qreal refreshRate() const override;
Qt::ScreenOrientation nativeOrientation() const override;
Qt::ScreenOrientation orientation() const override;
+ QString name() const override;
uint id() const;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
index e522c0ee1b..27c0af1f08 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro
@@ -4,7 +4,7 @@ PLUGIN_TYPE = egldeviceintegrations
PLUGIN_CLASS_NAME = QEglFSKmsGbmIntegrationPlugin
load(qt_plugin)
-QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private kms_support-private
+QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private kms_support-private edid_support-private
INCLUDEPATH += $$PWD/../../api $$PWD/../eglfs_kms_support
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
index 5b779d6732..a3868fdb1d 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmcursor.cpp
@@ -204,7 +204,7 @@ void QEglFSKmsGbmCursor::changeCursor(QCursor *windowCursor, QWindow *window)
painter.drawImage(0, 0, *m_cursorImage.image());
painter.end();
- gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.byteCount());
+ gbm_bo_write(m_bo, cursorImage.constBits(), cursorImage.sizeInBytes());
uint32_t handle = gbm_bo_get_handle(m_bo).u32;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
index b6cdcf92b6..058791e473 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.cpp
@@ -43,9 +43,11 @@
#include "qeglfskmsgbmdevice.h"
#include "qeglfskmsgbmscreen.h"
#include "qeglfskmsgbmcursor.h"
+#include "private/qeglfswindow_p.h"
#include "private/qeglfscursor_p.h"
#include <QtDeviceDiscoverySupport/private/qdevicediscovery_p.h>
+#include <QtEglSupport/private/qeglconvenience_p.h>
#include <QtCore/QLoggingCategory>
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonObject>
@@ -67,20 +69,35 @@ QEglFSKmsGbmIntegration::QEglFSKmsGbmIntegration()
qCDebug(qLcEglfsKmsDebug, "New DRM/KMS via GBM integration created");
}
-EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeWindow(QPlatformWindow *platformWindow,
- const QSize &size,
- const QSurfaceFormat &format)
+#ifndef EGL_EXT_platform_base
+typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list);
+typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list);
+#endif
+
+#ifndef EGL_PLATFORM_GBM_KHR
+#define EGL_PLATFORM_GBM_KHR 0x31D7
+#endif
+
+EGLDisplay QEglFSKmsGbmIntegration::createDisplay(EGLNativeDisplayType nativeDisplay)
{
- Q_UNUSED(size);
- Q_UNUSED(format);
+ qCDebug(qLcEglfsKmsDebug, "Querying EGLDisplay");
+ EGLDisplay display;
+
+ PFNEGLGETPLATFORMDISPLAYEXTPROC getPlatformDisplay = nullptr;
+ const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (extensions && (strstr(extensions, "EGL_KHR_platform_gbm") || strstr(extensions, "EGL_MESA_platform_gbm"))) {
+ getPlatformDisplay = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
+ eglGetProcAddress("eglGetPlatformDisplayEXT"));
+ }
- QEglFSKmsGbmScreen *screen = static_cast<QEglFSKmsGbmScreen *>(platformWindow->screen());
- if (screen->surface()) {
- qWarning("Only single window per screen supported!");
- return 0;
+ if (getPlatformDisplay) {
+ display = getPlatformDisplay(EGL_PLATFORM_GBM_KHR, nativeDisplay, nullptr);
+ } else {
+ qCDebug(qLcEglfsKmsDebug, "No eglGetPlatformDisplay for GBM, falling back to eglGetDisplay");
+ display = eglGetDisplay(nativeDisplay);
}
- return reinterpret_cast<EGLNativeWindowType>(screen->createSurface());
+ return display;
}
EGLNativeWindowType QEglFSKmsGbmIntegration::createNativeOffscreenWindow(const QSurfaceFormat &format)
@@ -143,4 +160,49 @@ QKmsDevice *QEglFSKmsGbmIntegration::createDevice()
return new QEglFSKmsGbmDevice(screenConfig(), path);
}
+class QEglFSKmsGbmWindow : public QEglFSWindow
+{
+public:
+ QEglFSKmsGbmWindow(QWindow *w, const QEglFSKmsGbmIntegration *integration)
+ : QEglFSWindow(w)
+ , m_integration(integration)
+ {}
+ void resetSurface() override;
+ const QEglFSKmsGbmIntegration *m_integration;
+};
+
+void QEglFSKmsGbmWindow::resetSurface()
+{
+ QEglFSKmsGbmScreen *gbmScreen = static_cast<QEglFSKmsGbmScreen *>(screen());
+ if (gbmScreen->surface()) {
+ qWarning("Only single window per screen supported!");
+ return;
+ }
+
+ EGLDisplay display = gbmScreen->display();
+ QSurfaceFormat platformFormat = m_integration->surfaceFormatFor(window()->requestedFormat());
+ m_config = QEglFSDeviceIntegration::chooseConfig(display, platformFormat);
+ m_format = q_glFormatFromConfig(display, m_config, platformFormat);
+ m_window = reinterpret_cast<EGLNativeWindowType>(gbmScreen->createSurface());
+
+ PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC createPlatformWindowSurface = nullptr;
+ const char *extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
+ if (extensions && (strstr(extensions, "EGL_KHR_platform_gbm") || strstr(extensions, "EGL_MESA_platform_gbm"))) {
+ createPlatformWindowSurface = reinterpret_cast<PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC>(
+ eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT"));
+ }
+
+ if (createPlatformWindowSurface) {
+ m_surface = createPlatformWindowSurface(display, m_config, reinterpret_cast<void *>(m_window), nullptr);
+ } else {
+ qCDebug(qLcEglfsKmsDebug, "No eglCreatePlatformWindowSurface for GBM, falling back to eglCreateWindowSurface");
+ m_surface = eglCreateWindowSurface(display, m_config, m_window, nullptr);
+ }
+}
+
+QEglFSWindow *QEglFSKmsGbmIntegration::createWindow(QWindow *window) const
+{
+ return new QEglFSKmsGbmWindow(window, this);
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h
index 38f132d72e..71f232abf9 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmintegration.h
@@ -55,14 +55,13 @@ class QEglFSKmsGbmIntegration : public QEglFSKmsIntegration
public:
QEglFSKmsGbmIntegration();
- EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow,
- const QSize &size,
- const QSurfaceFormat &format) override;
+ EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay) override;
EGLNativeWindowType createNativeOffscreenWindow(const QSurfaceFormat &format) override;
void destroyNativeWindow(EGLNativeWindowType window) override;
QPlatformCursor *createCursor(QPlatformScreen *screen) const override;
void presentBuffer(QPlatformSurface *surface) override;
+ QEglFSWindow *createWindow(QWindow *window) const override;
protected:
QKmsDevice *createDevice() override;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
index a2dc9c4a50..36f037ac6c 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/eglfs_kms_egldevice.pro
@@ -1,6 +1,6 @@
TARGET = qeglfs-kms-egldevice-integration
-QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private kms_support-private
+QT += core-private gui-private eglfsdeviceintegration-private eglfs_kms_support-private kms_support-private edid_support-private
INCLUDEPATH += $$PWD/../../api $$PWD/../eglfs_kms_support
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
index 0a66a897a1..cca413ff2d 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldevice.cpp
@@ -77,9 +77,9 @@ void QEglFSKmsEglDevice::close()
setFd(-1);
}
-EGLNativeDisplayType QEglFSKmsEglDevice::nativeDisplay() const
+void *QEglFSKmsEglDevice::nativeDisplay() const
{
- return reinterpret_cast<EGLNativeDisplayType>(m_devInt->eglDevice());
+ return m_devInt->eglDevice();
}
QPlatformScreen *QEglFSKmsEglDevice::createScreen(const QKmsOutput &output)
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
index 3c0a0ce30f..88cf6db33b 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/eglfs_kms_support.pro
@@ -2,7 +2,7 @@ TARGET = QtEglFsKmsSupport
CONFIG += no_module_headers internal_module
load(qt_module)
-QT += core-private gui-private eglfsdeviceintegration-private kms_support-private
+QT += core-private gui-private eglfsdeviceintegration-private kms_support-private edid_support-private
INCLUDEPATH += $$PWD/../../api
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
index 3951f46a82..734f5cd611 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2015 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2016 Pelagicore AG
** Contact: https://www.qt.io/licensing/
@@ -69,13 +69,29 @@ private:
};
QEglFSKmsScreen::QEglFSKmsScreen(QKmsDevice *device, const QKmsOutput &output)
- : QEglFSScreen(eglGetDisplay((EGLNativeDisplayType) device->nativeDisplay()))
+ : QEglFSScreen(static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->display())
, m_device(device)
, m_output(output)
, m_powerState(PowerStateOn)
, m_interruptHandler(new QEglFSKmsInterruptHandler(this))
{
m_siblings << this; // gets overridden later
+
+ if (m_output.edid_blob) {
+ QByteArray edid(reinterpret_cast<const char *>(m_output.edid_blob->data), m_output.edid_blob->length);
+ if (m_edid.parse(edid))
+ qCDebug(qLcEglfsKmsDebug, "EDID data for output \"%s\": identifier '%s', manufacturer '%s', model '%s', serial '%s', physical size: %.2fx%.2f",
+ name().toLatin1().constData(),
+ m_edid.identifier.toLatin1().constData(),
+ m_edid.manufacturer.toLatin1().constData(),
+ m_edid.model.toLatin1().constData(),
+ m_edid.serialNumber.toLatin1().constData(),
+ m_edid.physicalSize.width(), m_edid.physicalSize.height());
+ else
+ qCDebug(qLcEglfsKmsDebug) << "Failed to parse EDID data for output" << name(); // keep this debug, not warning
+ } else {
+ qCDebug(qLcEglfsKmsDebug) << "No EDID data for output" << name();
+ }
}
QEglFSKmsScreen::~QEglFSKmsScreen()
@@ -146,6 +162,21 @@ QString QEglFSKmsScreen::name() const
return m_output.name;
}
+QString QEglFSKmsScreen::manufacturer() const
+{
+ return m_edid.manufacturer;
+}
+
+QString QEglFSKmsScreen::model() const
+{
+ return m_edid.model.isEmpty() ? m_edid.identifier : m_edid.model;
+}
+
+QString QEglFSKmsScreen::serialNumber() const
+{
+ return m_edid.serialNumber;
+}
+
void QEglFSKmsScreen::destroySurface()
{
}
@@ -173,6 +204,28 @@ qreal QEglFSKmsScreen::refreshRate() const
return refresh > 0 ? refresh : 60;
}
+QVector<QPlatformScreen::Mode> QEglFSKmsScreen::modes() const
+{
+ QVector<QPlatformScreen::Mode> list;
+ list.reserve(m_output.modes.size());
+
+ for (const drmModeModeInfo &info : qAsConst(m_output.modes))
+ list.append({QSize(info.hdisplay, info.vdisplay),
+ qreal(info.vrefresh > 0 ? info.vrefresh : 60)});
+
+ return list;
+}
+
+int QEglFSKmsScreen::currentMode() const
+{
+ return m_output.mode;
+}
+
+int QEglFSKmsScreen::preferredMode() const
+{
+ return m_output.preferred_mode;
+}
+
QPlatformScreen::SubpixelAntialiasingType QEglFSKmsScreen::subpixelAntialiasingTypeHint() const
{
return m_output.subpixelAntialiasingTypeHint();
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
index 80bbb0c7f1..4e09929189 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsscreen.h
@@ -47,6 +47,7 @@
#include <QtCore/QMutex>
#include <QtKmsSupport/private/qkmsdevice_p.h>
+#include <QtEdidSupport/private/qedidparser_p.h>
QT_BEGIN_NAMESPACE
@@ -72,11 +73,20 @@ public:
QString name() const override;
+ QString manufacturer() const override;
+ QString model() const override;
+ QString serialNumber() const override;
+
qreal refreshRate() const override;
QList<QPlatformScreen *> virtualSiblings() const override { return m_siblings; }
void setVirtualSiblings(QList<QPlatformScreen *> sl) { m_siblings = sl; }
+ QVector<QPlatformScreen::Mode> modes() const override;
+
+ int currentMode() const override;
+ int preferredMode() const override;
+
QKmsDevice *device() const { return m_device; }
void destroySurface();
@@ -97,6 +107,7 @@ protected:
QKmsDevice *m_device;
QKmsOutput m_output;
+ QEdidParser m_edid;
QPoint m_pos;
QList<QPlatformScreen *> m_siblings;
diff --git a/src/plugins/platforms/haiku/qhaikuwindow.cpp b/src/plugins/platforms/haiku/qhaikuwindow.cpp
index 4634012eda..4bea7f7ff6 100644
--- a/src/plugins/platforms/haiku/qhaikuwindow.cpp
+++ b/src/plugins/platforms/haiku/qhaikuwindow.cpp
@@ -205,26 +205,23 @@ void QHaikuWindow::requestActivateWindow()
m_window->Activate(true);
}
-void QHaikuWindow::setWindowState(Qt::WindowState state)
+void QHaikuWindow::setWindowState(Qt::WindowStates state)
{
if (m_windowState == state)
return;
- const Qt::WindowState oldState = m_windowState;
+ const Qt::WindowStates oldState = m_windowState;
m_windowState = state;
- if (m_windowState == Qt::WindowMaximized) {
- m_window->zoomByQt();
- } else if (m_windowState == Qt::WindowMinimized) {
+ if (m_windowState & Qt::WindowMinimized)
m_window->Minimize(true);
- } else if (m_windowState == Qt::WindowNoState) {
- if (oldState == Qt::WindowMaximized)
- m_window->zoomByQt(); // undo zoom
-
- if (oldState == Qt::WindowMinimized)
- m_window->Minimize(false); // undo minimize
- }
+ else if (m_windowState & Qt::WindowMaximized)
+ m_window->zoomByQt();
+ else if (oldState & Qt::WindowMinimized)
+ m_window->Minimize(false); // undo minimize
+ else if (oldState & Qt::WindowMaximized)
+ m_window->zoomByQt(); // undo zoom
}
void QHaikuWindow::setWindowFlags(Qt::WindowFlags flags)
@@ -312,7 +309,6 @@ void QHaikuWindow::haikuWindowMoved(const QPoint &pos)
{
const QRect newGeometry(pos, geometry().size());
- QPlatformWindow::setGeometry(newGeometry);
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), newGeometry.size()));
}
@@ -321,7 +317,6 @@ void QHaikuWindow::haikuWindowResized(const QSize &size, bool zoomInProgress)
{
const QRect newGeometry(geometry().topLeft(), size);
- QPlatformWindow::setGeometry(newGeometry);
QWindowSystemInterface::handleGeometryChange(window(), newGeometry);
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), newGeometry.size()));
diff --git a/src/plugins/platforms/haiku/qhaikuwindow.h b/src/plugins/platforms/haiku/qhaikuwindow.h
index 75403fb421..5bfb99e532 100644
--- a/src/plugins/platforms/haiku/qhaikuwindow.h
+++ b/src/plugins/platforms/haiku/qhaikuwindow.h
@@ -94,7 +94,7 @@ public:
BWindow* nativeHandle() const;
void requestActivateWindow() Q_DECL_OVERRIDE;
- void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
+ void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE;
void setWindowTitle(const QString &title) Q_DECL_OVERRIDE;
@@ -120,7 +120,7 @@ private Q_SLOTS:
void haikuDrawRequest(const QRect &rect);
private:
- Qt::WindowState m_windowState;
+ Qt::WindowStates m_windowState;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosclipboard.mm b/src/plugins/platforms/ios/qiosclipboard.mm
index ef3b453bbf..15deb3332e 100644
--- a/src/plugins/platforms/ios/qiosclipboard.mm
+++ b/src/plugins/platforms/ios/qiosclipboard.mm
@@ -227,7 +227,19 @@ void QIOSClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
if (uti.isEmpty() || !converter->canConvert(mimeType, uti))
continue;
- QByteArray byteArray = converter->convertFromMime(mimeType, mimeData->data(mimeType), uti).first();
+ QVariant mimeDataAsVariant;
+ if (mimeData->hasImage()) {
+ mimeDataAsVariant = mimeData->imageData();
+ } else if (mimeData->hasUrls()) {
+ QVariantList urlList;
+ for (QUrl url : mimeData->urls())
+ urlList << url;
+ mimeDataAsVariant = QVariant(urlList);
+ } else {
+ mimeDataAsVariant = QVariant(mimeData->data(mimeType));
+ }
+
+ QByteArray byteArray = converter->convertFromMime(mimeType, mimeDataAsVariant, uti).first();
NSData *nsData = [NSData dataWithBytes:byteArray.constData() length:byteArray.size()];
[pbItem setValue:nsData forKey:uti.toNSString()];
break;
diff --git a/src/plugins/platforms/ios/qiosmenu.h b/src/plugins/platforms/ios/qiosmenu.h
index b7371a5f49..61cadab56d 100644
--- a/src/plugins/platforms/ios/qiosmenu.h
+++ b/src/plugins/platforms/ios/qiosmenu.h
@@ -56,9 +56,6 @@ class QIOSMenuItem : public QPlatformMenuItem
public:
QIOSMenuItem();
- void setTag(quintptr tag) Q_DECL_OVERRIDE;
- quintptr tag()const Q_DECL_OVERRIDE;
-
void setText(const QString &text) Q_DECL_OVERRIDE;
void setIcon(const QIcon &) Q_DECL_OVERRIDE {}
void setMenu(QPlatformMenu *) Q_DECL_OVERRIDE;
@@ -74,7 +71,6 @@ public:
void setEnabled(bool enabled) Q_DECL_OVERRIDE;
void setIconSize(int) Q_DECL_OVERRIDE {}
- quintptr m_tag;
bool m_visible;
QString m_text;
MenuRole m_role;
@@ -97,9 +93,6 @@ public:
void syncMenuItem(QPlatformMenuItem *) Q_DECL_OVERRIDE;
void syncSeparatorsCollapsible(bool) Q_DECL_OVERRIDE {}
- void setTag(quintptr tag) Q_DECL_OVERRIDE;
- quintptr tag()const Q_DECL_OVERRIDE;
-
void setText(const QString &) Q_DECL_OVERRIDE;
void setIcon(const QIcon &) Q_DECL_OVERRIDE {}
void setEnabled(bool enabled) Q_DECL_OVERRIDE;
@@ -121,7 +114,6 @@ protected:
bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE;
private:
- quintptr m_tag;
bool m_enabled;
bool m_visible;
QString m_text;
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
index 01cb3badea..6c70676a31 100644
--- a/src/plugins/platforms/ios/qiosmenu.mm
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -259,7 +259,6 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
QIOSMenuItem::QIOSMenuItem()
: QPlatformMenuItem()
- , m_tag(0)
, m_visible(true)
, m_text(QString())
, m_role(MenuRole(0))
@@ -269,16 +268,6 @@ QIOSMenuItem::QIOSMenuItem()
{
}
-void QIOSMenuItem::setTag(quintptr tag)
-{
- m_tag = tag;
-}
-
-quintptr QIOSMenuItem::tag() const
-{
- return m_tag;
-}
-
void QIOSMenuItem::setText(const QString &text)
{
m_text = QPlatformTheme::removeMnemonics(text);
@@ -319,7 +308,6 @@ void QIOSMenuItem::setEnabled(bool enabled)
QIOSMenu::QIOSMenu()
: QPlatformMenu()
- , m_tag(0)
, m_enabled(true)
, m_visible(false)
, m_text(QString())
@@ -371,16 +359,6 @@ void QIOSMenu::syncMenuItem(QPlatformMenuItem *)
}
}
-void QIOSMenu::setTag(quintptr tag)
-{
- m_tag = tag;
-}
-
-quintptr QIOSMenu::tag() const
-{
- return m_tag;
-}
-
void QIOSMenu::setText(const QString &text)
{
m_text = text;
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index 001985a128..84946a5c0f 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -880,9 +880,10 @@
- (UITextPosition *)closestPositionToPoint:(CGPoint)point
{
- // No API in Qt for determining this. Use sensible default instead:
- Q_UNUSED(point);
- return [QUITextPosition positionWithIndex:[self currentImeState:Qt::ImCursorPosition].toInt()];
+ QPointF p = QPointF::fromCGPoint(point);
+ const QTransform mapToLocal = QGuiApplication::inputMethod()->inputItemTransform().inverted();
+ int textPos = QInputMethod::queryFocusObject(Qt::ImCursorPosition, p * mapToLocal).toInt();
+ return [QUITextPosition positionWithIndex:textPos];
}
- (UITextPosition *)closestPositionToPoint:(CGPoint)point withinRange:(UITextRange *)range
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index c47b6d68b1..a4c151ed8b 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -176,8 +176,8 @@
return;
// Re-apply window states to update geometry
- if (window->windowState() & (Qt::WindowFullScreen | Qt::WindowMaximized))
- window->handle()->setWindowState(window->windowState());
+ if (window->windowStates() & (Qt::WindowFullScreen | Qt::WindowMaximized))
+ window->handle()->setWindowState(window->windowStates());
}
// Even if the root view controller has both wantsFullScreenLayout and
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
index 81fad420f6..da8a6aabdc 100644
--- a/src/plugins/platforms/ios/qioswindow.h
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -62,7 +62,7 @@ public:
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
- void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
+ void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE;
void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE;
void handleContentOrientationChange(Qt::ScreenOrientation orientation) Q_DECL_OVERRIDE;
void setVisible(bool visible) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index 8ff0dfbd5f..4e6d48423d 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -73,7 +73,7 @@ QIOSWindow::QIOSWindow(QWindow *window)
m_normalGeometry = initialGeometry(window, QPlatformWindow::geometry(),
screen()->availableGeometry().width(), screen()->availableGeometry().height());
- setWindowState(window->windowState());
+ setWindowState(window->windowStates());
setOpacity(window->opacity());
Qt::ScreenOrientation initialOrientation = window->contentOrientation();
@@ -229,7 +229,7 @@ bool QIOSWindow::isExposed() const
&& window()->isVisible() && !window()->geometry().isEmpty();
}
-void QIOSWindow::setWindowState(Qt::WindowState state)
+void QIOSWindow::setWindowState(Qt::WindowStates state)
{
// Update the QWindow representation straight away, so that
// we can update the statusbar visibility based on the new
@@ -239,25 +239,15 @@ void QIOSWindow::setWindowState(Qt::WindowState state)
if (window()->isTopLevel() && window()->isVisible() && window()->isActive())
[m_view.qtViewController updateProperties];
- switch (state) {
- case Qt::WindowNoState:
- applyGeometry(m_normalGeometry);
- break;
- case Qt::WindowMaximized:
+ if (state & Qt::WindowMinimized)
+ applyGeometry(QRect());
+ else if (state & Qt::WindowFullScreen)
+ applyGeometry(screen()->geometry());
+ else if (state & Qt::WindowMaximized)
applyGeometry(window()->flags() & Qt::MaximizeUsingFullscreenGeometryHint ?
screen()->geometry() : screen()->availableGeometry());
- break;
- case Qt::WindowFullScreen:
- applyGeometry(screen()->geometry());
- break;
- case Qt::WindowMinimized:
- applyGeometry(QRect());
- break;
- case Qt::WindowActive:
- Q_UNREACHABLE();
- default:
- Q_UNREACHABLE();
- }
+ else
+ applyGeometry(m_normalGeometry);
}
void QIOSWindow::setParent(const QPlatformWindow *parentWindow)
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 9966bd50a3..dcdb5ae53f 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -151,23 +151,12 @@
qWarning() << m_qioswindow->window()
<< "is backed by a UIView that has a transform set. This is not supported.";
- // The original geometry requested by setGeometry() might be different
- // from what we end up with after applying window constraints.
- QRect requestedGeometry = m_qioswindow->geometry();
-
- QRect actualGeometry = QRectF::fromCGRect(self.frame).toRect();
-
- // Persist the actual/new geometry so that QWindow::geometry() can
- // be queried on the resize event.
- m_qioswindow->QPlatformWindow::setGeometry(actualGeometry);
-
- QRect previousGeometry = requestedGeometry != actualGeometry ?
- requestedGeometry : qt_window_private(m_qioswindow->window())->geometry;
-
QWindow *window = m_qioswindow->window();
- QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(window, actualGeometry, previousGeometry);
+ QRect lastReportedGeometry = qt_window_private(window)->geometry;
+ QRect currentGeometry = QRectF::fromCGRect(self.frame).toRect();
+ QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(window, currentGeometry);
- if (actualGeometry.size() != previousGeometry.size()) {
+ if (currentGeometry.size() != lastReportedGeometry.size()) {
// Trigger expose event on resize
[self setNeedsDisplay];
diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.cpp b/src/plugins/platforms/mirclient/qmirclientwindow.cpp
index adc8ae652a..decd21516e 100644
--- a/src/plugins/platforms/mirclient/qmirclientwindow.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientwindow.cpp
@@ -516,7 +516,6 @@ UbuntuSurface::UbuntuSurface(QMirClientWindow *platformWindow, EGLDisplay displa
// Assume that the buffer size matches the surface size at creation time
mBufferSize = geom.size();
- platformWindow->QPlatformWindow::setGeometry(geom);
QWindowSystemInterface::handleGeometryChange(mWindow, geom);
qCDebug(mirclient) << "Created surface with geometry:" << geom << "title:" << mWindow->title()
@@ -636,7 +635,6 @@ void UbuntuSurface::onSwapBuffersDone()
QRect newGeometry = mPlatformWindow->geometry();
newGeometry.setSize(mBufferSize);
- mPlatformWindow->QPlatformWindow::setGeometry(newGeometry);
QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry);
} else {
qCDebug(mirclientBufferSwap, "onSwapBuffersDone(window=%p) [%d] - buffer size (%d,%d)",
@@ -785,8 +783,16 @@ void QMirClientWindow::handleSurfaceStateChanged(Qt::WindowState state)
QWindowSystemInterface::handleWindowStateChanged(window(), state);
}
-void QMirClientWindow::setWindowState(Qt::WindowState state)
+void QMirClientWindow::setWindowState(Qt::WindowStates states)
{
+ Qt::WindowState state = Qt::WindowNoState;
+ if (states & Qt::WindowMinimized)
+ state = Qt::WindowMinimized;
+ else if (states & Qt::WindowFullScreen)
+ state = Qt::WindowFullScreen;
+ else if (states & Qt::WindowMaximized)
+ state = Qt::WindowMaximized;
+
QMutexLocker lock(&mMutex);
qCDebug(mirclient, "setWindowState(window=%p, %s)", this, qtWindowStateToStr(state));
diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.h b/src/plugins/platforms/mirclient/qmirclientwindow.h
index 324e7691ff..6c5695d62f 100644
--- a/src/plugins/platforms/mirclient/qmirclientwindow.h
+++ b/src/plugins/platforms/mirclient/qmirclientwindow.h
@@ -73,7 +73,7 @@ public:
WId winId() const override;
QRect geometry() const override;
void setGeometry(const QRect&) override;
- void setWindowState(Qt::WindowState state) override;
+ void setWindowState(Qt::WindowStates state) override;
void setWindowFlags(Qt::WindowFlags flags) override;
void setVisible(bool visible) override;
void setWindowTitle(const QString &title) override;
diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.h b/src/plugins/platforms/offscreen/qoffscreencommon.h
index 72d6f16d26..1a9d65972d 100644
--- a/src/plugins/platforms/offscreen/qoffscreencommon.h
+++ b/src/plugins/platforms/offscreen/qoffscreencommon.h
@@ -75,7 +75,6 @@ public:
class QOffscreenDrag : public QPlatformDrag
{
public:
- QMimeData *platformDropData() Q_DECL_OVERRIDE { return 0; }
Qt::DropAction drag(QDrag *) Q_DECL_OVERRIDE { return Qt::IgnoreAction; }
};
#endif
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
index 0c39950019..3eb8675d77 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
@@ -59,6 +59,8 @@
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
+#include <qpa/qplatforminputcontextfactory_p.h>
+#include <qpa/qplatforminputcontext.h>
#include <qpa/qplatformservices.h>
@@ -118,6 +120,16 @@ QOffscreenIntegration::~QOffscreenIntegration()
{
}
+void QOffscreenIntegration::initialize()
+{
+ m_inputContext.reset(QPlatformInputContextFactory::create());
+}
+
+QPlatformInputContext *QOffscreenIntegration::inputContext() const
+{
+ return m_inputContext.data();
+}
+
bool QOffscreenIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{
switch (cap) {
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.h b/src/plugins/platforms/offscreen/qoffscreenintegration.h
index df647a31ef..569ec8fc28 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration.h
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration.h
@@ -54,6 +54,7 @@ public:
QOffscreenIntegration();
~QOffscreenIntegration();
+ void initialize() Q_DECL_OVERRIDE;
bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
@@ -61,6 +62,8 @@ public:
#ifndef QT_NO_DRAGANDDROP
QPlatformDrag *drag() const Q_DECL_OVERRIDE;
#endif
+
+ QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE;
QPlatformServices *services() const Q_DECL_OVERRIDE;
QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE;
@@ -73,6 +76,7 @@ private:
#ifndef QT_NO_DRAGANDDROP
QScopedPointer<QPlatformDrag> m_drag;
#endif
+ QScopedPointer<QPlatformInputContext> m_inputContext;
QScopedPointer<QPlatformServices> m_services;
};
diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp
index 81f262f9ed..832e94034d 100644
--- a/src/plugins/platforms/offscreen/qoffscreenwindow.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreenwindow.cpp
@@ -56,7 +56,7 @@ QOffscreenWindow::QOffscreenWindow(QWindow *window)
if (window->windowState() == Qt::WindowNoState)
setGeometry(window->geometry());
else
- setWindowState(window->windowState());
+ setWindowState(window->windowStates());
QWindowSystemInterface::flushWindowSystemEvents();
@@ -166,26 +166,19 @@ void QOffscreenWindow::setFrameMarginsEnabled(bool enabled)
}
}
-void QOffscreenWindow::setWindowState(Qt::WindowState state)
+void QOffscreenWindow::setWindowState(Qt::WindowStates state)
{
- setFrameMarginsEnabled(state != Qt::WindowFullScreen);
+ setFrameMarginsEnabled(!(state & Qt::WindowFullScreen));
m_positionIncludesFrame = false;
- switch (state) {
- case Qt::WindowFullScreen:
+ if (state & Qt::WindowMinimized)
+ ; // nothing to do
+ else if (state & Qt::WindowFullScreen)
setGeometryImpl(screen()->geometry());
- break;
- case Qt::WindowMaximized:
+ else if (state & Qt::WindowMaximized)
setGeometryImpl(screen()->availableGeometry().adjusted(m_margins.left(), m_margins.top(), -m_margins.right(), -m_margins.bottom()));
- break;
- case Qt::WindowMinimized:
- break;
- case Qt::WindowNoState:
+ else
setGeometryImpl(m_normalGeometry);
- break;
- default:
- break;
- }
QWindowSystemInterface::handleWindowStateChanged(window(), state);
}
diff --git a/src/plugins/platforms/offscreen/qoffscreenwindow.h b/src/plugins/platforms/offscreen/qoffscreenwindow.h
index f75458eb8e..0dced9680a 100644
--- a/src/plugins/platforms/offscreen/qoffscreenwindow.h
+++ b/src/plugins/platforms/offscreen/qoffscreenwindow.h
@@ -54,7 +54,7 @@ public:
~QOffscreenWindow();
void setGeometry(const QRect &rect) Q_DECL_OVERRIDE;
- void setWindowState(Qt::WindowState state) Q_DECL_OVERRIDE;
+ void setWindowState(Qt::WindowStates states) Q_DECL_OVERRIDE;
QMargins frameMargins() const Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/qnx/qqnxwindow.cpp b/src/plugins/platforms/qnx/qqnxwindow.cpp
index 30288ccb20..2253e3b23d 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.cpp
+++ b/src/plugins/platforms/qnx/qqnxwindow.cpp
@@ -586,7 +586,7 @@ void QQnxWindow::setFocus(screen_window_t newFocusWindow)
}
}
-void QQnxWindow::setWindowState(Qt::WindowState state)
+void QQnxWindow::setWindowState(Qt::WindowStates state)
{
qWindowDebug() << "state =" << state;
@@ -749,32 +749,19 @@ void QQnxWindow::updateZorder(screen_window_t window, int &topZorder)
void QQnxWindow::applyWindowState()
{
- switch (m_windowState) {
-
- // WindowActive is not an accepted parameter according to the docs
- case Qt::WindowActive:
- return;
-
- case Qt::WindowMinimized:
+ if (m_windowState & Qt::WindowMinimized) {
minimize();
if (m_unmaximizedGeometry.isValid())
setGeometry(m_unmaximizedGeometry);
else
setGeometry(m_screen->geometry());
-
- break;
-
- case Qt::WindowMaximized:
- case Qt::WindowFullScreen:
+ } else if (m_windowState & (Qt::WindowMaximized | Qt::WindowFullScreen)) {
m_unmaximizedGeometry = geometry();
- setGeometry(m_windowState == Qt::WindowMaximized ? m_screen->availableGeometry() : m_screen->geometry());
- break;
-
- case Qt::WindowNoState:
- if (m_unmaximizedGeometry.isValid())
- setGeometry(m_unmaximizedGeometry);
- break;
+ setGeometry(m_windowState & Qt::WindowFullScreen ? m_screen->geometry()
+ : m_screen->availableGeometry());
+ } else if (m_unmaximizedGeometry.isValid()) {
+ setGeometry(m_unmaximizedGeometry);
}
}
diff --git a/src/plugins/platforms/qnx/qqnxwindow.h b/src/plugins/platforms/qnx/qqnxwindow.h
index e248e04462..f96edc49e4 100644
--- a/src/plugins/platforms/qnx/qqnxwindow.h
+++ b/src/plugins/platforms/qnx/qqnxwindow.h
@@ -85,7 +85,7 @@ public:
void raise() override;
void lower() override;
void requestActivateWindow() override;
- void setWindowState(Qt::WindowState state) override;
+ void setWindowState(Qt::WindowStates state) override;
void setExposed(bool exposed);
void propagateSizeHints() override;
@@ -141,7 +141,7 @@ private:
bool m_visible;
bool m_exposed;
QRect m_unmaximizedGeometry;
- Qt::WindowState m_windowState;
+ Qt::WindowStates m_windowState;
QString m_mmRendererWindowName;
screen_window_t m_mmRendererWindow;
diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri
index 0e3aacc558..557bdfe307 100644
--- a/src/plugins/platforms/windows/accessible/accessible.pri
+++ b/src/plugins/platforms/windows/accessible/accessible.pri
@@ -6,13 +6,14 @@ HEADERS += \
$$PWD/qwindowsaccessibility.h \
$$PWD/comutils.h
-SOURCES += $$PWD/qwindowsmsaaaccessible.cpp
-HEADERS += $$PWD/qwindowsmsaaaccessible.h
+SOURCES += \
+ $$PWD/qwindowsmsaaaccessible.cpp \
+ $$PWD/iaccessible2.cpp
+
+HEADERS += \
+ $$PWD/qwindowsmsaaaccessible.h \
+ $$PWD/iaccessible2.h
-!mingw: {
- SOURCES += $$PWD/iaccessible2.cpp
- HEADERS += $$PWD/iaccessible2.h
- include(../../../../3rdparty/iaccessible2/iaccessible2.pri)
-}
+include(../../../../3rdparty/iaccessible2/iaccessible2.pri)
mingw: LIBS *= -luuid
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
index f9e8231843..9239facb0c 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
@@ -61,40 +61,7 @@ static inline T *coTaskMemAllocArray(int size)
/**************************************************************\
* AccessibleApplication *
**************************************************************/
-// IUnknown
-HRESULT STDMETHODCALLTYPE AccessibleApplication::QueryInterface(REFIID id, LPVOID *iface)
-{
- *iface = 0;
- if (id == IID_IUnknown) {
- qCDebug(lcQpaAccessibility) << "AccessibleApplication::QI(): IID_IUnknown";
- *iface = static_cast<IUnknown *>(this);
- } else if (id == IID_IAccessibleApplication) {
- qCDebug(lcQpaAccessibility) << "AccessibleApplication::QI(): IID_IAccessibleApplication";
- *iface = static_cast<IAccessibleApplication*>(this);
- }
-
- if (*iface) {
- AddRef();
- return S_OK;
- }
- return E_NOINTERFACE;
-}
-
-ULONG STDMETHODCALLTYPE AccessibleApplication::AddRef()
-{
- return ++m_ref;
-}
-ULONG STDMETHODCALLTYPE AccessibleApplication::Release()
-{
- if (!--m_ref) {
- delete this;
- return 0;
- }
- return m_ref;
-}
-
-/* IAccessibleApplication */
HRESULT STDMETHODCALLTYPE AccessibleApplication::get_appName(/* [retval][out] */ BSTR *name)
{
const QString appName = QGuiApplication::applicationName();
@@ -127,40 +94,11 @@ HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][
**************************************************************/
AccessibleRelation::AccessibleRelation(const QList<QAccessibleInterface *> &targets,
QAccessible::Relation relation)
- : m_targets(targets), m_relation(relation), m_ref(1)
+ : m_targets(targets), m_relation(relation)
{
Q_ASSERT(m_targets.count());
}
-/* IUnknown */
-HRESULT STDMETHODCALLTYPE AccessibleRelation::QueryInterface(REFIID id, LPVOID *iface)
-{
- *iface = 0;
- if (id == IID_IUnknown || id == IID_IAccessibleRelation)
- *iface = static_cast<IUnknown *>(this);
-
- if (*iface) {
- AddRef();
- return S_OK;
- }
-
- return E_NOINTERFACE;
-}
-
-ULONG STDMETHODCALLTYPE AccessibleRelation::AddRef()
-{
- return ++m_ref;
-}
-
-ULONG STDMETHODCALLTYPE AccessibleRelation::Release()
-{
- if (!--m_ref) {
- delete this;
- return 0;
- }
- return m_ref;
-}
-
/* IAccessibleRelation */
HRESULT STDMETHODCALLTYPE AccessibleRelation::get_relationType(
/* [retval][out] */ BSTR *relationType)
@@ -237,56 +175,53 @@ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets(
**************************************************************/
HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOID *iface)
{
+ *iface = nullptr;
QAccessibleInterface *accessible = accessibleInterface();
if (!accessible)
return E_NOINTERFACE;
- HRESULT hr = QWindowsMsaaAccessible::QueryInterface(id, iface);
- if (!SUCCEEDED(hr)) {
- if (id == IID_IServiceProvider) {
- *iface = static_cast<IServiceProvider *>(this);
- } else if (id == IID_IAccessible2) {
- *iface = static_cast<IAccessible2 *>(this);
- } else if (id == IID_IAccessibleAction) {
- if (accessible->actionInterface())
- *iface = static_cast<IAccessibleAction *>(this);
- } else if (id == IID_IAccessibleComponent) {
- *iface = static_cast<IAccessibleComponent *>(this);
- } else if (id == IID_IAccessibleEditableText) {
- if (accessible->editableTextInterface() ||
- accessible->role() == QAccessible::EditableText)
- {
- *iface = static_cast<IAccessibleEditableText *>(this);
- }
- } else if (id == IID_IAccessibleHyperlink) {
- //*iface = static_cast<IAccessibleHyperlink *>(this);
- } else if (id == IID_IAccessibleHypertext) {
- //*iface = static_cast<IAccessibleHypertext *>(this);
- } else if (id == IID_IAccessibleImage) {
- //*iface = static_cast<IAccessibleImage *>(this);
- } else if (id == IID_IAccessibleTable) {
- //*iface = static_cast<IAccessibleTable *>(this); // not supported
- } else if (id == IID_IAccessibleTable2) {
- if (accessible->tableInterface())
- *iface = static_cast<IAccessibleTable2 *>(this);
- } else if (id == IID_IAccessibleTableCell) {
- if (accessible->tableCellInterface())
- *iface = static_cast<IAccessibleTableCell *>(this);
- } else if (id == IID_IAccessibleText) {
- if (accessible->textInterface())
- *iface = static_cast<IAccessibleText *>(this);
- } else if (id == IID_IAccessibleValue) {
- if (accessible->valueInterface())
- *iface = static_cast<IAccessibleValue *>(this);
- }
- if (*iface) {
- AddRef();
- hr = S_OK;
- } else {
- hr = E_NOINTERFACE;
+ if (SUCCEEDED(QWindowsMsaaAccessible::QueryInterface(id, iface))
+ || qWindowsComQueryInterface<IServiceProvider>(this, id, iface)
+ || qWindowsComQueryInterface<IAccessible2>(this, id, iface)
+ || qWindowsComQueryInterface<IAccessibleComponent>(this, id, iface)) {
+ return S_OK;
+ }
+
+ if (id == IID_IAccessibleAction) {
+ if (accessible->actionInterface())
+ *iface = static_cast<IAccessibleAction *>(this);
+ } else if (id == IID_IAccessibleEditableText) {
+ if (accessible->editableTextInterface() ||
+ accessible->role() == QAccessible::EditableText)
+ {
+ *iface = static_cast<IAccessibleEditableText *>(this);
}
+ } else if (id == IID_IAccessibleHyperlink) {
+ //*iface = static_cast<IAccessibleHyperlink *>(this);
+ } else if (id == IID_IAccessibleHypertext) {
+ //*iface = static_cast<IAccessibleHypertext *>(this);
+ } else if (id == IID_IAccessibleImage) {
+ //*iface = static_cast<IAccessibleImage *>(this);
+ } else if (id == IID_IAccessibleTable) {
+ //*iface = static_cast<IAccessibleTable *>(this); // not supported
+ } else if (id == IID_IAccessibleTable2) {
+ if (accessible->tableInterface())
+ *iface = static_cast<IAccessibleTable2 *>(this);
+ } else if (id == IID_IAccessibleTableCell) {
+ if (accessible->tableCellInterface())
+ *iface = static_cast<IAccessibleTableCell *>(this);
+ } else if (id == IID_IAccessibleText) {
+ if (accessible->textInterface())
+ *iface = static_cast<IAccessibleText *>(this);
+ } else if (id == IID_IAccessibleValue) {
+ if (accessible->valueInterface())
+ *iface = static_cast<IAccessibleValue *>(this);
}
- return hr;
+ if (*iface) {
+ AddRef();
+ return S_OK;
+ }
+ return E_NOINTERFACE;
}
@@ -1593,7 +1528,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryService(REFGUID guidServic
return E_POINTER;
Q_UNUSED(guidService);
*iface = 0;
- qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QS(): " << IIDToString(riid);
+ qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QS(): " << QWindowsAccessibleGuid(riid);
if (guidService == IID_IAccessible) {
@@ -1692,45 +1627,6 @@ HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList<QAccessibleInterface*
return count > 0 ? S_OK : S_FALSE;
}
-#define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid)
-
-QByteArray QWindowsIA2Accessible::IIDToString(REFIID id)
-{
- QByteArray strGuid = QWindowsMsaaAccessible::IIDToString(id);
- if (!strGuid.isEmpty())
- return strGuid;
-
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IServiceProvider);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible2);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleAction);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleApplication);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleComponent);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleEditableText);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHyperlink);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleHypertext);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleImage);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleRelation);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTable2);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleTableCell);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleText);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessibleValue);
-
- // else...
-#if 0 // Can be useful for debugging, but normally we'd like to reduce the noise a bit...
- OLECHAR szGuid[39]={0};
- ::StringFromGUID2(id, szGuid, 39);
- strGuid.reserve(40);
- ::WideCharToMultiByte(CP_UTF8, 0, szGuid, 39, strGuid.data(), 39, NULL, NULL);
- strGuid[38] = '\0';
-#endif
- return strGuid;
-}
-
// Q_STATIC_ASSERT(IA2_ROLE_CANVAS == QAccessible::Canvas); // ### Qt 6: make them the same
Q_STATIC_ASSERT(IA2_ROLE_COLOR_CHOOSER == static_cast<IA2Role>(QAccessible::ColorChooser));
Q_STATIC_ASSERT(IA2_ROLE_FOOTER == static_cast<IA2Role>(QAccessible::Footer));
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h
index bc5f5be60f..e56106f247 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.h
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.h
@@ -42,6 +42,7 @@
#include <QtCore/QtConfig>
#ifndef QT_NO_ACCESSIBILITY
+#include "qwindowscombase.h"
#include "qwindowsmsaaaccessible.h"
#include "comutils.h"
@@ -51,6 +52,13 @@
QT_BEGIN_NAMESPACE
+#ifdef Q_CC_MINGW
+QT_WARNING_DISABLE_GCC("-Wunused-function") // MinGW 7.X claims it is unused
+// MinGW's __uuidof operator does not work for the Accessible2 interfaces
+template <>
+IID qUuidOf<IAccessibleComponent>() { return IID_IAccessibleComponent; }
+#endif // Q_CC_MINGW
+
class QWindowsIA2Accessible : public QWindowsMsaaAccessible,
public IAccessibleAction,
public IAccessibleComponent,
@@ -249,7 +257,6 @@ private:
HRESULT getRelationsHelper(IAccessibleRelation **relations, int startIndex, long maxRelations, long *nRelations = 0);
HRESULT wrapListOfCells(const QList<QAccessibleInterface*> &inputCells, IUnknown ***outputAccessibles, long *nCellCount);
- QByteArray IIDToString(REFIID id);
QString textForRange(int startOffset, int endOffset) const;
void replaceTextFallback(long startOffset, long endOffset, const QString &txt);
@@ -258,28 +265,31 @@ private:
/**************************************************************\
* AccessibleApplication *
**************************************************************/
-class AccessibleApplication : public IAccessibleApplication
+
+#ifdef Q_CC_MINGW
+// MinGW's __uuidof operator does not work for the IAccessible2 interfaces
+template <>
+IID qUuidOf<IAccessibleApplication>() { return IID_IAccessibleApplication; }
+
+template <>
+IID qUuidOf<IAccessible2>() { return IID_IAccessible2; }
+
+template <>
+IID qUuidOf<IAccessibleRelation>() { return IID_IAccessibleRelation; }
+#endif // Q_CC_MINGW
+
+class AccessibleApplication : public QWindowsComBase<IAccessibleApplication>
{
public:
- AccessibleApplication() : m_ref(1)
- {
-
- }
+ AccessibleApplication() {}
virtual ~AccessibleApplication() {}
- /* IUnknown */
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
/* IAccessibleApplication */
HRESULT STDMETHODCALLTYPE get_appName(/* [retval][out] */ BSTR *name);
HRESULT STDMETHODCALLTYPE get_appVersion(/* [retval][out] */ BSTR *version);
HRESULT STDMETHODCALLTYPE get_toolkitName(/* [retval][out] */ BSTR *name);
HRESULT STDMETHODCALLTYPE get_toolkitVersion(/* [retval][out] */ BSTR *version);
-private:
- ULONG m_ref;
};
@@ -287,7 +297,10 @@ private:
/**************************************************************\
* AccessibleRelation *
**************************************************************/
-class AccessibleRelation : public IAccessibleRelation
+
+
+
+class AccessibleRelation : public QWindowsComBase<IAccessibleRelation>
{
public:
AccessibleRelation(const QList<QAccessibleInterface *> &targets,
@@ -295,11 +308,6 @@ public:
virtual ~AccessibleRelation() {}
- /* IUnknown */
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
/* IAccessibleRelation */
HRESULT STDMETHODCALLTYPE get_relationType(BSTR *relationType);
HRESULT STDMETHODCALLTYPE get_localizedRelationType(BSTR *localizedRelationType);
@@ -341,7 +349,6 @@ private:
QList<QAccessibleInterface *> m_targets;
QAccessible::Relation m_relation;
- ULONG m_ref;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
index aed9c94003..e214d47137 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp
@@ -56,11 +56,7 @@
#include <QtFontDatabaseSupport/private/qwindowsfontdatabase_p.h> // registry helper
#include "qwindowsaccessibility.h"
-#ifdef Q_CC_MINGW
-# include "qwindowsmsaaaccessible.h"
-#else
-# include "iaccessible2.h"
-#endif
+#include "iaccessible2.h"
#include "comutils.h"
#include <oleacc.h>
@@ -198,11 +194,7 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc)
if (!QAccessible::uniqueId(acc))
QAccessible::registerAccessibleInterface(acc);
-# ifdef Q_CC_MINGW
- QWindowsMsaaAccessible *wacc = new QWindowsMsaaAccessible(acc);
-# else
QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc);
-# endif
IAccessible *iacc = 0;
wacc->QueryInterface(IID_IAccessible, reinterpret_cast<void **>(&iacc));
return iacc;
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
index 25b1577772..47b179250a 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
@@ -42,6 +42,7 @@
#include "qwindowsmsaaaccessible.h"
#include "qwindowsaccessibility.h"
+#include "qwindowscombase.h"
#include <oleacc.h>
#include <servprov.h>
#include <winuser.h>
@@ -71,61 +72,22 @@
QT_BEGIN_NAMESPACE
-class QWindowsEnumerate : public IEnumVARIANT
+class QWindowsEnumerate : public QWindowsComBase<IEnumVARIANT>
{
public:
- QWindowsEnumerate(const QVector<int> &a)
- : ref(0), current(0),array(a)
- {
- }
-
+ QWindowsEnumerate(const QVector<int> &a) : QWindowsComBase<IEnumVARIANT>(0), current(0),array(a) {}
virtual ~QWindowsEnumerate() {}
- HRESULT STDMETHODCALLTYPE QueryInterface(REFIID, LPVOID *);
- ULONG STDMETHODCALLTYPE AddRef();
- ULONG STDMETHODCALLTYPE Release();
-
HRESULT STDMETHODCALLTYPE Clone(IEnumVARIANT **ppEnum);
HRESULT STDMETHODCALLTYPE Next(unsigned long celt, VARIANT FAR* rgVar, unsigned long FAR* pCeltFetched);
HRESULT STDMETHODCALLTYPE Reset();
HRESULT STDMETHODCALLTYPE Skip(unsigned long celt);
private:
- ULONG ref;
ULONG current;
QVector<int> array;
};
-HRESULT STDMETHODCALLTYPE QWindowsEnumerate::QueryInterface(REFIID id, LPVOID *iface)
-{
- *iface = 0;
- if (id == IID_IUnknown)
- *iface = static_cast<IUnknown *>(this);
- else if (id == IID_IEnumVARIANT)
- *iface = static_cast<IEnumVARIANT *>(this);
-
- if (*iface) {
- AddRef();
- return S_OK;
- }
-
- return E_NOINTERFACE;
-}
-
-ULONG STDMETHODCALLTYPE QWindowsEnumerate::AddRef()
-{
- return ++ref;
-}
-
-ULONG STDMETHODCALLTYPE QWindowsEnumerate::Release()
-{
- if (!--ref) {
- delete this;
- return 0;
- }
- return ref;
-}
-
HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Clone(IEnumVARIANT **ppEnum)
{
QWindowsEnumerate *penum = 0;
@@ -193,29 +155,17 @@ void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleIn
**************************************************************/
HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::QueryInterface(REFIID id, LPVOID *iface)
{
- *iface = 0;
-
- QByteArray strIID = IIDToString(id);
- if (!strIID.isEmpty()) {
- qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QI() - IID:"
- << strIID << ", iface:" << accessibleInterface();
+ *iface = nullptr;
+ const bool result = qWindowsComQueryUnknownInterfaceMulti<IAccessible2>(this, id, iface)
+ || qWindowsComQueryInterface<IDispatch>(this, id, iface)
+ || qWindowsComQueryInterface<IAccessible>(this, id, iface)
+ || qWindowsComQueryInterface<IOleWindow>(this, id, iface);
+
+ if (result) {
+ qCDebug(lcQpaAccessibility) << "QWindowsIA2Accessible::QI() - "
+ << QWindowsAccessibleGuid(id) << ", iface:" << accessibleInterface();
}
- if (id == IID_IUnknown) {
- *iface = static_cast<IUnknown *>(static_cast<IDispatch *>(this));
- } else if (id == IID_IDispatch) {
- *iface = static_cast<IDispatch *>(this);
- } else if (id == IID_IAccessible) {
- *iface = static_cast<IAccessible *>(this);
- } else if (id == IID_IOleWindow) {
- *iface = static_cast<IOleWindow *>(this);
- }
-
- if (*iface) {
- AddRef();
- return S_OK;
- }
-
- return E_NOINTERFACE;
+ return result ? S_OK : E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE QWindowsMsaaAccessible::AddRef()
@@ -1209,16 +1159,64 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::ContextSensitiveHelp(BOOL)
return S_OK;
}
-#define IF_EQUAL_RETURN_IIDSTRING(id, iid) if (id == iid) return QByteArray(#iid)
-QByteArray QWindowsMsaaAccessible::IIDToString(REFIID id)
+const char *QWindowsAccessibleGuid::iidToString(const GUID &id)
{
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IUnknown);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IDispatch);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IAccessible);
- IF_EQUAL_RETURN_IIDSTRING(id, IID_IOleWindow);
+ const char *result = nullptr;
+ if (id == IID_IUnknown)
+ result = "IID_IUnknown";
+ else if (id == IID_IDispatch)
+ result = "IID_IDispatch";
+ else if (id == IID_IAccessible)
+ result = "IID_IAccessible";
+ else if (id == IID_IOleWindow)
+ result = "IID_IOleWindow";
+ else if (id == IID_IServiceProvider)
+ result = "IID_IServiceProvider";
+ else if (id == IID_IAccessible2)
+ result = "IID_IAccessible2";
+ else if (id == IID_IAccessibleAction)
+ result = "IID_IAccessibleAction";
+ else if (id == IID_IAccessibleApplication)
+ result = "IID_IAccessibleApplication";
+ else if (id == IID_IAccessibleComponent)
+ result = "IID_IAccessibleComponent";
+ else if (id == IID_IAccessibleEditableText)
+ result = "IID_IAccessibleEditableText";
+ else if (id == IID_IAccessibleHyperlink)
+ result = "IID_IAccessibleHyperlink";
+ else if (id == IID_IAccessibleHypertext)
+ result = "IID_IAccessibleHypertext";
+ else if (id == IID_IAccessibleImage)
+ result = "IID_IAccessibleImage";
+ else if (id == IID_IAccessibleRelation)
+ result = "IID_IAccessibleRelation";
+ else if (id == IID_IAccessibleTable)
+ result = "IID_IAccessibleTable";
+ else if (id == IID_IAccessibleTable2)
+ result = "IID_IAccessibleTable2";
+ else if (id == IID_IAccessibleTableCell)
+ result = "IID_IAccessibleTableCell";
+ else if (id == IID_IAccessibleText)
+ result = "IID_IAccessibleText";
+ else if (id == IID_IAccessibleValue)
+ result = "IID_IAccessibleValue";
+ return result;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug, const GUID &);
- return QByteArray();
+QDebug operator<<(QDebug d, const QWindowsAccessibleGuid &aguid)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ if (const char *ids = QWindowsAccessibleGuid::iidToString(aguid.guid()))
+ d << ids;
+ else
+ d << aguid.guid();
+ return d;
}
+#endif // !QT_NO_DEBUG_STREAM
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
index fd00f8ac8b..e654f262da 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.h
@@ -46,14 +46,8 @@
#include <QtCore/qt_windows.h>
#include <QtCore/qsharedpointer.h>
#include <QtGui/qaccessible.h>
-#ifndef Q_CC_MINGW
-# include <oleacc.h>
-# include "ia2_api_all.h" // IAccessible2 inherits from IAccessible
-#else
- // MinGW
-# include <basetyps.h>
-# include <oleacc.h>
-#endif
+#include <oleacc.h>
+#include "ia2_api_all.h" // IAccessible2 inherits from IAccessible
QT_BEGIN_NAMESPACE
@@ -69,16 +63,26 @@ void accessibleDebugClientCalls_helper(const char* funcName, const QAccessibleIn
QWindow *window_helper(const QAccessibleInterface *iface);
+class QWindowsAccessibleGuid // Helper for QDebug, outputs known ids by name.
+{
+public:
+ explicit QWindowsAccessibleGuid(const GUID &g) : m_guid(g) {}
+ GUID guid () const { return m_guid; }
+ static const char *iidToString(const GUID &id);
+
+private:
+ GUID m_guid;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const QWindowsAccessibleGuid &aguid);
+#endif
+
/**************************************************************\
* QWindowsAccessible *
**************************************************************/
-class QWindowsMsaaAccessible : public
-#ifdef Q_CC_MINGW
- IAccessible
-#else
- IAccessible2
-#endif
- , public IOleWindow
+
+class QWindowsMsaaAccessible : public IAccessible2, public IOleWindow
{
public:
QWindowsMsaaAccessible(QAccessibleInterface *a)
@@ -132,8 +136,6 @@ public:
HRESULT STDMETHODCALLTYPE ContextSensitiveHelp(BOOL fEnterMode);
protected:
- virtual QByteArray IIDToString(REFIID id);
-
QAccessible::Id id;
QAccessibleInterface *accessibleInterface() const
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index b2152e7ed4..d9c342be27 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -121,6 +121,9 @@ enum WindowsEventType // Simplify event types
EndSessionApplicationEvent = ApplicationEventFlag + 5,
AppCommandEvent = ApplicationEventFlag + 6,
DeviceChangeEvent = ApplicationEventFlag + 7,
+ MenuAboutToShowEvent = ApplicationEventFlag + 8,
+ AcceleratorCommandEvent = ApplicationEventFlag + 9,
+ MenuCommandEvent = ApplicationEventFlag + 10,
InputMethodStartCompositionEvent = InputMethodEventFlag + 1,
InputMethodCompositionEvent = InputMethodEventFlag + 2,
InputMethodEndCompositionEvent = InputMethodEventFlag + 3,
@@ -272,6 +275,11 @@ inline QtWindows::WindowsEventType windowsEventType(UINT message, WPARAM wParamI
return QtWindows::GestureEvent;
case WM_DEVICECHANGE:
return QtWindows::DeviceChangeEvent;
+ case WM_INITMENU:
+ case WM_INITMENUPOPUP:
+ return QtWindows::MenuAboutToShowEvent;
+ case WM_COMMAND:
+ return HIWORD(wParamIn) ? QtWindows::AcceleratorCommandEvent : QtWindows::MenuCommandEvent;
case WM_DPICHANGED:
return QtWindows::DpiChangedEvent;
default:
diff --git a/src/plugins/platforms/windows/qwindowscombase.h b/src/plugins/platforms/windows/qwindowscombase.h
new file mode 100644
index 0000000000..5e51b6b7b7
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowscombase.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSCOMBASE_H
+#define QWINDOWSCOMBASE_H
+
+#include <QtCore/QtGlobal>
+
+#include <unknwn.h>
+
+QT_BEGIN_NAMESPACE
+
+// The __uuidof operator of MinGW does not work for all interfaces (for example,
+// IAccessible2). Specializations of this function can be provides to work
+// around this.
+template <class DesiredInterface>
+static IID qUuidOf() { return __uuidof(DesiredInterface); }
+
+// Helper for implementing IUnknown::QueryInterface.
+template <class DesiredInterface, class Derived>
+bool qWindowsComQueryInterface(Derived *d, REFIID id, LPVOID *iface)
+{
+ if (id == qUuidOf<DesiredInterface>()) {
+ *iface = static_cast<DesiredInterface *>(d);
+ d->AddRef();
+ return true;
+ }
+ return false;
+}
+
+// Helper for implementing IUnknown::QueryInterface for IUnknown
+// in the case of multiple inheritance via the first inherited class.
+template <class FirstInheritedInterface, class Derived>
+bool qWindowsComQueryUnknownInterfaceMulti(Derived *d, REFIID id, LPVOID *iface)
+{
+ if (id == __uuidof(IUnknown)) {
+ *iface = static_cast<FirstInheritedInterface *>(d);
+ d->AddRef();
+ return true;
+ }
+ return false;
+}
+
+// Helper base class to provide IUnknown methods for COM classes (single inheritance)
+template <class ComInterface> class QWindowsComBase : public ComInterface
+{
+ Q_DISABLE_COPY(QWindowsComBase)
+public:
+ explicit QWindowsComBase(ULONG initialRefCount = 1) : m_ref(initialRefCount) {}
+ virtual ~QWindowsComBase() {}
+
+ HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface)
+ {
+ *iface = nullptr;
+ return qWindowsComQueryInterface<IUnknown>(this, id, iface) || qWindowsComQueryInterface<ComInterface>(this, id, iface)
+ ? S_OK : E_NOINTERFACE;
+ }
+
+ ULONG STDMETHODCALLTYPE AddRef() { return ++m_ref; }
+
+ ULONG STDMETHODCALLTYPE Release()
+ {
+ if (!--m_ref) {
+ delete this;
+ return 0;
+ }
+ return m_ref;
+ }
+
+private:
+ ULONG m_ref;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSCOMBASE_H
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 9ab131808b..6d4b7922db 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -44,6 +44,7 @@
#include "qwindowskeymapper.h"
#include "qwindowsmousehandler.h"
#include "qtwindowsglobal.h"
+#include "qwindowsmenu.h"
#include "qwindowsmime.h"
#include "qwindowsinputcontext.h"
#include "qwindowstabletsupport.h"
@@ -91,8 +92,10 @@ Q_LOGGING_CATEGORY(lcQpaGl, "qt.qpa.gl")
Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime")
Q_LOGGING_CATEGORY(lcQpaInputMethods, "qt.qpa.input.methods")
Q_LOGGING_CATEGORY(lcQpaDialogs, "qt.qpa.dialogs")
+Q_LOGGING_CATEGORY(lcQpaMenus, "qt.qpa.menus")
Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet")
Q_LOGGING_CATEGORY(lcQpaAccessibility, "qt.qpa.accessibility")
+Q_LOGGING_CATEGORY(lcQpaTrayIcon, "qt.qpa.trayicon")
int QWindowsContext::verbose = 0;
@@ -123,11 +126,19 @@ static inline bool useRTL_Extensions()
}
#if QT_CONFIG(sessionmanager)
-static inline QWindowsSessionManager *platformSessionManager() {
+static inline QWindowsSessionManager *platformSessionManager()
+{
QGuiApplicationPrivate *guiPrivate = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(qApp));
QSessionManagerPrivate *managerPrivate = static_cast<QSessionManagerPrivate*>(QObjectPrivate::get(guiPrivate->session_manager));
return static_cast<QWindowsSessionManager *>(managerPrivate->platformSessionManager);
}
+
+static inline bool sessionManagerInteractionBlocked()
+{
+ return platformSessionManager()->isInteractionBlocked();
+}
+#else // QT_CONFIG(sessionmanager)
+static inline bool sessionManagerInteractionBlocked() { return false; }
#endif
static inline int windowDpiAwareness(HWND hwnd)
@@ -394,9 +405,11 @@ QList<int> QWindowsContext::possibleKeys(const QKeyEvent *e) const
return d->m_keyMapper.possibleKeys(e);
}
-void QWindowsContext::setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx)
+QSharedPointer<QWindowCreationContext> QWindowsContext::setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx)
{
+ const QSharedPointer<QWindowCreationContext> old = d->m_creationContext;
d->m_creationContext = ctx;
+ return old;
}
QSharedPointer<QWindowCreationContext> QWindowsContext::windowCreationContext() const
@@ -594,6 +607,15 @@ void QWindowsContext::removeWindow(HWND hwnd)
}
}
+QWindowsWindow *QWindowsContext::findPlatformWindow(const QWindowsMenuBar *mb) const
+{
+ for (auto it = d->m_windows.cbegin(), end = d->m_windows.cend(); it != end; ++it) {
+ if ((*it)->menuBar() == mb)
+ return *it;
+ }
+ return nullptr;
+}
+
QWindowsWindow *QWindowsContext::findPlatformWindow(HWND hwnd) const
{
return d->m_windows.value(hwnd);
@@ -919,11 +941,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
switch (et) {
case QtWindows::GestureEvent:
-#if QT_CONFIG(sessionmanager)
- return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);
-#else
- return d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);
-#endif
+ return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateGestureEvent(platformWindow->window(), hwnd, et, msg, result);
case QtWindows::InputMethodOpenCandidateWindowEvent:
case QtWindows::InputMethodCloseCandidateWindowEvent:
// TODO: Release/regrab mouse if a popup has mouse grab.
@@ -1014,11 +1032,23 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::InputMethodKeyEvent:
case QtWindows::InputMethodKeyDownEvent:
case QtWindows::AppCommandEvent:
-#if QT_CONFIG(sessionmanager)
- return platformSessionManager()->isInteractionBlocked() ? true : d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result);
-#else
- return d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result);
-#endif
+ return sessionManagerInteractionBlocked() || d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result);
+ case QtWindows::MenuAboutToShowEvent:
+ if (sessionManagerInteractionBlocked())
+ return true;
+ if (QWindowsPopupMenu::notifyAboutToShow(reinterpret_cast<HMENU>(wParam)))
+ return true;
+ if (platformWindow == nullptr || platformWindow->menuBar() == nullptr)
+ return false;
+ return platformWindow->menuBar()->notifyAboutToShow(reinterpret_cast<HMENU>(wParam));
+ case QtWindows::MenuCommandEvent:
+ if (sessionManagerInteractionBlocked())
+ return true;
+ if (QWindowsPopupMenu::notifyTriggered(LOWORD(wParam)))
+ return true;
+ if (platformWindow == nullptr || platformWindow->menuBar() == nullptr)
+ return false;
+ return platformWindow->menuBar()->notifyTriggered(LOWORD(wParam));
case QtWindows::MoveEvent:
platformWindow->handleMoved();
return true;
@@ -1038,18 +1068,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return platformWindow->handleWmPaint(hwnd, message, wParam, lParam);
case QtWindows::NonClientMouseEvent:
if (platformWindow->frameStrutEventsEnabled())
-#if QT_CONFIG(sessionmanager)
- return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
-#else
- return d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
-#endif
+ return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
break;
case QtWindows::ScrollEvent:
-#if QT_CONFIG(sessionmanager)
- return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result);
-#else
- return d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result);
-#endif
+ return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateScrollEvent(platformWindow->window(), hwnd, msg, result);
case QtWindows::MouseWheelEvent:
case QtWindows::MouseEvent:
case QtWindows::LeaveEvent:
@@ -1059,18 +1081,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
window = window->parent();
if (!window)
return false;
-#if QT_CONFIG(sessionmanager)
- return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
-#else
- return d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
-#endif
+ return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(window, hwnd, et, msg, result);
}
case QtWindows::TouchEvent:
-#if QT_CONFIG(sessionmanager)
- return platformSessionManager()->isInteractionBlocked() ? true : d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result);
-#else
- return d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result);
-#endif
+ return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateTouchEvent(platformWindow->window(), hwnd, et, msg, result);
case QtWindows::FocusInEvent: // see QWindowsWindow::requestActivateWindow().
case QtWindows::FocusOutEvent:
handleFocusEvent(et, platformWindow);
@@ -1272,6 +1286,29 @@ QTouchDevice *QWindowsContext::touchDevice() const
return d->m_mouseHandler.touchDevice();
}
+static DWORD readDwordRegistrySetting(const wchar_t *regKey, const wchar_t *subKey, DWORD defaultValue)
+{
+ DWORD result = defaultValue;
+ HKEY handle;
+ if (RegOpenKeyEx(HKEY_CURRENT_USER, regKey, 0, KEY_READ, &handle) == ERROR_SUCCESS) {
+ DWORD type;
+ if (RegQueryValueEx(handle, subKey, 0, &type, 0, 0) == ERROR_SUCCESS && type == REG_DWORD) {
+ DWORD value;
+ DWORD size = sizeof(result);
+ if (RegQueryValueEx(handle, subKey, 0, 0, reinterpret_cast<unsigned char *>(&value), &size) == ERROR_SUCCESS)
+ result = value;
+ }
+ RegCloseKey(handle);
+ }
+ return result;
+}
+
+DWORD QWindowsContext::readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue)
+{
+ return readDwordRegistrySetting(L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced",
+ subKey, defaultValue);
+}
+
static inline bool isEmptyRect(const RECT &rect)
{
return rect.right - rect.left == 0 && rect.bottom - rect.top == 0;
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index b50010321b..5c39b6068b 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -63,11 +63,14 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaGl)
Q_DECLARE_LOGGING_CATEGORY(lcQpaMime)
Q_DECLARE_LOGGING_CATEGORY(lcQpaInputMethods)
Q_DECLARE_LOGGING_CATEGORY(lcQpaDialogs)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaMenus)
Q_DECLARE_LOGGING_CATEGORY(lcQpaTablet)
Q_DECLARE_LOGGING_CATEGORY(lcQpaAccessibility)
+Q_DECLARE_LOGGING_CATEGORY(lcQpaTrayIcon)
class QWindow;
class QPlatformScreen;
+class QWindowsMenuBar;
class QWindowsScreenManager;
class QWindowsTabletSupport;
class QWindowsWindow;
@@ -177,6 +180,7 @@ public:
QWindowsWindow *findClosestPlatformWindow(HWND) const;
QWindowsWindow *findPlatformWindow(HWND) const;
+ QWindowsWindow *findPlatformWindow(const QWindowsMenuBar *mb) const;
QWindow *findWindow(HWND) const;
QWindowsWindow *findPlatformWindowAt(HWND parent, const QPoint &screenPoint,
unsigned cwex_flags) const;
@@ -192,7 +196,7 @@ public:
QWindow *keyGrabber() const;
void setKeyGrabber(QWindow *hwnd);
- void setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx);
+ QSharedPointer<QWindowCreationContext> setWindowCreationContext(const QSharedPointer<QWindowCreationContext> &ctx);
QSharedPointer<QWindowCreationContext> windowCreationContext() const;
void setTabletAbsoluteRange(int a);
@@ -216,6 +220,8 @@ public:
bool asyncExpose() const;
void setAsyncExpose(bool value);
+ static DWORD readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue);
+
QTouchDevice *touchDevice() const;
private:
diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp
index 0a09b87ba3..e7ba08b719 100644
--- a/src/plugins/platforms/windows/qwindowscursor.cpp
+++ b/src/plugins/platforms/windows/qwindowscursor.cpp
@@ -586,6 +586,13 @@ QWindowsCursor::QWindowsCursor(const QPlatformScreen *screen)
Q_UNUSED(dummy)
}
+inline CursorHandlePtr QWindowsCursor::cursorHandle(const QCursor &cursor)
+{
+ return cursor.shape() == Qt::BitmapCursor
+ ? pixmapWindowCursor(cursor)
+ : standardWindowCursor(cursor.shape());
+}
+
/*!
\brief Set a cursor on a window.
@@ -603,9 +610,7 @@ void QWindowsCursor::changeCursor(QCursor *cursorIn, QWindow *window)
platformWindow->setCursor(CursorHandlePtr(new CursorHandle));
return;
}
- const CursorHandlePtr wcursor =
- cursorIn->shape() == Qt::BitmapCursor ?
- pixmapWindowCursor(*cursorIn) : standardWindowCursor(cursorIn->shape());
+ const CursorHandlePtr wcursor = cursorHandle(*cursorIn);
if (wcursor->handle()) {
platformWindow->setCursor(wcursor);
} else {
@@ -614,6 +619,25 @@ void QWindowsCursor::changeCursor(QCursor *cursorIn, QWindow *window)
}
}
+void QWindowsCursor::setOverrideCursor(const QCursor &cursor)
+{
+ const CursorHandlePtr wcursor = cursorHandle(cursor);
+ if (wcursor->handle()) {
+ m_overriddenCursor = SetCursor(wcursor->handle());
+ } else {
+ qWarning("%s: Unable to obtain system cursor for %d",
+ __FUNCTION__, cursor.shape());
+ }
+}
+
+void QWindowsCursor::clearOverrideCursor()
+{
+ if (m_overriddenCursor) {
+ SetCursor(m_overriddenCursor);
+ m_overriddenCursor = nullptr;
+ }
+}
+
QPoint QWindowsCursor::mousePosition()
{
POINT p;
diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h
index df2e22733b..9aa9523ac8 100644
--- a/src/plugins/platforms/windows/qwindowscursor.h
+++ b/src/plugins/platforms/windows/qwindowscursor.h
@@ -105,6 +105,9 @@ public:
explicit QWindowsCursor(const QPlatformScreen *screen);
void changeCursor(QCursor * widgetCursor, QWindow * widget) override;
+ void setOverrideCursor(const QCursor &cursor) override;
+ void clearOverrideCursor() override;
+
QPoint pos() const override;
void setPos(const QPoint &pos) override;
@@ -127,6 +130,8 @@ private:
typedef QHash<Qt::CursorShape, CursorHandlePtr> StandardCursorCache;
typedef QHash<QWindowsPixmapCursorCacheKey, CursorHandlePtr> PixmapCursorCache;
+ CursorHandlePtr cursorHandle(const QCursor &c);
+
const QPlatformScreen *const m_screen;
StandardCursorCache m_standardCursorCache;
PixmapCursorCache m_pixmapCursorCache;
@@ -135,6 +140,8 @@ private:
mutable QPixmap m_moveDragCursor;
mutable QPixmap m_linkDragCursor;
mutable QPixmap m_ignoreDragCursor;
+
+ HCURSOR m_overriddenCursor = nullptr;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
index f4527bcc60..c4aeb15bd1 100644
--- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
+++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
@@ -41,6 +41,7 @@
#define _WIN32_WINNT 0x0600
+#include "qwindowscombase.h"
#include "qwindowsdialoghelpers.h"
#include "qwindowscontext.h"
@@ -52,7 +53,7 @@
#include <QtGui/QColor>
#include <QtCore/QDebug>
-#include <QtCore/QRegExp>
+#include <QtCore/QRegularExpression>
#include <QtCore/QTimer>
#include <QtCore/QDir>
#include <QtCore/QScopedArrayPointer>
@@ -504,33 +505,11 @@ inline void QWindowsFileDialogSharedData::fromOptions(const QSharedPointer<QFile
class QWindowsNativeFileDialogBase;
-class QWindowsNativeFileDialogEventHandler : public IFileDialogEvents
+class QWindowsNativeFileDialogEventHandler : public QWindowsComBase<IFileDialogEvents>
{
public:
static IFileDialogEvents *create(QWindowsNativeFileDialogBase *nativeFileDialog);
- // IUnknown methods
- IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv)
- {
- if (riid != IID_IUnknown && riid != IID_IFileDialogEvents) {
- *ppv = NULL;
- return ResultFromScode(E_NOINTERFACE);
- }
- *ppv = this;
- AddRef();
- return NOERROR;
- }
-
- IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&m_ref); }
-
- IFACEMETHODIMP_(ULONG) Release()
- {
- const long ref = InterlockedDecrement(&m_ref);
- if (!ref)
- delete this;
- return ref;
- }
-
// IFileDialogEvents methods
IFACEMETHODIMP OnFileOk(IFileDialog *);
IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; }
@@ -546,7 +525,6 @@ public:
virtual ~QWindowsNativeFileDialogEventHandler() {}
private:
- long m_ref = 1;
QWindowsNativeFileDialogBase *m_nativeFileDialog;
};
@@ -931,7 +909,7 @@ IShellItem *QWindowsNativeFileDialogBase::shellItem(const QUrl &url)
// (see https://msdn.microsoft.com/en-us/library/windows/desktop/dd378457(v=vs.85).aspx)
// specified as "clsid:<GUID>" (without '{', '}').
IShellItem *result = Q_NULLPTR;
- const QUuid uuid(url.path());
+ const auto uuid = QUuid::fromString(url.path());
if (uuid.isNull()) {
qWarning() << __FUNCTION__ << ": Invalid CLSID: " << url.path();
return Q_NULLPTR;
@@ -995,7 +973,9 @@ void QWindowsNativeFileDialogBase::setMode(QFileDialogOptions::FileMode mode,
QFileDialogOptions::AcceptMode acceptMode,
QFileDialogOptions::FileDialogOptions options)
{
- DWORD flags = FOS_PATHMUSTEXIST | FOS_FORCESHOWHIDDEN;
+ DWORD flags = FOS_PATHMUSTEXIST;
+ if (QWindowsContext::readAdvancedExplorerSettings(L"Hidden", 1) == 1) // 1:show, 2:hidden
+ flags |= FOS_FORCESHOWHIDDEN;
if (options & QFileDialogOptions::DontResolveSymlinks)
flags |= FOS_NODEREFERENCELINKS;
switch (mode) {
@@ -1039,7 +1019,7 @@ static QList<FilterSpec> filterSpecs(const QStringList &filters,
result.reserve(filters.size());
*totalStringLength = 0;
- const QRegExp filterSeparatorRE(QStringLiteral("[;\\s]+"));
+ const QRegularExpression filterSeparatorRE(QStringLiteral("[;\\s]+"));
const QString separator = QStringLiteral(";");
Q_ASSERT(filterSeparatorRE.isValid());
// Split filter specification as 'Texts (*.txt[;] *.doc)', '*.txt[;] *.doc'
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 26403b68e5..857db7a65c 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -215,7 +215,7 @@ static inline Qt::MouseButtons toQtMouseButtons(DWORD keyState)
\ingroup qt-lighthouse-win
*/
-class QWindowsOleDropSource : public IDropSource
+class QWindowsOleDropSource : public QWindowsComBase<IDropSource>
{
public:
enum Mode {
@@ -228,11 +228,6 @@ public:
void createCursors();
- // IUnknown methods
- STDMETHOD(QueryInterface)(REFIID riid, void ** ppvObj);
- STDMETHOD_(ULONG,AddRef)(void);
- STDMETHOD_(ULONG,Release)(void);
-
// IDropSource methods
STDMETHOD(QueryContinueDrag)(BOOL fEscapePressed, DWORD grfKeyState);
STDMETHOD(GiveFeedback)(DWORD dwEffect);
@@ -257,7 +252,6 @@ private:
ActionCursorMap m_cursors;
QWindowsDragCursorWindow *m_touchDragWindow;
- ULONG m_refs;
#ifndef QT_NO_DEBUG_STREAM
friend QDebug operator<<(QDebug, const QWindowsOleDropSource::CursorEntry &);
#endif
@@ -268,7 +262,6 @@ QWindowsOleDropSource::QWindowsOleDropSource(QWindowsDrag *drag)
, m_drag(drag)
, m_currentButtons(Qt::NoButton)
, m_touchDragWindow(0)
- , m_refs(1)
{
qCDebug(lcQpaMime) << __FUNCTION__ << m_mode;
}
@@ -373,38 +366,6 @@ void QWindowsOleDropSource::createCursors()
#endif // !QT_NO_DEBUG_OUTPUT
}
-//---------------------------------------------------------------------
-// IUnknown Methods
-//---------------------------------------------------------------------
-
-STDMETHODIMP
-QWindowsOleDropSource::QueryInterface(REFIID iid, void FAR* FAR* ppv)
-{
- if (iid == IID_IUnknown || iid == IID_IDropSource) {
- *ppv = this;
- ++m_refs;
- return NOERROR;
- }
- *ppv = NULL;
- return ResultFromScode(E_NOINTERFACE);
-}
-
-STDMETHODIMP_(ULONG)
-QWindowsOleDropSource::AddRef(void)
-{
- return ++m_refs;
-}
-
-STDMETHODIMP_(ULONG)
-QWindowsOleDropSource::Release(void)
-{
- if (--m_refs == 0) {
- delete this;
- return 0;
- }
- return m_refs;
-}
-
/*!
\brief Check for cancel.
*/
@@ -509,34 +470,6 @@ QWindowsOleDropTarget::~QWindowsOleDropTarget()
qCDebug(lcQpaMime) << __FUNCTION__ << this;
}
-STDMETHODIMP
-QWindowsOleDropTarget::QueryInterface(REFIID iid, void FAR* FAR* ppv)
-{
- if (iid == IID_IUnknown || iid == IID_IDropTarget) {
- *ppv = this;
- AddRef();
- return NOERROR;
- }
- *ppv = NULL;
- return ResultFromScode(E_NOINTERFACE);
-}
-
-STDMETHODIMP_(ULONG)
-QWindowsOleDropTarget::AddRef(void)
-{
- return ++m_refs;
-}
-
-STDMETHODIMP_(ULONG)
-QWindowsOleDropTarget::Release(void)
-{
- if (--m_refs == 0) {
- delete this;
- return 0;
- }
- return m_refs;
-}
-
void QWindowsOleDropTarget::handleDrag(QWindow *window, DWORD grfKeyState,
const QPoint &point, LPDWORD pdwEffect)
{
diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h
index 983f3a67b4..2b4ca2dce1 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.h
+++ b/src/plugins/platforms/windows/qwindowsdrag.h
@@ -40,6 +40,7 @@
#ifndef QWINDOWSDRAG_H
#define QWINDOWSDRAG_H
+#include "qwindowscombase.h"
#include "qwindowsinternalmimedata.h"
#include <qpa/qplatformdrag.h>
@@ -57,17 +58,12 @@ public:
IDataObject *retrieveDataObject() const override;
};
-class QWindowsOleDropTarget : public IDropTarget
+class QWindowsOleDropTarget : public QWindowsComBase<IDropTarget>
{
public:
explicit QWindowsOleDropTarget(QWindow *w);
virtual ~QWindowsOleDropTarget();
- // IUnknown methods
- STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
- STDMETHOD_(ULONG, AddRef)(void);
- STDMETHOD_(ULONG, Release)(void);
-
// IDropTarget methods
STDMETHOD(DragEnter)(LPDATAOBJECT pDataObj, DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
STDMETHOD(DragOver)(DWORD grfKeyState, POINTL pt, LPDWORD pdwEffect);
@@ -77,7 +73,6 @@ public:
private:
void handleDrag(QWindow *window, DWORD grfKeyState, const QPoint &, LPDWORD pdwEffect);
- ULONG m_refs = 1;
QWindow *const m_window;
QRect m_answerRect;
QPoint m_lastPoint;
@@ -91,8 +86,6 @@ public:
QWindowsDrag();
virtual ~QWindowsDrag();
- QMimeData *platformDropData() override { return &m_dropData; }
-
Qt::DropAction drag(QDrag *drag) override;
static QWindowsDrag *instance();
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 751807e897..78368d87de 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -145,6 +145,10 @@
#define RESET_NOTIFICATION_STRATEGY_ARB 0x8256
#define LOSE_CONTEXT_ON_RESET_ARB 0x8252
+#ifndef WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT
+#define WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x20A9
+#endif
+
QT_BEGIN_NAMESPACE
QWindowsOpengl32DLL QOpenGLStaticContext::opengl32;
@@ -489,7 +493,7 @@ static int choosePixelFormat(HDC hdc,
const QWindowsOpenGLAdditionalFormat &additional,
PIXELFORMATDESCRIPTOR *obtainedPfd)
{
- enum { attribSize =40 };
+ enum { attribSize = 42 };
if ((additional.formatFlags & QWindowsGLRenderToPixmap) || !staticContext.hasExtensions())
return 0;
@@ -570,7 +574,15 @@ static int choosePixelFormat(HDC hdc,
iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB;
iAttributes[i++] = FALSE;
}
- // If sample buffer request cannot be satisfied, reduce request.
+ // must be the last
+ bool srgbRequested = format.colorSpace() == QSurfaceFormat::sRGBColorSpace;
+ int srgbValuePosition = 0;
+ if (srgbRequested) {
+ srgbValuePosition = i;
+ iAttributes[i++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT;
+ iAttributes[i++] = TRUE;
+ }
+ // If sample or sRGB request cannot be satisfied, reduce request.
int pixelFormat = 0;
uint numFormats = 0;
while (true) {
@@ -578,20 +590,25 @@ static int choosePixelFormat(HDC hdc,
staticContext.wglChoosePixelFormatARB(hdc, iAttributes, 0, 1,
&pixelFormat, &numFormats)
&& numFormats >= 1;
- if (valid || !sampleBuffersRequested)
- break;
- if (iAttributes[samplesValuePosition] > 1) {
- iAttributes[samplesValuePosition] /= 2;
- } else if (iAttributes[samplesValuePosition] == 1) {
- // Fallback in case it is unable to initialize with any
- // samples to avoid falling back to the GDI path
- // NB: The sample attributes needs to be at the end for this
- // to work correctly
- iAttributes[samplesValuePosition - 1] = FALSE;
- iAttributes[samplesValuePosition] = 0;
- iAttributes[samplesValuePosition + 1] = 0;
- } else {
+ if (valid || (!sampleBuffersRequested && !srgbRequested))
break;
+ if (srgbRequested) {
+ iAttributes[srgbValuePosition] = 0;
+ srgbRequested = false;
+ } else if (sampleBuffersRequested) {
+ if (iAttributes[samplesValuePosition] > 1) {
+ iAttributes[samplesValuePosition] /= 2;
+ } else if (iAttributes[samplesValuePosition] == 1) {
+ // Fallback in case it is unable to initialize with any
+ // samples to avoid falling back to the GDI path
+ // NB: The sample attributes needs to be at the end for this
+ // to work correctly
+ iAttributes[samplesValuePosition - 1] = FALSE;
+ iAttributes[samplesValuePosition] = 0;
+ iAttributes[samplesValuePosition + 1] = 0;
+ } else {
+ break;
+ }
}
}
// Verify if format is acceptable. Note that the returned
@@ -628,7 +645,7 @@ static QSurfaceFormat
HDC hdc, int pixelFormat,
QWindowsOpenGLAdditionalFormat *additionalIn = 0)
{
- enum { attribSize =40 };
+ enum { attribSize = 42 };
QSurfaceFormat result;
result.setRenderableType(QSurfaceFormat::OpenGL);
@@ -641,6 +658,7 @@ static QSurfaceFormat
int i = 0;
const bool hasSampleBuffers = testFlag(staticContext.extensions, QOpenGLStaticContext::SampleBuffers);
+ const bool hasSrgbSupport = testFlag(staticContext.extensions, QOpenGLStaticContext::sRGBCapableFramebuffer);
iAttributes[i++] = WGL_DOUBLE_BUFFER_ARB; // 0
iAttributes[i++] = WGL_DEPTH_BITS_ARB; // 1
@@ -658,6 +676,9 @@ static QSurfaceFormat
iAttributes[i++] = WGL_SAMPLE_BUFFERS_ARB; // 12
iAttributes[i++] = WGL_SAMPLES_ARB; // 13
}
+ if (hasSrgbSupport)
+ iAttributes[i++] = WGL_FRAMEBUFFER_SRGB_CAPABLE_EXT; // 12 or 14
+
if (!staticContext.wglGetPixelFormatAttribIVARB(hdc, pixelFormat, 0, i,
iAttributes, iValues)) {
qErrnoWarning("%s: wglGetPixelFormatAttribIVARB() failed for basic parameters.", __FUNCTION__);
@@ -673,8 +694,14 @@ static QSurfaceFormat
if (iValues[9])
result.setOption(QSurfaceFormat::StereoBuffers);
- if (hasSampleBuffers)
+ if (hasSampleBuffers) {
result.setSamples(iValues[13]);
+ if (hasSrgbSupport && iValues[14])
+ result.setColorSpace(QSurfaceFormat::sRGBColorSpace);
+ } else {
+ if (hasSrgbSupport && iValues[12])
+ result.setColorSpace(QSurfaceFormat::sRGBColorSpace);
+ }
if (additionalIn) {
if (iValues[7])
additionalIn->formatFlags |= QWindowsGLAccumBuffer;
@@ -947,7 +974,8 @@ QOpenGLStaticContext::QOpenGLStaticContext() :
wglChoosePixelFormatARB((WglChoosePixelFormatARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglChoosePixelFormatARB")),
wglCreateContextAttribsARB((WglCreateContextAttribsARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglCreateContextAttribsARB")),
wglSwapInternalExt((WglSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglSwapIntervalEXT")),
- wglGetSwapInternalExt((WglGetSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetSwapIntervalEXT"))
+ wglGetSwapInternalExt((WglGetSwapInternalExt)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetSwapIntervalEXT")),
+ wglGetExtensionsStringARB((WglGetExtensionsStringARB)QOpenGLStaticContext::opengl32.wglGetProcAddress("wglGetExtensionsStringARB"))
{
if (extensionNames.startsWith(SAMPLE_BUFFER_EXTENSION " ")
|| extensionNames.indexOf(" " SAMPLE_BUFFER_EXTENSION " ") != -1)
@@ -1091,6 +1119,14 @@ QWindowsGLContext::QWindowsGLContext(QOpenGLStaticContext *staticContext,
&& !(QWindowsIntegration::instance()->options() & QWindowsIntegration::DisableArb);
QWindowsOpenGLAdditionalFormat obtainedAdditional;
if (tryExtensions) {
+ if (m_staticContext->wglGetExtensionsStringARB) {
+ const char *exts = m_staticContext->wglGetExtensionsStringARB(hdc);
+ if (exts) {
+ qCDebug(lcQpaGl) << __FUNCTION__ << "WGL extensions:" << exts;
+ if (strstr(exts, "WGL_EXT_framebuffer_sRGB"))
+ m_staticContext->extensions |= QOpenGLStaticContext::sRGBCapableFramebuffer;
+ }
+ }
m_pixelFormat =
ARB::choosePixelFormat(hdc, *m_staticContext, format,
requestedAdditional, &m_obtainedPixelFormatDescriptor);
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.h b/src/plugins/platforms/windows/qwindowsglcontext.h
index dfaa428520..2d5b94af0e 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.h
+++ b/src/plugins/platforms/windows/qwindowsglcontext.h
@@ -139,7 +139,8 @@ class QOpenGLStaticContext : public QWindowsStaticOpenGLContext
public:
enum Extensions
{
- SampleBuffers = 0x1
+ SampleBuffers = 0x1,
+ sRGBCapableFramebuffer = 0x2
};
typedef bool
@@ -160,6 +161,9 @@ public:
typedef int
(APIENTRY *WglGetSwapInternalExt)(void);
+ typedef const char *
+ (APIENTRY *WglGetExtensionsStringARB)(HDC);
+
bool hasExtensions() const
{ return wglGetPixelFormatAttribIVARB && wglChoosePixelFormatARB && wglCreateContextAttribsARB; }
@@ -185,6 +189,7 @@ public:
WglCreateContextAttribsARB wglCreateContextAttribsARB;
WglSwapInternalExt wglSwapInternalExt;
WglGetSwapInternalExt wglGetSwapInternalExt;
+ WglGetExtensionsStringARB wglGetExtensionsStringARB;
static QWindowsOpengl32DLL opengl32;
};
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index 17cab69891..f9bac3920b 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -42,6 +42,7 @@
#include "qwindowswindow.h"
#include "qwindowscontext.h"
#include "qwin10helpers.h"
+#include "qwindowsmenu.h"
#include "qwindowsopenglcontext.h"
#include "qwindowsscreen.h"
@@ -71,6 +72,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/qpa/qplatforminputcontextfactory_p.h>
+#include <QtGui/qpa/qplatformcursor.h>
#include <QtEventDispatcherSupport/private/qwindowsguieventdispatcher_p.h>
@@ -206,6 +208,10 @@ static inline unsigned parseOptions(const QStringList &paramList,
} else if (parseIntOption(param, QLatin1String("verbose"), 0, INT_MAX, &QWindowsContext::verbose)
|| parseIntOption(param, QLatin1String("tabletabsoluterange"), 0, INT_MAX, tabletAbsoluteRange)
|| parseIntOption(param, QLatin1String("dpiawareness"), QtWindows::ProcessDpiUnaware, QtWindows::ProcessPerMonitorDpiAware, dpiAwareness)) {
+ } else if (param == QLatin1String("menus=native")) {
+ options |= QWindowsIntegration::AlwaysUseNativeMenus;
+ } else if (param == QLatin1String("menus=none")) {
+ options |= QWindowsIntegration::NoNativeMenus;
} else {
qWarning() << "Unknown option" << param;
}
@@ -237,6 +243,7 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList &paramL
}
m_context.initTouch(m_options);
+ QPlatformCursor::setCapability(QPlatformCursor::OverrideCursor);
}
QWindowsIntegrationPrivate::~QWindowsIntegrationPrivate()
@@ -334,20 +341,8 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
QWindowsWindow *result = createPlatformWindowHelper(window, obtained);
Q_ASSERT(result);
- if (requested.flags != obtained.flags)
- window->setFlags(obtained.flags);
- // Trigger geometry change (unless it has a special state in which case setWindowState()
- // will send the message) and screen change signals of QWindow.
- if ((obtained.flags & Qt::Desktop) != Qt::Desktop) {
- const Qt::WindowState state = window->windowState();
- if (state != Qt::WindowMaximized && state != Qt::WindowFullScreen
- && requested.geometry != obtained.geometry) {
- QWindowSystemInterface::handleGeometryChange(window, obtained.geometry);
- }
- QPlatformScreen *screen = result->screenForGeometry(obtained.geometry);
- if (screen && result->screen() != screen)
- QWindowSystemInterface::handleWindowScreenChanged(window, screen->screen());
- }
+ if (QWindowsMenuBar *menuBarToBeInstalled = QWindowsMenuBar::menuBarOf(window))
+ menuBarToBeInstalled->install(result);
return result;
}
@@ -611,4 +606,11 @@ void QWindowsIntegration::beep() const
MessageBeep(MB_OK); // For QApplication
}
+#if QT_CONFIG(vulkan)
+QPlatformVulkanInstance *QWindowsIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
+{
+ return new QWindowsVulkanInstance(instance);
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index 28d4fd3026..23f3d9ef4e 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -64,7 +64,9 @@ public:
DontPassOsMouseEventsSynthesizedFromTouch = 0x20, // Do not pass OS-generated mouse events from touch.
// Keep in sync with QWindowsFontDatabase::FontOptions
DontUseDirectWriteFonts = QWindowsFontDatabase::DontUseDirectWriteFonts,
- DontUseColorFonts = QWindowsFontDatabase::DontUseColorFonts
+ DontUseColorFonts = QWindowsFontDatabase::DontUseColorFonts,
+ AlwaysUseNativeMenus = 0x100,
+ NoNativeMenus = 0x200
};
explicit QWindowsIntegration(const QStringList &paramList);
@@ -113,6 +115,10 @@ public:
QPlatformSessionManager *createPlatformSessionManager(const QString &id, const QString &key) const override;
#endif
+#if QT_CONFIG(vulkan)
+ QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override;
+#endif
+
protected:
virtual QWindowsWindow *createPlatformWindowHelper(QWindow *window, const QWindowsWindowData &) const;
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 3987d8ca29..af62936a18 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -903,6 +903,12 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, const MSG &ms
return true;
}
+ // Enable Alt accelerators ("&File") on menus
+ if (msgType == WM_SYSKEYDOWN && (nModifiers & AltAny) != 0 && GetMenu(msg.hwnd) != nullptr)
+ return false;
+ if (msgType == WM_SYSKEYUP && nModifiers == 0 && GetMenu(msg.hwnd) != nullptr)
+ return false;
+
bool result = false;
// handle Directionality changes (BiDi) with RTL extensions
if (m_useRTLExtensions) {
diff --git a/src/plugins/platforms/windows/qwindowsmenu.cpp b/src/plugins/platforms/windows/qwindowsmenu.cpp
new file mode 100644
index 0000000000..4e1997c4f8
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsmenu.cpp
@@ -0,0 +1,962 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowsmenu.h"
+#include "qwindowscontext.h"
+#include "qwindowswindow.h"
+
+#include <QtGui/qwindow.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qpointer.h>
+
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWindowsMenuBar
+ \brief Windows native menu bar
+
+ \list
+ \li \l{https://msdn.microsoft.com/de-de/library/windows/desktop/ms647553(v=vs.85).aspx#_win32_Menu_Creation_Functions},
+ \e{About Menus}
+ \endlist
+
+ \note The destruction order of the QWindowsMenu/Item/Bar instances is
+ arbitrary depending on whether the application is Qt Quick or
+ Qt Widgets, either the containers or the items might be deleted first.
+
+ \internal
+ \ingroup qt-lighthouse-win
+*/
+
+static uint nextId = 1;
+
+// Find a QPlatformMenu[Item]* in a vector of QWindowsMenu[Item], where
+// QVector::indexOf() cannot be used since it wants a QWindowsMenu[Item]*
+template <class Derived, class Needle>
+static int indexOf(const QVector<Derived *> &v, const Needle *needle)
+{
+ for (int i = 0, size = v.size(); i < size; ++i) {
+ if (v.at(i) == needle)
+ return i;
+ }
+ return -1;
+}
+
+// Helper for inserting a QPlatformMenu[Item]* into a vector of QWindowsMenu[Item].
+template <class Derived, class Base>
+static int insertBefore(QVector<Derived *> *v, Base *newItemIn, const Base *before = nullptr)
+{
+ int index = before ? indexOf(*v, before) : -1;
+ if (index != -1) {
+ v->insert(index, static_cast<Derived *>(newItemIn));
+ } else {
+ index = v->size();
+ v->append(static_cast<Derived *>(newItemIn));
+ }
+ return index;
+}
+
+static inline const wchar_t *qStringToWChar(const QString &s)
+{
+ return reinterpret_cast<const wchar_t *>(s.utf16());
+}
+
+// Traverse menu and return the item for which predicate
+// "bool Function(QWindowsMenuItem *)" returns true
+template <class Predicate>
+static QWindowsMenuItem *traverseMenuItems(const QWindowsMenu *menu, Predicate p)
+{
+ const QWindowsMenu::MenuItems &items = menu->menuItems();
+ for (QWindowsMenuItem *item : items) {
+ if (p(item))
+ return item;
+ if (item->subMenu()) {
+ if (QWindowsMenuItem *subMenuItem = traverseMenuItems(item->subMenu(), p))
+ return subMenuItem;
+ }
+ }
+ return nullptr;
+}
+
+// Traverse menu bar return the item for which predicate
+// "bool Function(QWindowsMenuItem *)" returns true
+template <class Predicate>
+static QWindowsMenuItem *traverseMenuItems(const QWindowsMenuBar *menuBar, Predicate p)
+{
+ const QWindowsMenuBar::Menus &menus = menuBar->menus();
+ for (QWindowsMenu *menu : menus) {
+ if (QWindowsMenuItem *item = traverseMenuItems(menu, p))
+ return item;
+ }
+ return nullptr;
+}
+
+template <class Menu /* Menu[Bar] */>
+static QWindowsMenuItem *findMenuItemById(const Menu *menu, uint id)
+{
+ return traverseMenuItems(menu, [id] (const QWindowsMenuItem *i) { return i->id() == id; });
+}
+
+// Traverse menu and return the menu for which predicate
+// "bool Function(QWindowsMenu *)" returns true
+template <class Predicate>
+static QWindowsMenu *traverseMenus(const QWindowsMenu *menu, Predicate p)
+{
+ const QWindowsMenu::MenuItems &items = menu->menuItems();
+ for (QWindowsMenuItem *item : items) {
+ if (QWindowsMenu *subMenu = item->subMenu()) {
+ if (p(subMenu))
+ return subMenu;
+ if (QWindowsMenu *menu = traverseMenus(subMenu, p))
+ return menu;
+ }
+ }
+ return nullptr;
+}
+
+// Traverse menu bar return the item for which
+// function "bool Function(QWindowsMenu *)" returns true
+template <class Predicate>
+static QWindowsMenu *traverseMenus(const QWindowsMenuBar *menuBar, Predicate p)
+{
+ const QWindowsMenuBar::Menus &menus = menuBar->menus();
+ for (QWindowsMenu *menu : menus) {
+ if (p(menu))
+ return menu;
+ if (QWindowsMenu *subMenu = traverseMenus(menu, p))
+ return subMenu;
+ }
+ return nullptr;
+}
+
+template <class Menu /* Menu[Bar] */>
+static QWindowsMenu *findMenuByHandle(const Menu *menu, HMENU hMenu)
+{
+ return traverseMenus(menu, [hMenu] (const QWindowsMenu *i) { return i->menuHandle() == hMenu; });
+}
+
+template <class MenuType>
+static int findNextVisibleEntry(const QVector<MenuType *> &entries, int pos)
+{
+ for (int i = pos, size = entries.size(); i < size; ++i) {
+ if (entries.at(i)->isVisible())
+ return i;
+ }
+ return -1;
+}
+
+static inline void menuItemInfoInit(MENUITEMINFO &menuItemInfo)
+{
+ memset(&menuItemInfo, 0, sizeof(MENUITEMINFO));
+ menuItemInfo.cbSize = sizeof(MENUITEMINFO);
+}
+
+static inline void menuItemInfoSetText(MENUITEMINFO &menuItemInfo, const QString &text)
+{
+ menuItemInfoInit(menuItemInfo);
+ menuItemInfo.fMask = MIIM_STRING;
+ menuItemInfo.dwTypeData = const_cast<wchar_t *>(qStringToWChar(text));
+ menuItemInfo.cch = UINT(text.size());
+}
+
+static UINT menuItemState(HMENU hMenu, UINT uItem, BOOL fByPosition)
+{
+ MENUITEMINFO menuItemInfo;
+ menuItemInfoInit(menuItemInfo);
+ menuItemInfo.fMask = MIIM_STATE;
+ return GetMenuItemInfo(hMenu, uItem, fByPosition, &menuItemInfo) == TRUE ? menuItemInfo.fState : 0;
+}
+
+static void menuItemSetState(HMENU hMenu, UINT uItem, BOOL fByPosition, UINT flags)
+{
+ MENUITEMINFO menuItemInfo;
+ menuItemInfoInit(menuItemInfo);
+ menuItemInfo.fMask = MIIM_STATE;
+ menuItemInfo.fState = flags;
+ SetMenuItemInfo(hMenu, uItem, fByPosition, &menuItemInfo);
+}
+
+static void menuItemSetChangeState(HMENU hMenu, UINT uItem, BOOL fByPosition,
+ bool value, UINT trueState, UINT falseState)
+{
+ const UINT oldState = menuItemState(hMenu, uItem, fByPosition);
+ UINT newState = oldState;
+ if (value) {
+ newState |= trueState;
+ newState &= ~falseState;
+ } else {
+ newState &= ~trueState;
+ newState |= falseState;
+ }
+ if (oldState != newState)
+ menuItemSetState(hMenu, uItem, fByPosition, newState);
+}
+
+// ------------ QWindowsMenuItem
+QWindowsMenuItem::QWindowsMenuItem(QWindowsMenu *parentMenu)
+ : m_parentMenu(parentMenu)
+ , m_id(0)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << static_cast<const void *>(this)
+ << "parentMenu=" << parentMenu;
+}
+
+QWindowsMenuItem::~QWindowsMenuItem()
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << static_cast<const void *>(this);
+ removeFromMenu();
+ freeBitmap();
+}
+
+void QWindowsMenuItem::freeBitmap()
+{
+ if (m_hbitmap) {
+ DeleteObject(m_hbitmap);
+ m_hbitmap = nullptr;
+ }
+}
+
+void QWindowsMenuItem::setIcon(const QIcon &icon)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << icon << ')' << this;
+ if (m_icon.cacheKey() == icon.cacheKey())
+ return;
+ m_icon = icon;
+ if (m_parentMenu != nullptr)
+ updateBitmap();
+}
+
+Q_GUI_EXPORT HBITMAP qt_pixmapToWinHBITMAP(const QPixmap &p, int hbitmapFormat = 0);
+
+void QWindowsMenuItem::updateBitmap()
+{
+ freeBitmap();
+ if (!m_icon.isNull()) {
+ const int size = m_iconSize ? m_iconSize : GetSystemMetrics(SM_CYMENUCHECK);
+ m_hbitmap = qt_pixmapToWinHBITMAP(m_icon.pixmap(QSize(size, size)), 1);
+ }
+ MENUITEMINFO itemInfo;
+ menuItemInfoInit(itemInfo);
+ itemInfo.fMask = MIIM_BITMAP;
+ itemInfo.hbmpItem = m_hbitmap;
+ SetMenuItemInfo(parentMenuHandle(), m_id, FALSE, &itemInfo);
+}
+
+void QWindowsMenuItem::setText(const QString &text)
+{
+ qCDebug(lcQpaMenus).nospace().noquote()
+ << __FUNCTION__ << "(\"" << text << "\") " << this;
+ if (m_text == text)
+ return;
+ m_text = text;
+ if (m_parentMenu != nullptr)
+ updateText();
+}
+
+void QWindowsMenuItem::updateText()
+{
+ MENUITEMINFO menuItemInfo;
+ const QString &text = nativeText();
+ menuItemInfoSetText(menuItemInfo, text);
+ SetMenuItemInfo(parentMenuHandle(), m_id, FALSE, &menuItemInfo);
+}
+
+void QWindowsMenuItem::setMenu(QPlatformMenu *menuIn)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << menuIn << ')' << this;
+ if (menuIn == m_subMenu)
+ return;
+ const uint oldId = m_id;
+ if (menuIn != nullptr) { // Set submenu
+ m_subMenu = static_cast<QWindowsMenu *>(menuIn);
+ m_subMenu->setAsItemSubMenu(this);
+ m_id = m_subMenu->id();
+ if (m_parentMenu != nullptr) {
+ ModifyMenu(m_parentMenu->menuHandle(), oldId, MF_BYCOMMAND | MF_POPUP,
+ m_id, qStringToWChar(m_text));
+ }
+ return;
+ }
+ // Clear submenu
+ m_subMenu = nullptr;
+ if (m_parentMenu != nullptr) {
+ m_id = nextId++;
+ ModifyMenu(m_parentMenu->menuHandle(), oldId, MF_BYCOMMAND,
+ m_id, qStringToWChar(m_text));
+ } else {
+ m_id = 0;
+ }
+}
+
+void QWindowsMenuItem::setVisible(bool isVisible)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << isVisible << ')' << this;
+ if (m_visible == isVisible)
+ return;
+ m_visible = isVisible;
+ if (m_parentMenu == nullptr)
+ return;
+ // Windows menu items do not implement settable visibility, we need to work
+ // around by removing the item from the menu. It will be kept in the list.
+ if (isVisible)
+ insertIntoMenuHelper(m_parentMenu, false, m_parentMenu->menuItems().indexOf(this));
+ else
+ RemoveMenu(parentMenuHandle(), m_id, MF_BYCOMMAND);
+}
+
+void QWindowsMenuItem::setIsSeparator(bool isSeparator)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << isSeparator << ')' << this;
+ if (m_separator == isSeparator)
+ return;
+ m_separator = isSeparator;
+}
+
+void QWindowsMenuItem::setCheckable(bool checkable)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << checkable << ')' << this;
+ if (m_checkable == checkable)
+ return;
+ m_checkable = checkable;
+ if (m_parentMenu == nullptr)
+ return;
+ UINT state = menuItemState(parentMenuHandle(), m_id, FALSE);
+ if (m_checkable)
+ state |= m_checked ? MF_CHECKED : MF_UNCHECKED;
+ else
+ state &= ~(MF_CHECKED | MF_UNCHECKED);
+ menuItemSetState(parentMenuHandle(), m_id, FALSE, state);
+}
+
+void QWindowsMenuItem::setChecked(bool isChecked)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << isChecked << ')' << this;
+ if (m_checked == isChecked)
+ return;
+ m_checked = isChecked;
+ // Convenience: Allow to set checkable by calling setChecked(true) for
+ // Quick Controls 1
+ if (isChecked)
+ m_checkable = true;
+ if (m_parentMenu == nullptr || !m_checkable)
+ return;
+ menuItemSetChangeState(parentMenuHandle(), m_id, FALSE, m_checked, MF_CHECKED, MF_UNCHECKED);
+}
+
+void QWindowsMenuItem::setShortcut(const QKeySequence &shortcut)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << shortcut << ')' << this;
+ if (m_shortcut == shortcut)
+ return;
+ m_shortcut = shortcut;
+ if (m_parentMenu != nullptr)
+ updateText();
+}
+
+void QWindowsMenuItem::setEnabled(bool enabled)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << enabled << ')' << this;
+ if (m_enabled == enabled)
+ return;
+ m_enabled = enabled;
+ if (m_parentMenu != nullptr)
+ menuItemSetChangeState(parentMenuHandle(), m_id, FALSE, m_enabled, MF_ENABLED, MF_GRAYED);
+}
+
+void QWindowsMenuItem::setIconSize(int size)
+{
+ if (m_iconSize == size)
+ return;
+ m_iconSize = size;
+ if (m_parentMenu != nullptr)
+ updateBitmap();
+}
+
+HMENU QWindowsMenuItem::parentMenuHandle() const
+{
+ return m_parentMenu ? m_parentMenu->menuHandle() : nullptr;
+}
+
+UINT QWindowsMenuItem::state() const
+{
+ if (m_separator)
+ return MF_SEPARATOR;
+ UINT result = MF_STRING | (m_enabled ? MF_ENABLED : MF_GRAYED);
+ if (m_subMenu != nullptr)
+ result |= MF_POPUP;
+ if (m_checkable)
+ result |= m_checked ? MF_CHECKED : MF_UNCHECKED;
+ if (QGuiApplication::layoutDirection() == Qt::RightToLeft)
+ result |= MFT_RIGHTORDER;
+ return result;
+}
+
+QString QWindowsMenuItem::nativeText() const
+{
+ QString result = m_text;
+ if (!m_shortcut.isEmpty()) {
+ result += QLatin1Char('\t');
+ result += m_shortcut.toString(QKeySequence::NativeText);
+ }
+ return result;
+}
+
+void QWindowsMenuItem::insertIntoMenu(QWindowsMenu *menu, bool append, int index)
+{
+ if (m_id == 0 && m_subMenu == nullptr)
+ m_id = nextId++;
+ insertIntoMenuHelper(menu, append, index);
+ m_parentMenu = menu;
+}
+
+void QWindowsMenuItem::insertIntoMenuHelper(QWindowsMenu *menu, bool append, int index)
+{
+ const QString &text = nativeText();
+
+ UINT_PTR idBefore = 0;
+ if (!append) {
+ // Skip over self (either newly inserted or when called from setVisible()
+ const int nextIndex = findNextVisibleEntry(menu->menuItems(), index + 1);
+ if (nextIndex != -1)
+ idBefore = menu->menuItems().at(nextIndex)->id();
+ }
+
+ if (idBefore)
+ InsertMenu(menu->menuHandle(), idBefore, state(), m_id, qStringToWChar(text));
+ else
+ AppendMenu(menu->menuHandle(), state(), m_id, qStringToWChar(text));
+
+ updateBitmap();
+}
+
+bool QWindowsMenuItem::removeFromMenu()
+{
+ if (QWindowsMenu *parentMenu = m_parentMenu) {
+ m_parentMenu = nullptr;
+ RemoveMenu(parentMenu->menuHandle(), m_id, MF_BYCOMMAND);
+ parentMenu->notifyRemoved(this);
+ return true;
+ }
+ return false;
+}
+
+// ------------ QWindowsMenu
+
+QWindowsMenu::QWindowsMenu() : QWindowsMenu(nullptr, CreateMenu())
+{
+}
+
+QWindowsMenu::QWindowsMenu(QWindowsMenu *parentMenu, HMENU menu)
+ : m_parentMenu(parentMenu)
+ , m_hMenu(menu)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << static_cast<const void *>(this)
+ << "parentMenu=" << parentMenu << "HMENU=" << m_hMenu;
+}
+
+QWindowsMenu::~QWindowsMenu()
+{
+ qCDebug(lcQpaMenus).noquote().nospace() << __FUNCTION__
+ << " \"" <<m_text << "\", " << static_cast<const void *>(this);
+ for (int i = m_menuItems.size() - 1; i>= 0; --i)
+ m_menuItems.at(i)->removeFromMenu();
+ removeFromParent();
+ DestroyMenu(m_hMenu);
+}
+
+void QWindowsMenu::insertMenuItem(QPlatformMenuItem *menuItemIn, QPlatformMenuItem *before)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << menuItemIn << ", before=" << before << ')' << this;
+ QWindowsMenuItem *menuItem = static_cast<QWindowsMenuItem *>(menuItemIn);
+ const int index = insertBefore(&m_menuItems, menuItemIn, before);
+ const bool append = index == m_menuItems.size() - 1;
+ menuItem->insertIntoMenu(this, append, index);
+}
+
+void QWindowsMenu::removeMenuItem(QPlatformMenuItem *menuItemIn)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << menuItemIn << ')' << this;
+ static_cast<QWindowsMenuItem *>(menuItemIn)->removeFromMenu();
+}
+
+void QWindowsMenu::setText(const QString &text)
+{
+ qCDebug(lcQpaMenus).nospace().noquote()
+ << __FUNCTION__ << "(\"" << text << "\") " << this;
+ if (m_text == text)
+ return;
+ m_text = text;
+ if (!m_visible)
+ return;
+ const HMENU ph = parentHandle();
+ if (ph == nullptr)
+ return;
+ MENUITEMINFO menuItemInfo;
+ menuItemInfoSetText(menuItemInfo, m_text);
+ SetMenuItemInfo(ph, id(), FALSE, &menuItemInfo);
+}
+
+void QWindowsMenu::setIcon(const QIcon &icon)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << icon << ')' << this;
+ m_icon = icon;
+}
+
+void QWindowsMenu::setEnabled(bool enabled)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << enabled << ')' << this;
+ if (m_enabled == enabled)
+ return;
+ m_enabled = enabled;
+ if (!m_visible)
+ return;
+ if (const HMENU ph = parentHandle())
+ menuItemSetChangeState(ph, id(), FALSE, m_enabled, MF_ENABLED, MF_GRAYED);
+}
+
+QWindowsMenuItem *QWindowsMenu::itemForSubMenu(const QWindowsMenu *subMenu) const
+{
+ const auto it = std::find_if(m_menuItems.cbegin(), m_menuItems.cend(),
+ [subMenu] (const QWindowsMenuItem *i) { return i->subMenu() == subMenu; });
+ return it != m_menuItems.cend() ? *it : nullptr;
+}
+
+void QWindowsMenu::insertIntoMenuBar(QWindowsMenuBar *bar, bool append, int index)
+{
+ UINT_PTR idBefore = 0;
+ if (!append) {
+ // Skip over self (either newly inserted or when called from setVisible()
+ const int nextIndex = findNextVisibleEntry(bar->menus(), index + 1);
+ if (nextIndex != -1)
+ idBefore = bar->menus().at(nextIndex)->id();
+ }
+ m_parentMenuBar = bar;
+ m_parentMenu = nullptr;
+ if (idBefore)
+ InsertMenu(bar->menuBarHandle(), idBefore, MF_POPUP | MF_BYCOMMAND, id(), qStringToWChar(m_text));
+ else
+ AppendMenu(bar->menuBarHandle(), MF_POPUP, id(), qStringToWChar(m_text));
+}
+
+bool QWindowsMenu::removeFromParent()
+{
+ if (QWindowsMenuBar *bar = m_parentMenuBar) {
+ m_parentMenuBar = nullptr;
+ bar->notifyRemoved(this);
+ return RemoveMenu(bar->menuBarHandle(), id(), MF_BYCOMMAND) == TRUE;
+ }
+ if (QWindowsMenu *menu = m_parentMenu) {
+ m_parentMenu = nullptr;
+ QWindowsMenuItem *item = menu->itemForSubMenu(this);
+ if (item)
+ item->setMenu(nullptr);
+ return item != nullptr;
+ }
+ return false;
+}
+
+void QWindowsMenu::setVisible(bool visible)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << visible << ')' << this;
+ if (m_visible == visible)
+ return;
+ m_visible = visible;
+ const HMENU ph = parentHandle();
+ if (ph == nullptr)
+ return;
+ // Windows menus do not implement settable visibility, we need to work
+ // around by removing the menu from the parent. It will be kept in the list.
+ if (visible) {
+ if (m_parentMenuBar)
+ insertIntoMenuBar(m_parentMenuBar, false, m_parentMenuBar->menus().indexOf(this));
+ } else {
+ RemoveMenu(ph, id(), MF_BYCOMMAND);
+ }
+ if (m_parentMenuBar)
+ m_parentMenuBar->redraw();
+}
+
+QPlatformMenuItem *QWindowsMenu::menuItemAt(int position) const
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << position;
+ return position >= 0 && position < m_menuItems.size()
+ ? m_menuItems.at(position) : nullptr;
+}
+
+QPlatformMenuItem *QWindowsMenu::menuItemForTag(quintptr tag) const
+{
+ return traverseMenuItems(this, [tag] (const QPlatformMenuItem *i) { return i->tag() == tag; });
+}
+
+QPlatformMenuItem *QWindowsMenu::createMenuItem() const
+{
+ QPlatformMenuItem *result = new QWindowsMenuItem;
+ qCDebug(lcQpaMenus) << __FUNCTION__ << this << "returns" << result;
+ return result;
+}
+
+QPlatformMenu *QWindowsMenu::createSubMenu() const
+{
+ QPlatformMenu *result = new QWindowsMenu;
+ qCDebug(lcQpaMenus) << __FUNCTION__ << this << "returns" << result;
+ return result;
+}
+
+void QWindowsMenu::setAsItemSubMenu(QWindowsMenuItem *item)
+{
+ m_parentMenu = item->parentMenu();
+}
+
+HMENU QWindowsMenu::parentMenuHandle() const
+{
+ return m_parentMenu ? m_parentMenu->menuHandle() : nullptr;
+}
+
+HMENU QWindowsMenu::parentMenuBarHandle() const
+{
+ return m_parentMenuBar ? m_parentMenuBar->menuBarHandle() : nullptr;
+}
+
+HMENU QWindowsMenu::parentHandle() const
+{
+ if (m_parentMenuBar)
+ return m_parentMenuBar->menuBarHandle();
+ if (m_parentMenu)
+ return m_parentMenu->menuHandle();
+ return nullptr;
+}
+
+// --------------- QWindowsPopupMenu
+
+static QPointer<QWindowsPopupMenu> lastShownPopupMenu;
+
+QWindowsPopupMenu::QWindowsPopupMenu() : QWindowsMenu(nullptr, CreatePopupMenu())
+{
+}
+
+void QWindowsPopupMenu::showPopup(const QWindow *parentWindow, const QRect &targetRect,
+ const QPlatformMenuItem *item)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '>' << this << parentWindow << targetRect << item;
+ const QWindowsBaseWindow *window = static_cast<const QWindowsBaseWindow *>(parentWindow->handle());
+ const QPoint globalPos = window->mapToGlobal(targetRect.topLeft());
+ trackPopupMenu(window->handle(), globalPos.x(), globalPos.y());
+}
+
+bool QWindowsPopupMenu::trackPopupMenu(HWND windowHandle, int x, int y)
+{
+ lastShownPopupMenu = this;
+ return TrackPopupMenu(menuHandle(),
+ QGuiApplication::layoutDirection() == Qt::RightToLeft ? UINT(TPM_RIGHTALIGN) : UINT(0),
+ x, y, 0, windowHandle, nullptr) == TRUE;
+}
+
+bool QWindowsPopupMenu::notifyTriggered(uint id)
+{
+ QPlatformMenuItem *result = lastShownPopupMenu.isNull()
+ ? nullptr
+ : findMenuItemById(lastShownPopupMenu.data(), id);
+ if (result != nullptr) {
+ qCDebug(lcQpaMenus) << __FUNCTION__ << "id=" << id;
+ emit result->activated();
+ }
+ lastShownPopupMenu = nullptr;
+ return result != nullptr;
+}
+
+bool QWindowsPopupMenu::notifyAboutToShow(HMENU hmenu)
+{
+ if (lastShownPopupMenu.isNull())
+ return false;
+ if (lastShownPopupMenu->menuHandle() == hmenu) {
+ emit lastShownPopupMenu->aboutToShow();
+ return true;
+ }
+ if (QWindowsMenu *menu = findMenuByHandle(lastShownPopupMenu.data(), hmenu)) {
+ emit menu->aboutToShow();
+ return true;
+ }
+ return false;
+}
+
+// --------------- QWindowsMenuBar
+
+QWindowsMenuBar::QWindowsMenuBar() : m_hMenuBar(CreateMenu())
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << static_cast<const void *>(this);
+}
+
+QWindowsMenuBar::~QWindowsMenuBar()
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << static_cast<const void *>(this);
+ for (int m = m_menus.size() - 1; m >= 0; --m)
+ m_menus.at(m)->removeFromParent();
+ removeFromWindow();
+ DestroyMenu(m_hMenuBar);
+}
+
+void QWindowsMenuBar::insertMenu(QPlatformMenu *menuIn, QPlatformMenu *before)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << menuIn << "before=" << before;
+ QWindowsMenu *menu = static_cast<QWindowsMenu *>(menuIn);
+ const int index = insertBefore(&m_menus, menuIn, before);
+ menu->insertIntoMenuBar(this, index == m_menus.size() - 1, index);
+}
+
+void QWindowsMenuBar::removeMenu(QPlatformMenu *menu)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << menu << ')' << this;
+ const int index = indexOf(m_menus, menu);
+ if (index != -1)
+ m_menus[index]->removeFromParent();
+}
+
+// When calling handleReparent() for a QWindow instances that does not have
+// a platform window yet, set the menubar as dynamic property to be installed
+// on platform window creation.
+static const char menuBarPropertyName[] = "_q_windowsNativeMenuBar";
+
+void QWindowsMenuBar::handleReparent(QWindow *newParentWindow)
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__ << '(' << newParentWindow << ')' << this;
+ if (newParentWindow == nullptr) {
+ removeFromWindow();
+ return; // Happens during Quick Controls 1 property setup
+ }
+ if (QPlatformWindow *platWin = newParentWindow->handle())
+ install(static_cast<QWindowsWindow *>(platWin));
+ else // Store for later creation, see menuBarOf()
+ newParentWindow->setProperty(menuBarPropertyName, qVariantFromValue<QObject *>(this));
+}
+
+QWindowsMenuBar *QWindowsMenuBar::menuBarOf(const QWindow *notYetCreatedWindow)
+{
+ const QVariant menuBarV = notYetCreatedWindow->property(menuBarPropertyName);
+ return menuBarV.canConvert<QObject *>()
+ ? qobject_cast<QWindowsMenuBar *>(menuBarV.value<QObject *>()) : nullptr;
+}
+
+static inline void forceNcCalcSize(HWND hwnd)
+{
+ // Force WM_NCCALCSIZE to adjust margin: Does not appear to work?
+ SetWindowPos(hwnd, 0, 0, 0, 0, 0,
+ SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
+}
+
+void QWindowsMenuBar::install(QWindowsWindow *window)
+{
+ const HWND hwnd = window->handle();
+ const BOOL result = SetMenu(hwnd, m_hMenuBar);
+ if (result) {
+ window->setMenuBar(this);
+ forceNcCalcSize(hwnd);
+ }
+}
+
+void QWindowsMenuBar::removeFromWindow()
+{
+ if (QWindowsWindow *window = platformWindow()) {
+ const HWND hwnd = window->handle();
+ SetMenu(hwnd, nullptr);
+ window->setMenuBar(nullptr);
+ forceNcCalcSize(hwnd);
+ }
+}
+
+QPlatformMenu *QWindowsMenuBar::menuForTag(quintptr tag) const
+{
+ return traverseMenus(this, [tag] (const QWindowsMenu *m) { return m->tag() == tag; });
+}
+
+QPlatformMenu *QWindowsMenuBar::createMenu() const
+{
+ QPlatformMenu *result = new QWindowsMenu;
+ qCDebug(lcQpaMenus) << __FUNCTION__ << this << "returns" << result;
+ return result;
+}
+
+bool QWindowsMenuBar::notifyTriggered(uint id)
+{
+ QPlatformMenuItem *result = findMenuItemById(this, id);
+ if (result != nullptr) {
+ qCDebug(lcQpaMenus) << __FUNCTION__ << "id=" << id;
+ emit result->activated();
+ }
+ return result != nullptr;
+}
+
+bool QWindowsMenuBar::notifyAboutToShow(HMENU hmenu)
+{
+ if (QWindowsMenu *menu = findMenuByHandle(this, hmenu)) {
+ emit menu->aboutToShow();
+ return true;
+ }
+ return false;
+}
+
+QWindowsWindow *QWindowsMenuBar::platformWindow() const
+{
+ if (const QWindowsContext *ctx = QWindowsContext::instance()) {
+ if (QWindowsWindow *w = ctx->findPlatformWindow(this))
+ return w;
+ }
+ return nullptr;
+}
+
+void QWindowsMenuBar::redraw() const
+{
+ if (const QWindowsWindow *window = platformWindow())
+ DrawMenuBar(window->handle());
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+template <class M> /* Menu[Item] */
+static void formatTextSequence(QDebug &d, const QVector<M *> &v)
+{
+ if (const int size = v.size()) {
+ d << '[' << size << "](";
+ for (int i = 0; i < size; ++i) {
+ if (i)
+ d << ", ";
+ if (!v.at(i)->isVisible())
+ d << "[hidden] ";
+ d << '"' << v.at(i)->text() << '"';
+ }
+ d << ')';
+ }
+}
+
+void QWindowsMenuItem::formatDebug(QDebug &d) const
+{
+ if (m_separator)
+ d << "separator, ";
+ else
+ d << '"' << m_text << "\", ";
+ d << static_cast<const void *>(this);
+ if (m_parentMenu)
+ d << ", parentMenu=" << static_cast<const void *>(m_parentMenu);
+ if (m_subMenu)
+ d << ", subMenu=" << static_cast<const void *>(m_subMenu);
+ d << ", tag=" << showbase << hex
+ << tag() << noshowbase << dec << ", id=" << m_id;
+ if (!m_shortcut.isEmpty())
+ d << ", shortcut=" << m_shortcut;
+ if (m_visible)
+ d << " [visible]";
+ if (m_enabled)
+ d << " [enabled]";
+ if (m_checkable)
+ d << ", checked=" << m_checked;
+}
+
+QDebug operator<<(QDebug d, const QPlatformMenuItem *i)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d.noquote();
+ d << "QPlatformMenuItem(";
+ if (i)
+ static_cast<const QWindowsMenuItem *>(i)->formatDebug(d);
+ else
+ d << '0';
+ d << ')';
+ return d;
+}
+
+void QWindowsMenu::formatDebug(QDebug &d) const
+{
+ d << '"' << m_text << "\", " << static_cast<const void *>(this)
+ << ", handle=" << m_hMenu;
+ if (m_parentMenuBar != nullptr)
+ d << " [on menubar]";
+ if (m_parentMenu != nullptr)
+ d << " [on menu]";
+ if (tag())
+ d << ", tag=" << showbase << hex << tag() << noshowbase << dec;
+ if (m_visible)
+ d << " [visible]";
+ if (m_enabled)
+ d << " [enabled]";
+ d <<' ';
+ formatTextSequence(d, m_menuItems);
+}
+
+void QWindowsMenuBar::formatDebug(QDebug &d) const
+{
+ d << static_cast<const void *>(this) << ' ';
+ formatTextSequence(d, m_menus);
+}
+
+QDebug operator<<(QDebug d, const QPlatformMenu *m)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d.noquote();
+ if (m) {
+ d << m->metaObject()->className() << '(';
+ static_cast<const QWindowsMenu *>(m)->formatDebug(d);
+ d << ')';
+ } else {
+ d << "QPlatformMenu(0)";
+ }
+ return d;
+}
+
+QDebug operator<<(QDebug d, const QPlatformMenuBar *mb)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d.noquote();
+ d << "QPlatformMenuBar(";
+ if (mb)
+ static_cast<const QWindowsMenuBar *>(mb)->formatDebug(d);
+ else
+ d << '0';
+ d << ')';
+ return d;
+}
+
+#endif // !QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsmenu.h b/src/plugins/platforms/windows/qwindowsmenu.h
new file mode 100644
index 0000000000..d51a29676e
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsmenu.h
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSMENU_H
+#define QWINDOWSMENU_H
+
+#include "qtwindowsglobal.h"
+
+#include <qpa/qplatformmenu.h>
+
+#include <QtCore/QVector>
+#include <QtCore/QPair>
+
+QT_BEGIN_NAMESPACE
+
+class QDebug;
+
+class QWindowsMenu;
+class QWindowsMenuBar;
+class QWindowsWindow;
+
+class QWindowsMenuItem : public QPlatformMenuItem
+{
+ Q_OBJECT
+public:
+ explicit QWindowsMenuItem(QWindowsMenu *parentMenu = nullptr);
+ ~QWindowsMenuItem();
+
+ void setText(const QString &text) override;
+ void setIcon(const QIcon &icon) override;
+ void setMenu(QPlatformMenu *menu) override;
+ void setVisible(bool isVisible) override;
+ void setIsSeparator(bool isSeparator) override;
+ void setFont(const QFont &) override {}
+ void setRole(MenuRole) override {}
+ void setCheckable(bool checkable) override;
+ void setChecked(bool isChecked) override;
+#ifndef QT_NO_SHORTCUT
+ void setShortcut(const QKeySequence& shortcut) override;
+#endif
+ void setEnabled(bool enabled) override;
+ void setIconSize(int size) override;
+
+ const QWindowsMenu *parentMenu() const { return m_parentMenu; }
+ QWindowsMenu *parentMenu() { return m_parentMenu; }
+ HMENU parentMenuHandle() const;
+ QWindowsMenu *subMenu() const { return m_subMenu; }
+ UINT_PTR id() const { return m_id; }
+ void setId(uint id) { m_id = id; }
+ UINT state() const;
+ QString text() const { return m_text; }
+ QString nativeText() const;
+ bool isVisible() const { return m_visible; }
+
+ void insertIntoMenu(QWindowsMenu *menuItem, bool append, int index);
+ bool removeFromMenu();
+
+#ifndef QT_NO_DEBUG_STREAM
+ void formatDebug(QDebug &d) const;
+#endif
+
+private:
+ void updateBitmap();
+ void freeBitmap();
+ void updateText();
+ void insertIntoMenuHelper(QWindowsMenu *menu, bool append, int index);
+
+ QWindowsMenu *m_parentMenu = nullptr;
+ QWindowsMenu *m_subMenu = nullptr;
+ UINT_PTR m_id; // Windows Id sent as wParam with WM_COMMAND or submenu handle.
+ QString m_text;
+ QIcon m_icon;
+ HBITMAP m_hbitmap = nullptr;
+ int m_iconSize = 0;
+ bool m_separator = false;
+ bool m_visible = true;
+ bool m_checkable = false;
+ bool m_checked = false;
+ bool m_enabled = true;
+ QKeySequence m_shortcut;
+};
+
+class QWindowsMenu : public QPlatformMenu
+{
+ Q_OBJECT
+public:
+ typedef QVector<QWindowsMenuItem *> MenuItems;
+
+ QWindowsMenu();
+ ~QWindowsMenu();
+
+ void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) override;
+ void removeMenuItem(QPlatformMenuItem *menuItem) override;
+ void syncMenuItem(QPlatformMenuItem *) override {}
+ void syncSeparatorsCollapsible(bool) override {}
+
+ void setText(const QString &text) override;
+ void setIcon(const QIcon &icon) override;
+ void setEnabled(bool enabled) override;
+ bool isEnabled() const override { return m_enabled; }
+ void setVisible(bool visible) override;
+
+ QPlatformMenuItem *menuItemAt(int position) const override;
+ QPlatformMenuItem *menuItemForTag(quintptr tag) const override;
+
+ QPlatformMenuItem *createMenuItem() const override;
+ QPlatformMenu *createSubMenu() const override;
+
+ HMENU menuHandle() const { return m_hMenu; }
+ UINT_PTR id() const { return reinterpret_cast<UINT_PTR>(m_hMenu); }
+ QString text() const { return m_text; }
+ const MenuItems &menuItems() const { return m_menuItems; }
+ QWindowsMenuItem *itemForSubMenu(const QWindowsMenu *subMenu) const;
+
+ const QWindowsMenuBar *parentMenuBar() const { return m_parentMenuBar; }
+ HMENU parentMenuBarHandle() const;
+ const QWindowsMenu *parentMenu() const { return m_parentMenu; }
+ void setAsItemSubMenu(QWindowsMenuItem *item);
+ void notifyRemoved(QWindowsMenuItem *item) { m_menuItems.removeOne(item); }
+ HMENU parentMenuHandle() const;
+ HMENU parentHandle() const;
+ bool isVisible() const { return m_visible; }
+ void insertIntoMenuBar(QWindowsMenuBar *bar, bool append, int index);
+ bool removeFromParent();
+
+#ifndef QT_NO_DEBUG_STREAM
+ void formatDebug(QDebug &d) const;
+#endif
+
+protected:
+ explicit QWindowsMenu(QWindowsMenu *parentMenu, HMENU menu);
+
+private:
+ QWindowsMenuBar *m_parentMenuBar = nullptr;
+ QWindowsMenu *m_parentMenu = nullptr;
+ MenuItems m_menuItems;
+ HMENU m_hMenu = nullptr;
+ QString m_text;
+ QIcon m_icon;
+ bool m_visible = true;
+ bool m_enabled = true;
+};
+
+class QWindowsPopupMenu : public QWindowsMenu
+{
+ Q_OBJECT
+public:
+ QWindowsPopupMenu();
+
+ static bool notifyTriggered(uint id);
+ static bool notifyAboutToShow(HMENU hmenu);
+
+ void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) override;
+ void dismiss() override {}
+
+ bool trackPopupMenu(HWND windowHandle, int x, int y);
+};
+
+class QWindowsMenuBar : public QPlatformMenuBar
+{
+ Q_OBJECT
+public:
+ typedef QVector<QWindowsMenu *> Menus;
+
+ QWindowsMenuBar();
+ ~QWindowsMenuBar();
+
+ void insertMenu(QPlatformMenu *menu, QPlatformMenu *before) override;
+ void removeMenu(QPlatformMenu *menu) override;
+ void syncMenu(QPlatformMenu *) override {}
+ void handleReparent(QWindow *newParentWindow) override;
+
+ QPlatformMenu *menuForTag(quintptr tag) const override;
+ QPlatformMenu *createMenu() const override;
+
+ HMENU menuBarHandle() const { return m_hMenuBar; }
+ const Menus &menus() const { return m_menus; }
+ bool notifyTriggered(uint id);
+ bool notifyAboutToShow(HMENU hmenu);
+ void notifyRemoved(QWindowsMenu *menu) { m_menus.removeOne(menu); }
+ void redraw() const;
+
+ void install(QWindowsWindow *window);
+
+ static QWindowsMenuBar *menuBarOf(const QWindow *notYetCreatedWindow);
+
+#ifndef QT_NO_DEBUG_STREAM
+ void formatDebug(QDebug &d) const;
+#endif
+
+private:
+ QWindowsWindow *platformWindow() const;
+ void removeFromWindow();
+
+ Menus m_menus;
+ HMENU m_hMenuBar = nullptr;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const QPlatformMenuItem *);
+QDebug operator<<(QDebug d, const QPlatformMenu *);
+QDebug operator<<(QDebug d, const QPlatformMenuBar *);
+#endif // !QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSMENU_H
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 9c9382c44c..b892f1610d 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -41,6 +41,7 @@
#include "qwindowscontext.h"
#include <QtGui/private/qdnd_p.h>
+#include <QtCore/QByteArrayMatcher>
#include <QtCore/QTextCodec>
#include <QtCore/QMap>
#include <QtCore/QUrl>
@@ -955,9 +956,11 @@ QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pData
QVariant result;
if (canConvertToMime(mime, pDataObj)) {
QByteArray html = getData(CF_HTML, pDataObj);
+ static Q_RELAXED_CONSTEXPR auto startMatcher = qMakeStaticByteArrayMatcher("StartHTML:");
+ static Q_RELAXED_CONSTEXPR auto endMatcher = qMakeStaticByteArrayMatcher("EndHTML:");
qCDebug(lcQpaMime) << __FUNCTION__ << "raw:" << html;
- int start = html.indexOf("StartHTML:");
- int end = html.indexOf("EndHTML:");
+ int start = startMatcher.indexIn(html);
+ int end = endMatcher.indexIn(html);
if (start != -1) {
int startOffset = start + 10;
@@ -997,10 +1000,13 @@ bool QWindowsMimeHtml::convertFromMime(const FORMATETC &formatetc, const QMimeDa
"StartFragment:0000000000\r\n" // 56-81
"EndFragment:0000000000\r\n\r\n"; // 82-107
- if (data.indexOf("<!--StartFragment-->") == -1)
+ static Q_RELAXED_CONSTEXPR auto startFragmentMatcher = qMakeStaticByteArrayMatcher("<!--StartFragment-->");
+ static Q_RELAXED_CONSTEXPR auto endFragmentMatcher = qMakeStaticByteArrayMatcher("<!--EndFragment-->");
+
+ if (startFragmentMatcher.indexIn(data) == -1)
result += "<!--StartFragment-->";
result += data;
- if (data.indexOf("<!--EndFragment-->") == -1)
+ if (endFragmentMatcher.indexIn(data) == -1)
result += "<!--EndFragment-->";
// set the correct number for EndHTML
@@ -1008,9 +1014,9 @@ bool QWindowsMimeHtml::convertFromMime(const FORMATETC &formatetc, const QMimeDa
memcpy(reinterpret_cast<char *>(result.data() + 53 - pos.length()), pos.constData(), size_t(pos.length()));
// set correct numbers for StartFragment and EndFragment
- pos = QByteArray::number(result.indexOf("<!--StartFragment-->") + 20);
+ pos = QByteArray::number(startFragmentMatcher.indexIn(result) + 20);
memcpy(reinterpret_cast<char *>(result.data() + 79 - pos.length()), pos.constData(), size_t(pos.length()));
- pos = QByteArray::number(result.indexOf("<!--EndFragment-->"));
+ pos = QByteArray::number(endFragmentMatcher.indexIn(result));
memcpy(reinterpret_cast<char *>(result.data() + 103 - pos.length()), pos.constData(), size_t(pos.length()));
return setData(result, pmedium);
diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
index d21581ba8a..af4304cb19 100644
--- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp
+++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp
@@ -573,7 +573,8 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
QWindowSystemInterface::handleTouchEvent(window,
m_touchDevice,
- touchPoints);
+ touchPoints,
+ QWindowsKeyMapper::queryKeyboardModifiers());
return true;
}
diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
index d750eef19d..dc8e97c886 100644
--- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
+++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp
@@ -64,7 +64,8 @@ enum ResourceType {
HandleType,
GlHandleType,
GetDCType,
- ReleaseDCType
+ ReleaseDCType,
+ VkSurface
};
static int resourceType(const QByteArray &key)
@@ -77,7 +78,8 @@ static int resourceType(const QByteArray &key)
"handle",
"glhandle",
"getdc",
- "releasedc"
+ "releasedc",
+ "vkSurface"
};
const char ** const end = names + sizeof(names) / sizeof(names[0]);
const char **result = std::find(names, end, key);
@@ -112,6 +114,12 @@ void *QWindowsNativeInterface::nativeResourceForWindow(const QByteArray &resourc
case QWindow::OpenGLSurface:
case QWindow::OpenVGSurface:
break;
+ case QWindow::VulkanSurface:
+#if QT_CONFIG(vulkan)
+ if (type == VkSurface)
+ return bw->surface(nullptr, nullptr); // returns the address of the VkSurfaceKHR, not the value, as expected
+#endif
+ break;
}
qWarning("%s: Invalid key '%s' requested.", __FUNCTION__, resource.constData());
return 0;
diff --git a/src/plugins/platforms/windows/qwindowsole.cpp b/src/plugins/platforms/windows/qwindowsole.cpp
index 9b71061aa5..0ceb0d82fa 100644
--- a/src/plugins/platforms/windows/qwindowsole.cpp
+++ b/src/plugins/platforms/windows/qwindowsole.cpp
@@ -99,39 +99,6 @@ DWORD QWindowsOleDataObject::reportedPerformedEffect() const
return performedEffect;
}
-//---------------------------------------------------------------------
-// IUnknown Methods
-//---------------------------------------------------------------------
-
-STDMETHODIMP
-QWindowsOleDataObject::QueryInterface(REFIID iid, void FAR* FAR* ppv)
-{
- if (iid == IID_IUnknown || iid == IID_IDataObject) {
- *ppv = this;
- AddRef();
- return NOERROR;
- }
- *ppv = NULL;
- return ResultFromScode(E_NOINTERFACE);
-}
-
-STDMETHODIMP_(ULONG)
-QWindowsOleDataObject::AddRef(void)
-{
- return ++m_refs;
-}
-
-STDMETHODIMP_(ULONG)
-QWindowsOleDataObject::Release(void)
-{
- if (--m_refs == 0) {
- releaseQt();
- delete this;
- return 0;
- }
- return m_refs;
-}
-
STDMETHODIMP
QWindowsOleDataObject::GetData(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium)
{
@@ -323,35 +290,6 @@ bool QWindowsOleEnumFmtEtc::isNull() const
return m_isNull;
}
-// IUnknown methods
-STDMETHODIMP
-QWindowsOleEnumFmtEtc::QueryInterface(REFIID riid, void FAR* FAR* ppvObj)
-{
- if (riid == IID_IUnknown || riid == IID_IEnumFORMATETC) {
- *ppvObj = this;
- AddRef();
- return NOERROR;
- }
- *ppvObj = NULL;
- return ResultFromScode(E_NOINTERFACE);
-}
-
-STDMETHODIMP_(ULONG)
-QWindowsOleEnumFmtEtc::AddRef(void)
-{
- return ++m_dwRefs;
-}
-
-STDMETHODIMP_(ULONG)
-QWindowsOleEnumFmtEtc::Release(void)
-{
- if (--m_dwRefs == 0) {
- delete this;
- return 0;
- }
- return m_dwRefs;
-}
-
// IEnumFORMATETC methods
STDMETHODIMP
QWindowsOleEnumFmtEtc::Next(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched)
diff --git a/src/plugins/platforms/windows/qwindowsole.h b/src/plugins/platforms/windows/qwindowsole.h
index 643011272b..fc58858f2c 100644
--- a/src/plugins/platforms/windows/qwindowsole.h
+++ b/src/plugins/platforms/windows/qwindowsole.h
@@ -40,6 +40,7 @@
#ifndef QWINDOWSOLE_H
#define QWINDOWSOLE_H
+#include "qwindowscombase.h"
#include <QtCore/qt_windows.h>
#include <QtCore/QMap>
@@ -53,7 +54,7 @@ QT_BEGIN_NAMESPACE
class QMimeData;
class QWindow;
-class QWindowsOleDataObject : public IDataObject
+class QWindowsOleDataObject : public QWindowsComBase<IDataObject>
{
public:
explicit QWindowsOleDataObject(QMimeData *mimeData);
@@ -63,11 +64,6 @@ public:
QMimeData *mimeData() const;
DWORD reportedPerformedEffect() const;
- // IUnknown methods
- STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
- STDMETHOD_(ULONG,AddRef)(void);
- STDMETHOD_(ULONG,Release)(void);
-
// IDataObject methods
STDMETHOD(GetData)(LPFORMATETC pformatetcIn, LPSTGMEDIUM pmedium);
STDMETHOD(GetDataHere)(LPFORMATETC pformatetc, LPSTGMEDIUM pmedium);
@@ -82,13 +78,12 @@ public:
STDMETHOD(EnumDAdvise)(LPENUMSTATDATA FAR* ppenumAdvise);
private:
- ULONG m_refs = 1;
QPointer<QMimeData> data;
const int CF_PERFORMEDDROPEFFECT;
DWORD performedEffect = DROPEFFECT_NONE;
};
-class QWindowsOleEnumFmtEtc : public IEnumFORMATETC
+class QWindowsOleEnumFmtEtc : public QWindowsComBase<IEnumFORMATETC>
{
public:
explicit QWindowsOleEnumFmtEtc(const QVector<FORMATETC> &fmtetcs);
@@ -97,11 +92,6 @@ public:
bool isNull() const;
- // IUnknown methods
- STDMETHOD(QueryInterface)(REFIID riid, void FAR* FAR* ppvObj);
- STDMETHOD_(ULONG,AddRef)(void);
- STDMETHOD_(ULONG,Release)(void);
-
// IEnumFORMATETC methods
STDMETHOD(Next)(ULONG celt, LPFORMATETC rgelt, ULONG FAR* pceltFetched);
STDMETHOD(Skip)(ULONG celt);
@@ -111,7 +101,6 @@ public:
private:
bool copyFormatEtc(LPFORMATETC dest, const FORMATETC *src) const;
- ULONG m_dwRefs = 1;
ULONG m_nIndex = 0;
QVector<LPFORMATETC> m_lpfmtetcs;
bool m_isNull = false;
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
new file mode 100644
index 0000000000..3ee591de8c
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.cpp
@@ -0,0 +1,443 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#if defined(WINVER) && WINVER < 0x0601
+# undef WINVER
+#endif
+#if !defined(WINVER)
+# define WINVER 0x0601 // required for NOTIFYICONDATA_V2_SIZE, ChangeWindowMessageFilterEx() (MinGW 5.3)
+#endif
+
+#if defined(NTDDI_VERSION) && NTDDI_VERSION < 0x06010000
+# undef NTDDI_VERSION
+#endif
+#if !defined(NTDDI_VERSION)
+# define NTDDI_VERSION 0x06010000 // required for Shell_NotifyIconGetRect (MinGW 5.3)
+#endif
+
+#include "qwindowssystemtrayicon.h"
+#include "qwindowscontext.h"
+#include "qwindowstheme.h"
+#include "qwindowsmenu.h"
+#include "qwindowsscreen.h"
+
+#include <QtGui/qpixmap.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qrect.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qsettings.h>
+
+#include <qt_windows.h>
+#include <commctrl.h>
+#include <shellapi.h>
+#include <shlobj.h>
+#include <windowsx.h>
+
+QT_BEGIN_NAMESPACE
+
+static const UINT q_uNOTIFYICONID = 0;
+
+static uint MYWM_TASKBARCREATED = 0;
+#define MYWM_NOTIFYICON (WM_APP+101)
+
+Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
+
+// Copy QString data to a limited wchar_t array including \0.
+static inline void qStringToLimitedWCharArray(QString in, wchar_t *target, int maxLength)
+{
+ const int length = qMin(maxLength - 1, in.size());
+ if (length < in.size())
+ in.truncate(length);
+ in.toWCharArray(target);
+ target[length] = wchar_t(0);
+}
+
+static inline void initNotifyIconData(NOTIFYICONDATA &tnd)
+{
+ memset(&tnd, 0, sizeof(NOTIFYICONDATA));
+ tnd.cbSize = sizeof(NOTIFYICONDATA);
+ tnd.uVersion = NOTIFYICON_VERSION_4;
+}
+
+static void setIconContents(NOTIFYICONDATA &tnd, const QString &tip, HICON hIcon)
+{
+ tnd.uFlags |= NIF_MESSAGE | NIF_ICON | NIF_TIP;
+ tnd.uCallbackMessage = MYWM_NOTIFYICON;
+ tnd.hIcon = hIcon;
+ qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip) / sizeof(wchar_t));
+}
+
+// Match the HWND of the dummy window to the instances
+struct QWindowsHwndSystemTrayIconEntry
+{
+ HWND hwnd;
+ QWindowsSystemTrayIcon *trayIcon;
+};
+
+typedef QVector<QWindowsHwndSystemTrayIconEntry> HwndTrayIconEntries;
+
+Q_GLOBAL_STATIC(HwndTrayIconEntries, hwndTrayIconEntries)
+
+static int indexOfHwnd(HWND hwnd)
+{
+ const HwndTrayIconEntries *entries = hwndTrayIconEntries();
+ for (int i = 0, size = entries->size(); i < size; ++i) {
+ if (entries->at(i).hwnd == hwnd)
+ return i;
+ }
+ return -1;
+}
+
+extern "C" LRESULT QT_WIN_CALLBACK qWindowsTrayIconWndProc(HWND hwnd, UINT message,
+ WPARAM wParam, LPARAM lParam)
+{
+ if (message == MYWM_TASKBARCREATED || message == MYWM_NOTIFYICON
+ || message == WM_INITMENU || message == WM_INITMENUPOPUP
+ || message == WM_COMMAND) {
+ const int index = indexOfHwnd(hwnd);
+ if (index >= 0) {
+ MSG msg;
+ msg.hwnd = hwnd; // re-create MSG structure
+ msg.message = message; // time and pt fields ignored
+ msg.wParam = wParam;
+ msg.lParam = lParam;
+ msg.pt.x = GET_X_LPARAM(lParam);
+ msg.pt.y = GET_Y_LPARAM(lParam);
+ long result = 0;
+ if (hwndTrayIconEntries()->at(index).trayIcon->winEvent(msg, &result))
+ return result;
+ }
+ }
+ return DefWindowProc(hwnd, message, wParam, lParam);
+}
+
+// Note: Message windows (HWND_MESSAGE) are not sufficient, they
+// will not receive the "TaskbarCreated" message.
+static inline HWND createTrayIconMessageWindow()
+{
+ QWindowsContext *ctx = QWindowsContext::instance();
+ if (!ctx)
+ return 0;
+ // Register window class in the platform plugin.
+ const QString className =
+ ctx->registerWindowClass(QStringLiteral("QTrayIconMessageWindowClass"),
+ qWindowsTrayIconWndProc);
+ const wchar_t windowName[] = L"QTrayIconMessageWindow";
+ return CreateWindowEx(0, reinterpret_cast<const wchar_t *>(className.utf16()),
+ windowName, WS_OVERLAPPED,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ NULL, NULL, (HINSTANCE)GetModuleHandle(0), NULL);
+}
+
+/*!
+ \class QWindowsSystemTrayIcon
+ \brief Windows native system tray icon
+
+ \internal
+ \ingroup qt-lighthouse-win
+*/
+
+QWindowsSystemTrayIcon::QWindowsSystemTrayIcon()
+{
+ // For restoring the tray icon after explorer crashes
+ if (!MYWM_TASKBARCREATED)
+ MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
+ // Allow the WM_TASKBARCREATED message through the UIPI filter
+ ChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, MSGFLT_ALLOW, 0);
+ qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "MYWM_TASKBARCREATED=" << MYWM_TASKBARCREATED;
+}
+
+QWindowsSystemTrayIcon::~QWindowsSystemTrayIcon()
+{
+ qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this;
+ ensureCleanup();
+}
+
+void QWindowsSystemTrayIcon::init()
+{
+ qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this;
+ ensureInstalled();
+}
+
+void QWindowsSystemTrayIcon::cleanup()
+{
+ qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this;
+ ensureCleanup();
+}
+
+void QWindowsSystemTrayIcon::updateIcon(const QIcon &icon)
+{
+ qCDebug(lcQpaTrayIcon) << __FUNCTION__ << '(' << icon << ')' << this;
+ if (icon.cacheKey() == m_icon.cacheKey())
+ return;
+ const HICON hIconToDestroy = createIcon(icon);
+ if (ensureInstalled())
+ sendTrayMessage(NIM_MODIFY);
+ if (hIconToDestroy)
+ DestroyIcon(hIconToDestroy);
+}
+
+void QWindowsSystemTrayIcon::updateToolTip(const QString &tooltip)
+{
+ qCDebug(lcQpaTrayIcon) << __FUNCTION__ << '(' << tooltip << ')' << this;
+ if (m_toolTip == tooltip)
+ return;
+ m_toolTip = tooltip;
+ if (isInstalled())
+ sendTrayMessage(NIM_MODIFY);
+}
+
+QRect QWindowsSystemTrayIcon::geometry() const
+{
+ NOTIFYICONIDENTIFIER nid;
+ memset(&nid, 0, sizeof(nid));
+ nid.cbSize = sizeof(nid);
+ nid.hWnd = m_hwnd;
+ nid.uID = q_uNOTIFYICONID;
+ RECT rect;
+ const QRect result = SUCCEEDED(Shell_NotifyIconGetRect(&nid, &rect))
+ ? QRect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top)
+ : QRect();
+ qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "returns" << result;
+ return result;
+}
+
+void QWindowsSystemTrayIcon::showMessage(const QString &title, const QString &messageIn,
+ const QIcon &icon,
+ QPlatformSystemTrayIcon::MessageIcon iconType,
+ int msecsIn)
+{
+ qCDebug(lcQpaTrayIcon) << __FUNCTION__ << '(' << title << messageIn << icon
+ << iconType << msecsIn << ')' << this;
+ if (!supportsMessages())
+ return;
+ // For empty messages, ensures that they show when only title is set
+ QString message = messageIn;
+ if (message.isEmpty() && !title.isEmpty())
+ message.append(QLatin1Char(' '));
+
+ NOTIFYICONDATA tnd;
+ initNotifyIconData(tnd);
+ qStringToLimitedWCharArray(message, tnd.szInfo, 256);
+ qStringToLimitedWCharArray(title, tnd.szInfoTitle, 64);
+
+ tnd.uID = q_uNOTIFYICONID;
+ tnd.dwInfoFlags = NIIF_USER;
+
+ QSize size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
+ const QSize largeIcon(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
+ const QSize more = icon.actualSize(largeIcon);
+ if (more.height() > (largeIcon.height() * 3/4) || more.width() > (largeIcon.width() * 3/4)) {
+ tnd.dwInfoFlags |= NIIF_LARGE_ICON;
+ size = largeIcon;
+ }
+ QPixmap pm = icon.pixmap(size);
+ if (pm.isNull()) {
+ tnd.dwInfoFlags = NIIF_INFO;
+ } else {
+ if (pm.size() != size) {
+ qWarning("QSystemTrayIcon::showMessage: Wrong icon size (%dx%d), please add standard one: %dx%d",
+ pm.size().width(), pm.size().height(), size.width(), size.height());
+ pm = pm.scaled(size, Qt::IgnoreAspectRatio);
+ }
+ tnd.hBalloonIcon = qt_pixmapToWinHICON(pm);
+ }
+ tnd.hWnd = m_hwnd;
+ tnd.uTimeout = msecsIn <= 0 ? UINT(10000) : UINT(msecsIn); // 10s default
+ tnd.uFlags = NIF_INFO | NIF_SHOWTIP;
+
+ Shell_NotifyIcon(NIM_MODIFY, &tnd);
+}
+
+bool QWindowsSystemTrayIcon::supportsMessages() const
+{
+ // The key does typically not exist on Windows 10, default to true.
+ return QWindowsContext::readAdvancedExplorerSettings(L"EnableBalloonTips", 1) != 0;
+}
+
+QPlatformMenu *QWindowsSystemTrayIcon::createMenu() const
+{
+ if (QWindowsTheme::useNativeMenus() && m_menu.isNull())
+ m_menu = new QWindowsPopupMenu;
+ qCDebug(lcQpaTrayIcon) << __FUNCTION__ << this << "returns" << m_menu.data();
+ return m_menu.data();
+}
+
+// Delay-install until an Icon exists
+bool QWindowsSystemTrayIcon::ensureInstalled()
+{
+ if (isInstalled())
+ return true;
+ if (m_hIcon == nullptr)
+ return false;
+ m_hwnd = createTrayIconMessageWindow();
+ if (Q_UNLIKELY(m_hwnd == nullptr))
+ return false;
+ QWindowsHwndSystemTrayIconEntry entry{m_hwnd, this};
+ hwndTrayIconEntries()->append(entry);
+ sendTrayMessage(NIM_ADD);
+ return true;
+}
+
+void QWindowsSystemTrayIcon::ensureCleanup()
+{
+ if (isInstalled()) {
+ const int index = indexOfHwnd(m_hwnd);
+ if (index >= 0)
+ hwndTrayIconEntries()->removeAt(index);
+ sendTrayMessage(NIM_DELETE);
+ DestroyWindow(m_hwnd);
+ m_hwnd = nullptr;
+ }
+ if (m_hIcon != nullptr)
+ DestroyIcon(m_hIcon);
+ m_hIcon = nullptr;
+ m_menu = nullptr; // externally owned
+ m_toolTip.clear();
+}
+
+bool QWindowsSystemTrayIcon::sendTrayMessage(DWORD msg)
+{
+ NOTIFYICONDATA tnd;
+ initNotifyIconData(tnd);
+ tnd.uID = q_uNOTIFYICONID;
+ tnd.hWnd = m_hwnd;
+ tnd.uFlags = NIF_SHOWTIP;
+ if (msg == NIM_ADD || msg == NIM_MODIFY)
+ setIconContents(tnd, m_toolTip, m_hIcon);
+ if (!Shell_NotifyIcon(msg, &tnd))
+ return false;
+ return msg != NIM_ADD || Shell_NotifyIcon(NIM_SETVERSION, &tnd);
+}
+
+// Return the old icon to be freed after modifying the tray icon.
+HICON QWindowsSystemTrayIcon::createIcon(const QIcon &icon)
+{
+ const HICON oldIcon = m_hIcon;
+ m_hIcon = nullptr;
+ if (icon.isNull())
+ return oldIcon;
+ const QSize requestedSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
+ const QSize size = icon.actualSize(requestedSize);
+ const QPixmap pm = icon.pixmap(size);
+ if (!pm.isNull())
+ m_hIcon = qt_pixmapToWinHICON(pm);
+ return oldIcon;
+}
+
+bool QWindowsSystemTrayIcon::winEvent(const MSG &message, long *result)
+{
+ *result = 0;
+ switch (message.message) {
+ case MYWM_NOTIFYICON: {
+ Q_ASSERT(q_uNOTIFYICONID == HIWORD(message.lParam));
+ const int trayMessage = LOWORD(message.lParam);
+ switch (trayMessage) {
+ case NIN_SELECT:
+ case NIN_KEYSELECT:
+ if (m_ignoreNextMouseRelease)
+ m_ignoreNextMouseRelease = false;
+ else
+ emit activated(Trigger);
+ break;
+ case WM_LBUTTONDBLCLK:
+ m_ignoreNextMouseRelease = true; // Since DBLCLICK Generates a second mouse
+ emit activated(DoubleClick); // release we must ignore it
+ break;
+ case WM_CONTEXTMENU: {
+ const QPoint globalPos = QPoint(GET_X_LPARAM(message.wParam), GET_Y_LPARAM(message.wParam));
+ const QPlatformScreen *screen = QWindowsContext::instance()->screenManager().screenAtDp(globalPos);
+ emit contextMenuRequested(globalPos, screen);
+ emit activated(Context);
+ if (m_menu)
+ m_menu->trackPopupMenu(message.hwnd, globalPos.x(), globalPos.y());
+ }
+ break;
+ case NIN_BALLOONUSERCLICK:
+ emit messageClicked();
+ break;
+ case WM_MBUTTONUP:
+ emit activated(MiddleClick);
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case WM_INITMENU:
+ case WM_INITMENUPOPUP:
+ QWindowsPopupMenu::notifyAboutToShow(reinterpret_cast<HMENU>(message.wParam));
+ break;
+ case WM_COMMAND:
+ QWindowsPopupMenu::notifyTriggered(LOWORD(message.wParam));
+ break;
+ default:
+ if (message.message == MYWM_TASKBARCREATED) // self-registered message id (tray crashed)
+ sendTrayMessage(NIM_ADD);
+ break;
+ }
+ return false;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+void QWindowsSystemTrayIcon::formatDebug(QDebug &d) const
+{
+ d << static_cast<const void *>(this) << ", \"" << m_toolTip
+ << "\", hwnd=" << m_hwnd << ", m_hIcon=" << m_hIcon << ", menu="
+ << m_menu.data();
+}
+
+QDebug operator<<(QDebug d, const QWindowsSystemTrayIcon *t)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d.noquote();
+ d << "QWindowsSystemTrayIcon(";
+ if (t)
+ t->formatDebug(d);
+ else
+ d << '0';
+ d << ')';
+ return d;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowssystemtrayicon.h b/src/plugins/platforms/windows/qwindowssystemtrayicon.h
new file mode 100644
index 0000000000..1f696180cd
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowssystemtrayicon.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSSYSTEMTRAYICON_H
+#define QWINDOWSSYSTEMTRAYICON_H
+
+#include <QtGui/qicon.h>
+#include <QtGui/qpa/qplatformsystemtrayicon.h>
+
+#include <QtCore/qpointer.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDebug;
+
+class QWindowsPopupMenu;
+
+class QWindowsSystemTrayIcon : public QPlatformSystemTrayIcon
+{
+public:
+ QWindowsSystemTrayIcon();
+ ~QWindowsSystemTrayIcon();
+
+ void init() override;
+ void cleanup() override;
+ void updateIcon(const QIcon &icon) override;
+ void updateToolTip(const QString &tooltip) override;
+ void updateMenu(QPlatformMenu *) override {}
+ QRect geometry() const override;
+ void showMessage(const QString &title, const QString &msg,
+ const QIcon &icon, MessageIcon iconType, int msecs) override;
+
+ bool isSystemTrayAvailable() const override { return true; }
+ bool supportsMessages() const override;
+
+ QPlatformMenu *createMenu() const override;
+
+ bool winEvent(const MSG &message, long *result);
+
+#ifndef QT_NO_DEBUG_STREAM
+ void formatDebug(QDebug &d) const;
+#endif
+
+private:
+ bool isInstalled() const { return m_hwnd != nullptr; }
+ bool ensureInstalled();
+ void ensureCleanup();
+ bool sendTrayMessage(DWORD msg);
+ HICON createIcon(const QIcon &icon);
+
+ QIcon m_icon;
+ QString m_toolTip;
+ HWND m_hwnd = nullptr;
+ HICON m_hIcon = nullptr;
+ mutable QPointer<QWindowsPopupMenu> m_menu;
+ bool m_ignoreNextMouseRelease = false;
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, const QWindowsSystemTrayIcon *);
+#endif // !QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSSYSTEMTRAYICON_H
diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
index 7e1017426f..b1f0062979 100644
--- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp
+++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp
@@ -463,13 +463,13 @@ bool QWindowsTabletSupport::translateTabletPacketEvent()
// Z = sin(altitude)
// X Tilt = arctan(X / Z)
// Y Tilt = arctan(Y / Z)
- const double radAzim = (packet.pkOrientation.orAzimuth / 10.0) * (M_PI / 180);
- const double tanAlt = std::tan((std::abs(packet.pkOrientation.orAltitude / 10.0)) * (M_PI / 180));
+ const double radAzim = qDegreesToRadians(packet.pkOrientation.orAzimuth / 10.0);
+ const double tanAlt = std::tan(qDegreesToRadians(std::abs(packet.pkOrientation.orAltitude / 10.0)));
- const double degX = std::atan(std::sin(radAzim) / tanAlt);
- const double degY = std::atan(std::cos(radAzim) / tanAlt);
- tiltX = int(degX * (180 / M_PI));
- tiltY = int(-degY * (180 / M_PI));
+ const double radX = std::atan(std::sin(radAzim) / tanAlt);
+ const double radY = std::atan(std::cos(radAzim) / tanAlt);
+ tiltX = int(qRadiansToDegrees(radX));
+ tiltY = int(qRadiansToDegrees(-radY));
rotation = 360.0 - (packet.pkOrientation.orTwist / 10.0);
if (rotation > 180.0)
rotation -= 360.0;
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 7916211219..a1ccf1f83c 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -44,9 +44,13 @@
#endif
#include "qwindowstheme.h"
+#include "qwindowsmenu.h"
#include "qwindowsdialoghelpers.h"
#include "qwindowscontext.h"
#include "qwindowsintegration.h"
+#if QT_CONFIG(systemtrayicon)
+# include "qwindowssystemtrayicon.h"
+#endif
#include "qt_windows.h"
#include <commctrl.h>
#include <objbase.h>
@@ -415,13 +419,7 @@ static inline QStringList iconThemeSearchPaths()
static inline QStringList styleNames()
{
- QStringList result;
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
- result.append(QStringLiteral("WindowsVista"));
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP)
- result.append(QStringLiteral("WindowsXP"));
- result.append(QStringLiteral("Windows"));
- return result;
+ return { QStringLiteral("WindowsVista"), QStringLiteral("Windows") };
}
static inline int uiEffects()
@@ -554,6 +552,13 @@ QPlatformDialogHelper *QWindowsTheme::createPlatformDialogHelper(DialogType type
return QWindowsDialogs::createHelper(type);
}
+#if QT_CONFIG(systemtrayicon)
+QPlatformSystemTrayIcon *QWindowsTheme::createPlatformSystemTrayIcon() const
+{
+ return new QWindowsSystemTrayIcon;
+}
+#endif
+
void QWindowsTheme::windowsThemeChanged(QWindow * window)
{
refresh();
@@ -922,4 +927,55 @@ QIcon QWindowsTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOpt
return QIcon(new QWindowsFileIconEngine(fileInfo, iconOptions));
}
+static inline bool doUseNativeMenus()
+{
+ const unsigned options = QWindowsIntegration::instance()->options();
+ if ((options & QWindowsIntegration::NoNativeMenus) != 0)
+ return false;
+ if ((options & QWindowsIntegration::AlwaysUseNativeMenus) != 0)
+ return true;
+ // "Auto" mode: For non-widget or Quick Controls 2 applications
+ if (!QCoreApplication::instance()->inherits("QApplication"))
+ return true;
+ const QWindowList &topLevels = QGuiApplication::topLevelWindows();
+ for (const QWindow *t : topLevels) {
+ if (t->inherits("QQuickApplicationWindow"))
+ return true;
+ }
+ return false;
+}
+
+bool QWindowsTheme::useNativeMenus()
+{
+ static const bool result = doUseNativeMenus();
+ return result;
+}
+
+QPlatformMenuItem *QWindowsTheme::createPlatformMenuItem() const
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__;
+ return QWindowsTheme::useNativeMenus() ? new QWindowsMenuItem : nullptr;
+}
+
+QPlatformMenu *QWindowsTheme::createPlatformMenu() const
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__;
+ // We create a popup menu here, since it will likely be used as context
+ // menu. Submenus should be created the factory functions of
+ // QPlatformMenu/Bar. Note though that Quick Controls 1 will use this
+ // function for submenus as well, but this has been found to work.
+ return QWindowsTheme::useNativeMenus() ? new QWindowsPopupMenu : nullptr;
+}
+
+QPlatformMenuBar *QWindowsTheme::createPlatformMenuBar() const
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__;
+ return QWindowsTheme::useNativeMenus() ? new QWindowsMenuBar : nullptr;
+}
+
+void QWindowsTheme::showPlatformMenuBar()
+{
+ qCDebug(lcQpaMenus) << __FUNCTION__;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h
index a3019ff6eb..237e8158fa 100644
--- a/src/plugins/platforms/windows/qwindowstheme.h
+++ b/src/plugins/platforms/windows/qwindowstheme.h
@@ -59,6 +59,9 @@ public:
bool usePlatformNativeDialog(DialogType type) const override;
QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const override;
+#if QT_CONFIG(systemtrayicon)
+ QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override;
+#endif
QVariant themeHint(ThemeHint) const override;
const QPalette *palette(Palette type = SystemPalette) const override
{ return m_palettes[type]; }
@@ -74,6 +77,13 @@ public:
QList<QSize> availableFileIconSizes() const { return m_fileIconSizes; }
+ QPlatformMenuItem *createPlatformMenuItem() const override;
+ QPlatformMenu *createPlatformMenu() const override;
+ QPlatformMenuBar *createPlatformMenuBar() const override;
+ void showPlatformMenuBar() override;
+
+ static bool useNativeMenus();
+
static const char *name;
private:
diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
new file mode 100644
index 0000000000..d81ee8ba29
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowsvulkaninstance.h"
+
+QT_BEGIN_NAMESPACE
+
+QWindowsVulkanInstance::QWindowsVulkanInstance(QVulkanInstance *instance)
+ : m_instance(instance),
+ m_getPhysDevPresSupport(nullptr),
+ m_createSurface(nullptr),
+ m_destroySurface(nullptr)
+{
+ if (qEnvironmentVariableIsSet("QT_VULKAN_LIB"))
+ m_lib.setFileName(QString::fromUtf8(qgetenv("QT_VULKAN_LIB")));
+ else
+ m_lib.setFileName(QStringLiteral("vulkan-1"));
+
+ if (!m_lib.load()) {
+ qWarning("Failed to load %s: %s", qPrintable(m_lib.fileName()), qPrintable(m_lib.errorString()));
+ return;
+ }
+
+ init(&m_lib);
+}
+
+void QWindowsVulkanInstance::createOrAdoptInstance()
+{
+ initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_KHR_win32_surface"));
+
+ if (!m_vkInst)
+ return;
+
+ m_getPhysDevPresSupport = reinterpret_cast<PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceWin32PresentationSupportKHR"));
+ if (!m_getPhysDevPresSupport)
+ qWarning("Failed to find vkGetPhysicalDeviceWin32PresentationSupportKHR");
+}
+
+QWindowsVulkanInstance::~QWindowsVulkanInstance()
+{
+}
+
+bool QWindowsVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ QWindow *window)
+{
+ if (!m_getPhysDevPresSupport || !m_getPhysDevSurfaceSupport)
+ return true;
+
+ bool ok = m_getPhysDevPresSupport(physicalDevice, queueFamilyIndex);
+
+ VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(window);
+ VkBool32 supported = false;
+ m_getPhysDevSurfaceSupport(physicalDevice, queueFamilyIndex, surface, &supported);
+ ok &= bool(supported);
+
+ return ok;
+}
+
+VkSurfaceKHR QWindowsVulkanInstance::createSurface(HWND win)
+{
+ VkSurfaceKHR surface = 0;
+
+ if (!m_createSurface) {
+ m_createSurface = reinterpret_cast<PFN_vkCreateWin32SurfaceKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkCreateWin32SurfaceKHR"));
+ }
+ if (!m_createSurface) {
+ qWarning("Failed to find vkCreateWin32SurfaceKHR");
+ return surface;
+ }
+ if (!m_destroySurface) {
+ m_destroySurface = reinterpret_cast<PFN_vkDestroySurfaceKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkDestroySurfaceKHR"));
+ }
+ if (!m_destroySurface) {
+ qWarning("Failed to find vkDestroySurfaceKHR");
+ return surface;
+ }
+
+ VkWin32SurfaceCreateInfoKHR surfaceInfo;
+ memset(&surfaceInfo, 0, sizeof(surfaceInfo));
+ surfaceInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ surfaceInfo.hinstance = GetModuleHandle(nullptr);
+ surfaceInfo.hwnd = win;
+ VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface);
+ if (err != VK_SUCCESS)
+ qWarning("Failed to create Vulkan surface: %d", err);
+
+ return surface;
+}
+
+void QWindowsVulkanInstance::destroySurface(VkSurfaceKHR surface)
+{
+ if (m_destroySurface && surface)
+ m_destroySurface(m_vkInst, surface, nullptr);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsvulkaninstance.h b/src/plugins/platforms/windows/qwindowsvulkaninstance.h
new file mode 100644
index 0000000000..ca60ab7627
--- /dev/null
+++ b/src/plugins/platforms/windows/qwindowsvulkaninstance.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSVULKANINSTANCE_H
+#define QWINDOWSVULKANINSTANCE_H
+
+#if defined(VULKAN_H_) && !defined(VK_USE_PLATFORM_WIN32_KHR)
+#error "vulkan.h included without Win32 WSI"
+#endif
+
+#define VK_USE_PLATFORM_WIN32_KHR
+
+#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h>
+#include <QLibrary>
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsVulkanInstance : public QBasicPlatformVulkanInstance
+{
+public:
+ QWindowsVulkanInstance(QVulkanInstance *instance);
+ ~QWindowsVulkanInstance();
+
+ void createOrAdoptInstance() override;
+ bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override;
+
+ VkSurfaceKHR createSurface(HWND win);
+ void destroySurface(VkSurfaceKHR surface);
+
+private:
+ QVulkanInstance *m_instance;
+ QLibrary m_lib;
+ PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR m_getPhysDevPresSupport;
+ PFN_vkCreateWin32SurfaceKHR m_createSurface;
+ PFN_vkDestroySurfaceKHR m_destroySurface;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINDOWSVULKANINSTANCE_H
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 3c79c8aefe..3e445f0f7f 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -44,6 +44,7 @@
#endif
#include "qwindowsscreen.h"
#include "qwindowsintegration.h"
+#include "qwindowsmenu.h"
#include "qwindowsnativeinterface.h"
#if QT_CONFIG(dynamicgl)
# include "qwindowsglcontext.h"
@@ -69,8 +70,14 @@
#include <dwmapi.h>
+#if QT_CONFIG(vulkan)
+#include "qwindowsvulkaninstance.h"
+#endif
+
QT_BEGIN_NAMESPACE
+typedef QSharedPointer<QWindowCreationContext> QWindowCreationContextPtr;
+
enum {
defaultWindowWidth = 160,
defaultWindowHeight = 160
@@ -226,6 +233,23 @@ QDebug operator<<(QDebug d, const WINDOWPLACEMENT &wp)
<< ", rcNormalPosition=" << wp.rcNormalPosition;
return d;
}
+
+QDebug operator<<(QDebug d, const GUID &guid)
+{
+ QDebugStateSaver saver(d);
+ d.nospace();
+ d << '{' << hex << uppercasedigits << qSetPadChar(QLatin1Char('0'))
+ << qSetFieldWidth(8) << guid.Data1
+ << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
+ << guid.Data2 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
+ << guid.Data3 << qSetFieldWidth(0) << '-' << qSetFieldWidth(4)
+ << qSetFieldWidth(2) << guid.Data4[0] << guid.Data4[1]
+ << qSetFieldWidth(0) << '-' << qSetFieldWidth(2);
+ for (int i = 2; i < 8; ++i)
+ d << guid.Data4[i];
+ d << qSetFieldWidth(0) << '}';
+ return d;
+}
#endif // !QT_NO_DEBUG_STREAM
// QTBUG-43872, for windows that do not have WS_EX_TOOLWINDOW set, WINDOWPLACEMENT
@@ -293,13 +317,15 @@ static QWindow::Visibility windowVisibility_sys(HWND hwnd)
return QWindow::Windowed;
}
-static inline bool windowIsOpenGL(const QWindow *w)
+static inline bool windowIsAccelerated(const QWindow *w)
{
switch (w->surfaceType()) {
case QSurface::OpenGLSurface:
return true;
case QSurface::RasterGLSurface:
return qt_window_private(const_cast<QWindow *>(w))->compositing;
+ case QSurface::VulkanSurface:
+ return true;
default:
return false;
}
@@ -360,11 +386,11 @@ bool QWindowsWindow::setWindowLayered(HWND hwnd, Qt::WindowFlags flags, bool has
return needsLayered;
}
-static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bool openGL, qreal level)
+static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bool accelerated, qreal level)
{
if (QWindowsWindow::setWindowLayered(hwnd, flags, hasAlpha, level)) {
const BYTE alpha = BYTE(qRound(255.0 * level));
- if (hasAlpha && !openGL && (flags & Qt::FramelessWindowHint)) {
+ if (hasAlpha && !accelerated && (flags & Qt::FramelessWindowHint)) {
// Non-GL windows with alpha: Use blend function to update.
BLENDFUNCTION blend = {AC_SRC_OVER, 0, alpha, AC_SRC_ALPHA};
UpdateLayeredWindow(hwnd, NULL, NULL, NULL, NULL, NULL, 0, &blend, ULW_ALPHA);
@@ -378,13 +404,13 @@ static void setWindowOpacity(HWND hwnd, Qt::WindowFlags flags, bool hasAlpha, bo
static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::WindowFlags flags, qreal opacity)
{
- const bool isGL = windowIsOpenGL(w);
+ const bool isAccelerated = windowIsAccelerated(w);
const bool hasAlpha = w->format().hasAlpha();
- if (isGL && hasAlpha)
+ if (isAccelerated && hasAlpha)
applyBlurBehindWindow(hwnd);
- setWindowOpacity(hwnd, flags, hasAlpha, isGL, opacity);
+ setWindowOpacity(hwnd, flags, hasAlpha, isAccelerated, opacity);
}
/*!
@@ -597,8 +623,6 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
QWindowsWindowData
WindowCreationData::create(const QWindow *w, const WindowData &data, QString title) const
{
- typedef QSharedPointer<QWindowCreationContext> QWindowCreationContextPtr;
-
WindowData result;
result.flags = flags;
@@ -616,7 +640,7 @@ QWindowsWindowData
// Capture events before CreateWindowEx() returns. The context is cleared in
// the QWindowsWindow constructor.
- const QWindowCreationContextPtr context(new QWindowCreationContext(w, rect, data.customMargins, style, exStyle));
+ const QWindowCreationContextPtr context(new QWindowCreationContext(w, data.geometry, rect, data.customMargins, style, exStyle));
QWindowsContext::instance()->setWindowCreationContext(context);
qCDebug(lcQpaWindows).nospace()
@@ -980,10 +1004,11 @@ void QWindowsForeignWindow::setVisible(bool visible)
*/
QWindowCreationContext::QWindowCreationContext(const QWindow *w,
- const QRect &geometry,
+ const QRect &geometryIn, const QRect &geometry,
const QMargins &cm,
DWORD style_, DWORD exStyle_) :
geometryHint(w, cm), window(w), style(style_), exStyle(exStyle_),
+ requestedGeometryIn(geometryIn),
requestedGeometry(geometry), obtainedGeometry(geometry),
margins(QWindowsGeometryHint::frame(style, exStyle)), customMargins(cm)
{
@@ -997,6 +1022,8 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w,
const QMargins effectiveMargins = margins + customMargins;
frameWidth = effectiveMargins.left() + geometry.width() + effectiveMargins.right();
frameHeight = effectiveMargins.top() + geometry.height() + effectiveMargins.bottom();
+ if (QWindowsMenuBar::menuBarOf(w) != nullptr)
+ frameHeight += GetSystemMetrics(SM_CYMENU);
const bool isDefaultPosition = !frameX && !frameY && w->isTopLevel();
if (!QWindowsGeometryHint::positionIncludesFrame(w) && !isDefaultPosition) {
frameX -= effectiveMargins.left();
@@ -1042,9 +1069,10 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
m_data(data),
m_cursor(new CursorHandle),
m_format(aWindow->requestedFormat())
+#if QT_CONFIG(vulkan)
+ , m_vkSurface(0)
+#endif
{
- // Clear the creation context as the window can be found in QWindowsContext's map.
- QWindowsContext::instance()->setWindowCreationContext(QSharedPointer<QWindowCreationContext>());
QWindowsContext::instance()->addWindow(m_data.hwnd, this);
const Qt::WindowType type = aWindow->type();
if (type == Qt::Desktop)
@@ -1057,13 +1085,20 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data)
setFlag(OpenGL_ES2);
}
#endif // QT_NO_OPENGL
+#if QT_CONFIG(vulkan)
+ if (aWindow->surfaceType() == QSurface::VulkanSurface)
+ setFlag(VulkanSurface);
+#endif
updateDropSite(window()->isTopLevel());
registerTouchWindow();
- setWindowState(aWindow->windowState());
+ setWindowState(aWindow->windowStates());
const qreal opacity = qt_window_private(aWindow)->opacity;
if (!qFuzzyCompare(opacity, qreal(1.0)))
setOpacity(opacity);
+
+ setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
+
if (aWindow->isTopLevel())
setWindowIcon(aWindow->icon());
clearFlag(WithinCreate);
@@ -1078,6 +1113,27 @@ QWindowsWindow::~QWindowsWindow()
destroyIcon();
}
+void QWindowsWindow::initialize()
+{
+ // Clear the creation context as the window can be found in QWindowsContext's map.
+ QWindowCreationContextPtr creationContext =
+ QWindowsContext::instance()->setWindowCreationContext(QWindowCreationContextPtr());
+
+ // Trigger geometry change (unless it has a special state in which case setWindowState()
+ // will send the message) and screen change signals of QWindow.
+ QWindow *w = window();
+ if (w->type() != Qt::Desktop) {
+ const Qt::WindowState state = w->windowState();
+ if (state != Qt::WindowMaximized && state != Qt::WindowFullScreen
+ && creationContext->requestedGeometryIn != creationContext->obtainedGeometry) {
+ QWindowSystemInterface::handleGeometryChange(w, creationContext->obtainedGeometry);
+ }
+ QPlatformScreen *obtainedScreen = screenForGeometry(creationContext->obtainedGeometry);
+ if (obtainedScreen && screen() != obtainedScreen)
+ QWindowSystemInterface::handleWindowScreenChanged(w, obtainedScreen->screen());
+ }
+}
+
void QWindowsWindow::fireExpose(const QRegion &region, bool force)
{
if (region.isEmpty() && !force)
@@ -1110,6 +1166,14 @@ void QWindowsWindow::destroyWindow()
if (hasMouseCapture())
setMouseGrabEnabled(false);
setDropSiteEnabled(false);
+#if QT_CONFIG(vulkan)
+ if (m_vkSurface) {
+ QVulkanInstance *inst = window()->vulkanInstance();
+ if (inst)
+ static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
+ m_vkSurface = 0;
+ }
+#endif
#ifndef QT_NO_OPENGL
if (m_surface) {
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
@@ -1327,20 +1391,48 @@ static inline bool testShowWithoutActivating(const QWindow *window)
return showWithoutActivating.isValid() && showWithoutActivating.toBool();
}
+static void setMinimizedGeometry(HWND hwnd, const QRect &r)
+{
+ WINDOWPLACEMENT windowPlacement;
+ windowPlacement.length = sizeof(WINDOWPLACEMENT);
+ if (GetWindowPlacement(hwnd, &windowPlacement)) {
+ windowPlacement.showCmd = SW_SHOWMINIMIZED;
+ windowPlacement.rcNormalPosition = RECTfromQRect(r);
+ SetWindowPlacement(hwnd, &windowPlacement);
+ }
+}
+
+static void setRestoreMaximizedFlag(HWND hwnd, bool set = true)
+{
+ // Let Windows know that we need to restore as maximized
+ WINDOWPLACEMENT windowPlacement;
+ windowPlacement.length = sizeof(WINDOWPLACEMENT);
+ if (GetWindowPlacement(hwnd, &windowPlacement)) {
+ if (set)
+ windowPlacement.flags |= WPF_RESTORETOMAXIMIZED;
+ else
+ windowPlacement.flags &= ~WPF_RESTORETOMAXIMIZED;
+ SetWindowPlacement(hwnd, &windowPlacement);
+ }
+}
+
// partially from QWidgetPrivate::show_sys()
void QWindowsWindow::show_sys() const
{
int sm = SW_SHOWNORMAL;
bool fakedMaximize = false;
+ bool restoreMaximize = false;
const QWindow *w = window();
const Qt::WindowFlags flags = w->flags();
const Qt::WindowType type = w->type();
if (w->isTopLevel()) {
- const Qt::WindowState state = w->windowState();
+ const Qt::WindowStates state = w->windowStates();
if (state & Qt::WindowMinimized) {
sm = SW_SHOWMINIMIZED;
if (!isVisible())
sm = SW_SHOWMINNOACTIVE;
+ if (state & Qt::WindowMaximized)
+ restoreMaximize = true;
} else {
updateTransientParent();
if (state & Qt::WindowMaximized) {
@@ -1361,7 +1453,7 @@ void QWindowsWindow::show_sys() const
if (type == Qt::Popup || type == Qt::ToolTip || type == Qt::Tool || testShowWithoutActivating(w))
sm = SW_SHOWNOACTIVATE;
- if (w->windowState() & Qt::WindowMaximized)
+ if (w->windowStates() & Qt::WindowMaximized)
setFlag(WithinMaximize); // QTBUG-8361
ShowWindow(m_data.hwnd, sm);
@@ -1374,6 +1466,8 @@ void QWindowsWindow::show_sys() const
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER
| SWP_FRAMECHANGED);
}
+ if (restoreMaximize)
+ setRestoreMaximizedFlag(m_data.hwnd);
}
void QWindowsWindow::setParent(const QPlatformWindow *newParent)
@@ -1429,8 +1523,10 @@ void QWindowsWindow::handleHidden()
void QWindowsWindow::handleCompositionSettingsChanged()
{
const QWindow *w = window();
- if (w->surfaceType() == QWindow::OpenGLSurface && w->format().hasAlpha())
+ if ((w->surfaceType() == QWindow::OpenGLSurface || w->surfaceType() == QWindow::VulkanSurface)
+ && w->format().hasAlpha()) {
applyBlurBehindWindow(handle());
+ }
}
static QRect normalFrameGeometry(HWND hwnd)
@@ -1447,7 +1543,8 @@ static QRect normalFrameGeometry(HWND hwnd)
QRect QWindowsWindow::normalGeometry() const
{
// Check for fake 'fullscreen' mode.
- const bool fakeFullScreen = m_savedFrameGeometry.isValid() && window()->windowState() == Qt::WindowFullScreen;
+ const bool fakeFullScreen =
+ m_savedFrameGeometry.isValid() && (window()->windowStates() & Qt::WindowFullScreen);
const QRect frame = fakeFullScreen ? m_savedFrameGeometry : normalFrameGeometry(m_data.hwnd);
const QMargins margins = fakeFullScreen ? QWindowsGeometryHint::frame(m_savedStyle, 0) : frameMargins();
return frame.isValid() ? frame.marginsRemoved(margins) : frame;
@@ -1462,13 +1559,15 @@ void QWindowsWindow::setGeometry(const QRect &rectIn)
const QMargins margins = frameMargins();
rect.moveTopLeft(rect.topLeft() + QPoint(margins.left(), margins.top()));
}
- if (m_windowState == Qt::WindowMinimized)
+ if (m_windowState & Qt::WindowMinimized)
m_data.geometry = rect; // Otherwise set by handleGeometryChange() triggered by event.
if (m_data.hwnd) {
// A ResizeEvent with resulting geometry will be sent. If we cannot
// achieve that size (for example, window title minimal constraint),
// notify and warn.
+ setFlag(WithinSetGeometry);
setGeometry_sys(rect);
+ clearFlag(WithinSetGeometry);
if (m_data.geometry != rect) {
qWarning("%s: Unable to set geometry %dx%d+%d+%d on %s/'%s'."
" Resulting geometry: %dx%d+%d+%d "
@@ -1505,18 +1604,21 @@ void QWindowsWindow::handleResized(int wParam)
case SIZE_MAXSHOW:
return;
case SIZE_MINIMIZED: // QTBUG-53577, prevent state change events during programmatic state change
- if (!testFlag(WithinSetStyle))
- handleWindowStateChange(Qt::WindowMinimized);
+ if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry))
+ handleWindowStateChange(m_windowState | Qt::WindowMinimized);
return;
case SIZE_MAXIMIZED:
- if (!testFlag(WithinSetStyle))
- handleWindowStateChange(Qt::WindowMaximized);
+ if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry))
+ handleWindowStateChange(Qt::WindowMaximized | (isFullScreen_sys() ? Qt::WindowFullScreen
+ : Qt::WindowNoState));
handleGeometryChange();
break;
case SIZE_RESTORED:
- if (!testFlag(WithinSetStyle)) {
+ if (!testFlag(WithinSetStyle) && !testFlag(WithinSetGeometry)) {
if (isFullScreen_sys())
- handleWindowStateChange(Qt::WindowFullScreen);
+ handleWindowStateChange(
+ Qt::WindowFullScreen
+ | (testFlag(MaximizeToFullScreen) ? Qt::WindowMaximized : Qt::WindowNoState));
else if (m_windowState != Qt::WindowNoState && !testFlag(MaximizeToFullScreen))
handleWindowStateChange(Qt::WindowNoState);
}
@@ -1529,7 +1631,6 @@ void QWindowsWindow::handleGeometryChange()
{
const QRect previousGeometry = m_data.geometry;
m_data.geometry = geometry_sys();
- QPlatformWindow::setGeometry(m_data.geometry);
QWindowSystemInterface::handleGeometryChange(window(), m_data.geometry);
// QTBUG-32121: OpenGL/normal windows (with exception of ANGLE) do not receive
// expose events when shrinking, synthesize.
@@ -1651,8 +1752,11 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
BeginPaint(hwnd, &ps);
// Observed painting problems with Aero style disabled (QTBUG-7865).
- if (Q_UNLIKELY(testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered) && !dwmIsCompositionEnabled()))
+ if (Q_UNLIKELY(!dwmIsCompositionEnabled())
+ && ((testFlag(OpenGLSurface) && testFlag(OpenGLDoubleBuffered)) || testFlag(VulkanSurface)))
+ {
SelectClipRgn(ps.hdc, NULL);
+ }
// If the a window is obscured by another window (such as a child window)
// we still need to send isExposed=true, for compatibility.
@@ -1708,20 +1812,16 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
return result;
}
-void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
+void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
{
qCDebug(lcQpaWindows) << __FUNCTION__ << this << window()
<< "\n from " << m_windowState << " to " << state;
m_windowState = state;
QWindowSystemInterface::handleWindowStateChanged(window(), state);
- switch (state) {
- case Qt::WindowMinimized:
+ if (state & Qt::WindowMinimized) {
handleHidden();
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // Tell QQuickWindow to stop rendering now.
- break;
- case Qt::WindowMaximized:
- case Qt::WindowFullScreen:
- case Qt::WindowNoState: {
+ } else {
// QTBUG-17548: We send expose events when receiving WM_Paint, but for
// layered windows and transient children, we won't receive any WM_Paint.
QWindow *w = window();
@@ -1742,13 +1842,9 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
if (exposeEventsSent && !QWindowsContext::instance()->asyncExpose())
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
}
- break;
- default:
- break;
- }
}
-void QWindowsWindow::setWindowState(Qt::WindowState state)
+void QWindowsWindow::setWindowState(Qt::WindowStates state)
{
if (m_data.hwnd) {
setWindowState_sys(state);
@@ -1779,18 +1875,19 @@ bool QWindowsWindow::isFullScreen_sys() const
to ShowWindow.
*/
-void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
+void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
{
- const Qt::WindowState oldState = m_windowState;
+ const Qt::WindowStates oldState = m_windowState;
if (oldState == newState)
return;
qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window()
<< " from " << oldState << " to " << newState;
const bool visible = isVisible();
+ auto stateChange = oldState ^ newState;
- if ((oldState == Qt::WindowFullScreen) != (newState == Qt::WindowFullScreen)) {
- if (newState == Qt::WindowFullScreen) {
+ if (stateChange & Qt::WindowFullScreen) {
+ if (newState & Qt::WindowFullScreen) {
#ifndef Q_FLATTEN_EXPOSE
UINT newStyle = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
#else
@@ -1801,7 +1898,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
// Window state but emulated by changing geometry and style.
if (!m_savedStyle) {
m_savedStyle = style();
- if (oldState == Qt::WindowMinimized || oldState == Qt::WindowMaximized) {
+ if ((oldState & Qt::WindowMinimized) || (oldState & Qt::WindowMaximized)) {
const QRect nf = normalFrameGeometry(m_data.hwnd);
if (nf.isValid())
m_savedFrameGeometry = nf;
@@ -1809,6 +1906,8 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
m_savedFrameGeometry = frameGeometry_sys();
}
}
+ if (newState & Qt::WindowMaximized)
+ setFlag(MaximizeToFullScreen);
if (m_savedStyle & WS_SYSMENU)
newStyle |= WS_SYSMENU;
if (visible)
@@ -1822,15 +1921,23 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
if (!screen)
screen = QGuiApplication::primaryScreen();
const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry;
- const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
- const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
- setFlag(SynchronousGeometryChangeEvent);
- SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
- if (!wasSync)
- clearFlag(SynchronousGeometryChangeEvent);
- QWindowSystemInterface::handleGeometryChange(window(), r);
- QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
- } else if (newState != Qt::WindowMinimized) {
+
+ if (newState & Qt::WindowMinimized) {
+ setMinimizedGeometry(m_data.hwnd, r);
+ if (stateChange & Qt::WindowMaximized)
+ setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
+ } else {
+ const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
+ const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
+ setFlag(SynchronousGeometryChangeEvent);
+ SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf);
+ if (!wasSync)
+ clearFlag(SynchronousGeometryChangeEvent);
+ clearFlag(MaximizeToFullScreen);
+ QWindowSystemInterface::handleGeometryChange(window(), r);
+ QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
+ }
+ } else {
// Restore saved state.
unsigned newStyle = m_savedStyle ? m_savedStyle : style();
if (visible)
@@ -1844,43 +1951,58 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
if (!screen->geometry().intersects(m_savedFrameGeometry))
m_savedFrameGeometry.moveTo(screen->geometry().topLeft());
- UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
- if (!m_savedFrameGeometry.isValid())
- swpf |= SWP_NOSIZE | SWP_NOMOVE;
- const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
- setFlag(SynchronousGeometryChangeEvent);
- // After maximized/fullscreen; the window can be in a maximized state. Clear
- // it before applying the normal geometry.
- if (windowVisibility_sys(m_data.hwnd) == QWindow::Maximized)
- ShowWindow(m_data.hwnd, SW_SHOWNOACTIVATE);
- SetWindowPos(m_data.hwnd, 0, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(),
- m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf);
- if (!wasSync)
- clearFlag(SynchronousGeometryChangeEvent);
- // preserve maximized state
- if (visible) {
- setFlag(WithinMaximize);
- ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
- clearFlag(WithinMaximize);
+ if (newState & Qt::WindowMinimized) {
+ setMinimizedGeometry(m_data.hwnd, m_savedFrameGeometry);
+ if (stateChange & Qt::WindowMaximized)
+ setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
+ } else {
+ UINT swpf = SWP_FRAMECHANGED | SWP_NOZORDER | SWP_NOACTIVATE;
+ if (!m_savedFrameGeometry.isValid())
+ swpf |= SWP_NOSIZE | SWP_NOMOVE;
+ const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
+ setFlag(SynchronousGeometryChangeEvent);
+ // After maximized/fullscreen; the window can be in a maximized state. Clear
+ // it before applying the normal geometry.
+ if (windowVisibility_sys(m_data.hwnd) == QWindow::Maximized)
+ ShowWindow(m_data.hwnd, SW_SHOWNOACTIVATE);
+ SetWindowPos(m_data.hwnd, 0, m_savedFrameGeometry.x(), m_savedFrameGeometry.y(),
+ m_savedFrameGeometry.width(), m_savedFrameGeometry.height(), swpf);
+ if (!wasSync)
+ clearFlag(SynchronousGeometryChangeEvent);
+ // preserve maximized state
+ if (visible) {
+ setFlag(WithinMaximize);
+ ShowWindow(m_data.hwnd,
+ (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNA);
+ clearFlag(WithinMaximize);
+ }
}
m_savedStyle = 0;
m_savedFrameGeometry = QRect();
}
- } else if ((oldState == Qt::WindowMaximized) != (newState == Qt::WindowMaximized)) {
- if (visible && !(newState == Qt::WindowMinimized)) {
+ } else if ((oldState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized)) {
+ if (visible && !(newState & Qt::WindowMinimized)) {
setFlag(WithinMaximize);
- if (newState == Qt::WindowFullScreen)
+ if (newState & Qt::WindowFullScreen)
setFlag(MaximizeToFullScreen);
- ShowWindow(m_data.hwnd, (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
+ ShowWindow(m_data.hwnd,
+ (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
clearFlag(WithinMaximize);
clearFlag(MaximizeToFullScreen);
+ } else if (visible && (oldState & newState & Qt::WindowMinimized)) {
+ // change of the maximized state while keeping minimized
+ setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
}
}
- if ((oldState == Qt::WindowMinimized) != (newState == Qt::WindowMinimized)) {
- if (visible)
- ShowWindow(m_data.hwnd, (newState == Qt::WindowMinimized) ? SW_MINIMIZE :
- (newState == Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNORMAL);
+ if (stateChange & Qt::WindowMinimized) {
+ if (visible) {
+ ShowWindow(m_data.hwnd,
+ (newState & Qt::WindowMinimized) ? SW_MINIMIZE :
+ (newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNORMAL);
+ if ((newState & Qt::WindowMinimized) && (stateChange & Qt::WindowMaximized))
+ setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
+ }
}
qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << this << window() << newState;
}
@@ -1972,7 +2094,7 @@ void QWindowsWindow::setOpacity(qreal level)
m_opacity = level;
if (m_data.hwnd)
setWindowOpacity(m_data.hwnd, m_data.flags,
- window()->format().hasAlpha(), testFlag(OpenGLSurface),
+ window()->format().hasAlpha(), testFlag(OpenGLSurface) || testFlag(VulkanSurface),
level);
}
}
@@ -2141,7 +2263,7 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const
hint.applyToMinMaxInfo(m_data.hwnd, mmi);
}
- if ((testFlag(WithinMaximize) || (window()->windowState() == Qt::WindowMinimized))
+ if ((testFlag(WithinMaximize) || (window()->windowStates() & Qt::WindowMinimized))
&& (m_data.flags & Qt::FramelessWindowHint)) {
// This block fixes QTBUG-8361: Frameless windows shouldn't cover the
// taskbar when maximized
@@ -2171,7 +2293,7 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re
// QTBUG-32663, suppress resize cursor for fixed size windows.
const QWindow *w = window();
if (!w->isTopLevel() // Task 105852, minimized windows need to respond to user input.
- || (m_windowState != Qt::WindowNoState && m_windowState != Qt::WindowActive)
+ || !(m_windowState & ~Qt::WindowActive)
|| (m_data.flags & Qt::FramelessWindowHint)) {
return false;
}
@@ -2362,6 +2484,16 @@ bool QWindowsWindow::isTopLevel() const
return window()->isTopLevel() && !m_data.embedded;
}
+QWindowsMenuBar *QWindowsWindow::menuBar() const
+{
+ return m_menuBar.data();
+}
+
+void QWindowsWindow::setMenuBar(QWindowsMenuBar *mb)
+{
+ m_menuBar = mb;
+}
+
/*!
\brief Sets custom margins to be added to the default margins determined by
the windows style in the handling of the WM_NCCALCSIZE message.
@@ -2390,11 +2522,27 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins)
void *QWindowsWindow::surface(void *nativeConfig, int *err)
{
-#ifdef QT_NO_OPENGL
+#if QT_CONFIG(vulkan)
+ Q_UNUSED(nativeConfig);
+ Q_UNUSED(err);
+ if (window()->surfaceType() == QSurface::VulkanSurface) {
+ if (!m_vkSurface) {
+ QVulkanInstance *inst = window()->vulkanInstance();
+ if (inst)
+ m_vkSurface = static_cast<QWindowsVulkanInstance *>(inst->handle())->createSurface(handle());
+ else
+ qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?");
+ }
+ // Different semantics for VkSurfaces: the return value is the address,
+ // not the value, given that this is a 64-bit handle even on x86.
+ return &m_vkSurface;
+ }
+#elif defined(QT_NO_OPENGL)
Q_UNUSED(err)
Q_UNUSED(nativeConfig)
return 0;
-#else
+#endif
+#ifndef QT_NO_OPENGL
if (!m_surface) {
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, err);
@@ -2406,6 +2554,14 @@ void *QWindowsWindow::surface(void *nativeConfig, int *err)
void QWindowsWindow::invalidateSurface()
{
+#if QT_CONFIG(vulkan)
+ if (m_vkSurface) {
+ QVulkanInstance *inst = window()->vulkanInstance();
+ if (inst)
+ static_cast<QWindowsVulkanInstance *>(inst->handle())->destroySurface(m_vkSurface);
+ m_vkSurface = 0;
+ }
+#endif
#ifndef QT_NO_OPENGL
if (m_surface) {
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext())
diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h
index aa8ce7e73a..f0789e5167 100644
--- a/src/plugins/platforms/windows/qwindowswindow.h
+++ b/src/plugins/platforms/windows/qwindowswindow.h
@@ -41,14 +41,20 @@
#define QWINDOWSWINDOW_H
#include <QtCore/qt_windows.h>
+#include <QtCore/QPointer>
#include "qwindowscursor.h"
#include <qpa/qplatformwindow.h>
#include <QtPlatformHeaders/qwindowswindowfunctions.h>
+#if QT_CONFIG(vulkan)
+#include "qwindowsvulkaninstance.h"
+#endif
+
QT_BEGIN_NAMESPACE
class QWindowsOleDropTarget;
+class QWindowsMenuBar;
class QDebug;
struct QWindowsGeometryHint
@@ -75,9 +81,10 @@ struct QWindowsGeometryHint
struct QWindowCreationContext
{
- QWindowCreationContext(const QWindow *w, const QRect &r,
- const QMargins &customMargins,
- DWORD style, DWORD exStyle);
+ explicit QWindowCreationContext(const QWindow *w,
+ const QRect &geometryIn, const QRect &geometry,
+ const QMargins &customMargins,
+ DWORD style, DWORD exStyle);
void applyToMinMaxInfo(MINMAXINFO *mmi) const
{ geometryHint.applyToMinMaxInfo(style, exStyle, mmi); }
@@ -85,7 +92,8 @@ struct QWindowCreationContext
const QWindow *window;
DWORD style;
DWORD exStyle;
- QRect requestedGeometry;
+ QRect requestedGeometryIn; // QWindow scaled
+ QRect requestedGeometry; // after QPlatformWindow::initialGeometry()
QRect obtainedGeometry;
QMargins margins;
QMargins customMargins; // User-defined, additional frame for WM_NCCALCSIZE
@@ -188,6 +196,7 @@ public:
{
AutoMouseCapture = 0x1, //! Automatic mouse capture on button press.
WithinSetParent = 0x2,
+ WithinSetGeometry = 0x8,
OpenGLSurface = 0x10,
OpenGL_ES2 = 0x20,
OpenGLDoubleBuffered = 0x40,
@@ -208,11 +217,14 @@ public:
Compositing = 0x200000,
HasBorderInFullScreen = 0x400000,
WithinDpiChanged = 0x800000,
+ VulkanSurface = 0x1000000
};
QWindowsWindow(QWindow *window, const QWindowsWindowData &data);
~QWindowsWindow();
+ void initialize() override;
+
using QPlatformWindow::screenForGeometry;
QSurfaceFormat format() const override { return m_format; }
@@ -230,7 +242,7 @@ public:
QPoint mapFromGlobal(const QPoint &pos) const override;
void setWindowFlags(Qt::WindowFlags flags) override;
- void setWindowState(Qt::WindowState state) override;
+ void setWindowState(Qt::WindowStates state) override;
void setParent(const QPlatformWindow *window) override;
@@ -264,6 +276,9 @@ public:
HWND handle() const override { return m_data.hwnd; }
bool isTopLevel() const override;
+ QWindowsMenuBar *menuBar() const;
+ void setMenuBar(QWindowsMenuBar *mb);
+
QMargins customMargins() const { return m_data.customMargins; }
void setCustomMargins(const QMargins &m);
@@ -325,7 +340,7 @@ private:
inline void show_sys() const;
inline QWindowsWindowData setWindowFlags_sys(Qt::WindowFlags wt, unsigned flags = 0) const;
inline bool isFullScreen_sys() const;
- inline void setWindowState_sys(Qt::WindowState newState);
+ inline void setWindowState_sys(Qt::WindowStates newState);
inline void setParent_sys(const QPlatformWindow *parent);
inline void updateTransientParent() const;
void destroyWindow();
@@ -333,14 +348,15 @@ private:
void setDropSiteEnabled(bool enabled);
void updateDropSite(bool topLevel);
void handleGeometryChange();
- void handleWindowStateChange(Qt::WindowState state);
+ void handleWindowStateChange(Qt::WindowStates state);
inline void destroyIcon();
void fireExpose(const QRegion &region, bool force=false);
mutable QWindowsWindowData m_data;
+ QPointer<QWindowsMenuBar> m_menuBar;
mutable unsigned m_flags = WithinCreate;
HDC m_hdc = 0;
- Qt::WindowState m_windowState = Qt::WindowNoState;
+ Qt::WindowStates m_windowState = Qt::WindowNoState;
qreal m_opacity = 1;
#ifndef QT_NO_CURSOR
CursorHandlePtr m_cursor;
@@ -352,6 +368,11 @@ private:
HICON m_iconSmall = 0;
HICON m_iconBig = 0;
void *m_surface = nullptr;
+
+#if QT_CONFIG(vulkan)
+ // note: intentionally not using void * in order to avoid breaking x86
+ VkSurfaceKHR m_vkSurface = 0;
+#endif
};
#ifndef QT_NO_DEBUG_STREAM
@@ -361,6 +382,7 @@ QDebug operator<<(QDebug d, const MINMAXINFO &i);
QDebug operator<<(QDebug d, const NCCALCSIZE_PARAMS &p);
QDebug operator<<(QDebug d, const WINDOWPLACEMENT &);
QDebug operator<<(QDebug d, const WINDOWPOS &);
+QDebug operator<<(QDebug d, const GUID &guid);
#endif // !QT_NO_DEBUG_STREAM
// ---------- QWindowsGeometryHint inline functions.
diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri
index 6d01d05fcc..3ecd164c74 100644
--- a/src/plugins/platforms/windows/windows.pri
+++ b/src/plugins/platforms/windows/windows.pri
@@ -24,6 +24,7 @@ SOURCES += \
$$PWD/qwindowscursor.cpp \
$$PWD/qwindowsinputcontext.cpp \
$$PWD/qwindowstheme.cpp \
+ $$PWD/qwindowsmenu.cpp \
$$PWD/qwindowsdialoghelpers.cpp \
$$PWD/qwindowsservices.cpp \
$$PWD/qwindowsnativeinterface.cpp \
@@ -31,6 +32,7 @@ SOURCES += \
$$PWD/qwin10helpers.cpp
HEADERS += \
+ $$PWD/qwindowscombase.h \
$$PWD/qwindowswindow.h \
$$PWD/qwindowsintegration.h \
$$PWD/qwindowscontext.h \
@@ -44,6 +46,7 @@ HEADERS += \
$$PWD/qwindowscursor.h \
$$PWD/qwindowsinputcontext.h \
$$PWD/qwindowstheme.h \
+ $$PWD/qwindowsmenu.h \
$$PWD/qwindowsdialoghelpers.h \
$$PWD/qwindowsservices.h \
$$PWD/qwindowsnativeinterface.h \
@@ -69,6 +72,16 @@ qtConfig(dynamicgl) {
HEADERS += $$PWD/qwindowseglcontext.h
}
+qtConfig(systemtrayicon) {
+ SOURCES += $$PWD/qwindowssystemtrayicon.cpp
+ HEADERS += $$PWD/qwindowssystemtrayicon.h
+}
+
+qtConfig(vulkan) {
+ SOURCES += $$PWD/qwindowsvulkaninstance.cpp
+ HEADERS += $$PWD/qwindowsvulkaninstance.h
+}
+
qtConfig(clipboard) {
SOURCES += $$PWD/qwindowsclipboard.cpp
HEADERS += $$PWD/qwindowsclipboard.h
diff --git a/src/plugins/platforms/windows/windows.pro b/src/plugins/platforms/windows/windows.pro
index 23168c10dc..4d788d91f8 100644
--- a/src/plugins/platforms/windows/windows.pro
+++ b/src/plugins/platforms/windows/windows.pro
@@ -5,6 +5,8 @@ QT += \
eventdispatcher_support-private accessibility_support-private \
fontdatabase_support-private theme_support-private
+qtConfig(vulkan): QT += vulkan_support-private
+
LIBS += -lgdi32 -ldwmapi
include(windows.pri)
diff --git a/src/plugins/platforms/winrt/qwinrtdrag.cpp b/src/plugins/platforms/winrt/qwinrtdrag.cpp
index 15ae024d20..43c406e1fb 100644
--- a/src/plugins/platforms/winrt/qwinrtdrag.cpp
+++ b/src/plugins/platforms/winrt/qwinrtdrag.cpp
@@ -773,12 +773,6 @@ void QWinRTDrag::setDropTarget(QWindow *target)
m_dragTarget = target;
}
-QMimeData *QWinRTDrag::platformDropData()
-{
- qCDebug(lcQpaMime) << __FUNCTION__;
- return m_mimeData;
-}
-
void QWinRTDrag::setUiElement(ComPtr<ABI::Windows::UI::Xaml::IUIElement> &element)
{
qCDebug(lcQpaMime) << __FUNCTION__;
diff --git a/src/plugins/platforms/winrt/qwinrtdrag.h b/src/plugins/platforms/winrt/qwinrtdrag.h
index 6cbabfbf41..2371201507 100644
--- a/src/plugins/platforms/winrt/qwinrtdrag.h
+++ b/src/plugins/platforms/winrt/qwinrtdrag.h
@@ -94,7 +94,6 @@ public:
virtual ~QWinRTDrag();
static QWinRTDrag *instance();
- QMimeData *platformDropData(void) override;
Qt::DropAction drag(QDrag *) override;
void setDropTarget(QWindow *target);
diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
index 58375d331c..f037c516b5 100644
--- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp
+++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp
@@ -414,10 +414,11 @@ QDateTime QWinRTFileEngine::fileTime(FileTime type) const
HRESULT hr;
DateTime dateTime = { 0 };
switch (type) {
- case CreationTime:
+ case BirthTime:
hr = d->file->get_DateCreated(&dateTime);
RETURN_IF_FAILED("Failed to get file creation time", return QDateTime());
break;
+ case MetadataChangeTime:
case ModificationTime:
case AccessTime: {
ComPtr<IAsyncOperation<FileProperties::BasicProperties *>> op;
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.cpp b/src/plugins/platforms/winrt/qwinrtwindow.cpp
index c40a1b8c45..cbf0ba36c9 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.cpp
+++ b/src/plugins/platforms/winrt/qwinrtwindow.cpp
@@ -91,7 +91,7 @@ public:
QSurfaceFormat surfaceFormat;
QString windowTitle;
- Qt::WindowState state;
+ Qt::WindowStates state;
EGLDisplay display;
EGLSurface surface;
@@ -158,7 +158,7 @@ QWinRTWindow::QWinRTWindow(QWindow *window)
Q_ASSERT_SUCCEEDED(hr);
setWindowFlags(window->flags());
- setWindowState(window->windowState());
+ setWindowState(window->windowStates());
setWindowTitle(window->title());
setGeometry(window->geometry());
@@ -323,7 +323,7 @@ qreal QWinRTWindow::devicePixelRatio() const
return screen()->devicePixelRatio();
}
-void QWinRTWindow::setWindowState(Qt::WindowState state)
+void QWinRTWindow::setWindowState(Qt::WindowStates state)
{
Q_D(QWinRTWindow);
qCDebug(lcQpaWindows) << __FUNCTION__ << this << state;
@@ -331,7 +331,13 @@ void QWinRTWindow::setWindowState(Qt::WindowState state)
if (d->state == state)
return;
- if (state == Qt::WindowFullScreen) {
+ if (state & Qt::WindowMinimized) {
+ setUIElementVisibility(d->uiElement.Get(), false);
+ d->state = state;
+ return;
+ }
+
+ if (state & Qt::WindowFullScreen) {
HRESULT hr;
boolean success;
hr = QEventDispatcherWinRT::runOnXamlThread([&hr, &success]() {
@@ -356,7 +362,7 @@ void QWinRTWindow::setWindowState(Qt::WindowState state)
return;
}
- if (d->state == Qt::WindowFullScreen) {
+ if (d->state & Qt::WindowFullScreen) {
HRESULT hr;
hr = QEventDispatcherWinRT::runOnXamlThread([&hr]() {
ComPtr<IApplicationViewStatics2> applicationViewStatics;
@@ -378,10 +384,7 @@ void QWinRTWindow::setWindowState(Qt::WindowState state)
}
}
- if (state == Qt::WindowMinimized)
- setUIElementVisibility(d->uiElement.Get(), false);
-
- if (d->state == Qt::WindowMinimized || state == Qt::WindowNoState || state == Qt::WindowActive)
+ if (d->state & Qt::WindowMinimized || state == Qt::WindowNoState || state == Qt::WindowActive)
setUIElementVisibility(d->uiElement.Get(), true);
d->state = state;
diff --git a/src/plugins/platforms/winrt/qwinrtwindow.h b/src/plugins/platforms/winrt/qwinrtwindow.h
index 26c2fa800d..a8992450b9 100644
--- a/src/plugins/platforms/winrt/qwinrtwindow.h
+++ b/src/plugins/platforms/winrt/qwinrtwindow.h
@@ -68,7 +68,7 @@ public:
WId winId() const override;
qreal devicePixelRatio() const override;
- void setWindowState(Qt::WindowState state) override;
+ void setWindowState(Qt::WindowStates state) override;
bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h
index 48e774bbb2..fe50afa62a 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglcontext.h
@@ -47,38 +47,28 @@
QT_BEGIN_NAMESPACE
-//####todo remove the noops (looks like their where there in the initial commit)
class QXcbEglContext : public QEGLPlatformContext
{
public:
QXcbEglContext(const QSurfaceFormat &glFormat, QPlatformOpenGLContext *share,
- EGLDisplay display, QXcbConnection *c, const QVariant &nativeHandle)
+ EGLDisplay display, const QVariant &nativeHandle)
: QEGLPlatformContext(glFormat, share, display, 0, nativeHandle)
- , m_connection(c)
{
- Q_XCB_NOOP(m_connection);
}
void swapBuffers(QPlatformSurface *surface)
{
- Q_XCB_NOOP(m_connection);
QEGLPlatformContext::swapBuffers(surface);
- Q_XCB_NOOP(m_connection);
}
bool makeCurrent(QPlatformSurface *surface)
{
- Q_XCB_NOOP(m_connection);
- bool ret = QEGLPlatformContext::makeCurrent(surface);
- Q_XCB_NOOP(m_connection);
- return ret;
+ return QEGLPlatformContext::makeCurrent(surface);
}
void doneCurrent()
{
- Q_XCB_NOOP(m_connection);
QEGLPlatformContext::doneCurrent();
- Q_XCB_NOOP(m_connection);
}
EGLSurface eglSurfaceForPlatformSurface(QPlatformSurface *surface)
@@ -92,9 +82,6 @@ public:
QVariant nativeHandle() const {
return QVariant::fromValue<QEGLNativeContext>(QEGLNativeContext(eglContext(), eglDisplay()));
}
-
-private:
- QXcbConnection *m_connection;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
index 9c52733120..7aa1d631df 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_egl/qxcbeglintegration.cpp
@@ -102,7 +102,6 @@ QPlatformOpenGLContext *QXcbEglIntegration::createPlatformOpenGLContext(QOpenGLC
QXcbEglContext *platformContext = new QXcbEglContext(screen->surfaceFormatFor(context->format()),
context->shareHandle(),
eglDisplay(),
- screen->connection(),
context->nativeHandle());
context->setNativeHandle(platformContext->nativeHandle());
return platformContext;
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
index e2e573f0e1..3bc8590d36 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -167,7 +167,7 @@ static void updateFormatFromContext(QSurfaceFormat &format)
QGLXContext::QGLXContext(QXcbScreen *screen, const QSurfaceFormat &format, QPlatformOpenGLContext *share,
const QVariant &nativeHandle)
: QPlatformOpenGLContext()
- , m_display(DISPLAY_FROM_XCB(screen))
+ , m_display(static_cast<Display *>(screen->connection()->xlib_display()))
, m_config(0)
, m_context(0)
, m_shareContext(0)
@@ -196,7 +196,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
if (share)
m_shareContext = static_cast<const QGLXContext*>(share)->glxContext();
- GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(screen),screen->screenNumber(),m_format);
+ GLXFBConfig config = qglx_findConfig(m_display, screen->screenNumber(), m_format);
m_config = config;
XVisualInfo *visualInfo = 0;
Window window = 0; // Temporary window used to query OpenGL context
@@ -304,10 +304,10 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
// Get the basic surface format details
if (m_context)
- qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(screen), config);
+ qglx_surfaceFormatFromGLXFBConfig(&m_format, m_display, config);
// Create a temporary window so that we can make the new context current
- window = createDummyWindow(DISPLAY_FROM_XCB(screen), config, screen->screenNumber(), screen->root());
+ window = createDummyWindow(m_display, config, screen->screenNumber(), screen->root());
} else {
// requesting an OpenGL ES context requires glXCreateContextAttribsARB, so bail out
if (m_format.renderableType() == QSurfaceFormat::OpenGLES)
@@ -325,7 +325,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
}
// Create a temporary window so that we can make the new context current
- window = createDummyWindow(DISPLAY_FROM_XCB(screen), visualInfo, screen->screenNumber(), screen->root());
+ window = createDummyWindow(m_display, visualInfo, screen->screenNumber(), screen->root());
XFree(visualInfo);
}
@@ -360,7 +360,7 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share, const
// Use the provided Display, if available. If not, use our own. It may still work.
Display *dpy = handle.display();
if (!dpy)
- dpy = DISPLAY_FROM_XCB(screen);
+ dpy = m_display;
// Legacy contexts created using glXCreateContext are created using a visual
// and the FBConfig cannot be queried. The only way to adapt these contexts
@@ -665,8 +665,10 @@ void QGLXContext::queryDummyContext()
Display *display = glXGetCurrentDisplay();
if (!display) {
// FIXME: Since Qt 5.6 we don't need to check whether primary screen is NULL
- if (QScreen *screen = QGuiApplication::primaryScreen())
- display = DISPLAY_FROM_XCB(static_cast<QXcbScreen *>(screen->handle()));
+ if (QScreen *screen = QGuiApplication::primaryScreen()) {
+ QXcbScreen *xcbScreen = static_cast<QXcbScreen *>(screen->handle());
+ display = static_cast<Display *>(xcbScreen->connection()->xlib_display());
+ }
}
const char *glxvendor = glXGetClientString(display, GLX_VENDOR);
if (glxvendor && !strcmp(glxvendor, "ATI")) {
@@ -729,8 +731,7 @@ void QGLXContext::queryDummyContext()
bool QGLXContext::supportsThreading()
{
- if (!m_queriedDummyContext)
- queryDummyContext();
+ queryDummyContext();
return m_supportsThreading;
}
@@ -738,9 +739,10 @@ QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface)
: QPlatformOffscreenSurface(offscreenSurface)
, m_screen(static_cast<QXcbScreen *>(offscreenSurface->screen()->handle()))
, m_format(m_screen->surfaceFormatFor(offscreenSurface->requestedFormat()))
+ , m_display(static_cast<Display *>(m_screen->connection()->xlib_display()))
, m_pbuffer(0)
{
- GLXFBConfig config = qglx_findConfig(DISPLAY_FROM_XCB(m_screen), m_screen->screenNumber(), m_format);
+ GLXFBConfig config = qglx_findConfig(m_display, m_screen->screenNumber(), m_format);
if (config) {
const int attributes[] = {
@@ -751,17 +753,17 @@ QGLXPbuffer::QGLXPbuffer(QOffscreenSurface *offscreenSurface)
None
};
- m_pbuffer = glXCreatePbuffer(DISPLAY_FROM_XCB(m_screen), config, attributes);
+ m_pbuffer = glXCreatePbuffer(m_display, config, attributes);
if (m_pbuffer)
- qglx_surfaceFormatFromGLXFBConfig(&m_format, DISPLAY_FROM_XCB(m_screen), config);
+ qglx_surfaceFormatFromGLXFBConfig(&m_format, m_display, config);
}
}
QGLXPbuffer::~QGLXPbuffer()
{
if (m_pbuffer)
- glXDestroyPbuffer(DISPLAY_FROM_XCB(m_screen), m_pbuffer);
+ glXDestroyPbuffer(m_display, m_pbuffer);
}
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
index 3dfe0ac618..f6372582db 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.h
@@ -108,6 +108,7 @@ public:
private:
QXcbScreen *m_screen;
QSurfaceFormat m_format;
+ Display *m_display;
GLXPbuffer m_pbuffer;
};
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
index fea365cabc..377066df61 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp
@@ -108,18 +108,13 @@ bool QXcbGlxIntegration::initialize(QXcbConnection *connection)
m_glx_first_event = reply->first_event;
- xcb_generic_error_t *error = 0;
- xcb_glx_query_version_cookie_t xglx_query_cookie = xcb_glx_query_version(m_connection->xcb_connection(),
- XCB_GLX_MAJOR_VERSION,
- XCB_GLX_MINOR_VERSION);
- xcb_glx_query_version_reply_t *xglx_query = xcb_glx_query_version_reply(m_connection->xcb_connection(),
- xglx_query_cookie, &error);
- if (!xglx_query || error) {
+ auto xglx_query = Q_XCB_REPLY(xcb_glx_query_version, m_connection->xcb_connection(),
+ XCB_GLX_MAJOR_VERSION,
+ XCB_GLX_MINOR_VERSION);
+ if (!xglx_query) {
qCWarning(lcQpaGl) << "QXcbConnection: Failed to initialize GLX";
- free(error);
return false;
}
- free(xglx_query);
#endif
m_native_interface_handler.reset(new QXcbGlxNativeInterfaceHandler(connection->nativeInterface()));
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp
index 8df8b28f72..145a11a5e3 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxwindow.cpp
@@ -41,6 +41,7 @@
#include "qxcbscreen.h"
#include <QtGlxSupport/private/qglxconvenience_p.h>
+#include <QDebug>
QT_BEGIN_NAMESPACE
@@ -58,13 +59,28 @@ const xcb_visualtype_t *QXcbGlxWindow::createVisual()
QXcbScreen *scr = xcbScreen();
if (!scr)
return Q_NULLPTR;
- XVisualInfo *visualInfo = qglx_findVisualInfo(DISPLAY_FROM_XCB(scr), scr->screenNumber(), &m_format);
+
+ qDebug(lcQpaGl) << "Requested format before FBConfig/Visual selection:" << m_format;
+
+ Display *dpy = static_cast<Display *>(scr->connection()->xlib_display());
+ const char *glxExts = glXQueryExtensionsString(dpy, scr->screenNumber());
+ int flags = 0;
+ if (glxExts) {
+ qCDebug(lcQpaGl, "Available GLX extensions: %s", glxExts);
+ if (strstr(glxExts, "GLX_EXT_framebuffer_sRGB") || strstr(glxExts, "GLX_ARB_framebuffer_sRGB"))
+ flags |= QGLX_SUPPORTS_SRGB;
+ }
+
+ XVisualInfo *visualInfo = qglx_findVisualInfo(dpy, scr->screenNumber(), &m_format, GLX_WINDOW_BIT, flags);
if (!visualInfo) {
qWarning() << "No XVisualInfo for format" << m_format;
return Q_NULLPTR;
}
const xcb_visualtype_t *xcb_visualtype = scr->visualForId(visualInfo->visualid);
XFree(visualInfo);
+
+ qDebug(lcQpaGl) << "Got format:" << m_format;
+
return xcb_visualtype;
}
diff --git a/src/plugins/platforms/xcb/nativepainting/nativepainting.pri b/src/plugins/platforms/xcb/nativepainting/nativepainting.pri
new file mode 100644
index 0000000000..78ed00843f
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/nativepainting.pri
@@ -0,0 +1,22 @@
+qtConfig(xcb-native-painting) {
+ qtConfig(xrender): QMAKE_USE += xrender
+ qtConfig(fontconfig): QMAKE_USE_PRIVATE += freetype
+
+ INCLUDEPATH += $$PWD
+ HEADERS += \
+ $$PWD/qtessellator_p.h \
+ $$PWD/qpixmap_x11_p.h \
+ $$PWD/qpaintengine_x11_p.h \
+ $$PWD/qt_x11_p.h \
+ $$PWD/qcolormap_x11_p.h \
+ $$PWD/qbackingstore_x11_p.h \
+ $$PWD/qxcbnativepainting.h
+
+ SOURCES += \
+ $$PWD/qtessellator.cpp \
+ $$PWD/qpixmap_x11.cpp \
+ $$PWD/qpaintengine_x11.cpp \
+ $$PWD/qcolormap_x11.cpp \
+ $$PWD/qbackingstore_x11.cpp \
+ $$PWD/qxcbnativepainting.cpp
+}
diff --git a/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp
new file mode 100644
index 0000000000..2dd2cdd9e3
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp
@@ -0,0 +1,203 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbackingstore_x11_p.h"
+#include "qxcbwindow.h"
+#include "qpixmap_x11_p.h"
+
+#include <private/qhighdpiscaling_p.h>
+#include <QPainter>
+
+#if QT_CONFIG(xrender)
+# include <X11/extensions/Xrender.h>
+#endif
+
+#include <X11/Xlib.h>
+
+#ifndef None
+#define None 0L
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QXcbNativeBackingStore::QXcbNativeBackingStore(QWindow *window)
+ : QPlatformBackingStore(window)
+ , m_translucentBackground(false)
+{
+ if (QXcbWindow *w = static_cast<QXcbWindow *>(window->handle()))
+ m_translucentBackground = w->connection()->hasXRender() && QImage::toPixelFormat(w->imageFormat()).alphaSize() > 0;
+}
+
+QXcbNativeBackingStore::~QXcbNativeBackingStore()
+{}
+
+QPaintDevice *QXcbNativeBackingStore::paintDevice()
+{
+ return &m_pixmap;
+}
+
+void QXcbNativeBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
+ if (m_pixmap.isNull())
+ return;
+
+ QSize pixmapSize = m_pixmap.size();
+
+ QRegion clipped = region;
+ clipped &= QRect(QPoint(), QHighDpi::toNativePixels(window->size(), window));
+ clipped &= QRect(0, 0, pixmapSize.width(), pixmapSize.height()).translated(-offset);
+
+ QRect br = clipped.boundingRect();
+ if (br.isNull())
+ return;
+
+ QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
+ if (!platformWindow) {
+ qWarning("QXcbBackingStore::flush: QWindow has no platform window (QTBUG-32681)");
+ return;
+ }
+
+ Window wid = platformWindow->xcb_window();
+ Pixmap pid = qt_x11PixmapHandle(m_pixmap);
+
+ QVector<XRectangle> clipRects = qt_region_to_xrectangles(clipped);
+
+#if QT_CONFIG(xrender)
+ if (m_translucentBackground)
+ {
+ XWindowAttributes attrib;
+ XGetWindowAttributes(display(), wid, &attrib);
+ XRenderPictFormat *format = XRenderFindVisualFormat(display(), attrib.visual);
+
+ Picture srcPic = qt_x11PictureHandle(m_pixmap);
+ Picture dstPic = XRenderCreatePicture(display(), wid, format, 0, 0);
+
+ XRenderSetPictureClipRectangles(display(), dstPic, 0, 0, clipRects.constData(), clipRects.size());
+
+ XRenderComposite(display(), PictOpSrc, srcPic, None, dstPic,
+ br.x() + offset.x(), br.y() + offset.y(),
+ 0, 0,
+ br.x(), br.y(),
+ br.width(), br.height());
+
+ XRenderFreePicture(display(), dstPic);
+ }
+ else
+#endif
+ {
+ GC gc = XCreateGC(display(), wid, 0, Q_NULLPTR);
+
+ if (clipRects.size() != 1)
+ XSetClipRectangles(display(), gc, 0, 0, clipRects.data(), clipRects.size(), YXBanded);
+
+ XCopyArea(display(), pid, wid, gc, br.x() + offset.x(), br.y() + offset.y(), br.width(), br.height(), br.x(), br.y());
+ XFreeGC(display(), gc);
+ }
+
+
+ if (platformWindow->needsSync()) {
+ platformWindow->updateSyncRequestCounter();
+ } else {
+ XFlush(display());
+ }
+}
+
+QImage QXcbNativeBackingStore::toImage() const
+{
+ return m_pixmap.toImage();
+}
+
+void QXcbNativeBackingStore::resize(const QSize &size, const QRegion &staticContents)
+{
+ if (size == m_pixmap.size())
+ return;
+
+ QPixmap newPixmap(size);
+
+#if QT_CONFIG(xrender)
+ if (m_translucentBackground && newPixmap.depth() != 32)
+ qt_x11Pixmap(newPixmap)->convertToARGB32();
+#endif
+
+ if (!m_pixmap.isNull()) {
+ Pixmap from = qt_x11PixmapHandle(m_pixmap);
+ Pixmap to = qt_x11PixmapHandle(newPixmap);
+ QRect br = staticContents.boundingRect().intersected(QRect(QPoint(0, 0), size));
+
+ if (!br.isEmpty()) {
+ GC gc = XCreateGC(display(), to, 0, Q_NULLPTR);
+ XCopyArea(display(), from, to, gc, br.x(), br.y(), br.width(), br.height(), br.x(), br.y());
+ XFreeGC(display(), gc);
+ }
+ }
+
+ m_pixmap = newPixmap;
+}
+
+bool QXcbNativeBackingStore::scroll(const QRegion &area, int dx, int dy)
+{
+ if (m_pixmap.isNull())
+ return false;
+
+ QRect rect = area.boundingRect();
+ Pixmap pix = qt_x11PixmapHandle(m_pixmap);
+
+ GC gc = XCreateGC(display(), pix, 0, Q_NULLPTR);
+ XCopyArea(display(), pix, pix, gc,
+ rect.x(), rect.y(), rect.width(), rect.height(),
+ rect.x()+dx, rect.y()+dy);
+ XFreeGC(display(), gc);
+ return true;
+}
+
+void QXcbNativeBackingStore::beginPaint(const QRegion &region)
+{
+#if QT_CONFIG(xrender)
+ if (m_translucentBackground) {
+ const QVector<XRectangle> xrects = qt_region_to_xrectangles(region);
+ const XRenderColor color = { 0, 0, 0, 0 };
+ XRenderFillRectangles(display(), PictOpSrc,
+ qt_x11PictureHandle(m_pixmap), &color,
+ xrects.constData(), xrects.size());
+ }
+#else
+ Q_UNUSED(region);
+#endif
+}
+
+Display *QXcbNativeBackingStore::display() const
+{
+ return static_cast<Display *>(static_cast<QXcbWindow *>(window()->handle())->connection()->xlib_display());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11_p.h
new file mode 100644
index 0000000000..5f4c24ec11
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11_p.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBACKINGSTORE_X11_H
+#define QBACKINGSTORE_X11_H
+
+#include <qpa/qplatformbackingstore.h>
+
+typedef struct _XDisplay Display;
+
+QT_BEGIN_NAMESPACE
+
+class QXcbWindow;
+
+class QXcbNativeBackingStore : public QPlatformBackingStore
+{
+public:
+ QXcbNativeBackingStore(QWindow *window);
+ ~QXcbNativeBackingStore();
+
+ QPaintDevice *paintDevice() override;
+ void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
+
+ QImage toImage() const override;
+
+ void resize(const QSize &size, const QRegion &staticContents) override;
+ bool scroll(const QRegion &area, int dx, int dy) override;
+
+ void beginPaint(const QRegion &region) override;
+
+private:
+ Display *display() const;
+
+ QPixmap m_pixmap;
+ bool m_translucentBackground;
+};
+
+QT_END_NAMESPACE
+
+#endif // QBACKINGSTORE_X11_H
diff --git a/src/plugins/platforms/xcb/nativepainting/qcolormap_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qcolormap_x11.cpp
new file mode 100644
index 0000000000..8554c5445d
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qcolormap_x11.cpp
@@ -0,0 +1,644 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QVarLengthArray>
+
+#include <private/qguiapplication_p.h>
+
+#include "qcolormap_x11_p.h"
+#include "qxcbnativepainting.h"
+#include "qt_x11_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QXcbColormapPrivate
+{
+public:
+ QXcbColormapPrivate()
+ : ref(1), mode(QXcbColormap::Direct), depth(0),
+ colormap(0), defaultColormap(true),
+ visual(0), defaultVisual(true),
+ r_max(0), g_max(0), b_max(0),
+ r_shift(0), g_shift(0), b_shift(0)
+ {}
+
+ QAtomicInt ref;
+
+ QXcbColormap::Mode mode;
+ int depth;
+
+ Colormap colormap;
+ bool defaultColormap;
+
+ Visual *visual;
+ bool defaultVisual;
+
+ int r_max;
+ int g_max;
+ int b_max;
+
+ uint r_shift;
+ uint g_shift;
+ uint b_shift;
+
+ QVector<QColor> colors;
+ QVector<int> pixels;
+};
+
+static uint right_align(uint v)
+{
+ while (!(v & 0x1))
+ v >>= 1;
+ return v;
+}
+
+static int cube_root(int v)
+{
+ if (v == 1)
+ return 1;
+ // brute force algorithm
+ int i = 1;
+ for (;;) {
+ const int b = i * i * i;
+ if (b <= v) {
+ ++i;
+ } else {
+ --i;
+ break;
+ }
+ }
+ return i;
+}
+
+static Visual *find_visual(Display *display,
+ int screen,
+ int visual_class,
+ int visual_id,
+ int *depth,
+ bool *defaultVisual)
+{
+ XVisualInfo *vi, rvi;
+ int count;
+
+ uint mask = VisualScreenMask;
+ rvi.screen = screen;
+
+ if (visual_class != -1) {
+ rvi.c_class = visual_class;
+ mask |= VisualClassMask;
+ }
+ if (visual_id != -1) {
+ rvi.visualid = visual_id;
+ mask |= VisualIDMask;
+ }
+
+ Visual *visual = DefaultVisual(display, screen);
+ *defaultVisual = true;
+ *depth = DefaultDepth(display, screen);
+
+ vi = XGetVisualInfo(display, mask, &rvi, &count);
+ if (vi) {
+ int best = 0;
+ for (int x = 0; x < count; ++x) {
+ if (vi[x].depth > vi[best].depth)
+ best = x;
+ }
+ if (best >= 0 && best <= count && vi[best].visualid != XVisualIDFromVisual(visual)) {
+ visual = vi[best].visual;
+ *defaultVisual = (visual == DefaultVisual(display, screen));
+ *depth = vi[best].depth;
+ }
+ }
+ if (vi)
+ XFree((char *)vi);
+ return visual;
+}
+
+static void query_colormap(QXcbColormapPrivate *d, int screen)
+{
+ Display *display = X11->display;
+
+ // query existing colormap
+ int q_colors = (((1u << d->depth) > 256u) ? 256u : (1u << d->depth));
+ XColor queried[256];
+ memset(queried, 0, sizeof(queried));
+ for (int x = 0; x < q_colors; ++x)
+ queried[x].pixel = x;
+ XQueryColors(display, d->colormap, queried, q_colors);
+
+ d->colors.resize(q_colors);
+ for (int x = 0; x < q_colors; ++x) {
+ if (queried[x].red == 0
+ && queried[x].green == 0
+ && queried[x].blue == 0
+ && queried[x].pixel != BlackPixel(display, screen)) {
+ // unallocated color cell, skip it
+ continue;
+ }
+
+ d->colors[x] = QColor::fromRgbF(queried[x].red / float(USHRT_MAX),
+ queried[x].green / float(USHRT_MAX),
+ queried[x].blue / float(USHRT_MAX));
+ }
+
+ // for missing colors, find the closest color in the existing colormap
+ Q_ASSERT(d->pixels.size());
+ for (int x = 0; x < d->pixels.size(); ++x) {
+ if (d->pixels.at(x) != -1)
+ continue;
+
+ QRgb rgb;
+ if (d->mode == QXcbColormap::Indexed) {
+ const int r = (x / (d->g_max * d->b_max)) % d->r_max;
+ const int g = (x / d->b_max) % d->g_max;
+ const int b = x % d->b_max;
+ rgb = qRgb((r * 0xff + (d->r_max - 1) / 2) / (d->r_max - 1),
+ (g * 0xff + (d->g_max - 1) / 2) / (d->g_max - 1),
+ (b * 0xff + (d->b_max - 1) / 2) / (d->b_max - 1));
+ } else {
+ rgb = qRgb(x, x, x);
+ }
+
+ // find closest color
+ int mindist = INT_MAX, best = -1;
+ for (int y = 0; y < q_colors; ++y) {
+ int r = qRed(rgb) - (queried[y].red >> 8);
+ int g = qGreen(rgb) - (queried[y].green >> 8);
+ int b = qBlue(rgb) - (queried[y].blue >> 8);
+ int dist = (r * r) + (g * g) + (b * b);
+ if (dist < mindist) {
+ mindist = dist;
+ best = y;
+ }
+ }
+
+ Q_ASSERT(best >= 0 && best < q_colors);
+ if (d->visual->c_class & 1) {
+ XColor xcolor;
+ xcolor.red = queried[best].red;
+ xcolor.green = queried[best].green;
+ xcolor.blue = queried[best].blue;
+ xcolor.pixel = queried[best].pixel;
+
+ if (XAllocColor(display, d->colormap, &xcolor)) {
+ d->pixels[x] = xcolor.pixel;
+ } else {
+ // some weird stuff is going on...
+ d->pixels[x] = (qGray(rgb) < 127
+ ? BlackPixel(display, screen)
+ : WhitePixel(display, screen));
+ }
+ } else {
+ d->pixels[x] = best;
+ }
+ }
+}
+
+static void init_gray(QXcbColormapPrivate *d, int screen)
+{
+ d->pixels.resize(d->r_max);
+
+ for (int g = 0; g < d->g_max; ++g) {
+ const int gray = (g * 0xff + (d->r_max - 1) / 2) / (d->r_max - 1);
+ const QRgb rgb = qRgb(gray, gray, gray);
+
+ d->pixels[g] = -1;
+
+ if (d->visual->c_class & 1) {
+ XColor xcolor;
+ xcolor.red = qRed(rgb) * 0x101;
+ xcolor.green = qGreen(rgb) * 0x101;
+ xcolor.blue = qBlue(rgb) * 0x101;
+ xcolor.pixel = 0ul;
+
+ if (XAllocColor(X11->display, d->colormap, &xcolor))
+ d->pixels[g] = xcolor.pixel;
+ }
+ }
+
+ query_colormap(d, screen);
+}
+
+static void init_indexed(QXcbColormapPrivate *d, int screen)
+{
+ d->pixels.resize(d->r_max * d->g_max * d->b_max);
+
+ // create color cube
+ for (int x = 0, r = 0; r < d->r_max; ++r) {
+ for (int g = 0; g < d->g_max; ++g) {
+ for (int b = 0; b < d->b_max; ++b, ++x) {
+ const QRgb rgb = qRgb((r * 0xff + (d->r_max - 1) / 2) / (d->r_max - 1),
+ (g * 0xff + (d->g_max - 1) / 2) / (d->g_max - 1),
+ (b * 0xff + (d->b_max - 1) / 2) / (d->b_max - 1));
+
+ d->pixels[x] = -1;
+
+ if (d->visual->c_class & 1) {
+ XColor xcolor;
+ xcolor.red = qRed(rgb) * 0x101;
+ xcolor.green = qGreen(rgb) * 0x101;
+ xcolor.blue = qBlue(rgb) * 0x101;
+ xcolor.pixel = 0ul;
+
+ if (XAllocColor(X11->display, d->colormap, &xcolor))
+ d->pixels[x] = xcolor.pixel;
+ }
+ }
+ }
+ }
+
+ query_colormap(d, screen);
+}
+
+static void init_direct(QXcbColormapPrivate *d, bool ownColormap)
+{
+ if (d->visual->c_class != DirectColor || !ownColormap)
+ return;
+
+ // preallocate 768 on the stack, so that we don't have to malloc
+ // for the common case (<= 24 bpp)
+ QVarLengthArray<XColor, 768> colorTable(d->r_max + d->g_max + d->b_max);
+ int i = 0;
+
+ for (int r = 0; r < d->r_max; ++r) {
+ colorTable[i].red = r << 8 | r;
+ colorTable[i].pixel = r << d->r_shift;
+ colorTable[i].flags = DoRed;
+ ++i;
+ }
+
+ for (int g = 0; g < d->g_max; ++g) {
+ colorTable[i].green = g << 8 | g;
+ colorTable[i].pixel = g << d->g_shift;
+ colorTable[i].flags = DoGreen;
+ ++i;
+ }
+
+ for (int b = 0; b < d->b_max; ++b) {
+ colorTable[i].blue = (b << 8 | b);
+ colorTable[i].pixel = b << d->b_shift;
+ colorTable[i].flags = DoBlue;
+ ++i;
+ }
+
+ XStoreColors(X11->display, d->colormap, colorTable.data(), colorTable.count());
+}
+
+static QXcbColormap **cmaps = 0;
+
+void QXcbColormap::initialize()
+{
+ Display *display = X11->display;
+ const int screens = ScreenCount(display);
+
+ cmaps = new QXcbColormap*[screens];
+
+ for (int i = 0; i < screens; ++i) {
+ cmaps[i] = new QXcbColormap;
+ QXcbColormapPrivate * const d = cmaps[i]->d;
+
+ bool use_stdcmap = false;
+ int color_count = X11->color_count;
+
+ // defaults
+ d->depth = DefaultDepth(display, i);
+ d->colormap = DefaultColormap(display, i);
+ d->defaultColormap = true;
+ d->visual = DefaultVisual(display, i);
+ d->defaultVisual = true;
+
+ Visual *argbVisual = 0;
+
+ if (X11->visual && i == DefaultScreen(display)) {
+ // only use the outside colormap on the default screen
+ d->visual = find_visual(display, i, X11->visual->c_class,
+ XVisualIDFromVisual(X11->visual),
+ &d->depth, &d->defaultVisual);
+ } else if ((X11->visual_class != -1 && X11->visual_class >= 0 && X11->visual_class < 6)
+ || (X11->visual_id != -1)) {
+ // look for a specific visual or type of visual
+ d->visual = find_visual(display, i, X11->visual_class, X11->visual_id,
+ &d->depth, &d->defaultVisual);
+ } else if (!X11->custom_cmap) {
+ XStandardColormap *stdcmap = 0;
+ int ncmaps = 0;
+
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender) {
+ int nvi;
+ XVisualInfo templ;
+ templ.screen = i;
+ templ.depth = 32;
+ templ.c_class = TrueColor;
+ XVisualInfo *xvi = XGetVisualInfo(X11->display, VisualScreenMask |
+ VisualDepthMask |
+ VisualClassMask, &templ, &nvi);
+ for (int idx = 0; idx < nvi; ++idx) {
+ XRenderPictFormat *format = XRenderFindVisualFormat(X11->display,
+ xvi[idx].visual);
+ if (format->type == PictTypeDirect && format->direct.alphaMask) {
+ argbVisual = xvi[idx].visual;
+ break;
+ }
+ }
+ XFree(xvi);
+ }
+#endif
+ if (XGetRGBColormaps(display, RootWindow(display, i),
+ &stdcmap, &ncmaps, XA_RGB_DEFAULT_MAP)) {
+ if (stdcmap) {
+ for (int c = 0; c < ncmaps; ++c) {
+ if (!stdcmap[c].red_max ||
+ !stdcmap[c].green_max ||
+ !stdcmap[c].blue_max ||
+ !stdcmap[c].red_mult ||
+ !stdcmap[c].green_mult ||
+ !stdcmap[c].blue_mult)
+ continue; // invalid stdcmap
+
+ XVisualInfo proto;
+ proto.visualid = stdcmap[c].visualid;
+ proto.screen = i;
+
+ int nvisuals = 0;
+ XVisualInfo *vi = XGetVisualInfo(display, VisualIDMask | VisualScreenMask,
+ &proto, &nvisuals);
+ if (vi) {
+ if (nvisuals > 0) {
+ use_stdcmap = true;
+
+ d->mode = ((vi[0].visual->c_class < StaticColor)
+ ? Gray
+ : ((vi[0].visual->c_class < TrueColor)
+ ? Indexed
+ : Direct));
+
+ d->depth = vi[0].depth;
+ d->colormap = stdcmap[c].colormap;
+ d->defaultColormap = true;
+ d->visual = vi[0].visual;
+ d->defaultVisual = (d->visual == DefaultVisual(display, i));
+
+ d->r_max = stdcmap[c].red_max + 1;
+ d->g_max = stdcmap[c].green_max + 1;
+ d->b_max = stdcmap[c].blue_max + 1;
+
+ if (d->mode == Direct) {
+ // calculate offsets
+ d->r_shift = lowest_bit(d->visual->red_mask);
+ d->g_shift = lowest_bit(d->visual->green_mask);
+ d->b_shift = lowest_bit(d->visual->blue_mask);
+ } else {
+ d->r_shift = 0;
+ d->g_shift = 0;
+ d->b_shift = 0;
+ }
+ }
+ XFree(vi);
+ }
+ break;
+ }
+ XFree(stdcmap);
+ }
+ }
+ }
+ if (!use_stdcmap) {
+ switch (d->visual->c_class) {
+ case StaticGray:
+ d->mode = Gray;
+
+ d->r_max = d->g_max = d->b_max = d->visual->map_entries;
+ break;
+
+ case XGrayScale:
+ d->mode = Gray;
+
+ // follow precedent set in libXmu...
+ if (color_count != 0)
+ d->r_max = d->g_max = d->b_max = color_count;
+ else if (d->visual->map_entries > 65000)
+ d->r_max = d->g_max = d->b_max = 4096;
+ else if (d->visual->map_entries > 4000)
+ d->r_max = d->g_max = d->b_max = 512;
+ else if (d->visual->map_entries > 250)
+ d->r_max = d->g_max = d->b_max = 12;
+ else
+ d->r_max = d->g_max = d->b_max = 4;
+ break;
+
+ case StaticColor:
+ d->mode = Indexed;
+
+ d->r_max = right_align(d->visual->red_mask) + 1;
+ d->g_max = right_align(d->visual->green_mask) + 1;
+ d->b_max = right_align(d->visual->blue_mask) + 1;
+ break;
+
+ case PseudoColor:
+ d->mode = Indexed;
+
+ // follow precedent set in libXmu...
+ if (color_count != 0)
+ d->r_max = d->g_max = d->b_max = cube_root(color_count);
+ else if (d->visual->map_entries > 65000)
+ d->r_max = d->g_max = d->b_max = 27;
+ else if (d->visual->map_entries > 4000)
+ d->r_max = d->g_max = d->b_max = 12;
+ else if (d->visual->map_entries > 250)
+ d->r_max = d->g_max = d->b_max = cube_root(d->visual->map_entries - 125);
+ else
+ d->r_max = d->g_max = d->b_max = cube_root(d->visual->map_entries);
+ break;
+
+ case TrueColor:
+ case DirectColor:
+ d->mode = Direct;
+
+ d->r_max = right_align(d->visual->red_mask) + 1;
+ d->g_max = right_align(d->visual->green_mask) + 1;
+ d->b_max = right_align(d->visual->blue_mask) + 1;
+
+ d->r_shift = lowest_bit(d->visual->red_mask);
+ d->g_shift = lowest_bit(d->visual->green_mask);
+ d->b_shift = lowest_bit(d->visual->blue_mask);
+ break;
+ }
+ }
+
+ bool ownColormap = false;
+ if (X11->colormap && i == DefaultScreen(display)) {
+ // only use the outside colormap on the default screen
+ d->colormap = X11->colormap;
+ d->defaultColormap = (d->colormap == DefaultColormap(display, i));
+ } else if ((!use_stdcmap
+ && (((d->visual->c_class & 1) && X11->custom_cmap)
+ || d->visual != DefaultVisual(display, i)))
+ || d->visual->c_class == DirectColor) {
+ // allocate custom colormap (we always do this when using DirectColor visuals)
+ d->colormap =
+ XCreateColormap(display, RootWindow(display, i), d->visual,
+ d->visual->c_class == DirectColor ? AllocAll : AllocNone);
+ d->defaultColormap = false;
+ ownColormap = true;
+ }
+
+ switch (d->mode) {
+ case Gray:
+ init_gray(d, i);
+ break;
+ case Indexed:
+ init_indexed(d, i);
+ break;
+ case Direct:
+ init_direct(d, ownColormap);
+ break;
+ }
+
+ QX11InfoData *screen = X11->screens + i;
+ screen->depth = d->depth;
+ screen->visual = d->visual;
+ screen->defaultVisual = d->defaultVisual;
+ screen->colormap = d->colormap;
+ screen->defaultColormap = d->defaultColormap;
+ screen->cells = screen->visual->map_entries;
+
+ if (argbVisual) {
+ X11->argbVisuals[i] = argbVisual;
+ X11->argbColormaps[i] = XCreateColormap(display, RootWindow(display, i), argbVisual, AllocNone);
+ }
+
+ // ###
+ // We assume that 8bpp == pseudocolor, but this is not
+ // always the case (according to the X server), so we need
+ // to make sure that our internal data is setup in a way
+ // that is compatible with our assumptions
+ if (screen->visual->c_class == TrueColor && screen->depth == 8 && screen->cells == 8)
+ screen->cells = 256;
+ }
+}
+
+void QXcbColormap::cleanup()
+{
+ Display *display = X11->display;
+ const int screens = ScreenCount(display);
+
+ for (int i = 0; i < screens; ++i)
+ delete cmaps[i];
+
+ delete [] cmaps;
+ cmaps = 0;
+}
+
+
+QXcbColormap QXcbColormap::instance(int screen)
+{
+ if (screen == -1)
+ screen = QXcbX11Info::appScreen();
+ return *cmaps[screen];
+}
+
+/*! \internal
+ Constructs a new colormap.
+*/
+QXcbColormap::QXcbColormap()
+ : d(new QXcbColormapPrivate)
+{}
+
+QXcbColormap::QXcbColormap(const QXcbColormap &colormap)
+ :d (colormap.d)
+{ d->ref.ref(); }
+
+QXcbColormap::~QXcbColormap()
+{
+ if (!d->ref.deref()) {
+ if (!d->defaultColormap)
+ XFreeColormap(X11->display, d->colormap);
+ delete d;
+ }
+}
+
+QXcbColormap::Mode QXcbColormap::mode() const
+{ return d->mode; }
+
+int QXcbColormap::depth() const
+{ return d->depth; }
+
+int QXcbColormap::size() const
+{
+ return (d->mode == Gray
+ ? d->r_max
+ : (d->mode == Indexed
+ ? d->r_max * d->g_max * d->b_max
+ : -1));
+}
+
+uint QXcbColormap::pixel(const QColor &color) const
+{
+ const QRgba64 rgba64 = color.rgba64();
+ // XXX We emulate the raster engine here by getting the
+ // 8-bit values, but we could instead use the 16-bit
+ // values for slightly better color accuracy
+ const uint r = (rgba64.red8() * d->r_max) >> 8;
+ const uint g = (rgba64.green8() * d->g_max) >> 8;
+ const uint b = (rgba64.blue8() * d->b_max) >> 8;
+ if (d->mode != Direct) {
+ if (d->mode == Gray)
+ return d->pixels.at((r * 30 + g * 59 + b * 11) / 100);
+ return d->pixels.at(r * d->g_max * d->b_max + g * d->b_max + b);
+ }
+ return (r << d->r_shift) + (g << d->g_shift) + (b << d->b_shift);
+}
+
+const QColor QXcbColormap::colorAt(uint pixel) const
+{
+ if (d->mode != Direct) {
+ Q_ASSERT(pixel <= (uint)d->colors.size());
+ return d->colors.at(pixel);
+ }
+
+ const int r = (((pixel & d->visual->red_mask) >> d->r_shift) << 8) / d->r_max;
+ const int g = (((pixel & d->visual->green_mask) >> d->g_shift) << 8) / d->g_max;
+ const int b = (((pixel & d->visual->blue_mask) >> d->b_shift) << 8) / d->b_max;
+ return QColor(r, g, b);
+}
+
+const QVector<QColor> QXcbColormap::colormap() const
+{ return d->colors; }
+
+QXcbColormap &QXcbColormap::operator=(const QXcbColormap &colormap)
+{
+ qAtomicAssign(d, colormap.d);
+ return *this;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qcolormap_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qcolormap_x11_p.h
new file mode 100644
index 0000000000..530e3113e4
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qcolormap_x11_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOLORMAP_X11_H
+#define QCOLORMAP_X11_H
+
+#include <QColor>
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+class QXcbColormapPrivate;
+class QXcbColormap
+{
+public:
+ enum Mode { Direct, Indexed, Gray };
+
+ static void initialize();
+ static void cleanup();
+
+ static QXcbColormap instance(int screen = -1);
+
+ QXcbColormap(const QXcbColormap &colormap);
+ ~QXcbColormap();
+
+ QXcbColormap &operator=(const QXcbColormap &colormap);
+
+ Mode mode() const;
+
+ int depth() const;
+ int size() const;
+
+ uint pixel(const QColor &color) const;
+ const QColor colorAt(uint pixel) const;
+
+ const QVector<QColor> colormap() const;
+
+private:
+ QXcbColormap();
+ QXcbColormapPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QCOLORMAP_X11_H
diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
new file mode 100644
index 0000000000..3364b07c08
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
@@ -0,0 +1,2837 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <private/qpixmapcache_p.h>
+#include <private/qpaintengine_p.h>
+#include <private/qpolygonclipper_p.h>
+#include <private/qpainterpath_p.h>
+#include <private/qdrawhelper_p.h>
+#include <private/qfontengineglyphcache_p.h>
+
+#if QT_CONFIG(fontconfig)
+#include <private/qfontengine_ft_p.h>
+#endif
+
+#include "qpaintengine_x11_p.h"
+#include "qtessellator_p.h"
+#include "qpixmap_x11_p.h"
+#include "qcolormap_x11_p.h"
+#include "qt_x11_p.h"
+#include "qxcbexport.h"
+#include "qxcbnativepainting.h"
+
+QT_BEGIN_NAMESPACE
+
+#if QT_CONFIG(xrender)
+
+class QXRenderTessellator : public QTessellator
+{
+public:
+ QXRenderTessellator() : traps(0), allocated(0), size(0) {}
+ ~QXRenderTessellator() { free(traps); }
+ XTrapezoid *traps;
+ int allocated;
+ int size;
+ void addTrap(const Trapezoid &trap);
+ QRect tessellate(const QPointF *points, int nPoints, bool winding) {
+ size = 0;
+ setWinding(winding);
+ return QTessellator::tessellate(points, nPoints).toRect();
+ }
+ void done() {
+ if (allocated > 64) {
+ free(traps);
+ traps = 0;
+ allocated = 0;
+ }
+ }
+};
+
+void QXRenderTessellator::addTrap(const Trapezoid &trap)
+{
+ if (size == allocated) {
+ allocated = qMax(2*allocated, 64);
+ traps = q_check_ptr((XTrapezoid *)realloc(traps, allocated * sizeof(XTrapezoid)));
+ }
+ traps[size].top = Q27Dot5ToXFixed(trap.top);
+ traps[size].bottom = Q27Dot5ToXFixed(trap.bottom);
+ traps[size].left.p1.x = Q27Dot5ToXFixed(trap.topLeft->x);
+ traps[size].left.p1.y = Q27Dot5ToXFixed(trap.topLeft->y);
+ traps[size].left.p2.x = Q27Dot5ToXFixed(trap.bottomLeft->x);
+ traps[size].left.p2.y = Q27Dot5ToXFixed(trap.bottomLeft->y);
+ traps[size].right.p1.x = Q27Dot5ToXFixed(trap.topRight->x);
+ traps[size].right.p1.y = Q27Dot5ToXFixed(trap.topRight->y);
+ traps[size].right.p2.x = Q27Dot5ToXFixed(trap.bottomRight->x);
+ traps[size].right.p2.y = Q27Dot5ToXFixed(trap.bottomRight->y);
+ ++size;
+}
+
+#endif // QT_CONFIG(xrender)
+
+class QX11PaintEnginePrivate : public QPaintEnginePrivate
+{
+ Q_DECLARE_PUBLIC(QX11PaintEngine)
+public:
+ QX11PaintEnginePrivate()
+ {
+ opacity = 1.0;
+ scrn = -1;
+ hd = 0;
+ picture = 0;
+ gc = gc_brush = 0;
+ dpy = 0;
+ xinfo = 0;
+ txop = QTransform::TxNone;
+ has_clipping = false;
+ render_hints = 0;
+ xform_scale = 1;
+#if QT_CONFIG(xrender)
+ tessellator = 0;
+#endif
+ }
+ enum GCMode {
+ PenGC,
+ BrushGC
+ };
+
+ void init();
+ void fillPolygon_translated(const QPointF *points, int pointCount, GCMode gcMode,
+ QPaintEngine::PolygonDrawMode mode);
+ void fillPolygon_dev(const QPointF *points, int pointCount, GCMode gcMode,
+ QPaintEngine::PolygonDrawMode mode);
+ void fillPath(const QPainterPath &path, GCMode gcmode, bool transform);
+ void strokePolygon_dev(const QPointF *points, int pointCount, bool close);
+ void strokePolygon_translated(const QPointF *points, int pointCount, bool close);
+ void setupAdaptedOrigin(const QPoint &p);
+ void resetAdaptedOrigin();
+ void decidePathFallback() {
+ use_path_fallback = has_alpha_brush
+ || has_alpha_pen
+ || has_custom_pen
+ || has_complex_xform
+ || (render_hints & QPainter::Antialiasing);
+ }
+ void decideCoordAdjust() {
+ adjust_coords = !(render_hints & QPainter::Antialiasing)
+ && (render_hints & QPainter::Qt4CompatiblePainting)
+ && (has_alpha_pen
+ || (has_alpha_brush && has_pen && !has_alpha_pen)
+ || (cpen.style() > Qt::SolidLine));
+ }
+ void clipPolygon_dev(const QPolygonF &poly, QPolygonF *clipped_poly);
+ void systemStateChanged() override;
+ inline bool isCosmeticPen() const {
+ if ((render_hints & QPainter::Qt4CompatiblePainting) && cpen == QPen())
+ return true;
+ return cpen.isCosmetic();
+ }
+
+ Display *dpy;
+ int scrn;
+ int pdev_depth;
+ unsigned long hd;
+ QPixmap brush_pm;
+#if QT_CONFIG(xrender)
+ unsigned long picture;
+ unsigned long current_brush;
+ QPixmap bitmap_texture;
+ int composition_mode;
+#else
+ unsigned long picture;
+#endif
+ GC gc;
+ GC gc_brush;
+
+ QPen cpen;
+ QBrush cbrush;
+ QRegion crgn;
+ QTransform matrix;
+ qreal opacity;
+
+ uint has_complex_xform : 1;
+ uint has_scaling_xform : 1;
+ uint has_non_scaling_xform : 1;
+ uint has_custom_pen : 1;
+ uint use_path_fallback : 1;
+ uint adjust_coords : 1;
+ uint has_clipping : 1;
+ uint adapted_brush_origin : 1;
+ uint adapted_pen_origin : 1;
+ uint has_pen : 1;
+ uint has_brush : 1;
+ uint has_texture : 1;
+ uint has_alpha_texture : 1;
+ uint has_pattern : 1;
+ uint has_alpha_pen : 1;
+ uint has_alpha_brush : 1;
+ uint render_hints;
+
+ const QXcbX11Info *xinfo;
+ QPointF bg_origin;
+ QTransform::TransformationType txop;
+ qreal xform_scale;
+
+ struct qt_float_point
+ {
+ qreal x, y;
+ };
+ QPolygonClipper<qt_float_point, qt_float_point, float> polygonClipper;
+
+ int xlibMaxLinePoints;
+#if QT_CONFIG(xrender)
+ QXRenderTessellator *tessellator;
+#endif
+};
+
+#if QT_CONFIG(xrender)
+class QXRenderGlyphCache : public QFontEngineGlyphCache
+{
+public:
+ QXRenderGlyphCache(QXcbX11Info x, QFontEngine::GlyphFormat format, const QTransform &matrix);
+ ~QXRenderGlyphCache();
+
+ bool addGlyphs(const QTextItemInt &ti, QVarLengthArray<glyph_t> glyphs, QVarLengthArray<QFixedPoint> positions);
+ bool draw(Drawable src, Drawable dst, const QTransform &matrix, const QTextItemInt &ti);
+
+ inline GlyphSet glyphSet();
+ inline int glyphBufferSize(const QFontEngineFT::Glyph &glyph) const;
+
+ inline QImage::Format imageFormat() const;
+ inline const XRenderPictFormat *renderPictFormat() const;
+
+ static inline QFontEngine::GlyphFormat glyphFormatForDepth(QFontEngine *fontEngine, int depth);
+ static inline Glyph glyphId(glyph_t glyph, QFixed subPixelPosition);
+
+ static inline bool isValidCoordinate(const QFixedPoint &fp);
+
+private:
+ QXcbX11Info xinfo;
+ GlyphSet gset;
+ QSet<Glyph> cachedGlyphs;
+};
+#endif // QT_CONFIG(xrender)
+
+extern QPixmap qt_pixmapForBrush(int brushStyle, bool invert); //in qbrush.cpp
+extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
+
+extern "C" {
+Q_XCB_EXPORT Drawable qt_x11Handle(const QPaintDevice *pd)
+{
+ if (!pd)
+ return 0;
+
+// if (pd->devType() == QInternal::Widget)
+// return static_cast<const QWidget *>(pd)->handle();
+
+ if (pd->devType() == QInternal::Pixmap)
+ return qt_x11PixmapHandle(*static_cast<const QPixmap *>(pd));
+
+ return 0;
+}
+}
+
+static const QXcbX11Info *qt_x11Info(const QPaintDevice *pd)
+{
+ if (!pd)
+ return 0;
+
+// if (pd->devType() == QInternal::Widget)
+// return &static_cast<const QWidget *>(pd)->x11Info();
+
+ if (pd->devType() == QInternal::Pixmap)
+ return &qt_x11Info(*static_cast<const QPixmap *>(pd));
+
+ return 0;
+}
+
+// use the same rounding as in qrasterizer.cpp (6 bit fixed point)
+static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
+
+#undef X11 // defined in qt_x11_p.h
+extern "C" {
+/*!
+ Returns the X11 specific pen GC for the painter \a p. Note that
+ QPainter::begin() must be called before this function returns a
+ valid GC.
+*/
+GC Q_XCB_EXPORT qt_x11_get_pen_gc(QPainter *p)
+{
+ if (p && p->paintEngine()
+ && p->paintEngine()->isActive()
+ && p->paintEngine()->type() == QPaintEngine::X11) {
+ return static_cast<QX11PaintEngine *>(p->paintEngine())->d_func()->gc;
+ }
+ return 0;
+}
+
+/*!
+ Returns the X11 specific brush GC for the painter \a p. Note that
+ QPainter::begin() must be called before this function returns a
+ valid GC.
+*/
+GC Q_XCB_EXPORT qt_x11_get_brush_gc(QPainter *p)
+{
+ if (p && p->paintEngine()
+ && p->paintEngine()->isActive()
+ && p->paintEngine()->type() == QPaintEngine::X11) {
+ return static_cast<QX11PaintEngine *>(p->paintEngine())->d_func()->gc_brush;
+ }
+ return 0;
+}
+}
+#define X11 qt_x11Data
+
+// internal helper. Converts an integer value to an unique string token
+template <typename T>
+ struct HexString
+{
+ inline HexString(const T t)
+ : val(t)
+ {}
+
+ inline void write(QChar *&dest) const
+ {
+ const ushort hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+ const char *c = reinterpret_cast<const char *>(&val);
+ for (uint i = 0; i < sizeof(T); ++i) {
+ *dest++ = hexChars[*c & 0xf];
+ *dest++ = hexChars[(*c & 0xf0) >> 4];
+ ++c;
+ }
+ }
+ const T val;
+};
+
+// specialization to enable fast concatenating of our string tokens to a string
+template <typename T>
+ struct QConcatenable<HexString<T> >
+{
+ typedef HexString<T> type;
+ enum { ExactSize = true };
+ static int size(const HexString<T> &) { return sizeof(T) * 2; }
+ static inline void appendTo(const HexString<T> &str, QChar *&out) { str.write(out); }
+ typedef QString ConvertTo;
+};
+
+#if QT_CONFIG(xrender)
+static const int compositionModeToRenderOp[QPainter::CompositionMode_Xor + 1] = {
+ PictOpOver, //CompositionMode_SourceOver,
+ PictOpOverReverse, //CompositionMode_DestinationOver,
+ PictOpClear, //CompositionMode_Clear,
+ PictOpSrc, //CompositionMode_Source,
+ PictOpDst, //CompositionMode_Destination,
+ PictOpIn, //CompositionMode_SourceIn,
+ PictOpInReverse, //CompositionMode_DestinationIn,
+ PictOpOut, //CompositionMode_SourceOut,
+ PictOpOutReverse, //CompositionMode_DestinationOut,
+ PictOpAtop, //CompositionMode_SourceAtop,
+ PictOpAtopReverse, //CompositionMode_DestinationAtop,
+ PictOpXor //CompositionMode_Xor
+};
+
+static inline int qpainterOpToXrender(QPainter::CompositionMode mode)
+{
+ Q_ASSERT(mode <= QPainter::CompositionMode_Xor);
+ return compositionModeToRenderOp[mode];
+}
+
+static inline bool complexPictOp(int op)
+{
+ return op != PictOpOver && op != PictOpSrc;
+}
+#endif
+
+static inline void x11SetClipRegion(Display *dpy, GC gc, GC gc2,
+#if QT_CONFIG(xrender)
+ Picture picture,
+#else
+ Qt::HANDLE picture,
+#endif
+ const QRegion &r)
+{
+// int num;
+// XRectangle *rects = (XRectangle *)qt_getClipRects(r, num);
+ QVector<XRectangle> rects = qt_region_to_xrectangles(r);
+ int num = rects.size();
+
+ if (gc)
+ XSetClipRectangles( dpy, gc, 0, 0, rects.data(), num, Unsorted );
+ if (gc2)
+ XSetClipRectangles( dpy, gc2, 0, 0, rects.data(), num, Unsorted );
+
+#if QT_CONFIG(xrender)
+ if (picture)
+ XRenderSetPictureClipRectangles(dpy, picture, 0, 0, rects.data(), num);
+#else
+ Q_UNUSED(picture);
+#endif // QT_CONFIG(xrender)
+}
+
+
+static inline void x11ClearClipRegion(Display *dpy, GC gc, GC gc2,
+#if QT_CONFIG(xrender)
+ Picture picture
+#else
+ Qt::HANDLE picture
+#endif
+ )
+{
+ if (gc)
+ XSetClipMask(dpy, gc, XNone);
+ if (gc2)
+ XSetClipMask(dpy, gc2, XNone);
+
+#if QT_CONFIG(xrender)
+ if (picture) {
+ XRenderPictureAttributes attrs;
+ attrs.clip_mask = XNone;
+ XRenderChangePicture (dpy, picture, CPClipMask, &attrs);
+ }
+#else
+ Q_UNUSED(picture);
+#endif // QT_CONFIG(xrender)
+}
+
+
+#define DITHER_SIZE 16
+static const uchar base_dither_matrix[DITHER_SIZE][DITHER_SIZE] = {
+ { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
+ { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
+ { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
+ { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
+ { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
+ { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
+ { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
+ { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
+ { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
+ { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
+ { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
+ { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
+ { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
+ { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
+ { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
+ { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
+};
+
+static QPixmap qt_patternForAlpha(uchar alpha, int screen)
+{
+ QPixmap pm;
+ QString key = QLatin1Literal("$qt-alpha-brush$")
+ % HexString<uchar>(alpha)
+ % HexString<int>(screen);
+
+ if (!QPixmapCache::find(key, pm)) {
+ // #### why not use a mono image here????
+ QImage pattern(DITHER_SIZE, DITHER_SIZE, QImage::Format_ARGB32);
+ pattern.fill(0xffffffff);
+ for (int y = 0; y < DITHER_SIZE; ++y) {
+ for (int x = 0; x < DITHER_SIZE; ++x) {
+ if (base_dither_matrix[x][y] <= alpha)
+ pattern.setPixel(x, y, 0x00000000);
+ }
+ }
+ pm = QBitmap::fromImage(pattern);
+ qt_x11SetScreen(pm, screen);
+ //pm.x11SetScreen(screen);
+ QPixmapCache::insert(key, pm);
+ }
+ return pm;
+}
+
+
+#if QT_CONFIG(xrender)
+static Picture getPatternFill(int screen, const QBrush &b)
+{
+ if (!X11->use_xrender)
+ return XNone;
+
+ XRenderColor color = X11->preMultiply(b.color());
+ XRenderColor bg_color;
+
+ bg_color = X11->preMultiply(QColor(0, 0, 0, 0));
+
+ for (int i = 0; i < X11->pattern_fill_count; ++i) {
+ if (X11->pattern_fills[i].screen == screen
+ && X11->pattern_fills[i].opaque == false
+ && X11->pattern_fills[i].style == b.style()
+ && X11->pattern_fills[i].color.alpha == color.alpha
+ && X11->pattern_fills[i].color.red == color.red
+ && X11->pattern_fills[i].color.green == color.green
+ && X11->pattern_fills[i].color.blue == color.blue
+ && X11->pattern_fills[i].bg_color.alpha == bg_color.alpha
+ && X11->pattern_fills[i].bg_color.red == bg_color.red
+ && X11->pattern_fills[i].bg_color.green == bg_color.green
+ && X11->pattern_fills[i].bg_color.blue == bg_color.blue)
+ return X11->pattern_fills[i].picture;
+ }
+ // none found, replace one
+ int i = qrand() % 16;
+
+ if (X11->pattern_fills[i].screen != screen && X11->pattern_fills[i].picture) {
+ XRenderFreePicture (QXcbX11Info::display(), X11->pattern_fills[i].picture);
+ X11->pattern_fills[i].picture = 0;
+ }
+
+ if (!X11->pattern_fills[i].picture) {
+ Pixmap pixmap = XCreatePixmap (QXcbX11Info::display(), RootWindow (QXcbX11Info::display(), screen), 8, 8, 32);
+ XRenderPictureAttributes attrs;
+ attrs.repeat = True;
+ X11->pattern_fills[i].picture = XRenderCreatePicture (QXcbX11Info::display(), pixmap,
+ XRenderFindStandardFormat(QXcbX11Info::display(), PictStandardARGB32),
+ CPRepeat, &attrs);
+ XFreePixmap (QXcbX11Info::display(), pixmap);
+ }
+
+ X11->pattern_fills[i].screen = screen;
+ X11->pattern_fills[i].color = color;
+ X11->pattern_fills[i].bg_color = bg_color;
+ X11->pattern_fills[i].opaque = false;
+ X11->pattern_fills[i].style = b.style();
+
+ XRenderFillRectangle(QXcbX11Info::display(), PictOpSrc, X11->pattern_fills[i].picture, &bg_color, 0, 0, 8, 8);
+
+ QPixmap pattern(qt_pixmapForBrush(b.style(), true));
+ XRenderPictureAttributes attrs;
+ attrs.repeat = true;
+ XRenderChangePicture(QXcbX11Info::display(), qt_x11PictureHandle(pattern), CPRepeat, &attrs);
+
+ Picture fill_fg = X11->getSolidFill(screen, b.color());
+ XRenderComposite(QXcbX11Info::display(), PictOpOver, fill_fg, qt_x11PictureHandle(pattern),
+ X11->pattern_fills[i].picture,
+ 0, 0, 0, 0, 0, 0, 8, 8);
+
+ return X11->pattern_fills[i].picture;
+}
+
+static void qt_render_bitmap(Display *dpy, int scrn, Picture src, Picture dst,
+ int sx, int sy, int x, int y, int sw, int sh,
+ const QPen &pen)
+{
+ Picture fill_fg = X11->getSolidFill(scrn, pen.color());
+ XRenderComposite(dpy, PictOpOver,
+ fill_fg, src, dst, sx, sy, sx, sy, x, y, sw, sh);
+}
+#endif
+
+void QX11PaintEnginePrivate::init()
+{
+ dpy = 0;
+ scrn = 0;
+ hd = 0;
+ picture = 0;
+ xinfo = 0;
+#if QT_CONFIG(xrender)
+ current_brush = 0;
+ composition_mode = PictOpOver;
+ tessellator = new QXRenderTessellator;
+#endif
+}
+
+void QX11PaintEnginePrivate::setupAdaptedOrigin(const QPoint &p)
+{
+ if (adapted_pen_origin)
+ XSetTSOrigin(dpy, gc, p.x(), p.y());
+ if (adapted_brush_origin)
+ XSetTSOrigin(dpy, gc_brush, p.x(), p.y());
+}
+
+void QX11PaintEnginePrivate::resetAdaptedOrigin()
+{
+ if (adapted_pen_origin)
+ XSetTSOrigin(dpy, gc, 0, 0);
+ if (adapted_brush_origin)
+ XSetTSOrigin(dpy, gc_brush, 0, 0);
+}
+
+void QX11PaintEnginePrivate::clipPolygon_dev(const QPolygonF &poly, QPolygonF *clipped_poly)
+{
+ int clipped_count = 0;
+ qt_float_point *clipped_points = 0;
+ polygonClipper.clipPolygon((qt_float_point *) poly.data(), poly.size(),
+ &clipped_points, &clipped_count);
+ clipped_poly->resize(clipped_count);
+ for (int i=0; i<clipped_count; ++i)
+ (*clipped_poly)[i] = *((QPointF *)(&clipped_points[i]));
+}
+
+void QX11PaintEnginePrivate::systemStateChanged()
+{
+ Q_Q(QX11PaintEngine);
+ QPainter *painter = q->state ? q->state->painter() : nullptr;
+ if (painter && painter->hasClipping()) {
+ if (q->testDirty(QPaintEngine::DirtyTransform))
+ q->updateMatrix(q->state->transform());
+ QPolygonF clip_poly_dev(matrix.map(painter->clipPath().toFillPolygon()));
+ QPolygonF clipped_poly_dev;
+ clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
+ q->updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), Qt::ReplaceClip);
+ } else {
+ q->updateClipRegion_dev(QRegion(), Qt::NoClip);
+ }
+}
+
+static QPaintEngine::PaintEngineFeatures qt_decide_features()
+{
+ QPaintEngine::PaintEngineFeatures features =
+ QPaintEngine::PrimitiveTransform
+ | QPaintEngine::PatternBrush
+ | QPaintEngine::AlphaBlend
+ | QPaintEngine::PainterPaths
+ | QPaintEngine::RasterOpModes;
+
+ if (X11->use_xrender) {
+ features |= QPaintEngine::Antialiasing;
+ features |= QPaintEngine::PorterDuff;
+ features |= QPaintEngine::MaskedBrush;
+#if 0
+ if (X11->xrender_version > 10) {
+ features |= QPaintEngine::LinearGradientFill;
+ // ###
+ }
+#endif
+ }
+
+ return features;
+}
+
+/*
+ * QX11PaintEngine members
+ */
+
+QX11PaintEngine::QX11PaintEngine()
+ : QPaintEngine(*(new QX11PaintEnginePrivate), qt_decide_features())
+{
+ Q_D(QX11PaintEngine);
+ d->init();
+}
+
+QX11PaintEngine::QX11PaintEngine(QX11PaintEnginePrivate &dptr)
+ : QPaintEngine(dptr, qt_decide_features())
+{
+ Q_D(QX11PaintEngine);
+ d->init();
+}
+
+QX11PaintEngine::~QX11PaintEngine()
+{
+#if QT_CONFIG(xrender)
+ Q_D(QX11PaintEngine);
+ delete d->tessellator;
+#endif
+}
+
+bool QX11PaintEngine::begin(QPaintDevice *pdev)
+{
+ Q_D(QX11PaintEngine);
+ d->xinfo = qt_x11Info(pdev);
+#if QT_CONFIG(xrender)
+ if (pdev->devType() == QInternal::Pixmap) {
+ const QPixmap *pm = static_cast<const QPixmap *>(pdev);
+ QX11PlatformPixmap *data = static_cast<QX11PlatformPixmap*>(pm->handle());
+ if (X11->use_xrender && data->depth() != 32 && data->x11_mask)
+ data->convertToARGB32();
+ d->picture = qt_x11PictureHandle(*static_cast<const QPixmap *>(pdev));
+ }
+#else
+ d->picture = 0;
+#endif
+ d->hd = qt_x11Handle(pdev);
+
+ Q_ASSERT(d->xinfo != 0);
+ d->dpy = d->xinfo->display(); // get display variable
+ d->scrn = d->xinfo->screen(); // get screen variable
+
+ d->crgn = QRegion();
+ d->gc = XCreateGC(d->dpy, d->hd, 0, 0);
+ d->gc_brush = XCreateGC(d->dpy, d->hd, 0, 0);
+ d->has_alpha_brush = false;
+ d->has_alpha_pen = false;
+ d->has_clipping = false;
+ d->has_complex_xform = false;
+ d->has_scaling_xform = false;
+ d->has_non_scaling_xform = true;
+ d->xform_scale = 1;
+ d->has_custom_pen = false;
+ d->matrix = QTransform();
+ d->pdev_depth = d->pdev->depth();
+ d->render_hints = 0;
+ d->txop = QTransform::TxNone;
+ d->use_path_fallback = false;
+#if QT_CONFIG(xrender)
+ d->composition_mode = PictOpOver;
+#endif
+ d->xlibMaxLinePoints = 32762; // a safe number used to avoid, call to XMaxRequestSize(d->dpy) - 3;
+ d->opacity = 1;
+
+ // Set up the polygon clipper. Note: This will only work in
+ // polyline mode as long as we have a buffer zone, since a
+ // polyline may be clipped into several non-connected polylines.
+ const int BUFFERZONE = 1000;
+ QRect devClipRect(-BUFFERZONE, -BUFFERZONE,
+ pdev->width() + 2*BUFFERZONE, pdev->height() + 2*BUFFERZONE);
+ d->polygonClipper.setBoundingRect(devClipRect);
+
+ setSystemClip(systemClip());
+ d->systemStateChanged();
+
+ qt_x11SetDefaultScreen(d->xinfo->screen());
+
+ updatePen(QPen(Qt::black));
+ updateBrush(QBrush(Qt::white), QPoint());
+
+ setDirty(QPaintEngine::DirtyClipRegion);
+ setDirty(QPaintEngine::DirtyPen);
+ setDirty(QPaintEngine::DirtyBrush);
+ setDirty(QPaintEngine::DirtyBackground);
+
+ setActive(true);
+ return true;
+}
+
+bool QX11PaintEngine::end()
+{
+ Q_D(QX11PaintEngine);
+
+#if QT_CONFIG(xrender)
+ if (d->picture) {
+ // reset clipping/subwindow mode on our render picture
+ XRenderPictureAttributes attrs;
+ attrs.subwindow_mode = ClipByChildren;
+ attrs.clip_mask = XNone;
+ XRenderChangePicture(d->dpy, d->picture, CPClipMask|CPSubwindowMode, &attrs);
+ }
+#endif
+
+ if (d->gc_brush && d->pdev->painters < 2) {
+ XFreeGC(d->dpy, d->gc_brush);
+ d->gc_brush = 0;
+ }
+
+ if (d->gc && d->pdev->painters < 2) {
+ XFreeGC(d->dpy, d->gc);
+ d->gc = 0;
+ }
+
+ // Restore system clip for alien widgets painting outside the paint event.
+// if (d->pdev->devType() == QInternal::Widget && !static_cast<QWidget *>(d->pdev)->internalWinId())
+ d->currentClipDevice = nullptr;
+ setSystemClip(QRegion());
+
+ setActive(false);
+ return true;
+}
+
+static bool clipLine(QLineF *line, const QRect &rect)
+{
+ qreal x1 = line->x1();
+ qreal x2 = line->x2();
+ qreal y1 = line->y1();
+ qreal y2 = line->y2();
+
+ qreal left = rect.x();
+ qreal right = rect.x() + rect.width() - 1;
+ qreal top = rect.y();
+ qreal bottom = rect.y() + rect.height() - 1;
+
+ enum { Left, Right, Top, Bottom };
+ // clip the lines, after cohen-sutherland, see e.g. http://www.nondot.org/~sabre/graphpro/line6.html
+ int p1 = ((x1 < left) << Left)
+ | ((x1 > right) << Right)
+ | ((y1 < top) << Top)
+ | ((y1 > bottom) << Bottom);
+ int p2 = ((x2 < left) << Left)
+ | ((x2 > right) << Right)
+ | ((y2 < top) << Top)
+ | ((y2 > bottom) << Bottom);
+
+ if (p1 & p2)
+ // completely outside
+ return false;
+
+ if (p1 | p2) {
+ qreal dx = x2 - x1;
+ qreal dy = y2 - y1;
+
+ // clip x coordinates
+ if (x1 < left) {
+ y1 += dy/dx * (left - x1);
+ x1 = left;
+ } else if (x1 > right) {
+ y1 -= dy/dx * (x1 - right);
+ x1 = right;
+ }
+ if (x2 < left) {
+ y2 += dy/dx * (left - x2);
+ x2 = left;
+ } else if (x2 > right) {
+ y2 -= dy/dx * (x2 - right);
+ x2 = right;
+ }
+ p1 = ((y1 < top) << Top)
+ | ((y1 > bottom) << Bottom);
+ p2 = ((y2 < top) << Top)
+ | ((y2 > bottom) << Bottom);
+ if (p1 & p2)
+ return false;
+ // clip y coordinates
+ if (y1 < top) {
+ x1 += dx/dy * (top - y1);
+ y1 = top;
+ } else if (y1 > bottom) {
+ x1 -= dx/dy * (y1 - bottom);
+ y1 = bottom;
+ }
+ if (y2 < top) {
+ x2 += dx/dy * (top - y2);
+ y2 = top;
+ } else if (y2 > bottom) {
+ x2 -= dx/dy * (y2 - bottom);
+ y2 = bottom;
+ }
+ *line = QLineF(QPointF(x1, y1), QPointF(x2, y2));
+ }
+ return true;
+}
+
+void QX11PaintEngine::drawLines(const QLine *lines, int lineCount)
+{
+ Q_ASSERT(lines);
+ Q_ASSERT(lineCount);
+ Q_D(QX11PaintEngine);
+
+ if (d->has_alpha_brush
+ || d->has_alpha_pen
+ || d->has_custom_pen
+ || (d->cpen.widthF() > 0 && d->has_complex_xform
+ && !d->has_non_scaling_xform)
+ || (d->render_hints & QPainter::Antialiasing)) {
+ for (int i = 0; i < lineCount; ++i) {
+ QPainterPath path(lines[i].p1());
+ path.lineTo(lines[i].p2());
+ drawPath(path);
+ }
+ return;
+ }
+
+ if (d->has_pen) {
+ for (int i = 0; i < lineCount; ++i) {
+ QLineF linef;
+ if (d->txop == QTransform::TxNone) {
+ linef = lines[i];
+ } else {
+ linef = d->matrix.map(QLineF(lines[i]));
+ }
+ if (clipLine(&linef, d->polygonClipper.boundingRect())) {
+ int x1 = qRound(linef.x1() + aliasedCoordinateDelta);
+ int y1 = qRound(linef.y1() + aliasedCoordinateDelta);
+ int x2 = qRound(linef.x2() + aliasedCoordinateDelta);
+ int y2 = qRound(linef.y2() + aliasedCoordinateDelta);
+
+ XDrawLine(d->dpy, d->hd, d->gc, x1, y1, x2, y2);
+ }
+ }
+ }
+}
+
+void QX11PaintEngine::drawLines(const QLineF *lines, int lineCount)
+{
+ Q_ASSERT(lines);
+ Q_ASSERT(lineCount);
+ Q_D(QX11PaintEngine);
+
+ if (d->has_alpha_brush
+ || d->has_alpha_pen
+ || d->has_custom_pen
+ || (d->cpen.widthF() > 0 && d->has_complex_xform
+ && !d->has_non_scaling_xform)
+ || (d->render_hints & QPainter::Antialiasing)) {
+ for (int i = 0; i < lineCount; ++i) {
+ QPainterPath path(lines[i].p1());
+ path.lineTo(lines[i].p2());
+ drawPath(path);
+ }
+ return;
+ }
+
+ if (d->has_pen) {
+ for (int i = 0; i < lineCount; ++i) {
+ QLineF linef = d->matrix.map(lines[i]);
+ if (clipLine(&linef, d->polygonClipper.boundingRect())) {
+ int x1 = qRound(linef.x1() + aliasedCoordinateDelta);
+ int y1 = qRound(linef.y1() + aliasedCoordinateDelta);
+ int x2 = qRound(linef.x2() + aliasedCoordinateDelta);
+ int y2 = qRound(linef.y2() + aliasedCoordinateDelta);
+
+ XDrawLine(d->dpy, d->hd, d->gc, x1, y1, x2, y2);
+ }
+ }
+ }
+}
+
+static inline QLine clipStraightLine(const QRect &clip, const QLine &l)
+{
+ if (l.p1().x() == l.p2().x()) {
+ int x = qBound(clip.left(), l.p1().x(), clip.right());
+ int y1 = qBound(clip.top(), l.p1().y(), clip.bottom());
+ int y2 = qBound(clip.top(), l.p2().y(), clip.bottom());
+
+ return QLine(x, y1, x, y2);
+ } else {
+ Q_ASSERT(l.p1().y() == l.p2().y());
+
+ int x1 = qBound(clip.left(), l.p1().x(), clip.right());
+ int x2 = qBound(clip.left(), l.p2().x(), clip.right());
+ int y = qBound(clip.top(), l.p1().y(), clip.bottom());
+
+ return QLine(x1, y, x2, y);
+ }
+}
+
+void QX11PaintEngine::drawRects(const QRectF *rects, int rectCount)
+{
+ Q_D(QX11PaintEngine);
+ Q_ASSERT(rects);
+ Q_ASSERT(rectCount);
+
+ if (rectCount != 1
+ || d->has_pen
+ || d->has_alpha_brush
+ || d->has_complex_xform
+ || d->has_custom_pen
+ || d->cbrush.style() != Qt::SolidPattern
+#if QT_CONFIG(xrender)
+ || complexPictOp(d->composition_mode)
+#endif
+ )
+ {
+ QPaintEngine::drawRects(rects, rectCount);
+ return;
+ }
+
+ QPoint alignedOffset;
+ if (d->txop == QTransform::TxTranslate) {
+ QPointF offset(d->matrix.dx(), d->matrix.dy());
+ alignedOffset = offset.toPoint();
+ if (offset != QPointF(alignedOffset)) {
+ QPaintEngine::drawRects(rects, rectCount);
+ return;
+ }
+ }
+
+ const QRectF& r = rects[0];
+ QRect alignedRect = r.toAlignedRect();
+ if (r != QRectF(alignedRect)) {
+ QPaintEngine::drawRects(rects, rectCount);
+ return;
+ }
+ alignedRect.translate(alignedOffset);
+
+ QRect clip(d->polygonClipper.boundingRect());
+ alignedRect = alignedRect.intersected(clip);
+ if (alignedRect.isEmpty())
+ return;
+
+ // simple-case:
+ // the rectangle is pixel-aligned
+ // the fill brush is just a solid non-alpha color
+ // the painter transform is only integer translation
+ // ignore: antialiasing and just XFillRectangles directly
+ XRectangle xrect;
+ xrect.x = short(alignedRect.x());
+ xrect.y = short(alignedRect.y());
+ xrect.width = ushort(alignedRect.width());
+ xrect.height = ushort(alignedRect.height());
+ XFillRectangles(d->dpy, d->hd, d->gc_brush, &xrect, 1);
+}
+
+void QX11PaintEngine::drawRects(const QRect *rects, int rectCount)
+{
+ Q_D(QX11PaintEngine);
+ Q_ASSERT(rects);
+ Q_ASSERT(rectCount);
+
+ if (d->has_alpha_pen
+ || d->has_complex_xform
+ || d->has_custom_pen
+ || (d->render_hints & QPainter::Antialiasing))
+ {
+ for (int i = 0; i < rectCount; ++i) {
+ QPainterPath path;
+ path.addRect(rects[i]);
+ drawPath(path);
+ }
+ return;
+ }
+
+ QRect clip(d->polygonClipper.boundingRect());
+ QPoint offset(qRound(d->matrix.dx()), qRound(d->matrix.dy()));
+#if QT_CONFIG(xrender)
+ ::Picture pict = d->picture;
+
+ if (X11->use_xrender && pict && d->has_brush && d->pdev_depth != 1
+ && (d->has_texture || d->has_alpha_brush || complexPictOp(d->composition_mode)))
+ {
+ XRenderColor xc;
+ if (!d->has_texture && !d->has_pattern)
+ xc = X11->preMultiply(d->cbrush.color());
+
+ for (int i = 0; i < rectCount; ++i) {
+ QRect r(rects[i]);
+ if (d->txop == QTransform::TxTranslate)
+ r.translate(offset);
+
+ if (r.width() == 0 || r.height() == 0) {
+ if (d->has_pen) {
+ const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height()));
+ XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y());
+ }
+ continue;
+ }
+
+ r = r.intersected(clip);
+ if (r.isEmpty())
+ continue;
+ if (d->has_texture || d->has_pattern) {
+ XRenderComposite(d->dpy, d->composition_mode, d->current_brush, 0, pict,
+ qRound(r.x() - d->bg_origin.x()), qRound(r.y() - d->bg_origin.y()),
+ 0, 0, r.x(), r.y(), r.width(), r.height());
+ } else {
+ XRenderFillRectangle(d->dpy, d->composition_mode, pict, &xc, r.x(), r.y(), r.width(), r.height());
+ }
+ if (d->has_pen)
+ XDrawRectangle(d->dpy, d->hd, d->gc, r.x(), r.y(), r.width(), r.height());
+ }
+ } else
+#endif // QT_CONFIG(xrender)
+ {
+ if (d->has_brush && d->has_pen) {
+ for (int i = 0; i < rectCount; ++i) {
+ QRect r(rects[i]);
+ if (d->txop == QTransform::TxTranslate)
+ r.translate(offset);
+
+ if (r.width() == 0 || r.height() == 0) {
+ const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height()));
+ XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y());
+ continue;
+ }
+
+ r = r.intersected(clip);
+ if (r.isEmpty())
+ continue;
+ d->setupAdaptedOrigin(r.topLeft());
+ XFillRectangle(d->dpy, d->hd, d->gc_brush, r.x(), r.y(), r.width(), r.height());
+ XDrawRectangle(d->dpy, d->hd, d->gc, r.x(), r.y(), r.width(), r.height());
+ }
+ d->resetAdaptedOrigin();
+ } else {
+ QVarLengthArray<XRectangle> xrects(rectCount);
+ int numClipped = rectCount;
+ for (int i = 0; i < rectCount; ++i) {
+ QRect r(rects[i]);
+ if (d->txop == QTransform::TxTranslate)
+ r.translate(offset);
+
+ if (r.width() == 0 || r.height() == 0) {
+ --numClipped;
+ if (d->has_pen) {
+ const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height()));
+ XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y());
+ }
+ continue;
+ }
+
+ r = r.intersected(clip);
+ if (r.isEmpty()) {
+ --numClipped;
+ continue;
+ }
+ xrects[i].x = short(r.x());
+ xrects[i].y = short(r.y());
+ xrects[i].width = ushort(r.width());
+ xrects[i].height = ushort(r.height());
+ }
+ if (numClipped) {
+ d->setupAdaptedOrigin(rects[0].topLeft());
+ if (d->has_brush)
+ XFillRectangles(d->dpy, d->hd, d->gc_brush, xrects.data(), numClipped);
+ else if (d->has_pen)
+ XDrawRectangles(d->dpy, d->hd, d->gc, xrects.data(), numClipped);
+ d->resetAdaptedOrigin();
+ }
+ }
+ }
+}
+
+static inline void setCapStyle(int cap_style, GC gc)
+{
+ ulong mask = GCCapStyle;
+ XGCValues vals;
+ vals.cap_style = cap_style;
+ XChangeGC(QXcbX11Info::display(), gc, mask, &vals);
+}
+
+void QX11PaintEngine::drawPoints(const QPoint *points, int pointCount)
+{
+ Q_ASSERT(points);
+ Q_ASSERT(pointCount);
+ Q_D(QX11PaintEngine);
+
+ if (!d->has_pen)
+ return;
+
+ // use the same test here as in drawPath to ensure that we don't use the path fallback
+ // and end up in XDrawLines for pens with width <= 1
+ if (d->cpen.widthF() > 1.0f
+ || (X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing)))
+ || (!d->isCosmeticPen() && d->txop > QTransform::TxTranslate))
+ {
+ Qt::PenCapStyle capStyle = d->cpen.capStyle();
+ if (capStyle == Qt::FlatCap) {
+ setCapStyle(CapProjecting, d->gc);
+ d->cpen.setCapStyle(Qt::SquareCap);
+ }
+ const QPoint *end = points + pointCount;
+ while (points < end) {
+ QPainterPath path;
+ path.moveTo(*points);
+ path.lineTo(points->x()+.005, points->y());
+ drawPath(path);
+ ++points;
+ }
+
+ if (capStyle == Qt::FlatCap) {
+ setCapStyle(CapButt, d->gc);
+ d->cpen.setCapStyle(capStyle);
+ }
+ return;
+ }
+
+ static const int BUF_SIZE = 1024;
+ XPoint xPoints[BUF_SIZE];
+ int i = 0, j = 0;
+ while (i < pointCount) {
+ while (i < pointCount && j < BUF_SIZE) {
+ const QPoint &xformed = d->matrix.map(points[i]);
+ int x = xformed.x();
+ int y = xformed.y();
+ if (x >= SHRT_MIN && y >= SHRT_MIN && x < SHRT_MAX && y < SHRT_MAX) {
+ xPoints[j].x = x;
+ xPoints[j].y = y;
+ ++j;
+ }
+ ++i;
+ }
+ if (j)
+ XDrawPoints(d->dpy, d->hd, d->gc, xPoints, j, CoordModeOrigin);
+
+ j = 0;
+ }
+}
+
+void QX11PaintEngine::drawPoints(const QPointF *points, int pointCount)
+{
+ Q_ASSERT(points);
+ Q_ASSERT(pointCount);
+ Q_D(QX11PaintEngine);
+
+ if (!d->has_pen)
+ return;
+
+ // use the same test here as in drawPath to ensure that we don't use the path fallback
+ // and end up in XDrawLines for pens with width <= 1
+ if (d->cpen.widthF() > 1.0f
+ || (X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing)))
+ || (!d->isCosmeticPen() && d->txop > QTransform::TxTranslate))
+ {
+ Qt::PenCapStyle capStyle = d->cpen.capStyle();
+ if (capStyle == Qt::FlatCap) {
+ setCapStyle(CapProjecting, d->gc);
+ d->cpen.setCapStyle(Qt::SquareCap);
+ }
+
+ const QPointF *end = points + pointCount;
+ while (points < end) {
+ QPainterPath path;
+ path.moveTo(*points);
+ path.lineTo(points->x() + 0.005, points->y());
+ drawPath(path);
+ ++points;
+ }
+ if (capStyle == Qt::FlatCap) {
+ setCapStyle(CapButt, d->gc);
+ d->cpen.setCapStyle(capStyle);
+ }
+ return;
+ }
+
+ static const int BUF_SIZE = 1024;
+ XPoint xPoints[BUF_SIZE];
+ int i = 0, j = 0;
+ while (i < pointCount) {
+ while (i < pointCount && j < BUF_SIZE) {
+ const QPointF &xformed = d->matrix.map(points[i]);
+ int x = qFloor(xformed.x());
+ int y = qFloor(xformed.y());
+
+ if (x >= SHRT_MIN && y >= SHRT_MIN && x < SHRT_MAX && y < SHRT_MAX) {
+ xPoints[j].x = x;
+ xPoints[j].y = y;
+ ++j;
+ }
+ ++i;
+ }
+ if (j)
+ XDrawPoints(d->dpy, d->hd, d->gc, xPoints, j, CoordModeOrigin);
+
+ j = 0;
+ }
+}
+
+QPainter::RenderHints QX11PaintEngine::supportedRenderHints() const
+{
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender)
+ return QPainter::Antialiasing;
+#endif
+ return QFlag(0);
+}
+
+void QX11PaintEngine::updateState(const QPaintEngineState &state)
+{
+ Q_D(QX11PaintEngine);
+ QPaintEngine::DirtyFlags flags = state.state();
+
+
+ if (flags & DirtyOpacity) {
+ d->opacity = state.opacity();
+ // Force update pen/brush as to get proper alpha colors propagated
+ flags |= DirtyPen;
+ flags |= DirtyBrush;
+ }
+
+ if (flags & DirtyTransform) updateMatrix(state.transform());
+ if (flags & DirtyPen) updatePen(state.pen());
+ if (flags & (DirtyBrush | DirtyBrushOrigin)) updateBrush(state.brush(), state.brushOrigin());
+ if (flags & DirtyFont) updateFont(state.font());
+
+ if (state.state() & DirtyClipEnabled) {
+ if (state.isClipEnabled()) {
+ QPolygonF clip_poly_dev(d->matrix.map(painter()->clipPath().toFillPolygon()));
+ QPolygonF clipped_poly_dev;
+ d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
+ updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), Qt::ReplaceClip);
+ } else {
+ updateClipRegion_dev(QRegion(), Qt::NoClip);
+ }
+ }
+
+ if (flags & DirtyClipPath) {
+ QPolygonF clip_poly_dev(d->matrix.map(state.clipPath().toFillPolygon()));
+ QPolygonF clipped_poly_dev;
+ d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
+ updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon(), state.clipPath().fillRule()),
+ state.clipOperation());
+ } else if (flags & DirtyClipRegion) {
+ extern QPainterPath qt_regionToPath(const QRegion &region);
+ QPainterPath clip_path = qt_regionToPath(state.clipRegion());
+ QPolygonF clip_poly_dev(d->matrix.map(clip_path.toFillPolygon()));
+ QPolygonF clipped_poly_dev;
+ d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
+ updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), state.clipOperation());
+ }
+ if (flags & DirtyHints) updateRenderHints(state.renderHints());
+ if (flags & DirtyCompositionMode) {
+ int function = GXcopy;
+ if (state.compositionMode() >= QPainter::RasterOp_SourceOrDestination) {
+ switch (state.compositionMode()) {
+ case QPainter::RasterOp_SourceOrDestination:
+ function = GXor;
+ break;
+ case QPainter::RasterOp_SourceAndDestination:
+ function = GXand;
+ break;
+ case QPainter::RasterOp_SourceXorDestination:
+ function = GXxor;
+ break;
+ case QPainter::RasterOp_NotSourceAndNotDestination:
+ function = GXnor;
+ break;
+ case QPainter::RasterOp_NotSourceOrNotDestination:
+ function = GXnand;
+ break;
+ case QPainter::RasterOp_NotSourceXorDestination:
+ function = GXequiv;
+ break;
+ case QPainter::RasterOp_NotSource:
+ function = GXcopyInverted;
+ break;
+ case QPainter::RasterOp_SourceAndNotDestination:
+ function = GXandReverse;
+ break;
+ case QPainter::RasterOp_NotSourceAndDestination:
+ function = GXandInverted;
+ break;
+ default:
+ function = GXcopy;
+ }
+ }
+#if QT_CONFIG(xrender)
+ else {
+ d->composition_mode =
+ qpainterOpToXrender(state.compositionMode());
+ }
+#endif
+ XSetFunction(X11->display, d->gc, function);
+ XSetFunction(X11->display, d->gc_brush, function);
+ }
+ d->decidePathFallback();
+ d->decideCoordAdjust();
+}
+
+void QX11PaintEngine::updateRenderHints(QPainter::RenderHints hints)
+{
+ Q_D(QX11PaintEngine);
+ d->render_hints = hints;
+
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender && d->picture) {
+ XRenderPictureAttributes attrs;
+ attrs.poly_edge = (hints & QPainter::Antialiasing) ? PolyEdgeSmooth : PolyEdgeSharp;
+ XRenderChangePicture(d->dpy, d->picture, CPPolyEdge, &attrs);
+ }
+#endif
+}
+
+void QX11PaintEngine::updatePen(const QPen &pen)
+{
+ Q_D(QX11PaintEngine);
+ d->cpen = pen;
+ int cp = CapButt;
+ int jn = JoinMiter;
+ int ps = pen.style();
+
+ if (d->opacity < 1.0) {
+ QColor c = d->cpen.color();
+ c.setAlpha(qRound(c.alpha()*d->opacity));
+ d->cpen.setColor(c);
+ }
+
+ d->has_pen = (ps != Qt::NoPen);
+ d->has_alpha_pen = (pen.color().alpha() != 255);
+
+ switch (pen.capStyle()) {
+ case Qt::SquareCap:
+ cp = CapProjecting;
+ break;
+ case Qt::RoundCap:
+ cp = CapRound;
+ break;
+ case Qt::FlatCap:
+ default:
+ cp = CapButt;
+ break;
+ }
+ switch (pen.joinStyle()) {
+ case Qt::BevelJoin:
+ jn = JoinBevel;
+ break;
+ case Qt::RoundJoin:
+ jn = JoinRound;
+ break;
+ case Qt::MiterJoin:
+ default:
+ jn = JoinMiter;
+ break;
+ }
+
+ d->adapted_pen_origin = false;
+
+ char dashes[10]; // custom pen dashes
+ int dash_len = 0; // length of dash list
+ int xStyle = LineSolid;
+
+ /*
+ We are emulating Windows here. Windows treats cpen.width() == 1
+ (or 0) as a very special case. The fudge variable unifies this
+ case with the general case.
+ */
+ qreal pen_width = pen.widthF();
+ int scale = qRound(pen_width < 1 ? 1 : pen_width);
+ int space = (pen_width < 1 && pen_width > 0 ? 1 : (2 * scale));
+ int dot = 1 * scale;
+ int dash = 4 * scale;
+
+ d->has_custom_pen = false;
+
+ switch (ps) {
+ case Qt::NoPen:
+ case Qt::SolidLine:
+ xStyle = LineSolid;
+ break;
+ case Qt::DashLine:
+ dashes[0] = dash;
+ dashes[1] = space;
+ dash_len = 2;
+ xStyle = LineOnOffDash;
+ break;
+ case Qt::DotLine:
+ dashes[0] = dot;
+ dashes[1] = space;
+ dash_len = 2;
+ xStyle = LineOnOffDash;
+ break;
+ case Qt::DashDotLine:
+ dashes[0] = dash;
+ dashes[1] = space;
+ dashes[2] = dot;
+ dashes[3] = space;
+ dash_len = 4;
+ xStyle = LineOnOffDash;
+ break;
+ case Qt::DashDotDotLine:
+ dashes[0] = dash;
+ dashes[1] = space;
+ dashes[2] = dot;
+ dashes[3] = space;
+ dashes[4] = dot;
+ dashes[5] = space;
+ dash_len = 6;
+ xStyle = LineOnOffDash;
+ break;
+ case Qt::CustomDashLine:
+ d->has_custom_pen = true;
+ break;
+ }
+
+ ulong mask = GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth
+ | GCCapStyle | GCJoinStyle | GCLineStyle;
+ XGCValues vals;
+ vals.graphics_exposures = false;
+ if (d->pdev_depth == 1) {
+ vals.foreground = qGray(pen.color().rgb()) > 127 ? 0 : 1;
+ vals.background = qGray(QColor(Qt::transparent).rgb()) > 127 ? 0 : 1;
+ } else if (d->pdev->devType() == QInternal::Pixmap && d->pdev_depth == 32
+ && X11->use_xrender) {
+ vals.foreground = pen.color().rgba();
+ vals.background = QColor(Qt::transparent).rgba();
+ } else {
+ QXcbColormap cmap = QXcbColormap::instance(d->scrn);
+ vals.foreground = cmap.pixel(pen.color());
+ vals.background = cmap.pixel(QColor(Qt::transparent));
+ }
+
+
+ vals.line_width = qRound(pen.widthF());
+ vals.cap_style = cp;
+ vals.join_style = jn;
+ vals.line_style = xStyle;
+
+ XChangeGC(d->dpy, d->gc, mask, &vals);
+
+ if (dash_len) { // make dash list
+ XSetDashes(d->dpy, d->gc, 0, dashes, dash_len);
+ }
+
+ if (!d->has_clipping) { // if clipping is set the paintevent clip region is merged with the clip region
+ QRegion sysClip = systemClip();
+ if (!sysClip.isEmpty())
+ x11SetClipRegion(d->dpy, d->gc, 0, d->picture, sysClip);
+ else
+ x11ClearClipRegion(d->dpy, d->gc, 0, d->picture);
+ }
+}
+
+void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
+{
+ Q_D(QX11PaintEngine);
+ d->cbrush = brush;
+ d->bg_origin = origin;
+ d->adapted_brush_origin = false;
+#if QT_CONFIG(xrender)
+ d->current_brush = 0;
+#endif
+ if (d->opacity < 1.0) {
+ QColor c = d->cbrush.color();
+ c.setAlpha(qRound(c.alpha()*d->opacity));
+ d->cbrush.setColor(c);
+ }
+
+ int s = FillSolid;
+ int bs = d->cbrush.style();
+ d->has_brush = (bs != Qt::NoBrush);
+ d->has_pattern = bs >= Qt::Dense1Pattern && bs <= Qt::DiagCrossPattern;
+ d->has_texture = bs == Qt::TexturePattern;
+ d->has_alpha_brush = brush.color().alpha() != 255;
+ d->has_alpha_texture = d->has_texture && d->cbrush.texture().hasAlphaChannel();
+
+ ulong mask = GCForeground | GCBackground | GCGraphicsExposures
+ | GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle;
+ XGCValues vals;
+ vals.graphics_exposures = false;
+ if (d->pdev_depth == 1) {
+ vals.foreground = qGray(d->cbrush.color().rgb()) > 127 ? 0 : 1;
+ vals.background = qGray(QColor(Qt::transparent).rgb()) > 127 ? 0 : 1;
+ } else if (X11->use_xrender && d->pdev->devType() == QInternal::Pixmap
+ && d->pdev_depth == 32) {
+ vals.foreground = d->cbrush.color().rgba();
+ vals.background = QColor(Qt::transparent).rgba();
+ } else {
+ QXcbColormap cmap = QXcbColormap::instance(d->scrn);
+ vals.foreground = cmap.pixel(d->cbrush.color());
+ vals.background = cmap.pixel(QColor(Qt::transparent));
+
+ if (!X11->use_xrender && d->has_brush && !d->has_pattern && !brush.isOpaque()) {
+ QPixmap pattern = qt_patternForAlpha(brush.color().alpha(), d->scrn);
+ mask |= GCStipple;
+ vals.stipple = qt_x11PixmapHandle(pattern);
+ s = FillStippled;
+ d->adapted_brush_origin = true;
+ }
+ }
+ vals.cap_style = CapButt;
+ vals.join_style = JoinMiter;
+ vals.line_style = LineSolid;
+
+ if (d->has_pattern || d->has_texture) {
+ if (bs == Qt::TexturePattern) {
+ d->brush_pm = qt_toX11Pixmap(d->cbrush.texture());
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender) {
+ XRenderPictureAttributes attrs;
+ attrs.repeat = true;
+ XRenderChangePicture(d->dpy, qt_x11PictureHandle(d->brush_pm), CPRepeat, &attrs);
+ QX11PlatformPixmap *data = static_cast<QX11PlatformPixmap*>(d->brush_pm.handle());
+ if (data->mask_picture)
+ XRenderChangePicture(d->dpy, data->mask_picture, CPRepeat, &attrs);
+ }
+#endif
+ } else {
+ d->brush_pm = qt_toX11Pixmap(qt_pixmapForBrush(bs, true));
+ }
+ qt_x11SetScreen(d->brush_pm, d->scrn);
+ if (d->brush_pm.depth() == 1) {
+ mask |= GCStipple;
+ vals.stipple = qt_x11PixmapHandle(d->brush_pm);
+ s = FillStippled;
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender) {
+ d->bitmap_texture = QPixmap(d->brush_pm.size());
+ d->bitmap_texture.fill(Qt::transparent);
+ d->bitmap_texture = qt_toX11Pixmap(d->bitmap_texture);
+ qt_x11SetScreen(d->bitmap_texture, d->scrn);
+
+ ::Picture src = X11->getSolidFill(d->scrn, d->cbrush.color());
+ XRenderComposite(d->dpy, PictOpSrc, src, qt_x11PictureHandle(d->brush_pm),
+ qt_x11PictureHandle(d->bitmap_texture),
+ 0, 0, d->brush_pm.width(), d->brush_pm.height(),
+ 0, 0, d->brush_pm.width(), d->brush_pm.height());
+
+ XRenderPictureAttributes attrs;
+ attrs.repeat = true;
+ XRenderChangePicture(d->dpy, qt_x11PictureHandle(d->bitmap_texture), CPRepeat, &attrs);
+
+ d->current_brush = qt_x11PictureHandle(d->bitmap_texture);
+ }
+#endif
+ } else {
+ mask |= GCTile;
+#if QT_CONFIG(xrender)
+ if (d->pdev_depth == 32 && d->brush_pm.depth() != 32) {
+ d->brush_pm.detach();
+ QX11PlatformPixmap *brushData = static_cast<QX11PlatformPixmap*>(d->brush_pm.handle());
+ brushData->convertToARGB32();
+ }
+#endif
+ vals.tile = (d->brush_pm.depth() == d->pdev_depth
+ ? qt_x11PixmapHandle(d->brush_pm)
+ : static_cast<QX11PlatformPixmap*>(d->brush_pm.handle())->x11ConvertToDefaultDepth());
+ s = FillTiled;
+#if QT_CONFIG(xrender)
+ d->current_brush = qt_x11PictureHandle(d->cbrush.texture());
+#endif
+ }
+
+ mask |= GCTileStipXOrigin | GCTileStipYOrigin;
+ vals.ts_x_origin = qRound(origin.x());
+ vals.ts_y_origin = qRound(origin.y());
+ }
+#if QT_CONFIG(xrender)
+ else if (d->has_alpha_brush) {
+ d->current_brush = X11->getSolidFill(d->scrn, d->cbrush.color());
+ }
+#endif
+
+ vals.fill_style = s;
+ XChangeGC(d->dpy, d->gc_brush, mask, &vals);
+ if (!d->has_clipping) {
+ QRegion sysClip = systemClip();
+ if (!sysClip.isEmpty())
+ x11SetClipRegion(d->dpy, d->gc_brush, 0, d->picture, sysClip);
+ else
+ x11ClearClipRegion(d->dpy, d->gc_brush, 0, d->picture);
+ }
+}
+
+void QX11PaintEngine::drawEllipse(const QRectF &rect)
+{
+ QRect aligned = rect.toAlignedRect();
+ if (aligned == rect)
+ drawEllipse(aligned);
+ else
+ QPaintEngine::drawEllipse(rect);
+}
+
+void QX11PaintEngine::drawEllipse(const QRect &rect)
+{
+ if (rect.isEmpty()) {
+ drawRects(&rect, 1);
+ return;
+ }
+
+ Q_D(QX11PaintEngine);
+ QRect devclip(SHRT_MIN, SHRT_MIN, SHRT_MAX*2 - 1, SHRT_MAX*2 - 1);
+ QRect r(rect);
+ if (d->txop < QTransform::TxRotate) {
+ r = d->matrix.mapRect(rect);
+ } else if (d->txop == QTransform::TxRotate && rect.width() == rect.height()) {
+ QPainterPath path;
+ path.addEllipse(rect);
+ r = d->matrix.map(path).boundingRect().toRect();
+ }
+
+ if (d->has_alpha_brush || d->has_alpha_pen || d->has_custom_pen || (d->render_hints & QPainter::Antialiasing)
+ || d->has_alpha_texture || devclip.intersected(r) != r
+ || (d->has_complex_xform
+ && !(d->has_non_scaling_xform && rect.width() == rect.height())))
+ {
+ QPainterPath path;
+ path.addEllipse(rect);
+ drawPath(path);
+ return;
+ }
+
+ int x = r.x();
+ int y = r.y();
+ int w = r.width();
+ int h = r.height();
+ if (w < 1 || h < 1)
+ return;
+ if (w == 1 && h == 1) {
+ XDrawPoint(d->dpy, d->hd, d->has_pen ? d->gc : d->gc_brush, x, y);
+ return;
+ }
+ d->setupAdaptedOrigin(rect.topLeft());
+ if (d->has_brush) { // draw filled ellipse
+ XFillArc(d->dpy, d->hd, d->gc_brush, x, y, w, h, 0, 360*64);
+ if (!d->has_pen) // make smoother outline
+ XDrawArc(d->dpy, d->hd, d->gc_brush, x, y, w-1, h-1, 0, 360*64);
+ }
+ if (d->has_pen) // draw outline
+ XDrawArc(d->dpy, d->hd, d->gc, x, y, w, h, 0, 360*64);
+ d->resetAdaptedOrigin();
+}
+
+
+
+void QX11PaintEnginePrivate::fillPolygon_translated(const QPointF *polygonPoints, int pointCount,
+ QX11PaintEnginePrivate::GCMode gcMode,
+ QPaintEngine::PolygonDrawMode mode)
+{
+
+ QVarLengthArray<QPointF> translated_points(pointCount);
+ QPointF offset(matrix.dx(), matrix.dy());
+
+ qreal offs = adjust_coords ? aliasedCoordinateDelta : 0.0;
+ if (!X11->use_xrender || !(render_hints & QPainter::Antialiasing))
+ offset += QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta);
+
+ for (int i = 0; i < pointCount; ++i) {
+ translated_points[i] = polygonPoints[i] + offset;
+
+ translated_points[i].rx() = qRound(translated_points[i].x()) + offs;
+ translated_points[i].ry() = qRound(translated_points[i].y()) + offs;
+ }
+
+ fillPolygon_dev(translated_points.data(), pointCount, gcMode, mode);
+}
+
+#if QT_CONFIG(xrender)
+static void qt_XRenderCompositeTrapezoids(Display *dpy,
+ int op,
+ Picture src,
+ Picture dst,
+ _Xconst XRenderPictFormat *maskFormat,
+ int xSrc,
+ int ySrc,
+ const XTrapezoid *traps, int size)
+{
+ const int MAX_TRAPS = 50000;
+ while (size) {
+ int to_draw = size;
+ if (to_draw > MAX_TRAPS)
+ to_draw = MAX_TRAPS;
+ XRenderCompositeTrapezoids(dpy, op, src, dst,
+ maskFormat,
+ xSrc, ySrc,
+ traps, to_draw);
+ size -= to_draw;
+ traps += to_draw;
+ }
+}
+#endif
+
+void QX11PaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount,
+ QX11PaintEnginePrivate::GCMode gcMode,
+ QPaintEngine::PolygonDrawMode mode)
+{
+ Q_Q(QX11PaintEngine);
+
+ int clippedCount = 0;
+ qt_float_point *clippedPoints = 0;
+
+#if QT_CONFIG(xrender)
+ //can change if we switch to pen if gcMode != BrushGC
+ bool has_fill_texture = has_texture;
+ bool has_fill_pattern = has_pattern;
+ ::Picture src;
+#endif
+ QBrush fill;
+ GC fill_gc;
+ if (gcMode == BrushGC) {
+ fill = cbrush;
+ fill_gc = gc_brush;
+#if QT_CONFIG(xrender)
+ if (current_brush)
+ src = current_brush;
+ else
+ src = X11->getSolidFill(scrn, fill.color());
+#endif
+ } else {
+ fill = QBrush(cpen.brush());
+ fill_gc = gc;
+#if QT_CONFIG(xrender)
+ //we use the pens brush
+ has_fill_texture = (fill.style() == Qt::TexturePattern);
+ has_fill_pattern = (fill.style() >= Qt::Dense1Pattern && fill.style() <= Qt::DiagCrossPattern);
+ if (has_fill_texture)
+ src = qt_x11PictureHandle(fill.texture());
+ else if (has_fill_pattern)
+ src = getPatternFill(scrn, fill);
+ else
+ src = X11->getSolidFill(scrn, fill.color());
+#endif
+ }
+
+ polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount,
+ &clippedPoints, &clippedCount);
+
+#if QT_CONFIG(xrender)
+ bool solid_fill = fill.color().alpha() == 255;
+ if (has_fill_texture && fill.texture().depth() == 1 && solid_fill) {
+ has_fill_texture = false;
+ has_fill_pattern = true;
+ }
+
+ bool antialias = render_hints & QPainter::Antialiasing;
+
+ if (X11->use_xrender
+ && picture
+ && !has_fill_pattern
+ && (clippedCount > 0)
+ && (fill.style() != Qt::NoBrush)
+ && ((has_fill_texture && fill.texture().hasAlpha()) || antialias || !solid_fill || has_alpha_pen != has_alpha_brush))
+ {
+ tessellator->tessellate((QPointF *)clippedPoints, clippedCount,
+ mode == QPaintEngine::WindingMode);
+ if (tessellator->size > 0) {
+ XRenderPictureAttributes attrs;
+ attrs.poly_edge = antialias ? PolyEdgeSmooth : PolyEdgeSharp;
+ XRenderChangePicture(dpy, picture, CPPolyEdge, &attrs);
+ int x_offset = int(XFixedToDouble(tessellator->traps[0].left.p1.x) - bg_origin.x());
+ int y_offset = int(XFixedToDouble(tessellator->traps[0].left.p1.y) - bg_origin.y());
+ qt_XRenderCompositeTrapezoids(dpy, composition_mode, src, picture,
+ antialias
+ ? XRenderFindStandardFormat(dpy, PictStandardA8)
+ : XRenderFindStandardFormat(dpy, PictStandardA1),
+ x_offset, y_offset,
+ tessellator->traps, tessellator->size);
+ tessellator->done();
+ }
+ } else
+#endif
+ if (fill.style() != Qt::NoBrush) {
+ if (clippedCount > 200000) {
+ QPolygon poly;
+ for (int i = 0; i < clippedCount; ++i)
+ poly << QPoint(qFloor(clippedPoints[i].x), qFloor(clippedPoints[i].y));
+
+ const QRect bounds = poly.boundingRect();
+ const QRect aligned = bounds
+ & QRect(QPoint(), QSize(pdev->width(), pdev->height()));
+
+ QImage img(aligned.size(), QImage::Format_ARGB32_Premultiplied);
+ img.fill(0);
+
+ QPainter painter(&img);
+ painter.translate(-aligned.x(), -aligned.y());
+ painter.setPen(Qt::NoPen);
+ painter.setBrush(fill);
+ if (gcMode == BrushGC)
+ painter.setBrushOrigin(q->painter()->brushOrigin());
+ painter.drawPolygon(poly);
+ painter.end();
+
+ q->drawImage(aligned, img, img.rect(), Qt::AutoColor);
+ } else if (clippedCount > 0) {
+ QVarLengthArray<XPoint> xpoints(clippedCount);
+ for (int i = 0; i < clippedCount; ++i) {
+ xpoints[i].x = qFloor(clippedPoints[i].x);
+ xpoints[i].y = qFloor(clippedPoints[i].y);
+ }
+ if (mode == QPaintEngine::WindingMode)
+ XSetFillRule(dpy, fill_gc, WindingRule);
+ setupAdaptedOrigin(QPoint(xpoints[0].x, xpoints[0].y));
+ XFillPolygon(dpy, hd, fill_gc,
+ xpoints.data(), clippedCount,
+ mode == QPaintEngine::ConvexMode ? Convex : Complex, CoordModeOrigin);
+ resetAdaptedOrigin();
+ if (mode == QPaintEngine::WindingMode)
+ XSetFillRule(dpy, fill_gc, EvenOddRule);
+ }
+ }
+}
+
+void QX11PaintEnginePrivate::strokePolygon_translated(const QPointF *polygonPoints, int pointCount, bool close)
+{
+ QVarLengthArray<QPointF> translated_points(pointCount);
+ QPointF offset(matrix.dx(), matrix.dy());
+ for (int i = 0; i < pointCount; ++i)
+ translated_points[i] = polygonPoints[i] + offset;
+ strokePolygon_dev(translated_points.data(), pointCount, close);
+}
+
+void QX11PaintEnginePrivate::strokePolygon_dev(const QPointF *polygonPoints, int pointCount, bool close)
+{
+ int clippedCount = 0;
+ qt_float_point *clippedPoints = 0;
+ polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount,
+ &clippedPoints, &clippedCount, close);
+
+ if (clippedCount > 0) {
+ QVarLengthArray<XPoint> xpoints(clippedCount);
+ for (int i = 0; i < clippedCount; ++i) {
+ xpoints[i].x = qRound(clippedPoints[i].x + aliasedCoordinateDelta);
+ xpoints[i].y = qRound(clippedPoints[i].y + aliasedCoordinateDelta);
+ }
+ uint numberPoints = qMin(clippedCount, xlibMaxLinePoints);
+ XPoint *pts = xpoints.data();
+ XDrawLines(dpy, hd, gc, pts, numberPoints, CoordModeOrigin);
+ pts += numberPoints;
+ clippedCount -= numberPoints;
+ numberPoints = qMin(clippedCount, xlibMaxLinePoints-1);
+ while (clippedCount) {
+ XDrawLines(dpy, hd, gc, pts-1, numberPoints+1, CoordModeOrigin);
+ pts += numberPoints;
+ clippedCount -= numberPoints;
+ numberPoints = qMin(clippedCount, xlibMaxLinePoints-1);
+ }
+ }
+}
+
+void QX11PaintEngine::drawPolygon(const QPointF *polygonPoints, int pointCount, PolygonDrawMode mode)
+{
+ Q_D(QX11PaintEngine);
+
+ if (d->use_path_fallback) {
+ QPainterPath path(polygonPoints[0]);
+ for (int i = 1; i < pointCount; ++i)
+ path.lineTo(polygonPoints[i]);
+ if (mode == PolylineMode) {
+ QBrush oldBrush = d->cbrush;
+ d->cbrush = QBrush(Qt::NoBrush);
+ path.setFillRule(Qt::WindingFill);
+ drawPath(path);
+ d->cbrush = oldBrush;
+ } else {
+ path.setFillRule(mode == OddEvenMode ? Qt::OddEvenFill : Qt::WindingFill);
+ path.closeSubpath();
+ drawPath(path);
+ }
+ return;
+ }
+ if (mode != PolylineMode && d->has_brush)
+ d->fillPolygon_translated(polygonPoints, pointCount, QX11PaintEnginePrivate::BrushGC, mode);
+
+ if (d->has_pen)
+ d->strokePolygon_translated(polygonPoints, pointCount, mode != PolylineMode);
+}
+
+
+void QX11PaintEnginePrivate::fillPath(const QPainterPath &path, QX11PaintEnginePrivate::GCMode gc_mode, bool transform)
+{
+ qreal offs = adjust_coords ? aliasedCoordinateDelta : 0.0;
+
+ QPainterPath clippedPath;
+ QPainterPath clipPath;
+ clipPath.addRect(polygonClipper.boundingRect());
+
+ if (transform)
+ clippedPath = (path*matrix).intersected(clipPath);
+ else
+ clippedPath = path.intersected(clipPath);
+
+ QList<QPolygonF> polys = clippedPath.toFillPolygons();
+ for (int i = 0; i < polys.size(); ++i) {
+ QVarLengthArray<QPointF> translated_points(polys.at(i).size());
+
+ for (int j = 0; j < polys.at(i).size(); ++j) {
+ translated_points[j] = polys.at(i).at(j);
+ if (!X11->use_xrender || !(render_hints & QPainter::Antialiasing)) {
+ translated_points[j].rx() = qRound(translated_points[j].rx() + aliasedCoordinateDelta) + offs;
+ translated_points[j].ry() = qRound(translated_points[j].ry() + aliasedCoordinateDelta) + offs;
+ }
+ }
+
+ fillPolygon_dev(translated_points.data(), polys.at(i).size(), gc_mode,
+ path.fillRule() == Qt::OddEvenFill ? QPaintEngine::OddEvenMode : QPaintEngine::WindingMode);
+ }
+}
+
+void QX11PaintEngine::drawPath(const QPainterPath &path)
+{
+ Q_D(QX11PaintEngine);
+ if (path.isEmpty())
+ return;
+
+ if (d->has_brush)
+ d->fillPath(path, QX11PaintEnginePrivate::BrushGC, true);
+ if (d->has_pen
+ && ((X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing)))
+ || (!d->isCosmeticPen() && d->txop > QTransform::TxTranslate
+ && !d->has_non_scaling_xform)
+ || (d->cpen.style() == Qt::CustomDashLine))) {
+ QPainterPathStroker stroker;
+ if (d->cpen.style() == Qt::CustomDashLine) {
+ stroker.setDashPattern(d->cpen.dashPattern());
+ stroker.setDashOffset(d->cpen.dashOffset());
+ } else {
+ stroker.setDashPattern(d->cpen.style());
+ }
+ stroker.setCapStyle(d->cpen.capStyle());
+ stroker.setJoinStyle(d->cpen.joinStyle());
+ QPainterPath stroke;
+ qreal width = d->cpen.widthF();
+ QPolygonF poly;
+ QRectF deviceRect(0, 0, d->pdev->width(), d->pdev->height());
+ // necessary to get aliased alphablended primitives to be drawn correctly
+ if (d->isCosmeticPen() || d->has_scaling_xform) {
+ if (d->isCosmeticPen())
+ stroker.setWidth(width == 0 ? 1 : width);
+ else
+ stroker.setWidth(width * d->xform_scale);
+ stroker.d_ptr->stroker.setClipRect(deviceRect);
+ stroke = stroker.createStroke(path * d->matrix);
+ if (stroke.isEmpty())
+ return;
+ stroke.setFillRule(Qt::WindingFill);
+ d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, false);
+ } else {
+ stroker.setWidth(width);
+ stroker.d_ptr->stroker.setClipRect(d->matrix.inverted().mapRect(deviceRect));
+ stroke = stroker.createStroke(path);
+ if (stroke.isEmpty())
+ return;
+ stroke.setFillRule(Qt::WindingFill);
+ d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, true);
+ }
+ } else if (d->has_pen) {
+ // if we have a cosmetic pen - use XDrawLine() for speed
+ QList<QPolygonF> polys = path.toSubpathPolygons(d->matrix);
+ for (int i = 0; i < polys.size(); ++i)
+ d->strokePolygon_dev(polys.at(i).data(), polys.at(i).size(), false);
+ }
+}
+
+Q_GUI_EXPORT void qt_x11_drawImage(const QRect &rect, const QPoint &pos, const QImage &image,
+ Drawable hd, GC gc, Display *dpy, Visual *visual, int depth)
+{
+ Q_ASSERT(image.format() == QImage::Format_RGB32);
+ Q_ASSERT(image.depth() == 32);
+
+ XImage *xi;
+ // Note: this code assumes either RGB or BGR, 8 bpc server layouts
+ const uint red_mask = (uint) visual->red_mask;
+ bool bgr_layout = (red_mask == 0xff);
+
+ const int w = rect.width();
+ const int h = rect.height();
+
+ QImage im;
+ int image_byte_order = ImageByteOrder(QXcbX11Info::display());
+ if ((QSysInfo::ByteOrder == QSysInfo::BigEndian && ((image_byte_order == LSBFirst) || bgr_layout))
+ || (image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)
+ || (image_byte_order == LSBFirst && bgr_layout))
+ {
+ im = image.copy(rect);
+ const int iw = im.bytesPerLine() / 4;
+ uint *data = (uint *)im.bits();
+ for (int i=0; i < h; i++) {
+ uint *p = data;
+ uint *end = p + w;
+ if (bgr_layout && image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
+ while (p < end) {
+ *p = ((*p << 8) & 0xffffff00) | ((*p >> 24) & 0x000000ff);
+ p++;
+ }
+ } else if ((image_byte_order == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ || (image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) {
+ while (p < end) {
+ *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
+ | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
+ p++;
+ }
+ } else if ((image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian)
+ || (image_byte_order == LSBFirst && bgr_layout))
+ {
+ while (p < end) {
+ *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff)
+ | ((*p ) & 0xff00ff00);
+ p++;
+ }
+ }
+ data += iw;
+ }
+ xi = XCreateImage(dpy, visual, depth, ZPixmap,
+ 0, (char *) im.bits(), w, h, 32, im.bytesPerLine());
+ } else {
+ xi = XCreateImage(dpy, visual, depth, ZPixmap,
+ 0, (char *) image.scanLine(rect.y())+rect.x()*sizeof(uint), w, h, 32, image.bytesPerLine());
+ }
+ XPutImage(dpy, hd, gc, xi, 0, 0, pos.x(), pos.y(), w, h);
+ xi->data = 0; // QImage owns these bits
+ XDestroyImage(xi);
+}
+
+void QX11PaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags)
+{
+ Q_D(QX11PaintEngine);
+
+ if (image.format() == QImage::Format_RGB32
+ && d->pdev_depth >= 24 && image.depth() == 32
+ && r.size() == sr.size())
+ {
+ int sx = qRound(sr.x());
+ int sy = qRound(sr.y());
+ int x = qRound(r.x());
+ int y = qRound(r.y());
+ int w = qRound(r.width());
+ int h = qRound(r.height());
+
+ qt_x11_drawImage(QRect(sx, sy, w, h), QPoint(x, y), image, d->hd, d->gc, d->dpy,
+ (Visual *)d->xinfo->visual(), d->pdev_depth);
+ } else {
+ QPaintEngine::drawImage(r, image, sr, flags);
+ }
+}
+
+void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRectF &_sr)
+{
+ Q_D(QX11PaintEngine);
+ QRectF sr = _sr;
+ int x = qRound(r.x());
+ int y = qRound(r.y());
+ int sx = qRound(sr.x());
+ int sy = qRound(sr.y());
+ int sw = qRound(sr.width());
+ int sh = qRound(sr.height());
+
+ QPixmap pixmap = qt_toX11Pixmap(px);
+ if (pixmap.isNull())
+ return;
+
+ if ((d->xinfo && d->xinfo->screen() != qt_x11Info(pixmap).screen())
+ || (qt_x11Info(pixmap).screen() != DefaultScreen(QXcbX11Info::display()))) {
+ qt_x11SetScreen(pixmap, d->xinfo ? d->xinfo->screen() : DefaultScreen(X11->display));
+ }
+
+ qt_x11SetDefaultScreen(qt_x11Info(pixmap).screen());
+
+#if QT_CONFIG(xrender)
+ ::Picture src_pict = qt_x11PictureHandle(pixmap);
+ if (src_pict && d->picture) {
+ const int pDepth = pixmap.depth();
+ if (pDepth == 1 && (d->has_alpha_pen)) {
+ qt_render_bitmap(d->dpy, d->scrn, src_pict, d->picture,
+ sx, sy, x, y, sw, sh, d->cpen);
+ return;
+ } else if (pDepth != 1 && (pDepth == 32 || pDepth != d->pdev_depth)) {
+ XRenderComposite(d->dpy, d->composition_mode,
+ src_pict, 0, d->picture, sx, sy, 0, 0, x, y, sw, sh);
+ return;
+ }
+ }
+#endif
+
+ bool mono_src = pixmap.depth() == 1;
+ bool mono_dst = d->pdev_depth == 1;
+ bool restore_clip = false;
+
+ if (static_cast<QX11PlatformPixmap*>(pixmap.handle())->x11_mask) { // pixmap has a mask
+ QBitmap comb(sw, sh);
+ GC cgc = XCreateGC(d->dpy, qt_x11PixmapHandle(comb), 0, 0);
+ XSetForeground(d->dpy, cgc, 0);
+ XFillRectangle(d->dpy, qt_x11PixmapHandle(comb), cgc, 0, 0, sw, sh);
+ XSetBackground(d->dpy, cgc, 0);
+ XSetForeground(d->dpy, cgc, 1);
+ if (!d->crgn.isEmpty()) {
+ QVector<XRectangle> rects = qt_region_to_xrectangles(d->crgn);
+ XSetClipRectangles(d->dpy, cgc, -x, -y, rects.data(), rects.size(), Unsorted);
+ } else if (d->has_clipping) {
+ XSetClipRectangles(d->dpy, cgc, 0, 0, 0, 0, Unsorted);
+ }
+ XSetFillStyle(d->dpy, cgc, FillOpaqueStippled);
+ XSetTSOrigin(d->dpy, cgc, -sx, -sy);
+ XSetStipple(d->dpy, cgc,
+ static_cast<QX11PlatformPixmap*>(pixmap.handle())->x11_mask);
+ XFillRectangle(d->dpy, qt_x11PixmapHandle(comb), cgc, 0, 0, sw, sh);
+ XFreeGC(d->dpy, cgc);
+
+ XSetClipOrigin(d->dpy, d->gc, x, y);
+ XSetClipMask(d->dpy, d->gc, qt_x11PixmapHandle(comb));
+ restore_clip = true;
+ }
+
+ if (mono_src) {
+ if (!d->crgn.isEmpty()) {
+ Pixmap comb = XCreatePixmap(d->dpy, d->hd, sw, sh, 1);
+ GC cgc = XCreateGC(d->dpy, comb, 0, 0);
+ XSetForeground(d->dpy, cgc, 0);
+ XFillRectangle(d->dpy, comb, cgc, 0, 0, sw, sh);
+ QVector<XRectangle> rects = qt_region_to_xrectangles(d->crgn);
+ XSetClipRectangles(d->dpy, cgc, -x, -y, rects.data(), rects.size(), Unsorted);
+ XCopyArea(d->dpy, qt_x11PixmapHandle(pixmap), comb, cgc, sx, sy, sw, sh, 0, 0);
+ XFreeGC(d->dpy, cgc);
+
+ XSetClipMask(d->dpy, d->gc, comb);
+ XSetClipOrigin(d->dpy, d->gc, x, y);
+ XFreePixmap(d->dpy, comb);
+ } else {
+ XSetClipMask(d->dpy, d->gc, qt_x11PixmapHandle(pixmap));
+ XSetClipOrigin(d->dpy, d->gc, x - sx, y - sy);
+ }
+
+ if (mono_dst) {
+ XSetForeground(d->dpy, d->gc, qGray(d->cpen.color().rgb()) > 127 ? 0 : 1);
+ } else {
+ QXcbColormap cmap = QXcbColormap::instance(d->scrn);
+ XSetForeground(d->dpy, d->gc, cmap.pixel(d->cpen.color()));
+ }
+ XFillRectangle(d->dpy, d->hd, d->gc, x, y, sw, sh);
+ restore_clip = true;
+ } else if (mono_dst && !mono_src) {
+ QBitmap bitmap(pixmap);
+ XCopyArea(d->dpy, qt_x11PixmapHandle(bitmap), d->hd, d->gc, sx, sy, sw, sh, x, y);
+ } else {
+ XCopyArea(d->dpy, qt_x11PixmapHandle(pixmap), d->hd, d->gc, sx, sy, sw, sh, x, y);
+ }
+
+ if (d->pdev->devType() == QInternal::Pixmap) {
+ const QPixmap *px = static_cast<const QPixmap*>(d->pdev);
+ Pixmap src_mask = static_cast<QX11PlatformPixmap*>(pixmap.handle())->x11_mask;
+ Pixmap dst_mask = static_cast<QX11PlatformPixmap*>(px->handle())->x11_mask;
+ if (dst_mask) {
+ GC cgc = XCreateGC(d->dpy, dst_mask, 0, 0);
+ XSetClipOrigin(d->dpy, cgc, x, y);
+ XSetClipMask(d->dpy, cgc, src_mask);
+ if (src_mask) { // copy src mask into dst mask
+ XCopyArea(d->dpy, src_mask, dst_mask, cgc, sx, sy, sw, sh, x, y);
+ } else { // no src mask, but make sure the area copied is opaque in dest
+ XSetBackground(d->dpy, cgc, 0);
+ XSetForeground(d->dpy, cgc, 1);
+ XFillRectangle(d->dpy, dst_mask, cgc, x, y, sw, sh);
+ }
+ XFreeGC(d->dpy, cgc);
+ }
+ }
+
+ if (restore_clip) {
+ XSetClipOrigin(d->dpy, d->gc, 0, 0);
+ QVector<XRectangle> rects = qt_region_to_xrectangles(d->crgn);
+ if (rects.isEmpty())
+ XSetClipMask(d->dpy, d->gc, XNone);
+ else
+ XSetClipRectangles(d->dpy, d->gc, 0, 0, rects.data(), rects.size(), Unsorted);
+ }
+}
+
+void QX11PaintEngine::updateMatrix(const QTransform &mtx)
+{
+ Q_D(QX11PaintEngine);
+ d->txop = mtx.type();
+ d->matrix = mtx;
+
+ d->has_complex_xform = (d->txop > QTransform::TxTranslate);
+
+ extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
+ bool scaling = qt_scaleForTransform(d->matrix, &d->xform_scale);
+ d->has_scaling_xform = scaling && d->xform_scale != 1.0;
+ d->has_non_scaling_xform = scaling && d->xform_scale == 1.0;
+}
+
+/*
+ NB! the clip region is expected to be in dev coordinates
+*/
+void QX11PaintEngine::updateClipRegion_dev(const QRegion &clipRegion, Qt::ClipOperation op)
+{
+ Q_D(QX11PaintEngine);
+ QRegion sysClip = systemClip();
+ if (op == Qt::NoClip) {
+ d->has_clipping = false;
+ d->crgn = sysClip;
+ if (!sysClip.isEmpty()) {
+ x11SetClipRegion(d->dpy, d->gc, d->gc_brush, d->picture, sysClip);
+ } else {
+ x11ClearClipRegion(d->dpy, d->gc, d->gc_brush, d->picture);
+ }
+ return;
+ }
+
+ switch (op) {
+ case Qt::IntersectClip:
+ if (d->has_clipping) {
+ d->crgn &= clipRegion;
+ break;
+ }
+ // fall through
+ case Qt::ReplaceClip:
+ if (!sysClip.isEmpty())
+ d->crgn = clipRegion.intersected(sysClip);
+ else
+ d->crgn = clipRegion;
+ break;
+// case Qt::UniteClip:
+// d->crgn |= clipRegion;
+// if (!sysClip.isEmpty())
+// d->crgn = d->crgn.intersected(sysClip);
+// break;
+ default:
+ break;
+ }
+ d->has_clipping = true;
+ x11SetClipRegion(d->dpy, d->gc, d->gc_brush, d->picture, d->crgn);
+}
+
+void QX11PaintEngine::updateFont(const QFont &)
+{
+}
+
+Drawable QX11PaintEngine::handle() const
+{
+ Q_D(const QX11PaintEngine);
+ Q_ASSERT(isActive());
+ Q_ASSERT(d->hd);
+ return d->hd;
+}
+
+extern void qt_draw_tile(QPaintEngine *, qreal, qreal, qreal, qreal, const QPixmap &,
+ qreal, qreal);
+
+void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &p)
+{
+ int x = qRound(r.x());
+ int y = qRound(r.y());
+ int w = qRound(r.width());
+ int h = qRound(r.height());
+ int sx = qRound(p.x());
+ int sy = qRound(p.y());
+
+ bool mono_src = pixmap.depth() == 1;
+ Q_D(QX11PaintEngine);
+
+ if ((d->xinfo && d->xinfo->screen() != qt_x11Info(pixmap).screen())
+ || (qt_x11Info(pixmap).screen() != DefaultScreen(QXcbX11Info::display()))) {
+ QPixmap* p = const_cast<QPixmap *>(&pixmap);
+ qt_x11SetScreen(*p, d->xinfo ? d->xinfo->screen() : DefaultScreen(QXcbX11Info::display()));
+ }
+
+ qt_x11SetDefaultScreen(qt_x11Info(pixmap).screen());
+
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender && d->picture && qt_x11PictureHandle(pixmap)) {
+#if 0
+ // ### Qt 5: enable this
+ XRenderPictureAttributes attrs;
+ attrs.repeat = true;
+ XRenderChangePicture(d->dpy, pixmap.x11PictureHandle(), CPRepeat, &attrs);
+
+ if (mono_src) {
+ qt_render_bitmap(d->dpy, d->scrn, pixmap.x11PictureHandle(), d->picture,
+ sx, sy, x, y, w, h, d->cpen);
+ } else {
+ XRenderComposite(d->dpy, d->composition_mode,
+ pixmap.x11PictureHandle(), XNone, d->picture,
+ sx, sy, 0, 0, x, y, w, h);
+ }
+#else
+ const int numTiles = (w / pixmap.width()) * (h / pixmap.height());
+ if (numTiles < 100) {
+ // this is essentially qt_draw_tile(), inlined for
+ // the XRenderComposite call
+ int yPos, xPos, drawH, drawW, yOff, xOff;
+ yPos = y;
+ yOff = sy;
+ while (yPos < y + h) {
+ drawH = pixmap.height() - yOff; // Cropping first row
+ if (yPos + drawH > y + h) // Cropping last row
+ drawH = y + h - yPos;
+ xPos = x;
+ xOff = sx;
+ while (xPos < x + w) {
+ drawW = pixmap.width() - xOff; // Cropping first column
+ if (xPos + drawW > x + w) // Cropping last column
+ drawW = x + w - xPos;
+ if (mono_src) {
+ qt_render_bitmap(d->dpy, d->scrn, qt_x11PictureHandle(pixmap), d->picture,
+ xOff, yOff, xPos, yPos, drawW, drawH, d->cpen);
+ } else {
+ XRenderComposite(d->dpy, d->composition_mode,
+ qt_x11PictureHandle(pixmap), XNone, d->picture,
+ xOff, yOff, 0, 0, xPos, yPos, drawW, drawH);
+ }
+ xPos += drawW;
+ xOff = 0;
+ }
+ yPos += drawH;
+ yOff = 0;
+ }
+ } else {
+ w = qMin(w, d->pdev->width() - x);
+ h = qMin(h, d->pdev->height() - y);
+ if (w <= 0 || h <= 0)
+ return;
+
+ const int pw = w + sx;
+ const int ph = h + sy;
+ QPixmap pm(pw, ph);
+ if (pixmap.hasAlpha() || mono_src)
+ pm.fill(Qt::transparent);
+
+ const int mode = pixmap.hasAlpha() ? PictOpOver : PictOpSrc;
+ const ::Picture pmPicture = qt_x11PictureHandle(pm);
+
+ // first tile
+ XRenderComposite(d->dpy, mode,
+ qt_x11PictureHandle(pixmap), XNone, pmPicture,
+ 0, 0, 0, 0, 0, 0, qMin(pw, pixmap.width()), qMin(ph, pixmap.height()));
+
+ // first row of tiles
+ int xPos = pixmap.width();
+ const int sh = qMin(ph, pixmap.height());
+ while (xPos < pw) {
+ const int sw = qMin(xPos, pw - xPos);
+ XRenderComposite(d->dpy, mode,
+ pmPicture, XNone, pmPicture,
+ 0, 0, 0, 0, xPos, 0, sw, sh);
+ xPos *= 2;
+ }
+
+ // remaining rows
+ int yPos = pixmap.height();
+ const int sw = pw;
+ while (yPos < ph) {
+ const int sh = qMin(yPos, ph - yPos);
+ XRenderComposite(d->dpy, mode,
+ pmPicture, XNone, pmPicture,
+ 0, 0, 0, 0, 0, yPos, sw, sh);
+ yPos *= 2;
+ }
+
+ // composite
+ if (mono_src)
+ qt_render_bitmap(d->dpy, d->scrn, pmPicture, d->picture,
+ sx, sy, x, y, w, h, d->cpen);
+ else
+ XRenderComposite(d->dpy, d->composition_mode,
+ pmPicture, XNone, d->picture,
+ sx, sy, 0, 0, x, y, w, h);
+ }
+#endif
+ } else
+#endif // QT_CONFIG(xrender)
+ if (pixmap.depth() > 1 && !static_cast<QX11PlatformPixmap*>(pixmap.handle())->x11_mask) {
+ XSetTile(d->dpy, d->gc, qt_x11PixmapHandle(pixmap));
+ XSetFillStyle(d->dpy, d->gc, FillTiled);
+ XSetTSOrigin(d->dpy, d->gc, x-sx, y-sy);
+ XFillRectangle(d->dpy, d->hd, d->gc, x, y, w, h);
+ XSetTSOrigin(d->dpy, d->gc, 0, 0);
+ XSetFillStyle(d->dpy, d->gc, FillSolid);
+ } else {
+ qt_draw_tile(this, x, y, w, h, pixmap, sx, sy);
+ }
+}
+
+bool QX11PaintEngine::drawCachedGlyphs(const QTransform &transform, const QTextItemInt &ti)
+{
+#if QT_CONFIG(xrender)
+ Q_D(QX11PaintEngine);
+ Q_ASSERT(ti.fontEngine->type() == QFontEngine::Freetype);
+
+ if (!X11->use_xrender)
+ return false;
+
+ QFontEngineFT *ft = static_cast<QFontEngineFT *>(ti.fontEngine);
+ QFontEngineFT::QGlyphSet *set = ft->loadGlyphSet(transform);
+
+ if (!set || set->outline_drawing)
+ return false;
+
+ QFontEngine::GlyphFormat glyphFormat = QXRenderGlyphCache::glyphFormatForDepth(ft, d->pdev_depth);
+
+ QXRenderGlyphCache *cache = static_cast<QXRenderGlyphCache *>(ft->glyphCache(set, glyphFormat, transform));
+ if (!cache) {
+ cache = new QXRenderGlyphCache(QXcbX11Info(), glyphFormat, transform);
+ ft->setGlyphCache(set, cache);
+ }
+
+ return cache->draw(X11->getSolidFill(d->scrn, d->cpen.color()), d->picture, transform, ti);
+#else // !QT_CONFIG(xrender)
+ return false;
+#endif // QT_CONFIG(xrender)
+}
+
+void QX11PaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
+{
+ Q_D(QX11PaintEngine);
+ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
+
+ switch (ti.fontEngine->type()) {
+ case QFontEngine::TestFontEngine:
+ case QFontEngine::Box:
+ d->drawBoxTextItem(p, ti);
+ break;
+#if QT_CONFIG(fontconfig)
+ case QFontEngine::Freetype:
+ drawFreetype(p, ti);
+ break;
+#endif
+ default:
+ Q_ASSERT(false);
+ }
+}
+
+#if QT_CONFIG(fontconfig)
+static bool path_for_glyphs(QPainterPath *path,
+ const QVarLengthArray<glyph_t> &glyphs,
+ const QVarLengthArray<QFixedPoint> &positions,
+ const QFontEngineFT *ft)
+{
+ bool result = true;
+ *path = QPainterPath();
+ path->setFillRule(Qt::WindingFill);
+ ft->lockFace();
+ int i = 0;
+ while (i < glyphs.size()) {
+ QFontEngineFT::Glyph *glyph = ft->loadGlyph(glyphs[i], 0, QFontEngineFT::Format_Mono);
+ // #### fix case where we don't get a glyph
+ if (!glyph || glyph->format != QFontEngineFT::Format_Mono) {
+ result = false;
+ break;
+ }
+
+ int n = 0;
+ int h = glyph->height;
+ int xp = qRound(positions[i].x);
+ int yp = qRound(positions[i].y);
+
+ xp += glyph->x;
+ yp += -glyph->y + glyph->height;
+ int pitch = ((glyph->width + 31) & ~31) >> 3;
+
+ uchar *src = glyph->data;
+ while (h--) {
+ for (int x = 0; x < glyph->width; ++x) {
+ bool set = src[x >> 3] & (0x80 >> (x & 7));
+ if (set) {
+ QRect r(xp + x, yp - h, 1, 1);
+ while (x+1 < glyph->width && src[(x+1) >> 3] & (0x80 >> ((x+1) & 7))) {
+ ++x;
+ r.setRight(r.right()+1);
+ }
+
+ path->addRect(r);
+ ++n;
+ }
+ }
+ src += pitch;
+ }
+ ++i;
+ }
+ ft->unlockFace();
+ return result;
+}
+
+void QX11PaintEngine::drawFreetype(const QPointF &p, const QTextItemInt &ti)
+{
+ Q_D(QX11PaintEngine);
+
+ if (!ti.glyphs.numGlyphs)
+ return;
+
+ if (!d->cpen.isSolid()) {
+ QPaintEngine::drawTextItem(p, ti);
+ return;
+ }
+
+ const bool xrenderPath = (X11->use_xrender
+ && !(d->pdev->devType() == QInternal::Pixmap
+ && static_cast<const QPixmap *>(d->pdev)->handle()->pixelType() == QPlatformPixmap::BitmapType));
+
+ if (xrenderPath) {
+ QTransform transform = d->matrix;
+ transform.translate(p.x(), p.y());
+
+ if (drawCachedGlyphs(transform, ti))
+ return;
+ }
+
+ QTransform transform;
+ transform.translate(p.x(), p.y());
+
+ QVarLengthArray<QFixedPoint> positions;
+ QVarLengthArray<glyph_t> glyphs;
+ ti.fontEngine->getGlyphPositions(ti.glyphs, transform, ti.flags, glyphs, positions);
+
+ if (glyphs.count() == 0)
+ return;
+
+ QFontEngineFT *ft = static_cast<QFontEngineFT *>(ti.fontEngine);
+ QFontEngineFT::QGlyphSet *set = ft->loadGlyphSet(transform);
+ QPainterPath path;
+
+ if (!set || set->outline_drawing || !path_for_glyphs(&path, glyphs, positions, ft)) {
+ QPaintEngine::drawTextItem(p, ti);
+ return;
+ }
+
+ if (path.elementCount() <= 1)
+ return;
+
+ Q_ASSERT((path.elementCount() % 5) == 0);
+ if (d->txop >= QTransform::TxScale) {
+ painter()->save();
+ painter()->setBrush(d->cpen.brush());
+ painter()->setPen(Qt::NoPen);
+ painter()->drawPath(path);
+ painter()->restore();
+ return;
+ }
+
+ const int rectcount = 256;
+ XRectangle rects[rectcount];
+ int num_rects = 0;
+
+ QPoint delta(qRound(d->matrix.dx()), qRound(d->matrix.dy()));
+ QRect clip(d->polygonClipper.boundingRect());
+ for (int i=0; i < path.elementCount(); i+=5) {
+ int x = qRound(path.elementAt(i).x);
+ int y = qRound(path.elementAt(i).y);
+ int w = qRound(path.elementAt(i+1).x) - x;
+ int h = qRound(path.elementAt(i+2).y) - y;
+
+ QRect rect = QRect(x + delta.x(), y + delta.y(), w, h);
+ rect = rect.intersected(clip);
+ if (rect.isEmpty())
+ continue;
+
+ rects[num_rects].x = short(rect.x());
+ rects[num_rects].y = short(rect.y());
+ rects[num_rects].width = ushort(rect.width());
+ rects[num_rects].height = ushort(rect.height());
+ ++num_rects;
+ if (num_rects == rectcount) {
+ XFillRectangles(d->dpy, d->hd, d->gc, rects, num_rects);
+ num_rects = 0;
+ }
+ }
+ if (num_rects > 0)
+ XFillRectangles(d->dpy, d->hd, d->gc, rects, num_rects);
+}
+#endif // QT_CONFIG(fontconfig)
+
+#if QT_CONFIG(xrender)
+QXRenderGlyphCache::QXRenderGlyphCache(QXcbX11Info x, QFontEngine::GlyphFormat format, const QTransform &matrix)
+ : QFontEngineGlyphCache(format, matrix)
+ , xinfo(x)
+ , gset(XNone)
+{}
+
+QXRenderGlyphCache::~QXRenderGlyphCache()
+{
+ if (gset != XNone)
+ XRenderFreeGlyphSet(xinfo.display(), gset);
+}
+
+bool QXRenderGlyphCache::addGlyphs(const QTextItemInt &ti, QVarLengthArray<glyph_t> glyphs, QVarLengthArray<QFixedPoint> positions)
+{
+ Q_ASSERT(ti.fontEngine->type() == QFontEngine::Freetype);
+
+ QFontEngineFT *ft = static_cast<QFontEngineFT *>(ti.fontEngine);
+ QFontEngineFT::QGlyphSet *set = ft->loadGlyphSet(transform());
+
+ XGlyphInfo xglyphinfo;
+
+ for (int i = 0; i < glyphs.size(); ++i) {
+ const QFixed spp = ft->subPixelPositionForX(positions[i].x);
+ QFontEngineFT::Glyph *glyph = set->getGlyph(glyphs[i], spp);
+ Glyph xglyphid = qHash(QFontEngineFT::GlyphAndSubPixelPosition(glyphs[i], spp));
+
+ if (glyph && glyph->format == glyphFormat()) {
+ if (cachedGlyphs.contains(xglyphid)) {
+ continue;
+ } else {
+ set->setGlyph(glyphs[i], spp, nullptr);
+ delete glyph;
+ glyph = 0;
+ }
+ }
+
+ glyph = ft->loadGlyphFor(glyphs[i], spp, glyphFormat(), transform());
+
+ if (glyph == 0 || glyph->format != glyphFormat())
+ return false;
+
+ set->setGlyph(glyphs[i], spp, glyph);
+ Q_ASSERT(glyph->data || glyph->width == 0 || glyph->height == 0);
+
+ xglyphinfo.width = glyph->width;
+ xglyphinfo.height = glyph->height;
+ xglyphinfo.x = -glyph->x;
+ xglyphinfo.y = glyph->y;
+ xglyphinfo.xOff = glyph->advance;
+ xglyphinfo.yOff = 0;
+
+ XRenderAddGlyphs(xinfo.display(), glyphSet(), &xglyphid, &xglyphinfo, 1, (const char *) glyph->data, glyphBufferSize(*glyph));
+ cachedGlyphs.insert(xglyphid);
+ }
+
+ return true;
+}
+
+bool QXRenderGlyphCache::draw(Drawable src, Drawable dst, const QTransform &matrix, const QTextItemInt &ti)
+{
+ Q_ASSERT(ti.fontEngine->type() == QFontEngine::Freetype);
+
+ if (ti.glyphs.numGlyphs == 0)
+ return true;
+
+ QFontEngineFT *ft = static_cast<QFontEngineFT *>(ti.fontEngine);
+ QFontEngineFT::QGlyphSet *set = ft->loadGlyphSet(matrix);
+
+ QVarLengthArray<glyph_t> glyphs;
+ QVarLengthArray<QFixedPoint> positions;
+ ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
+
+ if (glyphs.isEmpty())
+ return true;
+
+ if (!addGlyphs(ti, glyphs, positions))
+ return false;
+
+ QVarLengthArray<unsigned int> chars(glyphs.size());
+
+ for (int i = 0; i < glyphs.size(); ++i)
+ chars[i] = glyphId(glyphs[i], ft->subPixelPositionForX(positions[i].x));
+
+ int i = 0;
+ while (i < glyphs.size() && !isValidCoordinate(positions[i]))
+ ++i;
+
+ if (i >= glyphs.size())
+ return true;
+
+ QFixed xp = positions[i].x;
+ QFixed yp = positions[i].y;
+ QFixed offs = QFixed::fromReal(aliasedCoordinateDelta);
+
+ XGlyphElt32 elt;
+ elt.glyphset = gset;
+ elt.chars = &chars[i];
+ elt.nchars = 1;
+ elt.xOff = qRound(xp + offs);
+ elt.yOff = qRound(yp + offs);
+
+ ++i;
+
+ for (; i < glyphs.size(); ++i) {
+ if (!isValidCoordinate(positions[i]))
+ break;
+
+ const QFixed spp = ft->subPixelPositionForX(positions[i].x);
+ QFontEngineFT::Glyph *g = set->getGlyph(glyphs[i], spp);
+
+ if (g
+ && positions[i].x == xp + g->advance
+ && positions[i].y == yp
+ && elt.nchars < 253 // don't draw more than 253 characters as some X servers
+ // hang with it
+ ) {
+ elt.nchars++;
+ xp += g->advance;
+ } else {
+ xp = positions[i].x;
+ yp = positions[i].y;
+
+ XRenderCompositeText32(xinfo.display(), PictOpOver, src, dst,
+ renderPictFormat(), 0, 0, 0, 0,
+ &elt, 1);
+ elt.chars = &chars[i];
+ elt.nchars = 1;
+ elt.xOff = qRound(xp + offs);
+ elt.yOff = qRound(yp + offs);
+ }
+ }
+
+ XRenderCompositeText32(xinfo.display(), PictOpOver, src, dst,
+ renderPictFormat(), 0, 0, 0, 0, &elt, 1);
+
+ return true;
+}
+
+GlyphSet QXRenderGlyphCache::glyphSet()
+{
+ if (gset == XNone)
+ gset = XRenderCreateGlyphSet(xinfo.display(), renderPictFormat());
+
+ Q_ASSERT(gset != XNone);
+ return gset;
+}
+
+int QXRenderGlyphCache::glyphBufferSize(const QFontEngineFT::Glyph &glyph) const
+{
+ int pitch = 0;
+
+ switch (glyphFormat()) {
+ case QFontEngine::Format_Mono:
+ pitch = ((glyph.width + 31) & ~31) >> 3;
+ break;
+ case QFontEngine::Format_A8:
+ pitch = (glyph.width + 3) & ~3;
+ break;
+ default:
+ pitch = glyph.width * 4;
+ break;
+ }
+
+ return pitch * glyph.height;
+}
+
+QImage::Format QXRenderGlyphCache::imageFormat() const
+{
+ switch (glyphFormat()) {
+ case QFontEngine::Format_None:
+ Q_UNREACHABLE();
+ break;
+ case QFontEngine::Format_Mono:
+ return QImage::Format_Mono;
+ break;
+ case QFontEngine::Format_A8:
+ return QImage::Format_Alpha8;
+ break;
+ case QFontEngine::Format_A32:
+ case QFontEngine::Format_ARGB:
+ return QImage::Format_ARGB32_Premultiplied;
+ break;
+ }
+
+ Q_UNREACHABLE();
+}
+
+const XRenderPictFormat *QXRenderGlyphCache::renderPictFormat() const
+{
+ switch (glyphFormat()) {
+ case QFontEngine::Format_None:
+ Q_UNREACHABLE();
+ break;
+ case QFontEngine::Format_Mono:
+ return XRenderFindStandardFormat(xinfo.display(), PictStandardA1);
+ break;
+ case QFontEngine::Format_A8:
+ return XRenderFindStandardFormat(xinfo.display(), PictStandardA8);
+ break;
+ case QFontEngine::Format_A32:
+ case QFontEngine::Format_ARGB:
+ return XRenderFindStandardFormat(xinfo.display(), PictStandardARGB32);
+ break;
+ }
+
+ Q_UNREACHABLE();
+}
+
+QFontEngine::GlyphFormat QXRenderGlyphCache::glyphFormatForDepth(QFontEngine *fontEngine, int depth)
+{
+ QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat;
+
+ if (glyphFormat == QFontEngine::Format_None) {
+ switch (depth) {
+ case 32:
+ glyphFormat = QFontEngine::Format_ARGB;
+ break;
+ case 24:
+ glyphFormat = QFontEngine::Format_A32;
+ break;
+ case 1:
+ glyphFormat = QFontEngine::Format_Mono;
+ break;
+ default:
+ glyphFormat = QFontEngine::Format_A8;
+ break;
+ }
+ }
+
+ return glyphFormat;
+}
+
+Glyph QXRenderGlyphCache::glyphId(glyph_t glyph, QFixed subPixelPosition)
+{
+ return qHash(QFontEngineFT::GlyphAndSubPixelPosition(glyph, subPixelPosition));
+}
+
+bool QXRenderGlyphCache::isValidCoordinate(const QFixedPoint &fp)
+{
+ enum { t_min = SHRT_MIN, t_max = SHRT_MAX };
+ return (fp.x < t_min || fp.x > t_max || fp.y < t_min || fp.y > t_max) ? false : true;
+}
+#endif // QT_CONFIG(xrender)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h
new file mode 100644
index 0000000000..34b5d929d5
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAINTENGINE_X11_H
+#define QPAINTENGINE_X11_H
+
+#include <QtGui/QPaintEngine>
+
+typedef unsigned long XID;
+typedef XID Drawable;
+typedef struct _XGC *GC;
+
+QT_BEGIN_NAMESPACE
+
+extern "C" {
+Drawable qt_x11Handle(const QPaintDevice *pd);
+GC qt_x11_get_pen_gc(QPainter *);
+GC qt_x11_get_brush_gc(QPainter *);
+}
+
+class QX11PaintEnginePrivate;
+class QX11PaintEngine : public QPaintEngine
+{
+ Q_DECLARE_PRIVATE(QX11PaintEngine)
+public:
+ QX11PaintEngine();
+ ~QX11PaintEngine();
+
+ bool begin(QPaintDevice *pdev) Q_DECL_OVERRIDE;
+ bool end() Q_DECL_OVERRIDE;
+
+ void updateState(const QPaintEngineState &state) Q_DECL_OVERRIDE;
+
+ void updatePen(const QPen &pen);
+ void updateBrush(const QBrush &brush, const QPointF &pt);
+ void updateRenderHints(QPainter::RenderHints hints);
+ void updateFont(const QFont &font);
+ void updateMatrix(const QTransform &matrix);
+ void updateClipRegion_dev(const QRegion &region, Qt::ClipOperation op);
+
+ void drawLines(const QLine *lines, int lineCount) Q_DECL_OVERRIDE;
+ void drawLines(const QLineF *lines, int lineCount) Q_DECL_OVERRIDE;
+
+ void drawRects(const QRect *rects, int rectCount) Q_DECL_OVERRIDE;
+ void drawRects(const QRectF *rects, int rectCount) Q_DECL_OVERRIDE;
+
+ void drawPoints(const QPoint *points, int pointCount) Q_DECL_OVERRIDE;
+ void drawPoints(const QPointF *points, int pointCount) Q_DECL_OVERRIDE;
+
+ void drawEllipse(const QRect &r) Q_DECL_OVERRIDE;
+ void drawEllipse(const QRectF &r) Q_DECL_OVERRIDE;
+
+ virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE;
+ inline void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) Q_DECL_OVERRIDE
+ { QPaintEngine::drawPolygon(points, pointCount, mode); }
+
+ void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) Q_DECL_OVERRIDE;
+ void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) Q_DECL_OVERRIDE;
+ void drawPath(const QPainterPath &path) Q_DECL_OVERRIDE;
+ void drawTextItem(const QPointF &p, const QTextItem &textItem) Q_DECL_OVERRIDE;
+ void drawImage(const QRectF &r, const QImage &img, const QRectF &sr,
+ Qt::ImageConversionFlags flags = Qt::AutoColor) Q_DECL_OVERRIDE;
+
+ virtual Drawable handle() const;
+ inline Type type() const Q_DECL_OVERRIDE { return QPaintEngine::X11; }
+
+ QPainter::RenderHints supportedRenderHints() const;
+
+protected:
+ QX11PaintEngine(QX11PaintEnginePrivate &dptr);
+
+#if QT_CONFIG(fontconfig)
+ void drawFreetype(const QPointF &p, const QTextItemInt &ti);
+ bool drawCachedGlyphs(const QTransform &transform, const QTextItemInt &ti);
+#endif // QT_CONFIG(fontconfig)
+
+ friend class QPixmap;
+ friend class QFontEngineBox;
+ friend GC qt_x11_get_pen_gc(QPainter *);
+ friend GC qt_x11_get_brush_gc(QPainter *);
+
+private:
+ Q_DISABLE_COPY(QX11PaintEngine)
+};
+
+QT_END_NAMESPACE
+
+#endif // QPAINTENGINE_X11_H
diff --git a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
new file mode 100644
index 0000000000..f791c90346
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
@@ -0,0 +1,2108 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+
+#include <private/qdrawhelper_p.h>
+#include <private/qimage_p.h>
+#include <private/qimagepixmapcleanuphooks_p.h>
+
+#include "qxcbnativepainting.h"
+#include "qpixmap_x11_p.h"
+#include "qcolormap_x11_p.h"
+#include "qpaintengine_x11_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#if QT_POINTER_SIZE == 8 // 64-bit versions
+
+Q_ALWAYS_INLINE uint PREMUL(uint x) {
+ uint a = x >> 24;
+ quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
+ t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
+ t &= 0x000000ff00ff00ff;
+ return (uint(t)) | (uint(t >> 24)) | (a << 24);
+}
+
+#else // 32-bit versions
+
+Q_ALWAYS_INLINE uint PREMUL(uint x) {
+ uint a = x >> 24;
+ uint t = (x & 0xff00ff) * a;
+ t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
+ t &= 0xff00ff;
+
+ x = ((x >> 8) & 0xff) * a;
+ x = (x + ((x >> 8) & 0xff) + 0x80);
+ x &= 0xff00;
+ x |= t | (a << 24);
+ return x;
+}
+#endif
+
+
+
+struct QXImageWrapper
+{
+ XImage *xi;
+};
+
+QPixmap qt_toX11Pixmap(const QImage &image)
+{
+ QPlatformPixmap *data =
+ new QX11PlatformPixmap(image.depth() == 1
+ ? QPlatformPixmap::BitmapType
+ : QPlatformPixmap::PixmapType);
+
+ data->fromImage(image, Qt::AutoColor);
+
+ return QPixmap(data);
+}
+
+QPixmap qt_toX11Pixmap(const QPixmap &pixmap)
+{
+ if (pixmap.isNull())
+ return QPixmap();
+
+ if (QPixmap(pixmap).data_ptr()->classId() == QPlatformPixmap::X11Class)
+ return pixmap;
+
+ return qt_toX11Pixmap(pixmap.toImage());
+}
+
+// For thread-safety:
+// image->data does not belong to X11, so we must free it ourselves.
+
+inline static void qSafeXDestroyImage(XImage *x)
+{
+ if (x->data) {
+ free(x->data);
+ x->data = 0;
+ }
+ XDestroyImage(x);
+}
+
+QBitmap QX11PlatformPixmap::mask_to_bitmap(int screen) const
+{
+ if (!x11_mask)
+ return QBitmap();
+ qt_x11SetDefaultScreen(screen);
+ QBitmap bm(w, h);
+ QX11PlatformPixmap *that = qt_x11Pixmap(bm);
+ const QXcbX11Info *x = that->x11_info();
+ GC gc = XCreateGC(x->display(), that->handle(), 0, 0);
+ XCopyArea(x->display(), x11_mask, that->handle(), gc, 0, 0,
+ that->width(), that->height(), 0, 0);
+ XFreeGC(x->display(), gc);
+ return bm;
+}
+
+void QX11PlatformPixmap::bitmapFromImage(const QImage &image)
+{
+ w = image.width();
+ h = image.height();
+ d = 1;
+ is_null = (w <= 0 || h <= 0);
+ hd = createBitmapFromImage(image);
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender)
+ picture = XRenderCreatePicture(xinfo.display(), hd,
+ XRenderFindStandardFormat(xinfo.display(), PictStandardA1), 0, 0);
+#endif // QT_CONFIG(xrender)
+}
+
+bool QX11PlatformPixmap::canTakeQImageFromXImage(const QXImageWrapper &xiWrapper) const
+{
+ XImage *xi = xiWrapper.xi;
+
+ if (xi->format != ZPixmap)
+ return false;
+
+ // ARGB32_Premultiplied
+ if (picture && depth() == 32)
+ return true;
+
+ // RGB32
+ if (depth() == 24 && xi->bits_per_pixel == 32 && xi->red_mask == 0xff0000
+ && xi->green_mask == 0xff00 && xi->blue_mask == 0xff)
+ return true;
+
+ // RGB16
+ if (depth() == 16 && xi->bits_per_pixel == 16 && xi->red_mask == 0xf800
+ && xi->green_mask == 0x7e0 && xi->blue_mask == 0x1f)
+ return true;
+
+ return false;
+}
+
+QImage QX11PlatformPixmap::takeQImageFromXImage(const QXImageWrapper &xiWrapper) const
+{
+ XImage *xi = xiWrapper.xi;
+
+ QImage::Format format = QImage::Format_ARGB32_Premultiplied;
+ if (depth() == 24)
+ format = QImage::Format_RGB32;
+ else if (depth() == 16)
+ format = QImage::Format_RGB16;
+
+ QImage image((uchar *)xi->data, xi->width, xi->height, xi->bytes_per_line, format);
+ image.setDevicePixelRatio(devicePixelRatio());
+ // take ownership
+ image.data_ptr()->own_data = true;
+ xi->data = 0;
+
+ // we may have to swap the byte order
+ if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
+ || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst))
+ {
+ for (int i=0; i < image.height(); i++) {
+ if (depth() == 16) {
+ ushort *p = (ushort*)image.scanLine(i);
+ ushort *end = p + image.width();
+ while (p < end) {
+ *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
+ p++;
+ }
+ } else {
+ uint *p = (uint*)image.scanLine(i);
+ uint *end = p + image.width();
+ while (p < end) {
+ *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
+ | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
+ p++;
+ }
+ }
+ }
+ }
+
+ // fix-up alpha channel
+ if (format == QImage::Format_RGB32) {
+ QRgb *p = (QRgb *)image.bits();
+ for (int y = 0; y < xi->height; ++y) {
+ for (int x = 0; x < xi->width; ++x)
+ p[x] |= 0xff000000;
+ p += xi->bytes_per_line / 4;
+ }
+ }
+
+ XDestroyImage(xi);
+ return image;
+}
+
+XID QX11PlatformPixmap::bitmap_to_mask(const QBitmap &bitmap, int screen)
+{
+ if (bitmap.isNull())
+ return 0;
+ QBitmap bm = bitmap;
+ qt_x11SetScreen(bm, screen);
+
+ QX11PlatformPixmap *that = qt_x11Pixmap(bm);
+ const QXcbX11Info *x = that->x11_info();
+ Pixmap mask = XCreatePixmap(x->display(), RootWindow(x->display(), screen),
+ that->width(), that->height(), 1);
+ GC gc = XCreateGC(x->display(), mask, 0, 0);
+ XCopyArea(x->display(), that->handle(), mask, gc, 0, 0,
+ that->width(), that->height(), 0, 0);
+ XFreeGC(x->display(), gc);
+ return mask;
+}
+
+Drawable qt_x11Handle(const QPixmap &pixmap)
+{
+ if (pixmap.isNull())
+ return XNone;
+
+ if (pixmap.handle()->classId() != QPlatformPixmap::X11Class)
+ return XNone;
+
+ return static_cast<const QX11PlatformPixmap *>(pixmap.handle())->handle();
+}
+
+
+/*****************************************************************************
+ Internal functions
+ *****************************************************************************/
+
+//extern const uchar *qt_get_bitflip_array(); // defined in qimage.cpp
+
+// Returns position of highest bit set or -1 if none
+static int highest_bit(uint v)
+{
+ int i;
+ uint b = (uint)1 << 31;
+ for (i=31; ((b & v) == 0) && i>=0; i--)
+ b >>= 1;
+ return i;
+}
+
+// Counts the number of bits set in 'v'
+static uint n_bits(uint v)
+{
+ int i = 0;
+ while (v) {
+ v = v & (v - 1);
+ i++;
+ }
+ return i;
+}
+
+static uint *red_scale_table = 0;
+static uint *green_scale_table = 0;
+static uint *blue_scale_table = 0;
+
+static void cleanup_scale_tables()
+{
+ delete[] red_scale_table;
+ delete[] green_scale_table;
+ delete[] blue_scale_table;
+}
+
+/*
+ Could do smart bitshifting, but the "obvious" algorithm only works for
+ nBits >= 4. This is more robust.
+*/
+static void build_scale_table(uint **table, uint nBits)
+{
+ if (nBits > 7) {
+ qWarning("build_scale_table: internal error, nBits = %i", nBits);
+ return;
+ }
+ if (!*table) {
+ static bool firstTable = true;
+ if (firstTable) {
+ qAddPostRoutine(cleanup_scale_tables);
+ firstTable = false;
+ }
+ *table = new uint[256];
+ }
+ int maxVal = (1 << nBits) - 1;
+ int valShift = 8 - nBits;
+ int i;
+ for (i = 0 ; i < maxVal + 1 ; i++)
+ (*table)[i << valShift] = i*255/maxVal;
+}
+
+static int defaultScreen = -1;
+
+int qt_x11SetDefaultScreen(int screen)
+{
+ int old = defaultScreen;
+ defaultScreen = screen;
+ return old;
+}
+
+void qt_x11SetScreen(QPixmap &pixmap, int screen)
+{
+ if (pixmap.paintingActive()) {
+ qWarning("qt_x11SetScreen(): Cannot change screens during painting");
+ return;
+ }
+
+ if (pixmap.isNull())
+ return;
+
+ if (pixmap.handle()->classId() != QPlatformPixmap::X11Class)
+ return;
+
+ if (screen < 0)
+ screen = QXcbX11Info::appScreen();
+
+ QX11PlatformPixmap *pm = static_cast<QX11PlatformPixmap *>(pixmap.handle());
+ if (screen == pm->xinfo.screen())
+ return; // nothing to do
+
+ if (pixmap.isNull()) {
+ pm->xinfo = QXcbX11Info::fromScreen(screen);
+ return;
+ }
+
+#if 0
+ qDebug("qt_x11SetScreen for %p from %d to %d. Size is %d/%d", pm, pm->xinfo.screen(), screen, pm->width(), pm->height());
+#endif
+
+ qt_x11SetDefaultScreen(screen);
+ pixmap = qt_toX11Pixmap(pixmap.toImage());
+}
+
+/*****************************************************************************
+ QPixmap member functions
+ *****************************************************************************/
+
+QBasicAtomicInt qt_pixmap_serial = Q_BASIC_ATOMIC_INITIALIZER(0);
+int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0;
+
+QX11PlatformPixmap::QX11PlatformPixmap(PixelType pixelType)
+ : QPlatformPixmap(pixelType, X11Class), hd(0),
+ flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0),
+ dpr(1.0), pengine(0)
+{}
+
+QX11PlatformPixmap::~QX11PlatformPixmap()
+{
+ // Cleanup hooks have to be called before the handles are freed
+ if (is_cached) {
+ QImagePixmapCleanupHooks::executePlatformPixmapDestructionHooks(this);
+ is_cached = false;
+ }
+
+ release();
+}
+
+QPlatformPixmap *QX11PlatformPixmap::createCompatiblePlatformPixmap() const
+{
+ QX11PlatformPixmap *p = new QX11PlatformPixmap(pixelType());
+ p->setDevicePixelRatio(devicePixelRatio());
+ return p;
+}
+
+void QX11PlatformPixmap::resize(int width, int height)
+{
+ setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
+
+ w = width;
+ h = height;
+ is_null = (w <= 0 || h <= 0);
+
+ if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) {
+ xinfo = QXcbX11Info::fromScreen(defaultScreen);
+ }
+
+ int dd = xinfo.depth();
+
+ if (qt_x11_preferred_pixmap_depth)
+ dd = qt_x11_preferred_pixmap_depth;
+
+ bool make_null = w <= 0 || h <= 0; // create null pixmap
+ d = (pixelType() == BitmapType ? 1 : dd);
+ if (make_null || d == 0) {
+ w = 0;
+ h = 0;
+ is_null = true;
+ hd = 0;
+ picture = 0;
+ d = 0;
+ if (!make_null)
+ qWarning("QPixmap: Invalid pixmap parameters");
+ return;
+ }
+ hd = XCreatePixmap(xinfo.display(),
+ RootWindow(xinfo.display(), xinfo.screen()),
+ w, h, d);
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender) {
+ XRenderPictFormat *format = d == 1
+ ? XRenderFindStandardFormat(xinfo.display(), PictStandardA1)
+ : XRenderFindVisualFormat(xinfo.display(), (Visual *) xinfo.visual());
+ picture = XRenderCreatePicture(xinfo.display(), hd, format, 0, 0);
+ }
+#endif // QT_CONFIG(xrender)
+}
+
+struct QX11AlphaDetector
+{
+ bool hasAlpha() const {
+ if (checked)
+ return has;
+ // Will implicitly also check format and return quickly for opaque types...
+ checked = true;
+ has = image->isNull() ? false : const_cast<QImage *>(image)->data_ptr()->checkForAlphaPixels();
+ return has;
+ }
+
+ bool hasXRenderAndAlpha() const {
+ if (!X11->use_xrender)
+ return false;
+ return hasAlpha();
+ }
+
+ QX11AlphaDetector(const QImage *i, Qt::ImageConversionFlags flags)
+ : image(i), checked(false), has(false)
+ {
+ if (flags & Qt::NoOpaqueDetection) {
+ checked = true;
+ has = image->hasAlphaChannel();
+ }
+ }
+
+ const QImage *image;
+ mutable bool checked;
+ mutable bool has;
+};
+
+void QX11PlatformPixmap::fromImage(const QImage &img, Qt::ImageConversionFlags flags)
+{
+ setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
+
+ w = img.width();
+ h = img.height();
+ d = img.depth();
+ is_null = (w <= 0 || h <= 0);
+ setDevicePixelRatio(img.devicePixelRatio());
+
+ if (is_null) {
+ w = h = 0;
+ return;
+ }
+
+ if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) {
+ xinfo = QXcbX11Info::fromScreen(defaultScreen);
+ }
+
+ if (pixelType() == BitmapType) {
+ bitmapFromImage(img);
+ return;
+ }
+
+ if (uint(w) >= 32768 || uint(h) >= 32768) {
+ w = h = 0;
+ is_null = true;
+ return;
+ }
+
+ QX11AlphaDetector alphaCheck(&img, flags);
+ int dd = alphaCheck.hasXRenderAndAlpha() ? 32 : xinfo.depth();
+
+ if (qt_x11_preferred_pixmap_depth)
+ dd = qt_x11_preferred_pixmap_depth;
+
+ QImage image = img;
+
+ // must be monochrome
+ if (dd == 1 || (flags & Qt::ColorMode_Mask) == Qt::MonoOnly) {
+ if (d != 1) {
+ // dither
+ image = image.convertToFormat(QImage::Format_MonoLSB, flags);
+ d = 1;
+ }
+ } else { // can be both
+ bool conv8 = false;
+ if (d > 8 && dd <= 8) { // convert to 8 bit
+ if ((flags & Qt::DitherMode_Mask) == Qt::AutoDither)
+ flags = (flags & ~Qt::DitherMode_Mask)
+ | Qt::PreferDither;
+ conv8 = true;
+ } else if ((flags & Qt::ColorMode_Mask) == Qt::ColorOnly) {
+ conv8 = (d == 1); // native depth wanted
+ } else if (d == 1) {
+ if (image.colorCount() == 2) {
+ QRgb c0 = image.color(0); // Auto: convert to best
+ QRgb c1 = image.color(1);
+ conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255);
+ } else {
+ // eg. 1-color monochrome images (they do exist).
+ conv8 = true;
+ }
+ }
+ if (conv8) {
+ image = image.convertToFormat(QImage::Format_Indexed8, flags);
+ d = 8;
+ }
+ }
+
+ if (d == 1 || image.format() > QImage::Format_ARGB32_Premultiplied) {
+ QImage::Format fmt = QImage::Format_RGB32;
+ if (alphaCheck.hasXRenderAndAlpha() && d > 1)
+ fmt = QImage::Format_ARGB32_Premultiplied;
+ image = image.convertToFormat(fmt, flags);
+ fromImage(image, Qt::AutoColor);
+ return;
+ }
+
+ Display *dpy = xinfo.display();
+ Visual *visual = (Visual *)xinfo.visual();
+ XImage *xi = 0;
+ bool trucol = (visual->c_class >= TrueColor);
+ size_t nbytes = image.sizeInBytes();
+ uchar *newbits= 0;
+
+#if QT_CONFIG(xrender)
+ if (alphaCheck.hasXRenderAndAlpha()) {
+ const QImage &cimage = image;
+
+ d = 32;
+
+ if (QXcbX11Info::appDepth() != d) {
+ xinfo.setDepth(d);
+ }
+
+ hd = XCreatePixmap(dpy, RootWindow(dpy, xinfo.screen()), w, h, d);
+ picture = XRenderCreatePicture(dpy, hd,
+ XRenderFindStandardFormat(dpy, PictStandardARGB32), 0, 0);
+
+ xi = XCreateImage(dpy, visual, d, ZPixmap, 0, 0, w, h, 32, 0);
+ Q_CHECK_PTR(xi);
+ newbits = (uchar *)malloc(xi->bytes_per_line*h);
+ Q_CHECK_PTR(newbits);
+ xi->data = (char *)newbits;
+
+ switch (cimage.format()) {
+ case QImage::Format_Indexed8: {
+ QVector<QRgb> colorTable = cimage.colorTable();
+ uint *xidata = (uint *)xi->data;
+ for (int y = 0; y < h; ++y) {
+ const uchar *p = cimage.scanLine(y);
+ for (int x = 0; x < w; ++x) {
+ const QRgb rgb = colorTable[p[x]];
+ const int a = qAlpha(rgb);
+ if (a == 0xff)
+ *xidata = rgb;
+ else
+ // RENDER expects premultiplied alpha
+ *xidata = qRgba(qt_div_255(qRed(rgb) * a),
+ qt_div_255(qGreen(rgb) * a),
+ qt_div_255(qBlue(rgb) * a),
+ a);
+ ++xidata;
+ }
+ }
+ }
+ break;
+ case QImage::Format_RGB32: {
+ uint *xidata = (uint *)xi->data;
+ for (int y = 0; y < h; ++y) {
+ const QRgb *p = (const QRgb *) cimage.scanLine(y);
+ for (int x = 0; x < w; ++x)
+ *xidata++ = p[x] | 0xff000000;
+ }
+ }
+ break;
+ case QImage::Format_ARGB32: {
+ uint *xidata = (uint *)xi->data;
+ for (int y = 0; y < h; ++y) {
+ const QRgb *p = (const QRgb *) cimage.scanLine(y);
+ for (int x = 0; x < w; ++x) {
+ const QRgb rgb = p[x];
+ const int a = qAlpha(rgb);
+ if (a == 0xff)
+ *xidata = rgb;
+ else
+ // RENDER expects premultiplied alpha
+ *xidata = qRgba(qt_div_255(qRed(rgb) * a),
+ qt_div_255(qGreen(rgb) * a),
+ qt_div_255(qBlue(rgb) * a),
+ a);
+ ++xidata;
+ }
+ }
+
+ }
+ break;
+ case QImage::Format_ARGB32_Premultiplied: {
+ uint *xidata = (uint *)xi->data;
+ for (int y = 0; y < h; ++y) {
+ const QRgb *p = (const QRgb *) cimage.scanLine(y);
+ memcpy(xidata, p, w*sizeof(QRgb));
+ xidata += w;
+ }
+ }
+ break;
+ default:
+ Q_ASSERT(false);
+ }
+
+ if ((xi->byte_order == MSBFirst) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
+ uint *xidata = (uint *)xi->data;
+ uint *xiend = xidata + w*h;
+ while (xidata < xiend) {
+ *xidata = (*xidata >> 24)
+ | ((*xidata >> 8) & 0xff00)
+ | ((*xidata << 8) & 0xff0000)
+ | (*xidata << 24);
+ ++xidata;
+ }
+ }
+
+ GC gc = XCreateGC(dpy, hd, 0, 0);
+ XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h);
+ XFreeGC(dpy, gc);
+
+ qSafeXDestroyImage(xi);
+
+ return;
+ }
+#endif // QT_CONFIG(xrender)
+
+ if (trucol) { // truecolor display
+ if (image.format() == QImage::Format_ARGB32_Premultiplied)
+ image = image.convertToFormat(QImage::Format_ARGB32);
+
+ const QImage &cimage = image;
+ QRgb pix[256]; // pixel translation table
+ const bool d8 = (d == 8);
+ const uint red_mask = (uint)visual->red_mask;
+ const uint green_mask = (uint)visual->green_mask;
+ const uint blue_mask = (uint)visual->blue_mask;
+ const int red_shift = highest_bit(red_mask) - 7;
+ const int green_shift = highest_bit(green_mask) - 7;
+ const int blue_shift = highest_bit(blue_mask) - 7;
+ const uint rbits = highest_bit(red_mask) - lowest_bit(red_mask) + 1;
+ const uint gbits = highest_bit(green_mask) - lowest_bit(green_mask) + 1;
+ const uint bbits = highest_bit(blue_mask) - lowest_bit(blue_mask) + 1;
+
+ if (d8) { // setup pixel translation
+ QVector<QRgb> ctable = cimage.colorTable();
+ for (int i=0; i < cimage.colorCount(); i++) {
+ int r = qRed (ctable[i]);
+ int g = qGreen(ctable[i]);
+ int b = qBlue (ctable[i]);
+ r = red_shift > 0 ? r << red_shift : r >> -red_shift;
+ g = green_shift > 0 ? g << green_shift : g >> -green_shift;
+ b = blue_shift > 0 ? b << blue_shift : b >> -blue_shift;
+ pix[i] = (b & blue_mask) | (g & green_mask) | (r & red_mask)
+ | ~(blue_mask | green_mask | red_mask);
+ }
+ }
+
+ xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0);
+ Q_CHECK_PTR(xi);
+ newbits = (uchar *)malloc(xi->bytes_per_line*h);
+ Q_CHECK_PTR(newbits);
+ if (!newbits) // no memory
+ return;
+ int bppc = xi->bits_per_pixel;
+
+ bool contig_bits = n_bits(red_mask) == rbits &&
+ n_bits(green_mask) == gbits &&
+ n_bits(blue_mask) == bbits;
+ bool dither_tc =
+ // Want it?
+ (flags & Qt::Dither_Mask) != Qt::ThresholdDither &&
+ (flags & Qt::DitherMode_Mask) != Qt::AvoidDither &&
+ // Need it?
+ bppc < 24 && !d8 &&
+ // Can do it? (Contiguous bits?)
+ contig_bits;
+
+ static bool init=false;
+ static int D[16][16];
+ if (dither_tc && !init) {
+ // I also contributed this code to XV - WWA.
+ /*
+ The dither matrix, D, is obtained with this formula:
+
+ D2 = [0 2]
+ [3 1]
+
+
+ D2*n = [4*Dn 4*Dn+2*Un]
+ [4*Dn+3*Un 4*Dn+1*Un]
+ */
+ int n,i,j;
+ init=1;
+
+ /* Set D2 */
+ D[0][0]=0;
+ D[1][0]=2;
+ D[0][1]=3;
+ D[1][1]=1;
+
+ /* Expand using recursive definition given above */
+ for (n=2; n<16; n*=2) {
+ for (i=0; i<n; i++) {
+ for (j=0; j<n; j++) {
+ D[i][j]*=4;
+ D[i+n][j]=D[i][j]+2;
+ D[i][j+n]=D[i][j]+3;
+ D[i+n][j+n]=D[i][j]+1;
+ }
+ }
+ }
+ init=true;
+ }
+
+ enum { BPP8,
+ BPP16_565, BPP16_555,
+ BPP16_MSB, BPP16_LSB,
+ BPP24_888,
+ BPP24_MSB, BPP24_LSB,
+ BPP32_8888,
+ BPP32_MSB, BPP32_LSB
+ } mode = BPP8;
+
+ bool same_msb_lsb = (xi->byte_order == MSBFirst) == (QSysInfo::ByteOrder == QSysInfo::BigEndian);
+
+ if (bppc == 8) // 8 bit
+ mode = BPP8;
+ else if (bppc == 16) { // 16 bit MSB/LSB
+ if (red_shift == 8 && green_shift == 3 && blue_shift == -3 && !d8 && same_msb_lsb)
+ mode = BPP16_565;
+ else if (red_shift == 7 && green_shift == 2 && blue_shift == -3 && !d8 && same_msb_lsb)
+ mode = BPP16_555;
+ else
+ mode = (xi->byte_order == LSBFirst) ? BPP16_LSB : BPP16_MSB;
+ } else if (bppc == 24) { // 24 bit MSB/LSB
+ if (red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb)
+ mode = BPP24_888;
+ else
+ mode = (xi->byte_order == LSBFirst) ? BPP24_LSB : BPP24_MSB;
+ } else if (bppc == 32) { // 32 bit MSB/LSB
+ if (red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb)
+ mode = BPP32_8888;
+ else
+ mode = (xi->byte_order == LSBFirst) ? BPP32_LSB : BPP32_MSB;
+ } else
+ qFatal("Logic error 3");
+
+#define GET_PIXEL \
+ uint pixel; \
+ if (d8) pixel = pix[*src++]; \
+ else { \
+ int r = qRed (*p); \
+ int g = qGreen(*p); \
+ int b = qBlue (*p++); \
+ r = red_shift > 0 \
+ ? r << red_shift : r >> -red_shift; \
+ g = green_shift > 0 \
+ ? g << green_shift : g >> -green_shift; \
+ b = blue_shift > 0 \
+ ? b << blue_shift : b >> -blue_shift; \
+ pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask) \
+ | ~(blue_mask | green_mask | red_mask); \
+ }
+
+#define GET_PIXEL_DITHER_TC \
+ int r = qRed (*p); \
+ int g = qGreen(*p); \
+ int b = qBlue (*p++); \
+ const int thres = D[x%16][y%16]; \
+ if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
+ > thres) \
+ r += (1<<(8-rbits)); \
+ if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
+ > thres) \
+ g += (1<<(8-gbits)); \
+ if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
+ > thres) \
+ b += (1<<(8-bbits)); \
+ r = red_shift > 0 \
+ ? r << red_shift : r >> -red_shift; \
+ g = green_shift > 0 \
+ ? g << green_shift : g >> -green_shift; \
+ b = blue_shift > 0 \
+ ? b << blue_shift : b >> -blue_shift; \
+ uint pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask);
+
+// again, optimized case
+// can't be optimized that much :(
+#define GET_PIXEL_DITHER_TC_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask, \
+ rbits,gbits,bbits) \
+ const int thres = D[x%16][y%16]; \
+ int r = qRed (*p); \
+ if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
+ > thres) \
+ r += (1<<(8-rbits)); \
+ int g = qGreen(*p); \
+ if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
+ > thres) \
+ g += (1<<(8-gbits)); \
+ int b = qBlue (*p++); \
+ if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
+ > thres) \
+ b += (1<<(8-bbits)); \
+ uint pixel = ((r red_shift) & red_mask) \
+ | ((g green_shift) & green_mask) \
+ | ((b blue_shift) & blue_mask);
+
+#define CYCLE(body) \
+ for (int y=0; y<h; y++) { \
+ const uchar* src = cimage.scanLine(y); \
+ uchar* dst = newbits + xi->bytes_per_line*y; \
+ const QRgb* p = (const QRgb *)src; \
+ body \
+ }
+
+ if (dither_tc) {
+ switch (mode) {
+ case BPP16_565:
+ CYCLE(
+ quint16* dst16 = (quint16*)dst;
+ for (int x=0; x<w; x++) {
+ GET_PIXEL_DITHER_TC_OPT(<<8,<<3,>>3,0xf800,0x7e0,0x1f,5,6,5)
+ *dst16++ = pixel;
+ }
+ )
+ break;
+ case BPP16_555:
+ CYCLE(
+ quint16* dst16 = (quint16*)dst;
+ for (int x=0; x<w; x++) {
+ GET_PIXEL_DITHER_TC_OPT(<<7,<<2,>>3,0x7c00,0x3e0,0x1f,5,5,5)
+ *dst16++ = pixel;
+ }
+ )
+ break;
+ case BPP16_MSB: // 16 bit MSB
+ CYCLE(
+ for (int x=0; x<w; x++) {
+ GET_PIXEL_DITHER_TC
+ *dst++ = (pixel >> 8);
+ *dst++ = pixel;
+ }
+ )
+ break;
+ case BPP16_LSB: // 16 bit LSB
+ CYCLE(
+ for (int x=0; x<w; x++) {
+ GET_PIXEL_DITHER_TC
+ *dst++ = pixel;
+ *dst++ = pixel >> 8;
+ }
+ )
+ break;
+ default:
+ qFatal("Logic error");
+ }
+ } else {
+ switch (mode) {
+ case BPP8: // 8 bit
+ CYCLE(
+ Q_UNUSED(p);
+ for (int x=0; x<w; x++)
+ *dst++ = pix[*src++];
+ )
+ break;
+ case BPP16_565:
+ CYCLE(
+ quint16* dst16 = (quint16*)dst;
+ for (int x = 0; x < w; x++) {
+ *dst16++ = ((*p >> 8) & 0xf800)
+ | ((*p >> 5) & 0x7e0)
+ | ((*p >> 3) & 0x1f);
+ ++p;
+ }
+ )
+ break;
+ case BPP16_555:
+ CYCLE(
+ quint16* dst16 = (quint16*)dst;
+ for (int x=0; x<w; x++) {
+ *dst16++ = ((*p >> 9) & 0x7c00)
+ | ((*p >> 6) & 0x3e0)
+ | ((*p >> 3) & 0x1f);
+ ++p;
+ }
+ )
+ break;
+ case BPP16_MSB: // 16 bit MSB
+ CYCLE(
+ for (int x=0; x<w; x++) {
+ GET_PIXEL
+ *dst++ = (pixel >> 8);
+ *dst++ = pixel;
+ }
+ )
+ break;
+ case BPP16_LSB: // 16 bit LSB
+ CYCLE(
+ for (int x=0; x<w; x++) {
+ GET_PIXEL
+ *dst++ = pixel;
+ *dst++ = pixel >> 8;
+ }
+ )
+ break;
+ case BPP24_888:
+ CYCLE(
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ for (int x=0; x<w; x++) {
+ *dst++ = qRed (*p);
+ *dst++ = qGreen(*p);
+ *dst++ = qBlue (*p++);
+ }
+ } else {
+ for (int x=0; x<w; x++) {
+ *dst++ = qBlue (*p);
+ *dst++ = qGreen(*p);
+ *dst++ = qRed (*p++);
+ }
+ }
+ )
+ break;
+ case BPP24_MSB: // 24 bit MSB
+ CYCLE(
+ for (int x=0; x<w; x++) {
+ GET_PIXEL
+ *dst++ = pixel >> 16;
+ *dst++ = pixel >> 8;
+ *dst++ = pixel;
+ }
+ )
+ break;
+ case BPP24_LSB: // 24 bit LSB
+ CYCLE(
+ for (int x=0; x<w; x++) {
+ GET_PIXEL
+ *dst++ = pixel;
+ *dst++ = pixel >> 8;
+ *dst++ = pixel >> 16;
+ }
+ )
+ break;
+ case BPP32_8888:
+ CYCLE(
+ memcpy(dst, p, w * 4);
+ )
+ break;
+ case BPP32_MSB: // 32 bit MSB
+ CYCLE(
+ for (int x=0; x<w; x++) {
+ GET_PIXEL
+ *dst++ = pixel >> 24;
+ *dst++ = pixel >> 16;
+ *dst++ = pixel >> 8;
+ *dst++ = pixel;
+ }
+ )
+ break;
+ case BPP32_LSB: // 32 bit LSB
+ CYCLE(
+ for (int x=0; x<w; x++) {
+ GET_PIXEL
+ *dst++ = pixel;
+ *dst++ = pixel >> 8;
+ *dst++ = pixel >> 16;
+ *dst++ = pixel >> 24;
+ }
+ )
+ break;
+ default:
+ qFatal("Logic error 2");
+ }
+ }
+ xi->data = (char *)newbits;
+ }
+
+ if (d == 8 && !trucol) { // 8 bit pixmap
+ int pop[256]; // pixel popularity
+
+ if (image.colorCount() == 0)
+ image.setColorCount(1);
+
+ const QImage &cimage = image;
+ memset(pop, 0, sizeof(int)*256); // reset popularity array
+ for (int i = 0; i < h; i++) { // for each scanline...
+ const uchar* p = cimage.scanLine(i);
+ const uchar *end = p + w;
+ while (p < end) // compute popularity
+ pop[*p++]++;
+ }
+
+ newbits = (uchar *)malloc(nbytes); // copy image into newbits
+ Q_CHECK_PTR(newbits);
+ if (!newbits) // no memory
+ return;
+ uchar* p = newbits;
+ memcpy(p, cimage.bits(), nbytes); // copy image data into newbits
+
+ /*
+ * The code below picks the most important colors. It is based on the
+ * diversity algorithm, implemented in XV 3.10. XV is (C) by John Bradley.
+ */
+
+ struct PIX { // pixel sort element
+ uchar r,g,b,n; // color + pad
+ int use; // popularity
+ int index; // index in colormap
+ int mindist;
+ };
+ int ncols = 0;
+ for (int i=0; i< cimage.colorCount(); i++) { // compute number of colors
+ if (pop[i] > 0)
+ ncols++;
+ }
+ for (int i = cimage.colorCount(); i < 256; i++) // ignore out-of-range pixels
+ pop[i] = 0;
+
+ // works since we make sure above to have at least
+ // one color in the image
+ if (ncols == 0)
+ ncols = 1;
+
+ PIX pixarr[256]; // pixel array
+ PIX pixarr_sorted[256]; // pixel array (sorted)
+ memset(pixarr, 0, ncols*sizeof(PIX));
+ PIX *px = &pixarr[0];
+ int maxpop = 0;
+ int maxpix = 0;
+ uint j = 0;
+ QVector<QRgb> ctable = cimage.colorTable();
+ for (int i = 0; i < 256; i++) { // init pixel array
+ if (pop[i] > 0) {
+ px->r = qRed (ctable[i]);
+ px->g = qGreen(ctable[i]);
+ px->b = qBlue (ctable[i]);
+ px->n = 0;
+ px->use = pop[i];
+ if (pop[i] > maxpop) { // select most popular entry
+ maxpop = pop[i];
+ maxpix = j;
+ }
+ px->index = i;
+ px->mindist = 1000000;
+ px++;
+ j++;
+ }
+ }
+ pixarr_sorted[0] = pixarr[maxpix];
+ pixarr[maxpix].use = 0;
+
+ for (int i = 1; i < ncols; i++) { // sort pixels
+ int minpix = -1, mindist = -1;
+ px = &pixarr_sorted[i-1];
+ int r = px->r;
+ int g = px->g;
+ int b = px->b;
+ int dist;
+ if ((i & 1) || i<10) { // sort on max distance
+ for (int j=0; j<ncols; j++) {
+ px = &pixarr[j];
+ if (px->use) {
+ dist = (px->r - r)*(px->r - r) +
+ (px->g - g)*(px->g - g) +
+ (px->b - b)*(px->b - b);
+ if (px->mindist > dist)
+ px->mindist = dist;
+ if (px->mindist > mindist) {
+ mindist = px->mindist;
+ minpix = j;
+ }
+ }
+ }
+ } else { // sort on max popularity
+ for (int j=0; j<ncols; j++) {
+ px = &pixarr[j];
+ if (px->use) {
+ dist = (px->r - r)*(px->r - r) +
+ (px->g - g)*(px->g - g) +
+ (px->b - b)*(px->b - b);
+ if (px->mindist > dist)
+ px->mindist = dist;
+ if (px->use > mindist) {
+ mindist = px->use;
+ minpix = j;
+ }
+ }
+ }
+ }
+ pixarr_sorted[i] = pixarr[minpix];
+ pixarr[minpix].use = 0;
+ }
+
+ QXcbColormap cmap = QXcbColormap::instance(xinfo.screen());
+ uint pix[256]; // pixel translation table
+ px = &pixarr_sorted[0];
+ for (int i = 0; i < ncols; i++) { // allocate colors
+ QColor c(px->r, px->g, px->b);
+ pix[px->index] = cmap.pixel(c);
+ px++;
+ }
+
+ p = newbits;
+ for (size_t i = 0; i < nbytes; i++) { // translate pixels
+ *p = pix[*p];
+ p++;
+ }
+ }
+
+ if (!xi) { // X image not created
+ xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0);
+ if (xi->bits_per_pixel == 16) { // convert 8 bpp ==> 16 bpp
+ ushort *p2;
+ int p2inc = xi->bytes_per_line/sizeof(ushort);
+ ushort *newerbits = (ushort *)malloc(xi->bytes_per_line * h);
+ Q_CHECK_PTR(newerbits);
+ if (!newerbits) // no memory
+ return;
+ uchar* p = newbits;
+ for (int y = 0; y < h; y++) { // OOPS: Do right byte order!!
+ p2 = newerbits + p2inc*y;
+ for (int x = 0; x < w; x++)
+ *p2++ = *p++;
+ }
+ free(newbits);
+ newbits = (uchar *)newerbits;
+ } else if (xi->bits_per_pixel != 8) {
+ qWarning("QPixmap::fromImage: Display not supported "
+ "(bpp=%d)", xi->bits_per_pixel);
+ }
+ xi->data = (char *)newbits;
+ }
+
+ hd = XCreatePixmap(dpy,
+ RootWindow(dpy, xinfo.screen()),
+ w, h, dd);
+
+ GC gc = XCreateGC(dpy, hd, 0, 0);
+ XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h);
+ XFreeGC(dpy, gc);
+
+ qSafeXDestroyImage(xi);
+ d = dd;
+
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender) {
+ XRenderPictFormat *format = d == 1
+ ? XRenderFindStandardFormat(dpy, PictStandardA1)
+ : XRenderFindVisualFormat(dpy, (Visual *)xinfo.visual());
+ picture = XRenderCreatePicture(dpy, hd, format, 0, 0);
+ }
+#endif
+
+ if (alphaCheck.hasAlpha()) {
+ QBitmap m = QBitmap::fromImage(image.createAlphaMask(flags));
+ setMask(m);
+ }
+}
+
+void QX11PlatformPixmap::copy(const QPlatformPixmap *data, const QRect &rect)
+{
+ if (data->pixelType() == BitmapType) {
+ fromImage(data->toImage().copy(rect), Qt::AutoColor);
+ return;
+ }
+
+ const QX11PlatformPixmap *x11Data = static_cast<const QX11PlatformPixmap*>(data);
+
+ setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
+
+ flags &= ~Uninitialized;
+ xinfo = x11Data->xinfo;
+ d = x11Data->d;
+ w = rect.width();
+ h = rect.height();
+ is_null = (w <= 0 || h <= 0);
+ hd = XCreatePixmap(xinfo.display(),
+ RootWindow(xinfo.display(), x11Data->xinfo.screen()),
+ w, h, d);
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender) {
+ XRenderPictFormat *format = d == 32
+ ? XRenderFindStandardFormat(xinfo.display(), PictStandardARGB32)
+ : XRenderFindVisualFormat(xinfo.display(), (Visual *)xinfo.visual());
+ picture = XRenderCreatePicture(xinfo.display(), hd, format, 0, 0);
+ }
+#endif // QT_CONFIG(xrender)
+ if (x11Data->x11_mask) {
+ x11_mask = XCreatePixmap(xinfo.display(), hd, w, h, 1);
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender) {
+ mask_picture = XRenderCreatePicture(xinfo.display(), x11_mask,
+ XRenderFindStandardFormat(xinfo.display(), PictStandardA1), 0, 0);
+ XRenderPictureAttributes attrs;
+ attrs.alpha_map = x11Data->mask_picture;
+ XRenderChangePicture(xinfo.display(), x11Data->picture, CPAlphaMap, &attrs);
+ }
+#endif
+ }
+
+#if QT_CONFIG(xrender)
+ if (x11Data->picture && x11Data->d == 32) {
+ XRenderComposite(xinfo.display(), PictOpSrc,
+ x11Data->picture, 0, picture,
+ rect.x(), rect.y(), 0, 0, 0, 0, w, h);
+ } else
+#endif
+ {
+ GC gc = XCreateGC(xinfo.display(), hd, 0, 0);
+ XCopyArea(xinfo.display(), x11Data->hd, hd, gc,
+ rect.x(), rect.y(), w, h, 0, 0);
+ if (x11Data->x11_mask) {
+ GC monogc = XCreateGC(xinfo.display(), x11_mask, 0, 0);
+ XCopyArea(xinfo.display(), x11Data->x11_mask, x11_mask, monogc,
+ rect.x(), rect.y(), w, h, 0, 0);
+ XFreeGC(xinfo.display(), monogc);
+ }
+ XFreeGC(xinfo.display(), gc);
+ }
+}
+
+bool QX11PlatformPixmap::scroll(int dx, int dy, const QRect &rect)
+{
+ GC gc = XCreateGC(xinfo.display(), hd, 0, 0);
+ XCopyArea(xinfo.display(), hd, hd, gc,
+ rect.left(), rect.top(), rect.width(), rect.height(),
+ rect.left() + dx, rect.top() + dy);
+ XFreeGC(xinfo.display(), gc);
+ return true;
+}
+
+int QX11PlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ switch (metric) {
+ case QPaintDevice::PdmDevicePixelRatio:
+ return devicePixelRatio();
+ break;
+ case QPaintDevice::PdmDevicePixelRatioScaled:
+ return devicePixelRatio() * QPaintDevice::devicePixelRatioFScale();
+ break;
+ case QPaintDevice::PdmWidth:
+ return w;
+ case QPaintDevice::PdmHeight:
+ return h;
+ case QPaintDevice::PdmNumColors:
+ return 1 << d;
+ case QPaintDevice::PdmDepth:
+ return d;
+ case QPaintDevice::PdmWidthMM: {
+ const int screen = xinfo.screen();
+ const int mm = DisplayWidthMM(xinfo.display(), screen) * w
+ / DisplayWidth(xinfo.display(), screen);
+ return mm;
+ }
+ case QPaintDevice::PdmHeightMM: {
+ const int screen = xinfo.screen();
+ const int mm = (DisplayHeightMM(xinfo.display(), screen) * h)
+ / DisplayHeight(xinfo.display(), screen);
+ return mm;
+ }
+ case QPaintDevice::PdmDpiX:
+ case QPaintDevice::PdmPhysicalDpiX:
+ return QXcbX11Info::appDpiX(xinfo.screen());
+ case QPaintDevice::PdmDpiY:
+ case QPaintDevice::PdmPhysicalDpiY:
+ return QXcbX11Info::appDpiY(xinfo.screen());
+ default:
+ qWarning("QX11PlatformPixmap::metric(): Invalid metric");
+ return 0;
+ }
+}
+
+void QX11PlatformPixmap::fill(const QColor &fillColor)
+{
+ if (fillColor.alpha() != 255) {
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender) {
+ if (!picture || d != 32)
+ convertToARGB32(/*preserveContents = */false);
+
+ ::Picture src = X11->getSolidFill(xinfo.screen(), fillColor);
+ XRenderComposite(xinfo.display(), PictOpSrc, src, 0, picture,
+ 0, 0, width(), height(),
+ 0, 0, width(), height());
+ } else
+#endif
+ {
+ QImage im(width(), height(), QImage::Format_ARGB32_Premultiplied);
+ im.fill(PREMUL(fillColor.rgba()));
+ release();
+ fromImage(im, Qt::AutoColor | Qt::OrderedAlphaDither);
+ }
+ return;
+ }
+
+ GC gc = XCreateGC(xinfo.display(), hd, 0, 0);
+ if (depth() == 1) {
+ XSetForeground(xinfo.display(), gc, qGray(fillColor.rgb()) > 127 ? 0 : 1);
+ } else if (X11->use_xrender && d >= 24) {
+ XSetForeground(xinfo.display(), gc, fillColor.rgba());
+ } else {
+ XSetForeground(xinfo.display(), gc,
+ QXcbColormap::instance(xinfo.screen()).pixel(fillColor));
+ }
+ XFillRectangle(xinfo.display(), hd, gc, 0, 0, width(), height());
+ XFreeGC(xinfo.display(), gc);
+}
+
+QBitmap QX11PlatformPixmap::mask() const
+{
+ QBitmap mask;
+#if QT_CONFIG(xrender)
+ if (picture && d == 32) {
+ // #### slow - there must be a better way..
+ mask = QBitmap::fromImage(toImage().createAlphaMask());
+ } else
+#endif
+ if (d == 1) {
+ QX11PlatformPixmap *that = const_cast<QX11PlatformPixmap*>(this);
+ mask = QPixmap(that);
+ } else {
+ mask = mask_to_bitmap(xinfo.screen());
+ }
+ return mask;
+}
+
+void QX11PlatformPixmap::setMask(const QBitmap &newmask)
+{
+ if (newmask.isNull()) { // clear mask
+#if QT_CONFIG(xrender)
+ if (picture && d == 32) {
+ QX11PlatformPixmap newData(pixelType());
+ newData.resize(w, h);
+ newData.fill(Qt::black);
+ XRenderComposite(xinfo.display(), PictOpOver,
+ picture, 0, newData.picture,
+ 0, 0, 0, 0, 0, 0, w, h);
+ release();
+ *this = newData;
+ // the new QX11PlatformPixmap object isn't referenced yet, so
+ // ref it
+ ref.ref();
+
+ // the below is to make sure the QX11PlatformPixmap destructor
+ // doesn't delete our newly created render picture
+ newData.hd = 0;
+ newData.x11_mask = 0;
+ newData.picture = 0;
+ newData.mask_picture = 0;
+ newData.hd2 = 0;
+ } else
+#endif
+ if (x11_mask) {
+#if QT_CONFIG(xrender)
+ if (picture) {
+ XRenderPictureAttributes attrs;
+ attrs.alpha_map = 0;
+ XRenderChangePicture(xinfo.display(), picture, CPAlphaMap,
+ &attrs);
+ }
+ if (mask_picture)
+ XRenderFreePicture(xinfo.display(), mask_picture);
+ mask_picture = 0;
+#endif
+ XFreePixmap(xinfo.display(), x11_mask);
+ x11_mask = 0;
+ }
+ return;
+ }
+
+#if QT_CONFIG(xrender)
+ if (picture && d == 32) {
+ XRenderComposite(xinfo.display(), PictOpSrc,
+ picture, qt_x11Pixmap(newmask)->x11PictureHandle(),
+ picture, 0, 0, 0, 0, 0, 0, w, h);
+ } else
+#endif
+ if (depth() == 1) {
+ XGCValues vals;
+ vals.function = GXand;
+ GC gc = XCreateGC(xinfo.display(), hd, GCFunction, &vals);
+ XCopyArea(xinfo.display(), qt_x11Pixmap(newmask)->handle(), hd, gc, 0, 0,
+ width(), height(), 0, 0);
+ XFreeGC(xinfo.display(), gc);
+ } else {
+ // ##### should or the masks together
+ if (x11_mask) {
+ XFreePixmap(xinfo.display(), x11_mask);
+#if QT_CONFIG(xrender)
+ if (mask_picture)
+ XRenderFreePicture(xinfo.display(), mask_picture);
+#endif
+ }
+ x11_mask = QX11PlatformPixmap::bitmap_to_mask(newmask, xinfo.screen());
+#if QT_CONFIG(xrender)
+ if (picture) {
+ mask_picture = XRenderCreatePicture(xinfo.display(), x11_mask,
+ XRenderFindStandardFormat(xinfo.display(), PictStandardA1), 0, 0);
+ XRenderPictureAttributes attrs;
+ attrs.alpha_map = mask_picture;
+ XRenderChangePicture(xinfo.display(), picture, CPAlphaMap, &attrs);
+ }
+#endif
+ }
+}
+
+bool QX11PlatformPixmap::hasAlphaChannel() const
+{
+ if (picture && d == 32)
+ return true;
+
+ if (x11_mask && d == 1)
+ return true;
+
+ return false;
+}
+
+QPixmap QX11PlatformPixmap::transformed(const QTransform &transform, Qt::TransformationMode mode) const
+{
+ if (mode == Qt::SmoothTransformation || transform.type() >= QTransform::TxProject) {
+ QImage image = toImage();
+ return QPixmap::fromImage(image.transformed(transform, mode));
+ }
+
+ uint w = 0;
+ uint h = 0; // size of target pixmap
+ uint ws, hs; // size of source pixmap
+ uchar *dptr; // data in target pixmap
+ uint dbpl, dbytes; // bytes per line/bytes total
+ uchar *sptr; // data in original pixmap
+ int sbpl; // bytes per line in original
+ int bpp; // bits per pixel
+ bool depth1 = depth() == 1;
+ Display *dpy = xinfo.display();
+
+ ws = width();
+ hs = height();
+
+ QTransform mat(transform.m11(), transform.m12(), transform.m13(),
+ transform.m21(), transform.m22(), transform.m23(),
+ 0., 0., 1);
+ bool complex_xform = false;
+ qreal scaledWidth;
+ qreal scaledHeight;
+
+ if (mat.type() <= QTransform::TxScale) {
+ scaledHeight = qAbs(mat.m22()) * hs + 0.9999;
+ scaledWidth = qAbs(mat.m11()) * ws + 0.9999;
+ h = qAbs(int(scaledHeight));
+ w = qAbs(int(scaledWidth));
+ } else { // rotation or shearing
+ QPolygonF a(QRectF(0, 0, ws, hs));
+ a = mat.map(a);
+ QRect r = a.boundingRect().toAlignedRect();
+ w = r.width();
+ h = r.height();
+ scaledWidth = w;
+ scaledHeight = h;
+ complex_xform = true;
+ }
+ mat = QPixmap::trueMatrix(mat, ws, hs); // true matrix
+
+ bool invertible;
+ mat = mat.inverted(&invertible); // invert matrix
+
+ if (h == 0 || w == 0 || !invertible
+ || qAbs(scaledWidth) >= 32768 || qAbs(scaledHeight) >= 32768 )
+ // error, return null pixmap
+ return QPixmap();
+
+ XImage *xi = XGetImage(xinfo.display(), handle(), 0, 0, ws, hs, AllPlanes,
+ depth1 ? XYPixmap : ZPixmap);
+
+ if (!xi)
+ return QPixmap();
+
+ sbpl = xi->bytes_per_line;
+ sptr = (uchar *)xi->data;
+ bpp = xi->bits_per_pixel;
+
+ if (depth1)
+ dbpl = (w+7)/8;
+ else
+ dbpl = ((w*bpp+31)/32)*4;
+ dbytes = dbpl*h;
+
+ dptr = (uchar *)malloc(dbytes); // create buffer for bits
+ Q_CHECK_PTR(dptr);
+ if (depth1) // fill with zeros
+ memset(dptr, 0, dbytes);
+ else if (bpp == 8) // fill with background color
+ memset(dptr, WhitePixel(xinfo.display(), xinfo.screen()), dbytes);
+ else
+ memset(dptr, 0, dbytes);
+
+ // #define QT_DEBUG_XIMAGE
+#if defined(QT_DEBUG_XIMAGE)
+ qDebug("----IMAGE--INFO--------------");
+ qDebug("width............. %d", xi->width);
+ qDebug("height............ %d", xi->height);
+ qDebug("xoffset........... %d", xi->xoffset);
+ qDebug("format............ %d", xi->format);
+ qDebug("byte order........ %d", xi->byte_order);
+ qDebug("bitmap unit....... %d", xi->bitmap_unit);
+ qDebug("bitmap bit order.. %d", xi->bitmap_bit_order);
+ qDebug("depth............. %d", xi->depth);
+ qDebug("bytes per line.... %d", xi->bytes_per_line);
+ qDebug("bits per pixel.... %d", xi->bits_per_pixel);
+#endif
+
+ int type;
+ if (xi->bitmap_bit_order == MSBFirst)
+ type = QT_XFORM_TYPE_MSBFIRST;
+ else
+ type = QT_XFORM_TYPE_LSBFIRST;
+ int xbpl, p_inc;
+ if (depth1) {
+ xbpl = (w+7)/8;
+ p_inc = dbpl - xbpl;
+ } else {
+ xbpl = (w*bpp)/8;
+ p_inc = dbpl - xbpl;
+ }
+
+ if (!qt_xForm_helper(mat, xi->xoffset, type, bpp, dptr, xbpl, p_inc, h, sptr, sbpl, ws, hs)){
+ qWarning("QPixmap::transform: display not supported (bpp=%d)",bpp);
+ QPixmap pm;
+ free(dptr);
+ return pm;
+ }
+
+ qSafeXDestroyImage(xi);
+
+ if (depth1) { // mono bitmap
+ QBitmap bm = QBitmap::fromData(QSize(w, h), dptr,
+ BitmapBitOrder(xinfo.display()) == MSBFirst
+ ? QImage::Format_Mono
+ : QImage::Format_MonoLSB);
+ free(dptr);
+ return bm;
+ } else { // color pixmap
+ QX11PlatformPixmap *x11Data = new QX11PlatformPixmap(QPlatformPixmap::PixmapType);
+ QPixmap pm(x11Data);
+ x11Data->flags &= ~QX11PlatformPixmap::Uninitialized;
+ x11Data->xinfo = xinfo;
+ x11Data->d = d;
+ x11Data->w = w;
+ x11Data->h = h;
+ x11Data->is_null = (w <= 0 || h <= 0);
+ x11Data->hd = XCreatePixmap(xinfo.display(),
+ RootWindow(xinfo.display(), xinfo.screen()),
+ w, h, d);
+ x11Data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
+
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender) {
+ XRenderPictFormat *format = x11Data->d == 32
+ ? XRenderFindStandardFormat(xinfo.display(), PictStandardARGB32)
+ : XRenderFindVisualFormat(xinfo.display(), (Visual *) x11Data->xinfo.visual());
+ x11Data->picture = XRenderCreatePicture(xinfo.display(), x11Data->hd, format, 0, 0);
+ }
+#endif // QT_CONFIG(xrender)
+
+ GC gc = XCreateGC(xinfo.display(), x11Data->hd, 0, 0);
+ xi = XCreateImage(dpy, (Visual*)x11Data->xinfo.visual(),
+ x11Data->d,
+ ZPixmap, 0, (char *)dptr, w, h, 32, 0);
+ XPutImage(dpy, qt_x11Pixmap(pm)->handle(), gc, xi, 0, 0, 0, 0, w, h);
+ qSafeXDestroyImage(xi);
+ XFreeGC(xinfo.display(), gc);
+
+ if (x11_mask) { // xform mask, too
+ pm.setMask(mask_to_bitmap(xinfo.screen()).transformed(transform));
+ } else if (d != 32 && complex_xform) { // need a mask!
+ QBitmap mask(ws, hs);
+ mask.fill(Qt::color1);
+ pm.setMask(mask.transformed(transform));
+ }
+ return pm;
+ }
+}
+
+QImage QX11PlatformPixmap::toImage() const
+{
+ return toImage(QRect(0, 0, w, h));
+}
+
+QImage QX11PlatformPixmap::toImage(const QRect &rect) const
+{
+ Window root_return;
+ int x_return;
+ int y_return;
+ unsigned int width_return;
+ unsigned int height_return;
+ unsigned int border_width_return;
+ unsigned int depth_return;
+
+ XGetGeometry(xinfo.display(), hd, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return);
+
+ QXImageWrapper xiWrapper;
+ xiWrapper.xi = XGetImage(xinfo.display(), hd, rect.x(), rect.y(), rect.width(), rect.height(),
+ AllPlanes, (depth() == 1) ? XYPixmap : ZPixmap);
+
+ Q_CHECK_PTR(xiWrapper.xi);
+ if (!xiWrapper.xi)
+ return QImage();
+
+ if (!x11_mask && canTakeQImageFromXImage(xiWrapper))
+ return takeQImageFromXImage(xiWrapper);
+
+ QImage image = toImage(xiWrapper, rect);
+ qSafeXDestroyImage(xiWrapper.xi);
+ return image;
+}
+
+#if QT_CONFIG(xrender)
+static XRenderPictFormat *qt_renderformat_for_depth(const QXcbX11Info &xinfo, int depth)
+{
+ if (depth == 1)
+ return XRenderFindStandardFormat(xinfo.display(), PictStandardA1);
+ else if (depth == 32)
+ return XRenderFindStandardFormat(xinfo.display(), PictStandardARGB32);
+ else
+ return XRenderFindVisualFormat(xinfo.display(), (Visual *)xinfo.visual());
+}
+#endif
+
+Q_GLOBAL_STATIC(QX11PaintEngine, qt_x11_paintengine)
+
+QPaintEngine *QX11PlatformPixmap::paintEngine() const
+{
+ QX11PlatformPixmap *that = const_cast<QX11PlatformPixmap*>(this);
+
+ if ((flags & Readonly)/* && share_mode == QPixmap::ImplicitlyShared*/) {
+ // if someone wants to draw onto us, copy the shared contents
+ // and turn it into a fully fledged QPixmap
+ ::Pixmap hd_copy = XCreatePixmap(xinfo.display(), RootWindow(xinfo.display(), xinfo.screen()),
+ w, h, d);
+#if QT_CONFIG(xrender)
+ if (picture && d == 32) {
+ XRenderPictFormat *format = qt_renderformat_for_depth(xinfo, d);
+ ::Picture picture_copy = XRenderCreatePicture(xinfo.display(),
+ hd_copy, format,
+ 0, 0);
+
+ XRenderComposite(xinfo.display(), PictOpSrc, picture, 0, picture_copy,
+ 0, 0, 0, 0, 0, 0, w, h);
+ XRenderFreePicture(xinfo.display(), picture);
+ that->picture = picture_copy;
+ } else
+#endif
+ {
+ GC gc = XCreateGC(xinfo.display(), hd_copy, 0, 0);
+ XCopyArea(xinfo.display(), hd, hd_copy, gc, 0, 0, w, h, 0, 0);
+ XFreeGC(xinfo.display(), gc);
+ }
+ that->hd = hd_copy;
+ that->flags &= ~QX11PlatformPixmap::Readonly;
+ }
+
+ if (qt_x11_paintengine->isActive()) {
+ if (!that->pengine)
+ that->pengine = new QX11PaintEngine;
+
+ return that->pengine;
+ }
+
+ return qt_x11_paintengine();
+}
+
+qreal QX11PlatformPixmap::devicePixelRatio() const
+{
+ return dpr;
+}
+
+void QX11PlatformPixmap::setDevicePixelRatio(qreal scaleFactor)
+{
+ dpr = scaleFactor;
+}
+
+Pixmap QX11PlatformPixmap::x11ConvertToDefaultDepth()
+{
+#if QT_CONFIG(xrender)
+ if (d == xinfo.appDepth() || !X11->use_xrender)
+ return hd;
+ if (!hd2) {
+ hd2 = XCreatePixmap(xinfo.display(), hd, w, h, xinfo.appDepth());
+ XRenderPictFormat *format = XRenderFindVisualFormat(xinfo.display(),
+ (Visual*) xinfo.visual());
+ Picture pic = XRenderCreatePicture(xinfo.display(), hd2, format, 0, 0);
+ XRenderComposite(xinfo.display(), PictOpSrc, picture,
+ XNone, pic, 0, 0, 0, 0, 0, 0, w, h);
+ XRenderFreePicture(xinfo.display(), pic);
+ }
+ return hd2;
+#else
+ return hd;
+#endif
+}
+
+XID QX11PlatformPixmap::createBitmapFromImage(const QImage &image)
+{
+ QImage img = image.convertToFormat(QImage::Format_MonoLSB);
+ const QRgb c0 = QColor(Qt::black).rgb();
+ const QRgb c1 = QColor(Qt::white).rgb();
+ if (img.color(0) == c0 && img.color(1) == c1) {
+ img.invertPixels();
+ img.setColor(0, c1);
+ img.setColor(1, c0);
+ }
+
+ char *bits;
+ uchar *tmp_bits;
+ int w = img.width();
+ int h = img.height();
+ int bpl = (w + 7) / 8;
+ int ibpl = img.bytesPerLine();
+ if (bpl != ibpl) {
+ tmp_bits = new uchar[bpl*h];
+ bits = (char *)tmp_bits;
+ uchar *p, *b;
+ int y;
+ b = tmp_bits;
+ p = img.scanLine(0);
+ for (y = 0; y < h; y++) {
+ memcpy(b, p, bpl);
+ b += bpl;
+ p += ibpl;
+ }
+ } else {
+ bits = (char *)img.bits();
+ tmp_bits = 0;
+ }
+ XID hd = XCreateBitmapFromData(QXcbX11Info::display(),
+ QXcbX11Info::appRootWindow(),
+ bits, w, h);
+ if (tmp_bits) // Avoid purify complaint
+ delete [] tmp_bits;
+ return hd;
+}
+
+#if QT_CONFIG(xrender)
+void QX11PlatformPixmap::convertToARGB32(bool preserveContents)
+{
+ if (!X11->use_xrender)
+ return;
+
+ // Q_ASSERT(count == 1);
+ if ((flags & Readonly)/* && share_mode == QPixmap::ExplicitlyShared*/)
+ return;
+
+ Pixmap pm = XCreatePixmap(xinfo.display(), RootWindow(xinfo.display(), xinfo.screen()),
+ w, h, 32);
+ Picture p = XRenderCreatePicture(xinfo.display(), pm,
+ XRenderFindStandardFormat(xinfo.display(), PictStandardARGB32), 0, 0);
+ if (picture) {
+ if (preserveContents)
+ XRenderComposite(xinfo.display(), PictOpSrc, picture, 0, p, 0, 0, 0, 0, 0, 0, w, h);
+ if (!(flags & Readonly))
+ XRenderFreePicture(xinfo.display(), picture);
+ }
+ if (hd && !(flags & Readonly))
+ XFreePixmap(xinfo.display(), hd);
+ if (x11_mask) {
+ XFreePixmap(xinfo.display(), x11_mask);
+ if (mask_picture)
+ XRenderFreePicture(xinfo.display(), mask_picture);
+ x11_mask = 0;
+ mask_picture = 0;
+ }
+ hd = pm;
+ picture = p;
+
+ d = 32;
+ xinfo.setDepth(32);
+
+ XVisualInfo visinfo;
+ if (XMatchVisualInfo(xinfo.display(), xinfo.screen(), 32, TrueColor, &visinfo))
+ xinfo.setVisual(visinfo.visual);
+}
+#endif
+
+void QX11PlatformPixmap::release()
+{
+ delete pengine;
+ pengine = 0;
+
+ if (/*!X11*/ QCoreApplication::closingDown()) {
+ // At this point, the X server will already have freed our resources,
+ // so there is nothing to do.
+ return;
+ }
+
+ if (x11_mask) {
+#if QT_CONFIG(xrender)
+ if (mask_picture)
+ XRenderFreePicture(xinfo.display(), mask_picture);
+ mask_picture = 0;
+#endif
+ XFreePixmap(xinfo.display(), x11_mask);
+ x11_mask = 0;
+ }
+
+ if (hd) {
+#if QT_CONFIG(xrender)
+ if (picture) {
+ XRenderFreePicture(xinfo.display(), picture);
+ picture = 0;
+ }
+#endif // QT_CONFIG(xrender)
+
+ if (hd2) {
+ XFreePixmap(xinfo.display(), hd2);
+ hd2 = 0;
+ }
+ if (!(flags & Readonly))
+ XFreePixmap(xinfo.display(), hd);
+ hd = 0;
+ }
+}
+
+QImage QX11PlatformPixmap::toImage(const QXImageWrapper &xiWrapper, const QRect &rect) const
+{
+ XImage *xi = xiWrapper.xi;
+
+ int d = depth();
+ Visual *visual = (Visual *)xinfo.visual();
+ bool trucol = (visual->c_class >= TrueColor) && d > 1;
+
+ QImage::Format format = QImage::Format_Mono;
+ if (d > 1 && d <= 8) {
+ d = 8;
+ format = QImage::Format_Indexed8;
+ }
+ // we could run into the situation where d == 8 AND trucol is true, which can
+ // cause problems when converting to and from images. in this case, always treat
+ // the depth as 32...
+ if (d > 8 || trucol) {
+ d = 32;
+ format = QImage::Format_RGB32;
+ }
+
+ if (d == 1 && xi->bitmap_bit_order == LSBFirst)
+ format = QImage::Format_MonoLSB;
+ if (x11_mask && format == QImage::Format_RGB32)
+ format = QImage::Format_ARGB32;
+
+ QImage image(xi->width, xi->height, format);
+ image.setDevicePixelRatio(devicePixelRatio());
+ if (image.isNull()) // could not create image
+ return image;
+
+ QImage alpha;
+ if (x11_mask) {
+ if (rect.contains(QRect(0, 0, w, h)))
+ alpha = mask().toImage();
+ else
+ alpha = mask().toImage().copy(rect);
+ }
+ bool ale = alpha.format() == QImage::Format_MonoLSB;
+
+ if (trucol) { // truecolor
+ const uint red_mask = (uint)visual->red_mask;
+ const uint green_mask = (uint)visual->green_mask;
+ const uint blue_mask = (uint)visual->blue_mask;
+ const int red_shift = highest_bit(red_mask) - 7;
+ const int green_shift = highest_bit(green_mask) - 7;
+ const int blue_shift = highest_bit(blue_mask) - 7;
+
+ const uint red_bits = n_bits(red_mask);
+ const uint green_bits = n_bits(green_mask);
+ const uint blue_bits = n_bits(blue_mask);
+
+ static uint red_table_bits = 0;
+ static uint green_table_bits = 0;
+ static uint blue_table_bits = 0;
+
+ if (red_bits < 8 && red_table_bits != red_bits) {
+ build_scale_table(&red_scale_table, red_bits);
+ red_table_bits = red_bits;
+ }
+ if (blue_bits < 8 && blue_table_bits != blue_bits) {
+ build_scale_table(&blue_scale_table, blue_bits);
+ blue_table_bits = blue_bits;
+ }
+ if (green_bits < 8 && green_table_bits != green_bits) {
+ build_scale_table(&green_scale_table, green_bits);
+ green_table_bits = green_bits;
+ }
+
+ int r, g, b;
+
+ QRgb *dst;
+ uchar *src;
+ uint pixel;
+ int bppc = xi->bits_per_pixel;
+
+ if (bppc > 8 && xi->byte_order == LSBFirst)
+ bppc++;
+
+ for (int y = 0; y < xi->height; ++y) {
+ uchar* asrc = x11_mask ? alpha.scanLine(y) : 0;
+ dst = (QRgb *)image.scanLine(y);
+ src = (uchar *)xi->data + xi->bytes_per_line*y;
+ for (int x = 0; x < xi->width; x++) {
+ switch (bppc) {
+ case 8:
+ pixel = *src++;
+ break;
+ case 16: // 16 bit MSB
+ pixel = src[1] | (uint)src[0] << 8;
+ src += 2;
+ break;
+ case 17: // 16 bit LSB
+ pixel = src[0] | (uint)src[1] << 8;
+ src += 2;
+ break;
+ case 24: // 24 bit MSB
+ pixel = src[2] | (uint)src[1] << 8 | (uint)src[0] << 16;
+ src += 3;
+ break;
+ case 25: // 24 bit LSB
+ pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16;
+ src += 3;
+ break;
+ case 32: // 32 bit MSB
+ pixel = src[3] | (uint)src[2] << 8 | (uint)src[1] << 16 | (uint)src[0] << 24;
+ src += 4;
+ break;
+ case 33: // 32 bit LSB
+ pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16 | (uint)src[3] << 24;
+ src += 4;
+ break;
+ default: // should not really happen
+ x = xi->width; // leave loop
+ y = xi->height;
+ pixel = 0; // eliminate compiler warning
+ qWarning("QPixmap::convertToImage: Invalid depth %d", bppc);
+ }
+ if (red_shift > 0)
+ r = (pixel & red_mask) >> red_shift;
+ else
+ r = (pixel & red_mask) << -red_shift;
+ if (green_shift > 0)
+ g = (pixel & green_mask) >> green_shift;
+ else
+ g = (pixel & green_mask) << -green_shift;
+ if (blue_shift > 0)
+ b = (pixel & blue_mask) >> blue_shift;
+ else
+ b = (pixel & blue_mask) << -blue_shift;
+
+ if (red_bits < 8)
+ r = red_scale_table[r];
+ if (green_bits < 8)
+ g = green_scale_table[g];
+ if (blue_bits < 8)
+ b = blue_scale_table[b];
+
+ if (x11_mask) {
+ if (ale) {
+ *dst++ = (asrc[x >> 3] & (1 << (x & 7))) ? qRgba(r, g, b, 0xff) : 0;
+ } else {
+ *dst++ = (asrc[x >> 3] & (0x80 >> (x & 7))) ? qRgba(r, g, b, 0xff) : 0;
+ }
+ } else {
+ *dst++ = qRgb(r, g, b);
+ }
+ }
+ }
+ } else if (xi->bits_per_pixel == d) { // compatible depth
+ char *xidata = xi->data; // copy each scanline
+ int bpl = qMin(image.bytesPerLine(),xi->bytes_per_line);
+ for (int y=0; y<xi->height; y++) {
+ memcpy(image.scanLine(y), xidata, bpl);
+ xidata += xi->bytes_per_line;
+ }
+ } else {
+ /* Typically 2 or 4 bits display depth */
+ qWarning("QPixmap::convertToImage: Display not supported (bpp=%d)",
+ xi->bits_per_pixel);
+ return QImage();
+ }
+
+ if (d == 1) { // bitmap
+ image.setColorCount(2);
+ image.setColor(0, qRgb(255,255,255));
+ image.setColor(1, qRgb(0,0,0));
+ } else if (!trucol) { // pixmap with colormap
+ uchar *p;
+ uchar *end;
+ uchar use[256]; // pixel-in-use table
+ uchar pix[256]; // pixel translation table
+ int ncols, bpl;
+ memset(use, 0, 256);
+ memset(pix, 0, 256);
+ bpl = image.bytesPerLine();
+
+ if (x11_mask) { // which pixels are used?
+ for (int i = 0; i < xi->height; i++) {
+ uchar* asrc = alpha.scanLine(i);
+ p = image.scanLine(i);
+ if (ale) {
+ for (int x = 0; x < xi->width; x++) {
+ if (asrc[x >> 3] & (1 << (x & 7)))
+ use[*p] = 1;
+ ++p;
+ }
+ } else {
+ for (int x = 0; x < xi->width; x++) {
+ if (asrc[x >> 3] & (0x80 >> (x & 7)))
+ use[*p] = 1;
+ ++p;
+ }
+ }
+ }
+ } else {
+ for (int i = 0; i < xi->height; i++) {
+ p = image.scanLine(i);
+ end = p + bpl;
+ while (p < end)
+ use[*p++] = 1;
+ }
+ }
+ ncols = 0;
+ for (int i = 0; i < 256; i++) { // build translation table
+ if (use[i])
+ pix[i] = ncols++;
+ }
+ for (int i = 0; i < xi->height; i++) { // translate pixels
+ p = image.scanLine(i);
+ end = p + bpl;
+ while (p < end) {
+ *p = pix[*p];
+ p++;
+ }
+ }
+ if (x11_mask) {
+ int trans;
+ if (ncols < 256) {
+ trans = ncols++;
+ image.setColorCount(ncols); // create color table
+ image.setColor(trans, 0x00000000);
+ } else {
+ image.setColorCount(ncols); // create color table
+ // oh dear... no spare "transparent" pixel.
+ // use first pixel in image (as good as any).
+ trans = image.scanLine(0)[0];
+ }
+ for (int i = 0; i < xi->height; i++) {
+ uchar* asrc = alpha.scanLine(i);
+ p = image.scanLine(i);
+ if (ale) {
+ for (int x = 0; x < xi->width; x++) {
+ if (!(asrc[x >> 3] & (1 << (x & 7))))
+ *p = trans;
+ ++p;
+ }
+ } else {
+ for (int x = 0; x < xi->width; x++) {
+ if (!(asrc[x >> 3] & (1 << (7 -(x & 7)))))
+ *p = trans;
+ ++p;
+ }
+ }
+ }
+ } else {
+ image.setColorCount(ncols); // create color table
+ }
+ QVector<QColor> colors = QXcbColormap::instance(xinfo.screen()).colormap();
+ int j = 0;
+ for (int i=0; i<colors.size(); i++) { // translate pixels
+ if (use[i])
+ image.setColor(j++, 0xff000000 | colors.at(i).rgb());
+ }
+ }
+
+ return image;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h
new file mode 100644
index 0000000000..2cbd1fe3d0
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h
@@ -0,0 +1,160 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QX11PLATFORMPIXMAP_H
+#define QX11PLATFORMPIXMAP_H
+
+#include <QBitmap>
+#include <QPixmap>
+
+#include <qpa/qplatformpixmap.h>
+#include "qxcbnativepainting.h"
+
+typedef unsigned long XID;
+typedef XID Drawable;
+typedef XID Picture;
+typedef XID Pixmap;
+
+QT_BEGIN_NAMESPACE
+
+class QX11PaintEngine;
+struct QXImageWrapper;
+
+class QX11PlatformPixmap : public QPlatformPixmap
+{
+public:
+ QX11PlatformPixmap(PixelType pixelType);
+ ~QX11PlatformPixmap();
+
+ QPlatformPixmap *createCompatiblePlatformPixmap() const Q_DECL_OVERRIDE;
+ void resize(int width, int height) Q_DECL_OVERRIDE;
+ void fromImage(const QImage &img, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE;
+ void copy(const QPlatformPixmap *data, const QRect &rect) Q_DECL_OVERRIDE;
+ bool scroll(int dx, int dy, const QRect &rect) Q_DECL_OVERRIDE;
+ int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE;
+ void fill(const QColor &fillColor) Q_DECL_OVERRIDE;
+ QBitmap mask() const Q_DECL_OVERRIDE;
+ void setMask(const QBitmap &mask) Q_DECL_OVERRIDE;
+ bool hasAlphaChannel() const Q_DECL_OVERRIDE;
+ QPixmap transformed(const QTransform &matrix, Qt::TransformationMode mode) const Q_DECL_OVERRIDE;
+ QImage toImage() const Q_DECL_OVERRIDE;
+ QImage toImage(const QRect &rect) const Q_DECL_OVERRIDE;
+ QPaintEngine *paintEngine() const Q_DECL_OVERRIDE;
+ qreal devicePixelRatio() const Q_DECL_OVERRIDE;
+ void setDevicePixelRatio(qreal scaleFactor) Q_DECL_OVERRIDE;
+
+ inline Drawable handle() const { return hd; }
+ inline Picture x11PictureHandle() const { return picture; }
+ inline const QXcbX11Info *x11_info() const { return &xinfo; }
+
+ Pixmap x11ConvertToDefaultDepth();
+ static XID createBitmapFromImage(const QImage &image);
+
+#if QT_CONFIG(xrender)
+ void convertToARGB32(bool preserveContents = true);
+#endif
+
+private:
+ friend class QX11PaintEngine;
+ friend const QXcbX11Info &qt_x11Info(const QPixmap &pixmap);
+ friend void qt_x11SetScreen(QPixmap &pixmap, int screen);
+
+ void release();
+ QImage toImage(const QXImageWrapper &xi, const QRect &rect) const;
+ QBitmap mask_to_bitmap(int screen) const;
+ static Pixmap bitmap_to_mask(const QBitmap &, int screen);
+ void bitmapFromImage(const QImage &image);
+ bool canTakeQImageFromXImage(const QXImageWrapper &xi) const;
+ QImage takeQImageFromXImage(const QXImageWrapper &xi) const;
+
+ Pixmap hd = 0;
+
+ enum Flag {
+ NoFlags = 0x0,
+ Uninitialized = 0x1,
+ Readonly = 0x2,
+ InvertedWhenBoundToTexture = 0x4,
+ GlSurfaceCreatedWithAlpha = 0x8
+ };
+ uint flags;
+
+ QXcbX11Info xinfo;
+ Pixmap x11_mask;
+ Picture picture;
+ Picture mask_picture;
+ Pixmap hd2; // sorted in the default display depth
+ //QPixmap::ShareMode share_mode;
+ qreal dpr;
+
+ QX11PaintEngine *pengine;
+};
+
+inline QX11PlatformPixmap *qt_x11Pixmap(const QPixmap &pixmap)
+{
+ return (pixmap.handle() && pixmap.handle()->classId() == QPlatformPixmap::X11Class)
+ ? static_cast<QX11PlatformPixmap *>(pixmap.handle())
+ : Q_NULLPTR;
+}
+
+inline Picture qt_x11PictureHandle(const QPixmap &pixmap)
+{
+ if (QX11PlatformPixmap *pm = qt_x11Pixmap(pixmap))
+ return pm->x11PictureHandle();
+
+ return 0;
+}
+
+inline Pixmap qt_x11PixmapHandle(const QPixmap &pixmap)
+{
+ if (QX11PlatformPixmap *pm = qt_x11Pixmap(pixmap))
+ return pm->handle();
+
+ return 0;
+}
+
+inline const QXcbX11Info &qt_x11Info(const QPixmap &pixmap)
+{
+ if (QX11PlatformPixmap *pm = qt_x11Pixmap(pixmap)) {
+ return pm->xinfo;
+ } else {
+ static QXcbX11Info nullX11Info;
+ return nullX11Info;
+ }
+}
+
+int qt_x11SetDefaultScreen(int screen);
+void qt_x11SetScreen(QPixmap &pixmap, int screen);
+
+QT_END_NAMESPACE
+
+#endif // QX11PLATFORMPIXMAP_H
diff --git a/src/plugins/platforms/xcb/nativepainting/qt_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qt_x11_p.h
new file mode 100644
index 0000000000..a0e5131ea7
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qt_x11_p.h
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_X11_P_H
+#define QT_X11_P_H
+
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+
+#if QT_CONFIG(xrender)
+# include "qtessellator_p.h"
+# include <X11/extensions/Xrender.h>
+#endif
+
+#if QT_CONFIG(fontconfig)
+#include <fontconfig/fontconfig.h>
+#endif
+
+#if defined(FT_LCD_FILTER_H)
+#include FT_LCD_FILTER_H
+#endif
+
+#if defined(FC_LCD_FILTER)
+
+#ifndef FC_LCD_FILTER_NONE
+#define FC_LCD_FILTER_NONE FC_LCD_NONE
+#endif
+
+#ifndef FC_LCD_FILTER_DEFAULT
+#define FC_LCD_FILTER_DEFAULT FC_LCD_DEFAULT
+#endif
+
+#ifndef FC_LCD_FILTER_LIGHT
+#define FC_LCD_FILTER_LIGHT FC_LCD_LIGHT
+#endif
+
+#ifndef FC_LCD_FILTER_LEGACY
+#define FC_LCD_FILTER_LEGACY FC_LCD_LEGACY
+#endif
+
+#endif
+
+QT_BEGIN_NAMESPACE
+
+// rename a couple of X defines to get rid of name clashes
+// resolve the conflict between X11's FocusIn and QEvent::FocusIn
+enum {
+ XFocusOut = FocusOut,
+ XFocusIn = FocusIn,
+ XKeyPress = KeyPress,
+ XKeyRelease = KeyRelease,
+ XNone = None,
+ XRevertToParent = RevertToParent,
+ XGrayScale = GrayScale,
+ XCursorShape = CursorShape,
+};
+#undef FocusOut
+#undef FocusIn
+#undef KeyPress
+#undef KeyRelease
+#undef None
+#undef RevertToParent
+#undef GrayScale
+#undef CursorShape
+
+#ifdef FontChange
+#undef FontChange
+#endif
+
+Q_DECLARE_TYPEINFO(XPoint, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(XRectangle, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(XChar2b, Q_PRIMITIVE_TYPE);
+#if QT_CONFIG(xrender)
+Q_DECLARE_TYPEINFO(XGlyphElt32, Q_PRIMITIVE_TYPE);
+#endif
+
+struct QX11InfoData;
+
+enum DesktopEnvironment {
+ DE_UNKNOWN,
+ DE_KDE,
+ DE_GNOME,
+ DE_CDE,
+ DE_MEEGO_COMPOSITOR,
+ DE_4DWM
+};
+
+struct QXcbX11Data {
+ Display *display = nullptr;
+
+ // true if Qt is compiled w/ RENDER support and RENDER is supported on the connected Display
+ bool use_xrender = false;
+ int xrender_major = 0;
+ int xrender_version = 0;
+
+ QX11InfoData *screens = nullptr;
+ Visual **argbVisuals = nullptr;
+ Colormap *argbColormaps = nullptr;
+ int screenCount = 0;
+ int defaultScreen = 0;
+
+ // options
+ int visual_class = 0;
+ int visual_id = 0;
+ int color_count = 0;
+ bool custom_cmap = false;
+
+ // outside visual/colormap
+ Visual *visual = nullptr;
+ Colormap colormap = 0;
+
+#if QT_CONFIG(xrender)
+ enum { solid_fill_count = 16 };
+ struct SolidFills {
+ XRenderColor color;
+ int screen;
+ Picture picture;
+ } solid_fills[solid_fill_count];
+ enum { pattern_fill_count = 16 };
+ struct PatternFills {
+ XRenderColor color;
+ XRenderColor bg_color;
+ int screen;
+ int style;
+ bool opaque;
+ Picture picture;
+ } pattern_fills[pattern_fill_count];
+ Picture getSolidFill(int screen, const QColor &c);
+ XRenderColor preMultiply(const QColor &c);
+#endif
+
+ bool fc_antialias = true;
+ int fc_hint_style = 0;
+
+ DesktopEnvironment desktopEnvironment = DE_GNOME;
+};
+
+extern QXcbX11Data *qt_x11Data;
+#define X11 qt_x11Data
+
+struct QX11InfoData {
+ int screen;
+ int dpiX;
+ int dpiY;
+ int depth;
+ int cells;
+ Colormap colormap;
+ Visual *visual;
+ bool defaultColormap;
+ bool defaultVisual;
+ int subpixel = 0;
+};
+
+template <class T>
+Q_DECL_RELAXED_CONSTEXPR inline int lowest_bit(T v) Q_DECL_NOTHROW
+{
+ int result = qCountTrailingZeroBits(v);
+ return ((result >> 3) == sizeof(T)) ? -1 : result;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_X11_P_H
diff --git a/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp b/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
new file mode 100644
index 0000000000..9acb21f95f
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
@@ -0,0 +1,1494 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtessellator_p.h"
+
+#include <QRect>
+#include <QList>
+#include <QDebug>
+
+#include <qmath.h>
+#include <limits.h>
+#include <algorithm>
+
+QT_BEGIN_NAMESPACE
+
+//#define DEBUG
+#ifdef DEBUG
+#define QDEBUG qDebug
+#else
+#define QDEBUG if (1){} else qDebug
+#endif
+
+static const bool emit_clever = true;
+static const bool mark_clever = false;
+
+enum VertexFlags {
+ LineBeforeStarts = 0x1,
+ LineBeforeEnds = 0x2,
+ LineBeforeHorizontal = 0x4,
+ LineAfterStarts = 0x8,
+ LineAfterEnds = 0x10,
+ LineAfterHorizontal = 0x20
+};
+
+
+
+class QTessellatorPrivate {
+public:
+ struct Vertices;
+
+ QTessellatorPrivate() {}
+
+ QRectF collectAndSortVertices(const QPointF *points, int *maxActiveEdges);
+ void cancelCoincidingEdges();
+
+ void emitEdges(QTessellator *tessellator);
+ void processIntersections();
+ void removeEdges();
+ void addEdges();
+ void addIntersections();
+
+ struct Vertex : public QTessellator::Vertex
+ {
+ int flags;
+ };
+
+ struct Intersection
+ {
+ Q27Dot5 y;
+ int edge;
+ bool operator <(const Intersection &other) const {
+ if (y != other.y)
+ return y < other.y;
+ return edge < other.edge;
+ }
+ };
+ struct IntersectionLink
+ {
+ int next;
+ int prev;
+ };
+ typedef QMap<Intersection, IntersectionLink> Intersections;
+
+ struct Edge {
+ Edge(const Vertices &v, int _edge);
+ int edge;
+ const Vertex *v0;
+ const Vertex *v1;
+ Q27Dot5 y_left;
+ Q27Dot5 y_right;
+ signed int winding : 8;
+ bool mark;
+ bool free;
+ bool intersect_left;
+ bool intersect_right;
+ bool isLeftOf(const Edge &other, Q27Dot5 y) const;
+ Q27Dot5 positionAt(Q27Dot5 y) const;
+ bool intersect(const Edge &other, Q27Dot5 *y, bool *det_positive) const;
+
+ };
+
+ class EdgeSorter
+ {
+ public:
+ EdgeSorter(int _y) : y(_y) {}
+ bool operator() (const Edge *e1, const Edge *e2);
+ int y;
+ };
+
+ class Scanline {
+ public:
+ Scanline();
+ ~Scanline();
+
+ void init(int maxActiveEdges);
+ void done();
+
+ int findEdgePosition(Q27Dot5 x, Q27Dot5 y) const;
+ int findEdgePosition(const Edge &e) const;
+ int findEdge(int edge) const;
+ void clearMarks();
+
+ void swap(int p1, int p2) {
+ Edge *tmp = edges[p1];
+ edges[p1] = edges[p2];
+ edges[p2] = tmp;
+ }
+ void insert(int pos, const Edge &e);
+ void removeAt(int pos);
+ void markEdges(int pos1, int pos2);
+
+ void prepareLine();
+ void lineDone();
+
+ Edge **old;
+ int old_size;
+
+ Edge **edges;
+ int size;
+
+ private:
+ Edge *edge_table;
+ int first_unused;
+ int max_edges;
+ enum { default_alloc = 32 };
+ };
+
+ struct Vertices {
+ enum { default_alloc = 128 };
+ Vertices();
+ ~Vertices();
+ void init(int maxVertices);
+ void done();
+ Vertex *storage;
+ Vertex **sorted;
+
+ Vertex *operator[] (int i) { return storage + i; }
+ const Vertex *operator[] (int i) const { return storage + i; }
+ int position(const Vertex *v) const {
+ return v - storage;
+ }
+ Vertex *next(Vertex *v) {
+ ++v;
+ if (v == storage + nPoints)
+ v = storage;
+ return v;
+ }
+ const Vertex *next(const Vertex *v) const {
+ ++v;
+ if (v == storage + nPoints)
+ v = storage;
+ return v;
+ }
+ int nextPos(const Vertex *v) const {
+ ++v;
+ if (v == storage + nPoints)
+ return 0;
+ return v - storage;
+ }
+ Vertex *prev(Vertex *v) {
+ if (v == storage)
+ v = storage + nPoints;
+ --v;
+ return v;
+ }
+ const Vertex *prev(const Vertex *v) const {
+ if (v == storage)
+ v = storage + nPoints;
+ --v;
+ return v;
+ }
+ int prevPos(const Vertex *v) const {
+ if (v == storage)
+ v = storage + nPoints;
+ --v;
+ return v - storage;
+ }
+ int nPoints;
+ int allocated;
+ };
+ Vertices vertices;
+ Intersections intersections;
+ Scanline scanline;
+ bool winding;
+ Q27Dot5 y;
+ int currentVertex;
+
+private:
+ void addIntersection(const Edge *e1, const Edge *e2);
+ bool edgeInChain(Intersection i, int edge);
+};
+
+
+QTessellatorPrivate::Edge::Edge(const QTessellatorPrivate::Vertices &vertices, int edge)
+{
+ this->edge = edge;
+ intersect_left = intersect_right = true;
+ mark = false;
+ free = false;
+
+ v0 = vertices[edge];
+ v1 = vertices.next(v0);
+
+ Q_ASSERT(v0->y != v1->y);
+
+ if (v0->y > v1->y) {
+ qSwap(v0, v1);
+ winding = -1;
+ } else {
+ winding = 1;
+ }
+ y_left = y_right = v0->y;
+}
+
+// This is basically the algorithm from graphics gems. The algorithm
+// is cubic in the coordinates at one place. Since we use 64bit
+// integers, this implies, that the allowed range for our coordinates
+// is limited to 21 bits. With 5 bits behind the decimal, this
+// implies that differences in coordaintes can range from 2*SHORT_MIN
+// to 2*SHORT_MAX, giving us efficiently a coordinate system from
+// SHORT_MIN to SHORT_MAX.
+//
+
+// WARNING: It's absolutely critical that the intersect() and isLeftOf() methods use
+// exactly the same algorithm to calulate yi. It's also important to be sure the algorithms
+// are transitive (ie. the conditions below are true for all input data):
+//
+// a.intersect(b) == b.intersect(a)
+// a.isLeftOf(b) != b.isLeftOf(a)
+//
+// This is tricky to get right, so be very careful when changing anything in here!
+
+static inline bool sameSign(qint64 a, qint64 b) {
+ return (((qint64) ((quint64) a ^ (quint64) b)) >= 0 );
+}
+
+bool QTessellatorPrivate::Edge::intersect(const Edge &other, Q27Dot5 *y, bool *det_positive) const
+{
+ qint64 a1 = v1->y - v0->y;
+ qint64 b1 = v0->x - v1->x;
+
+ qint64 a2 = other.v1->y - other.v0->y;
+ qint64 b2 = other.v0->x - other.v1->x;
+
+ qint64 det = a1 * b2 - a2 * b1;
+ if (det == 0)
+ return false;
+
+ qint64 c1 = qint64(v1->x) * v0->y - qint64(v0->x) * v1->y;
+
+ qint64 r3 = a1 * other.v0->x + b1 * other.v0->y + c1;
+ qint64 r4 = a1 * other.v1->x + b1 * other.v1->y + c1;
+
+ // Check signs of r3 and r4. If both point 3 and point 4 lie on
+ // same side of line 1, the line segments do not intersect.
+ QDEBUG() << " " << r3 << r4;
+ if (r3 != 0 && r4 != 0 && sameSign( r3, r4 ))
+ return false;
+
+ qint64 c2 = qint64(other.v1->x) * other.v0->y - qint64(other.v0->x) * other.v1->y;
+
+ qint64 r1 = a2 * v0->x + b2 * v0->y + c2;
+ qint64 r2 = a2 * v1->x + b2 * v1->y + c2;
+
+ // Check signs of r1 and r2. If both point 1 and point 2 lie
+ // on same side of second line segment, the line segments do not intersect.
+ QDEBUG() << " " << r1 << r2;
+ if (r1 != 0 && r2 != 0 && sameSign( r1, r2 ))
+ return false;
+
+ // The det/2 is to get rounding instead of truncating. It
+ // is added or subtracted to the numerator, depending upon the
+ // sign of the numerator.
+ qint64 offset = det < 0 ? -det : det;
+ offset >>= 1;
+
+ qint64 num = a2 * c1 - a1 * c2;
+ *y = ( num < 0 ? num - offset : num + offset ) / det;
+
+ *det_positive = (det > 0);
+
+ return true;
+}
+
+#undef SAME_SIGNS
+
+bool QTessellatorPrivate::Edge::isLeftOf(const Edge &other, Q27Dot5 y) const
+{
+// QDEBUG() << "isLeftOf" << edge << other.edge << y;
+ qint64 a1 = v1->y - v0->y;
+ qint64 b1 = v0->x - v1->x;
+ qint64 a2 = other.v1->y - other.v0->y;
+ qint64 b2 = other.v0->x - other.v1->x;
+
+ qint64 c2 = qint64(other.v1->x) * other.v0->y - qint64(other.v0->x) * other.v1->y;
+
+ qint64 det = a1 * b2 - a2 * b1;
+ if (det == 0) {
+ // lines are parallel. Only need to check side of one point
+ // fixed ordering for coincident edges
+ qint64 r1 = a2 * v0->x + b2 * v0->y + c2;
+// QDEBUG() << "det = 0" << r1;
+ if (r1 == 0)
+ return edge < other.edge;
+ return (r1 < 0);
+ }
+
+ // not parallel, need to find the y coordinate of the intersection point
+ qint64 c1 = qint64(v1->x) * v0->y - qint64(v0->x) * v1->y;
+
+ qint64 offset = det < 0 ? -det : det;
+ offset >>= 1;
+
+ qint64 num = a2 * c1 - a1 * c2;
+ qint64 yi = ( num < 0 ? num - offset : num + offset ) / det;
+// QDEBUG() << " num=" << num << "offset=" << offset << "det=" << det;
+
+ return ((yi > y) ^ (det < 0));
+}
+
+static inline bool compareVertex(const QTessellatorPrivate::Vertex *p1,
+ const QTessellatorPrivate::Vertex *p2)
+{
+ if (p1->y == p2->y) {
+ if (p1->x == p2->x)
+ return p1 < p2;
+ return p1->x < p2->x;
+ }
+ return p1->y < p2->y;
+}
+
+Q27Dot5 QTessellatorPrivate::Edge::positionAt(Q27Dot5 y) const
+{
+ if (y == v0->y)
+ return v0->x;
+ else if (y == v1->y)
+ return v1->x;
+
+ qint64 d = v1->x - v0->x;
+ return (v0->x + d*(y - v0->y)/(v1->y-v0->y));
+}
+
+bool QTessellatorPrivate::EdgeSorter::operator() (const Edge *e1, const Edge *e2)
+{
+ return e1->isLeftOf(*e2, y);
+}
+
+
+QTessellatorPrivate::Scanline::Scanline()
+{
+ edges = 0;
+ edge_table = 0;
+ old = 0;
+}
+
+void QTessellatorPrivate::Scanline::init(int maxActiveEdges)
+{
+ maxActiveEdges *= 2;
+ if (!edges || maxActiveEdges > default_alloc) {
+ max_edges = maxActiveEdges;
+ int s = qMax(maxActiveEdges + 1, default_alloc + 1);
+ edges = q_check_ptr((Edge **)realloc(edges, s*sizeof(Edge *)));
+ edge_table = q_check_ptr((Edge *)realloc(edge_table, s*sizeof(Edge)));
+ old = q_check_ptr((Edge **)realloc(old, s*sizeof(Edge *)));
+ }
+ size = 0;
+ old_size = 0;
+ first_unused = 0;
+ for (int i = 0; i < maxActiveEdges; ++i)
+ edge_table[i].edge = i+1;
+ edge_table[maxActiveEdges].edge = -1;
+}
+
+void QTessellatorPrivate::Scanline::done()
+{
+ if (max_edges > default_alloc) {
+ free(edges);
+ free(old);
+ free(edge_table);
+ edges = 0;
+ old = 0;
+ edge_table = 0;
+ }
+}
+
+QTessellatorPrivate::Scanline::~Scanline()
+{
+ free(edges);
+ free(old);
+ free(edge_table);
+}
+
+int QTessellatorPrivate::Scanline::findEdgePosition(Q27Dot5 x, Q27Dot5 y) const
+{
+ int min = 0;
+ int max = size - 1;
+ while (min < max) {
+ int pos = min + ((max - min + 1) >> 1);
+ Q27Dot5 ax = edges[pos]->positionAt(y);
+ if (ax > x) {
+ max = pos - 1;
+ } else {
+ min = pos;
+ }
+ }
+ return min;
+}
+
+int QTessellatorPrivate::Scanline::findEdgePosition(const Edge &e) const
+{
+// qDebug() << ">> findEdgePosition";
+ int min = 0;
+ int max = size;
+ while (min < max) {
+ int pos = min + ((max - min) >> 1);
+// qDebug() << " " << min << max << pos << edges[pos]->isLeftOf(e, e.y0);
+ if (edges[pos]->isLeftOf(e, e.v0->y)) {
+ min = pos + 1;
+ } else {
+ max = pos;
+ }
+ }
+// qDebug() << "<< findEdgePosition got" << min;
+ return min;
+}
+
+int QTessellatorPrivate::Scanline::findEdge(int edge) const
+{
+ for (int i = 0; i < size; ++i) {
+ int item_edge = edges[i]->edge;
+ if (item_edge == edge)
+ return i;
+ }
+ //Q_ASSERT(false);
+ return -1;
+}
+
+void QTessellatorPrivate::Scanline::clearMarks()
+{
+ for (int i = 0; i < size; ++i) {
+ edges[i]->mark = false;
+ edges[i]->intersect_left = false;
+ edges[i]->intersect_right = false;
+ }
+}
+
+void QTessellatorPrivate::Scanline::prepareLine()
+{
+ Edge **end = edges + size;
+ Edge **e = edges;
+ Edge **o = old;
+ while (e < end) {
+ *o = *e;
+ ++o;
+ ++e;
+ }
+ old_size = size;
+}
+
+void QTessellatorPrivate::Scanline::lineDone()
+{
+ Edge **end = old + old_size;
+ Edge **e = old;
+ while (e < end) {
+ if ((*e)->free) {
+ (*e)->edge = first_unused;
+ first_unused = (*e - edge_table);
+ }
+ ++e;
+ }
+}
+
+void QTessellatorPrivate::Scanline::insert(int pos, const Edge &e)
+{
+ Edge *edge = edge_table + first_unused;
+ first_unused = edge->edge;
+ Q_ASSERT(first_unused != -1);
+ *edge = e;
+ memmove(edges + pos + 1, edges + pos, (size - pos)*sizeof(Edge *));
+ edges[pos] = edge;
+ ++size;
+}
+
+void QTessellatorPrivate::Scanline::removeAt(int pos)
+{
+ Edge *e = edges[pos];
+ e->free = true;
+ --size;
+ memmove(edges + pos, edges + pos + 1, (size - pos)*sizeof(Edge *));
+}
+
+void QTessellatorPrivate::Scanline::markEdges(int pos1, int pos2)
+{
+ if (pos2 < pos1)
+ return;
+
+ for (int i = pos1; i <= pos2; ++i)
+ edges[i]->mark = true;
+}
+
+
+QTessellatorPrivate::Vertices::Vertices()
+{
+ storage = 0;
+ sorted = 0;
+ allocated = 0;
+ nPoints = 0;
+}
+
+QTessellatorPrivate::Vertices::~Vertices()
+{
+ if (storage) {
+ free(storage);
+ free(sorted);
+ }
+}
+
+void QTessellatorPrivate::Vertices::init(int maxVertices)
+{
+ if (!storage || maxVertices > allocated) {
+ int size = qMax((int)default_alloc, maxVertices);
+ storage = q_check_ptr((Vertex *)realloc(storage, size*sizeof(Vertex)));
+ sorted = q_check_ptr((Vertex **)realloc(sorted, size*sizeof(Vertex *)));
+ allocated = maxVertices;
+ }
+}
+
+void QTessellatorPrivate::Vertices::done()
+{
+ if (allocated > default_alloc) {
+ free(storage);
+ free(sorted);
+ storage = 0;
+ sorted = 0;
+ allocated = 0;
+ }
+}
+
+
+
+static inline void fillTrapezoid(Q27Dot5 y1, Q27Dot5 y2, int left, int right,
+ const QTessellatorPrivate::Vertices &vertices,
+ QTessellator::Trapezoid *trap)
+{
+ trap->top = y1;
+ trap->bottom = y2;
+ const QTessellatorPrivate::Vertex *v = vertices[left];
+ trap->topLeft = v;
+ trap->bottomLeft = vertices.next(v);
+ if (trap->topLeft->y > trap->bottomLeft->y)
+ qSwap(trap->topLeft,trap->bottomLeft);
+ v = vertices[right];
+ trap->topRight = v;
+ trap->bottomRight = vertices.next(v);
+ if (trap->topRight->y > trap->bottomRight->y)
+ qSwap(trap->topRight, trap->bottomRight);
+}
+
+QRectF QTessellatorPrivate::collectAndSortVertices(const QPointF *points, int *maxActiveEdges)
+{
+ *maxActiveEdges = 0;
+ Vertex *v = vertices.storage;
+ Vertex **vv = vertices.sorted;
+
+ qreal xmin(points[0].x());
+ qreal xmax(points[0].x());
+ qreal ymin(points[0].y());
+ qreal ymax(points[0].y());
+
+ // collect vertex data
+ Q27Dot5 y_prev = FloatToQ27Dot5(points[vertices.nPoints-1].y());
+ Q27Dot5 x_next = FloatToQ27Dot5(points[0].x());
+ Q27Dot5 y_next = FloatToQ27Dot5(points[0].y());
+ int j = 0;
+ int i = 0;
+ while (i < vertices.nPoints) {
+ Q27Dot5 y_curr = y_next;
+
+ *vv = v;
+
+ v->x = x_next;
+ v->y = y_next;
+ v->flags = 0;
+
+ next_point:
+
+ xmin = qMin(xmin, points[i+1].x());
+ xmax = qMax(xmax, points[i+1].x());
+ ymin = qMin(ymin, points[i+1].y());
+ ymax = qMax(ymax, points[i+1].y());
+
+ y_next = FloatToQ27Dot5(points[i+1].y());
+ x_next = FloatToQ27Dot5(points[i+1].x());
+
+ // skip vertices on top of each other
+ if (v->x == x_next && v->y == y_next) {
+ ++i;
+ if (i < vertices.nPoints)
+ goto next_point;
+ Vertex *v0 = vertices.storage;
+ v0->flags &= ~(LineBeforeStarts|LineBeforeEnds|LineBeforeHorizontal);
+ if (y_prev < y_curr)
+ v0->flags |= LineBeforeEnds;
+ else if (y_prev > y_curr)
+ v0->flags |= LineBeforeStarts;
+ else
+ v0->flags |= LineBeforeHorizontal;
+ if ((v0->flags & (LineBeforeStarts|LineAfterStarts))
+ && !(v0->flags & (LineAfterEnds|LineBeforeEnds)))
+ *maxActiveEdges += 2;
+ break;
+ }
+
+ if (y_prev < y_curr)
+ v->flags |= LineBeforeEnds;
+ else if (y_prev > y_curr)
+ v->flags |= LineBeforeStarts;
+ else
+ v->flags |= LineBeforeHorizontal;
+
+
+ if (y_curr < y_next)
+ v->flags |= LineAfterStarts;
+ else if (y_curr > y_next)
+ v->flags |= LineAfterEnds;
+ else
+ v->flags |= LineAfterHorizontal;
+ // ### could probably get better limit by looping over sorted list and counting down on ending edges
+ if ((v->flags & (LineBeforeStarts|LineAfterStarts))
+ && !(v->flags & (LineAfterEnds|LineBeforeEnds)))
+ *maxActiveEdges += 2;
+ y_prev = y_curr;
+ ++v;
+ ++vv;
+ ++j;
+ ++i;
+ }
+ vertices.nPoints = j;
+
+ QDEBUG() << "maxActiveEdges=" << *maxActiveEdges;
+ vv = vertices.sorted;
+ std::sort(vv, vv + vertices.nPoints, compareVertex);
+
+ return QRectF(xmin, ymin, xmax-xmin, ymax-ymin);
+}
+
+struct QCoincidingEdge {
+ QTessellatorPrivate::Vertex *start;
+ QTessellatorPrivate::Vertex *end;
+ bool used;
+ bool before;
+
+ inline bool operator<(const QCoincidingEdge &e2) const
+ {
+ return end->y == e2.end->y ? end->x < e2.end->x : end->y < e2.end->y;
+ }
+};
+
+static void cancelEdges(QCoincidingEdge &e1, QCoincidingEdge &e2)
+{
+ if (e1.before) {
+ e1.start->flags &= ~(LineBeforeStarts|LineBeforeHorizontal);
+ e1.end->flags &= ~(LineAfterEnds|LineAfterHorizontal);
+ } else {
+ e1.start->flags &= ~(LineAfterStarts|LineAfterHorizontal);
+ e1.end->flags &= ~(LineBeforeEnds|LineBeforeHorizontal);
+ }
+ if (e2.before) {
+ e2.start->flags &= ~(LineBeforeStarts|LineBeforeHorizontal);
+ e2.end->flags &= ~(LineAfterEnds|LineAfterHorizontal);
+ } else {
+ e2.start->flags &= ~(LineAfterStarts|LineAfterHorizontal);
+ e2.end->flags &= ~(LineBeforeEnds|LineBeforeHorizontal);
+ }
+ e1.used = e2.used = true;
+}
+
+void QTessellatorPrivate::cancelCoincidingEdges()
+{
+ Vertex **vv = vertices.sorted;
+
+ QCoincidingEdge *tl = 0;
+ int tlSize = 0;
+
+ for (int i = 0; i < vertices.nPoints - 1; ++i) {
+ Vertex *v = vv[i];
+ int testListSize = 0;
+ while (i < vertices.nPoints - 1) {
+ Vertex *n = vv[i];
+ if (v->x != n->x || v->y != n->y)
+ break;
+
+ if (testListSize > tlSize - 2) {
+ tlSize = qMax(tlSize*2, 16);
+ tl = q_check_ptr((QCoincidingEdge *)realloc(tl, tlSize*sizeof(QCoincidingEdge)));
+ }
+ if (n->flags & (LineBeforeStarts|LineBeforeHorizontal)) {
+ tl[testListSize].start = n;
+ tl[testListSize].end = vertices.prev(n);
+ tl[testListSize].used = false;
+ tl[testListSize].before = true;
+ ++testListSize;
+ }
+ if (n->flags & (LineAfterStarts|LineAfterHorizontal)) {
+ tl[testListSize].start = n;
+ tl[testListSize].end = vertices.next(n);
+ tl[testListSize].used = false;
+ tl[testListSize].before = false;
+ ++testListSize;
+ }
+ ++i;
+ }
+ if (!testListSize)
+ continue;
+
+ std::sort(tl, tl + testListSize);
+
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_CLANG("-Wfor-loop-analysis")
+ for (int j = 0; j < testListSize; ++j) {
+ if (tl[j].used)
+ continue;
+
+ for (int k = j + 1; k < testListSize; ++k) {
+ if (tl[j].end->x != tl[k].end->x
+ || tl[j].end->y != tl[k].end->y
+ || tl[k].used)
+ break;
+
+ if (!winding || tl[j].before != tl[k].before) {
+ cancelEdges(tl[j], tl[k]);
+ break;
+ }
+ ++k;
+ }
+ ++j;
+ }
+QT_WARNING_POP
+ }
+ free(tl);
+}
+
+
+void QTessellatorPrivate::emitEdges(QTessellator *tessellator)
+{
+ //QDEBUG() << "TRAPS:";
+ if (!scanline.old_size)
+ return;
+
+ // emit edges
+ if (winding) {
+ // winding fill rule
+ int w = 0;
+
+ scanline.old[0]->y_left = y;
+
+ for (int i = 0; i < scanline.old_size - 1; ++i) {
+ Edge *left = scanline.old[i];
+ Edge *right = scanline.old[i+1];
+ w += left->winding;
+// qDebug() << "i=" << i << "edge->winding=" << left->winding << "winding=" << winding;
+ if (w == 0) {
+ left->y_right = y;
+ right->y_left = y;
+ } else if (!emit_clever || left->mark || right->mark) {
+ Q27Dot5 top = qMax(left->y_right, right->y_left);
+ if (top != y) {
+ QTessellator::Trapezoid trap;
+ fillTrapezoid(top, y, left->edge, right->edge, vertices, &trap);
+ tessellator->addTrap(trap);
+// QDEBUG() << " top=" << Q27Dot5ToDouble(top) << "left=" << left->edge << "right=" << right->edge;
+ }
+ right->y_left = y;
+ left->y_right = y;
+ }
+ left->mark = false;
+ }
+ if (scanline.old[scanline.old_size - 1]->mark) {
+ scanline.old[scanline.old_size - 1]->y_right = y;
+ scanline.old[scanline.old_size - 1]->mark = false;
+ }
+ } else {
+ // odd-even fill rule
+ for (int i = 0; i < scanline.old_size; i += 2) {
+ Edge *left = scanline.old[i];
+ Edge *right = scanline.old[i+1];
+ if (!emit_clever || left->mark || right->mark) {
+ Q27Dot5 top = qMax(left->y_right, right->y_left);
+ if (top != y) {
+ QTessellator::Trapezoid trap;
+ fillTrapezoid(top, y, left->edge, right->edge, vertices, &trap);
+ tessellator->addTrap(trap);
+ }
+// QDEBUG() << " top=" << Q27Dot5ToDouble(top) << "left=" << left->edge << "right=" << right->edge;
+ left->y_left = y;
+ left->y_right = y;
+ right->y_left = y;
+ right->y_right = y;
+ left->mark = right->mark = false;
+ }
+ }
+ }
+}
+
+
+void QTessellatorPrivate::processIntersections()
+{
+ QDEBUG() << "PROCESS INTERSECTIONS";
+ // process intersections
+ while (!intersections.isEmpty()) {
+ Intersections::iterator it = intersections.begin();
+ if (it.key().y != y)
+ break;
+
+ // swap edges
+ QDEBUG() << " swapping intersecting edges ";
+ int min = scanline.size;
+ int max = 0;
+ Q27Dot5 xmin = INT_MAX;
+ Q27Dot5 xmax = INT_MIN;
+ int num = 0;
+ while (1) {
+ const Intersection i = it.key();
+ int next = it->next;
+
+ int edgePos = scanline.findEdge(i.edge);
+ if (edgePos >= 0) {
+ ++num;
+ min = qMin(edgePos, min);
+ max = qMax(edgePos, max);
+ Edge *edge = scanline.edges[edgePos];
+ xmin = qMin(xmin, edge->positionAt(y));
+ xmax = qMax(xmax, edge->positionAt(y));
+ }
+ Intersection key;
+ key.y = y;
+ key.edge = next;
+ it = intersections.find(key);
+ intersections.remove(i);
+ if (it == intersections.end())
+ break;
+ }
+ if (num < 2)
+ continue;
+
+ Q_ASSERT(min != max);
+ QDEBUG() << "sorting between" << min << "and" << max << "xpos=" << xmin << xmax;
+ while (min > 0 && scanline.edges[min - 1]->positionAt(y) >= xmin) {
+ QDEBUG() << " adding edge on left";
+ --min;
+ }
+ while (max < scanline.size - 1 && scanline.edges[max + 1]->positionAt(y) <= xmax) {
+ QDEBUG() << " adding edge on right";
+ ++max;
+ }
+
+ std::sort(scanline.edges + min, scanline.edges + max + 1, EdgeSorter(y));
+#ifdef DEBUG
+ for (int i = min; i <= max; ++i)
+ QDEBUG() << " " << scanline.edges[i]->edge << "at pos" << i;
+#endif
+ for (int i = min; i <= max; ++i) {
+ Edge *edge = scanline.edges[i];
+ edge->intersect_left = true;
+ edge->intersect_right = true;
+ edge->mark = true;
+ }
+ }
+}
+
+void QTessellatorPrivate::removeEdges()
+{
+ int cv = currentVertex;
+ while (cv < vertices.nPoints) {
+ const Vertex *v = vertices.sorted[cv];
+ if (v->y > y)
+ break;
+ if (v->flags & LineBeforeEnds) {
+ QDEBUG() << " removing edge" << vertices.prevPos(v);
+ int pos = scanline.findEdge(vertices.prevPos(v));
+ if (pos == -1)
+ continue;
+ scanline.edges[pos]->mark = true;
+ if (pos > 0)
+ scanline.edges[pos - 1]->intersect_right = true;
+ if (pos < scanline.size - 1)
+ scanline.edges[pos + 1]->intersect_left = true;
+ scanline.removeAt(pos);
+ }
+ if (v->flags & LineAfterEnds) {
+ QDEBUG() << " removing edge" << vertices.position(v);
+ int pos = scanline.findEdge(vertices.position(v));
+ if (pos == -1)
+ continue;
+ scanline.edges[pos]->mark = true;
+ if (pos > 0)
+ scanline.edges[pos - 1]->intersect_right = true;
+ if (pos < scanline.size - 1)
+ scanline.edges[pos + 1]->intersect_left = true;
+ scanline.removeAt(pos);
+ }
+ ++cv;
+ }
+}
+
+void QTessellatorPrivate::addEdges()
+{
+ while (currentVertex < vertices.nPoints) {
+ const Vertex *v = vertices.sorted[currentVertex];
+ if (v->y > y)
+ break;
+ if (v->flags & LineBeforeStarts) {
+ // add new edge
+ int start = vertices.prevPos(v);
+ Edge e(vertices, start);
+ int pos = scanline.findEdgePosition(e);
+ QDEBUG() << " adding edge" << start << "at position" << pos;
+ scanline.insert(pos, e);
+ if (!mark_clever || !(v->flags & LineAfterEnds)) {
+ if (pos > 0)
+ scanline.edges[pos - 1]->mark = true;
+ if (pos < scanline.size - 1)
+ scanline.edges[pos + 1]->mark = true;
+ }
+ }
+ if (v->flags & LineAfterStarts) {
+ Edge e(vertices, vertices.position(v));
+ int pos = scanline.findEdgePosition(e);
+ QDEBUG() << " adding edge" << vertices.position(v) << "at position" << pos;
+ scanline.insert(pos, e);
+ if (!mark_clever || !(v->flags & LineBeforeEnds)) {
+ if (pos > 0)
+ scanline.edges[pos - 1]->mark = true;
+ if (pos < scanline.size - 1)
+ scanline.edges[pos + 1]->mark = true;
+ }
+ }
+ if (v->flags & LineAfterHorizontal) {
+ int pos1 = scanline.findEdgePosition(v->x, v->y);
+ const Vertex *next = vertices.next(v);
+ Q_ASSERT(v->y == next->y);
+ int pos2 = scanline.findEdgePosition(next->x, next->y);
+ if (pos2 < pos1)
+ qSwap(pos1, pos2);
+ if (pos1 > 0)
+ --pos1;
+ if (pos2 == scanline.size)
+ --pos2;
+ //QDEBUG() << "marking horizontal edge from " << pos1 << "to" << pos2;
+ scanline.markEdges(pos1, pos2);
+ }
+ ++currentVertex;
+ }
+}
+
+#ifdef DEBUG
+static void checkLinkChain(const QTessellatorPrivate::Intersections &intersections,
+ QTessellatorPrivate::Intersection i)
+{
+// qDebug() << " Link chain: ";
+ int end = i.edge;
+ while (1) {
+ QTessellatorPrivate::IntersectionLink l = intersections.value(i);
+// qDebug() << " " << i.edge << "next=" << l.next << "prev=" << l.prev;
+ if (l.next == end)
+ break;
+ Q_ASSERT(l.next != -1);
+ Q_ASSERT(l.prev != -1);
+
+ QTessellatorPrivate::Intersection i2 = i;
+ i2.edge = l.next;
+ QTessellatorPrivate::IntersectionLink l2 = intersections.value(i2);
+
+ Q_ASSERT(l2.next != -1);
+ Q_ASSERT(l2.prev != -1);
+ Q_ASSERT(l.next == i2.edge);
+ Q_ASSERT(l2.prev == i.edge);
+ i = i2;
+ }
+}
+#endif
+
+bool QTessellatorPrivate::edgeInChain(Intersection i, int edge)
+{
+ int end = i.edge;
+ while (1) {
+ if (i.edge == edge)
+ return true;
+ IntersectionLink l = intersections.value(i);
+ if (l.next == end)
+ break;
+ Q_ASSERT(l.next != -1);
+ Q_ASSERT(l.prev != -1);
+
+ Intersection i2 = i;
+ i2.edge = l.next;
+
+#ifndef QT_NO_DEBUG
+ IntersectionLink l2 = intersections.value(i2);
+ Q_ASSERT(l2.next != -1);
+ Q_ASSERT(l2.prev != -1);
+ Q_ASSERT(l.next == i2.edge);
+ Q_ASSERT(l2.prev == i.edge);
+#endif
+ i = i2;
+ }
+ return false;
+}
+
+
+void QTessellatorPrivate::addIntersection(const Edge *e1, const Edge *e2)
+{
+ const IntersectionLink emptyLink = {-1, -1};
+
+ int next = vertices.nextPos(vertices[e1->edge]);
+ if (e2->edge == next)
+ return;
+ int prev = vertices.prevPos(vertices[e1->edge]);
+ if (e2->edge == prev)
+ return;
+
+ Q27Dot5 yi;
+ bool det_positive;
+ bool isect = e1->intersect(*e2, &yi, &det_positive);
+ QDEBUG("checking edges %d and %d", e1->edge, e2->edge);
+ if (!isect) {
+ QDEBUG() << " no intersection";
+ return;
+ }
+
+ // don't emit an intersection if it's at the start of a line segment or above us
+ if (yi <= y) {
+ if (!det_positive)
+ return;
+ QDEBUG() << " ----->>>>>> WRONG ORDER!";
+ yi = y;
+ }
+ QDEBUG() << " between edges " << e1->edge << "and" << e2->edge << "at point ("
+ << Q27Dot5ToDouble(yi) << ')';
+
+ Intersection i1;
+ i1.y = yi;
+ i1.edge = e1->edge;
+ IntersectionLink link1 = intersections.value(i1, emptyLink);
+ Intersection i2;
+ i2.y = yi;
+ i2.edge = e2->edge;
+ IntersectionLink link2 = intersections.value(i2, emptyLink);
+
+ // new pair of edges
+ if (link1.next == -1 && link2.next == -1) {
+ link1.next = link1.prev = i2.edge;
+ link2.next = link2.prev = i1.edge;
+ } else if (link1.next == i2.edge || link1.prev == i2.edge
+ || link2.next == i1.edge || link2.prev == i1.edge) {
+#ifdef DEBUG
+ checkLinkChain(intersections, i1);
+ checkLinkChain(intersections, i2);
+ Q_ASSERT(edgeInChain(i1, i2.edge));
+#endif
+ return;
+ } else if (link1.next == -1 || link2.next == -1) {
+ if (link2.next == -1) {
+ qSwap(i1, i2);
+ qSwap(link1, link2);
+ }
+ Q_ASSERT(link1.next == -1);
+#ifdef DEBUG
+ checkLinkChain(intersections, i2);
+#endif
+ // only i2 in list
+ link1.next = i2.edge;
+ link1.prev = link2.prev;
+ link2.prev = i1.edge;
+ Intersection other;
+ other.y = yi;
+ other.edge = link1.prev;
+ IntersectionLink link = intersections.value(other, emptyLink);
+ Q_ASSERT(link.next == i2.edge);
+ Q_ASSERT(link.prev != -1);
+ link.next = i1.edge;
+ intersections.insert(other, link);
+ } else {
+ bool connected = edgeInChain(i1, i2.edge);
+ if (connected)
+ return;
+#ifdef DEBUG
+ checkLinkChain(intersections, i1);
+ checkLinkChain(intersections, i2);
+#endif
+ // both already in some list. Have to make sure they are connected
+ // this can be done by cutting open the ring(s) after the two eges and
+ // connecting them again
+ Intersection other1;
+ other1.y = yi;
+ other1.edge = link1.next;
+ IntersectionLink linko1 = intersections.value(other1, emptyLink);
+ Intersection other2;
+ other2.y = yi;
+ other2.edge = link2.next;
+ IntersectionLink linko2 = intersections.value(other2, emptyLink);
+
+ linko1.prev = i2.edge;
+ link2.next = other1.edge;
+
+ linko2.prev = i1.edge;
+ link1.next = other2.edge;
+ intersections.insert(other1, linko1);
+ intersections.insert(other2, linko2);
+ }
+ intersections.insert(i1, link1);
+ intersections.insert(i2, link2);
+#ifdef DEBUG
+ checkLinkChain(intersections, i1);
+ checkLinkChain(intersections, i2);
+ Q_ASSERT(edgeInChain(i1, i2.edge));
+#endif
+ return;
+
+}
+
+
+void QTessellatorPrivate::addIntersections()
+{
+ if (scanline.size) {
+ QDEBUG() << "INTERSECTIONS";
+ // check marked edges for intersections
+#ifdef DEBUG
+ for (int i = 0; i < scanline.size; ++i) {
+ Edge *e = scanline.edges[i];
+ QDEBUG() << " " << i << e->edge << "isect=(" << e->intersect_left << e->intersect_right
+ << ')';
+ }
+#endif
+
+ for (int i = 0; i < scanline.size - 1; ++i) {
+ Edge *e1 = scanline.edges[i];
+ Edge *e2 = scanline.edges[i + 1];
+ // check for intersection
+ if (e1->intersect_right || e2->intersect_left)
+ addIntersection(e1, e2);
+ }
+ }
+#if 0
+ if (intersections.constBegin().key().y == y) {
+ QDEBUG() << "----------------> intersection on same line";
+ scanline.clearMarks();
+ scanline.processIntersections(y, &intersections);
+ goto redo;
+ }
+#endif
+}
+
+
+QTessellator::QTessellator()
+{
+ d = new QTessellatorPrivate;
+}
+
+QTessellator::~QTessellator()
+{
+ delete d;
+}
+
+void QTessellator::setWinding(bool w)
+{
+ d->winding = w;
+}
+
+
+QRectF QTessellator::tessellate(const QPointF *points, int nPoints)
+{
+ Q_ASSERT(points[0] == points[nPoints-1]);
+ --nPoints;
+
+#ifdef DEBUG
+ QDEBUG()<< "POINTS:";
+ for (int i = 0; i < nPoints; ++i) {
+ QDEBUG() << points[i];
+ }
+#endif
+
+ // collect edges and calculate bounds
+ d->vertices.nPoints = nPoints;
+ d->vertices.init(nPoints);
+
+ int maxActiveEdges = 0;
+ QRectF br = d->collectAndSortVertices(points, &maxActiveEdges);
+ d->cancelCoincidingEdges();
+
+#ifdef DEBUG
+ QDEBUG() << "nPoints = " << nPoints << "using " << d->vertices.nPoints;
+ QDEBUG()<< "VERTICES:";
+ for (int i = 0; i < d->vertices.nPoints; ++i) {
+ QDEBUG() << " " << i << ": "
+ << "point=" << d->vertices.position(d->vertices.sorted[i])
+ << "flags=" << d->vertices.sorted[i]->flags
+ << "pos=(" << Q27Dot5ToDouble(d->vertices.sorted[i]->x) << '/'
+ << Q27Dot5ToDouble(d->vertices.sorted[i]->y) << ')';
+ }
+#endif
+
+ d->scanline.init(maxActiveEdges);
+ d->y = INT_MIN/256;
+ d->currentVertex = 0;
+
+ while (d->currentVertex < d->vertices.nPoints) {
+ d->scanline.clearMarks();
+
+ d->y = d->vertices.sorted[d->currentVertex]->y;
+ if (!d->intersections.isEmpty())
+ d->y = qMin(d->y, d->intersections.constBegin().key().y);
+
+ QDEBUG()<< "===== SCANLINE: y =" << Q27Dot5ToDouble(d->y) << " =====";
+
+ d->scanline.prepareLine();
+ d->processIntersections();
+ d->removeEdges();
+ d->addEdges();
+ d->addIntersections();
+ d->emitEdges(this);
+ d->scanline.lineDone();
+
+#ifdef DEBUG
+ QDEBUG()<< "===== edges:";
+ for (int i = 0; i < d->scanline.size; ++i) {
+ QDEBUG() << " " << d->scanline.edges[i]->edge
+ << "p0= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v0->x)
+ << '/' << Q27Dot5ToDouble(d->scanline.edges[i]->v0->y)
+ << ") p1= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v1->x)
+ << '/' << Q27Dot5ToDouble(d->scanline.edges[i]->v1->y) << ')'
+ << "x=" << Q27Dot5ToDouble(d->scanline.edges[i]->positionAt(d->y))
+ << "isLeftOfNext="
+ << ((i < d->scanline.size - 1)
+ ? d->scanline.edges[i]->isLeftOf(*d->scanline.edges[i+1], d->y)
+ : true);
+ }
+#endif
+}
+
+ d->scanline.done();
+ d->intersections.clear();
+ return br;
+}
+
+// tessellates the given convex polygon
+void QTessellator::tessellateConvex(const QPointF *points, int nPoints)
+{
+ Q_ASSERT(points[0] == points[nPoints-1]);
+ --nPoints;
+
+ d->vertices.nPoints = nPoints;
+ d->vertices.init(nPoints);
+
+ for (int i = 0; i < nPoints; ++i) {
+ d->vertices[i]->x = FloatToQ27Dot5(points[i].x());
+ d->vertices[i]->y = FloatToQ27Dot5(points[i].y());
+ }
+
+ int left = 0, right = 0;
+
+ int top = 0;
+ for (int i = 1; i < nPoints; ++i) {
+ if (d->vertices[i]->y < d->vertices[top]->y)
+ top = i;
+ }
+
+ left = (top + nPoints - 1) % nPoints;
+ right = (top + 1) % nPoints;
+
+ while (d->vertices[left]->x == d->vertices[top]->x && d->vertices[left]->y == d->vertices[top]->y && left != right)
+ left = (left + nPoints - 1) % nPoints;
+
+ while (d->vertices[right]->x == d->vertices[top]->x && d->vertices[right]->y == d->vertices[top]->y && left != right)
+ right = (right + 1) % nPoints;
+
+ if (left == right)
+ return;
+
+ int dir = 1;
+
+ Vertex dLeft = { d->vertices[top]->x - d->vertices[left]->x,
+ d->vertices[top]->y - d->vertices[left]->y };
+
+ Vertex dRight = { d->vertices[right]->x - d->vertices[top]->x,
+ d->vertices[right]->y - d->vertices[top]->y };
+
+ Q27Dot5 cross = dLeft.x * dRight.y - dLeft.y * dRight.x;
+
+ // flip direction if polygon is clockwise
+ if (cross < 0 || (cross == 0 && dLeft.x > 0)) {
+ qSwap(left, right);
+ dir = -1;
+ }
+
+ Vertex *lastLeft = d->vertices[top];
+ Vertex *lastRight = d->vertices[top];
+
+ QTessellator::Trapezoid trap;
+
+ while (lastLeft->y == d->vertices[left]->y && left != right) {
+ lastLeft = d->vertices[left];
+ left = (left + nPoints - dir) % nPoints;
+ }
+
+ while (lastRight->y == d->vertices[right]->y && left != right) {
+ lastRight = d->vertices[right];
+ right = (right + nPoints + dir) % nPoints;
+ }
+
+ while (true) {
+ trap.top = qMax(lastRight->y, lastLeft->y);
+ trap.bottom = qMin(d->vertices[left]->y, d->vertices[right]->y);
+ trap.topLeft = lastLeft;
+ trap.topRight = lastRight;
+ trap.bottomLeft = d->vertices[left];
+ trap.bottomRight = d->vertices[right];
+
+ if (trap.bottom > trap.top)
+ addTrap(trap);
+
+ if (left == right)
+ break;
+
+ if (d->vertices[right]->y < d->vertices[left]->y) {
+ do {
+ lastRight = d->vertices[right];
+ right = (right + nPoints + dir) % nPoints;
+ }
+ while (lastRight->y == d->vertices[right]->y && left != right);
+ } else {
+ do {
+ lastLeft = d->vertices[left];
+ left = (left + nPoints - dir) % nPoints;
+ }
+ while (lastLeft->y == d->vertices[left]->y && left != right);
+ }
+ }
+}
+
+// tessellates the stroke of the line from a_ to b_ with the given width and a flat cap
+void QTessellator::tessellateRect(const QPointF &a_, const QPointF &b_, qreal width)
+{
+ Vertex a = { FloatToQ27Dot5(a_.x()), FloatToQ27Dot5(a_.y()) };
+ Vertex b = { FloatToQ27Dot5(b_.x()), FloatToQ27Dot5(b_.y()) };
+
+ QPointF pa = a_, pb = b_;
+
+ if (a.y > b.y) {
+ qSwap(a, b);
+ qSwap(pa, pb);
+ }
+
+ Vertex delta = { b.x - a.x, b.y - a.y };
+
+ if (delta.x == 0 && delta.y == 0)
+ return;
+
+ qreal hw = 0.5 * width;
+
+ if (delta.x == 0) {
+ Q27Dot5 halfWidth = FloatToQ27Dot5(hw);
+
+ if (halfWidth == 0)
+ return;
+
+ Vertex topLeft = { a.x - halfWidth, a.y };
+ Vertex topRight = { a.x + halfWidth, a.y };
+ Vertex bottomLeft = { a.x - halfWidth, b.y };
+ Vertex bottomRight = { a.x + halfWidth, b.y };
+
+ QTessellator::Trapezoid trap = { topLeft.y, bottomLeft.y, &topLeft, &bottomLeft, &topRight, &bottomRight };
+ addTrap(trap);
+ } else if (delta.y == 0) {
+ Q27Dot5 halfWidth = FloatToQ27Dot5(hw);
+
+ if (halfWidth == 0)
+ return;
+
+ if (a.x > b.x)
+ qSwap(a.x, b.x);
+
+ Vertex topLeft = { a.x, a.y - halfWidth };
+ Vertex topRight = { b.x, a.y - halfWidth };
+ Vertex bottomLeft = { a.x, a.y + halfWidth };
+ Vertex bottomRight = { b.x, a.y + halfWidth };
+
+ QTessellator::Trapezoid trap = { topLeft.y, bottomLeft.y, &topLeft, &bottomLeft, &topRight, &bottomRight };
+ addTrap(trap);
+ } else {
+ QPointF perp(pb.y() - pa.y(), pa.x() - pb.x());
+ qreal length = qSqrt(perp.x() * perp.x() + perp.y() * perp.y());
+
+ if (qFuzzyIsNull(length))
+ return;
+
+ // need the half of the width
+ perp *= hw / length;
+
+ QPointF pta = pa + perp;
+ QPointF ptb = pa - perp;
+ QPointF ptc = pb - perp;
+ QPointF ptd = pb + perp;
+
+ Vertex ta = { FloatToQ27Dot5(pta.x()), FloatToQ27Dot5(pta.y()) };
+ Vertex tb = { FloatToQ27Dot5(ptb.x()), FloatToQ27Dot5(ptb.y()) };
+ Vertex tc = { FloatToQ27Dot5(ptc.x()), FloatToQ27Dot5(ptc.y()) };
+ Vertex td = { FloatToQ27Dot5(ptd.x()), FloatToQ27Dot5(ptd.y()) };
+
+ if (ta.y < tb.y) {
+ if (tb.y < td.y) {
+ QTessellator::Trapezoid top = { ta.y, tb.y, &ta, &tb, &ta, &td };
+ QTessellator::Trapezoid bottom = { td.y, tc.y, &tb, &tc, &td, &tc };
+ addTrap(top);
+ addTrap(bottom);
+
+ QTessellator::Trapezoid middle = { tb.y, td.y, &tb, &tc, &ta, &td };
+ addTrap(middle);
+ } else {
+ QTessellator::Trapezoid top = { ta.y, td.y, &ta, &tb, &ta, &td };
+ QTessellator::Trapezoid bottom = { tb.y, tc.y, &tb, &tc, &td, &tc };
+ addTrap(top);
+ addTrap(bottom);
+
+ if (tb.y != td.y) {
+ QTessellator::Trapezoid middle = { td.y, tb.y, &ta, &tb, &td, &tc };
+ addTrap(middle);
+ }
+ }
+ } else {
+ if (ta.y < tc.y) {
+ QTessellator::Trapezoid top = { tb.y, ta.y, &tb, &tc, &tb, &ta };
+ QTessellator::Trapezoid bottom = { tc.y, td.y, &tc, &td, &ta, &td };
+ addTrap(top);
+ addTrap(bottom);
+
+ QTessellator::Trapezoid middle = { ta.y, tc.y, &tb, &tc, &ta, &td };
+ addTrap(middle);
+ } else {
+ QTessellator::Trapezoid top = { tb.y, tc.y, &tb, &tc, &tb, &ta };
+ QTessellator::Trapezoid bottom = { ta.y, td.y, &tc, &td, &ta, &td };
+ addTrap(top);
+ addTrap(bottom);
+
+ if (ta.y != tc.y) {
+ QTessellator::Trapezoid middle = { tc.y, ta.y, &tc, &td, &tb, &ta };
+ addTrap(middle);
+ }
+ }
+ }
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qtessellator_p.h b/src/plugins/platforms/xcb/nativepainting/qtessellator_p.h
new file mode 100644
index 0000000000..65ae6bdc41
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qtessellator_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESSELATOR_P_H
+#define QTESSELATOR_P_H
+
+#include <QPoint>
+#include <QRect>
+
+QT_BEGIN_NAMESPACE
+
+class QTessellatorPrivate;
+
+typedef int Q27Dot5;
+#define Q27Dot5ToDouble(i) ((i)/32.)
+#define FloatToQ27Dot5(i) (int)((i) * 32)
+#define IntToQ27Dot5(i) ((i) << 5)
+#define Q27Dot5ToXFixed(i) ((i) << 11)
+#define Q27Dot5Factor 32
+
+class QTessellator {
+public:
+ QTessellator();
+ virtual ~QTessellator();
+
+ QRectF tessellate(const QPointF *points, int nPoints);
+ void tessellateConvex(const QPointF *points, int nPoints);
+ void tessellateRect(const QPointF &a, const QPointF &b, qreal width);
+
+ void setWinding(bool w);
+
+ struct Vertex {
+ Q27Dot5 x;
+ Q27Dot5 y;
+ };
+ struct Trapezoid {
+ Q27Dot5 top;
+ Q27Dot5 bottom;
+ const Vertex *topLeft;
+ const Vertex *bottomLeft;
+ const Vertex *topRight;
+ const Vertex *bottomRight;
+ };
+ virtual void addTrap(const Trapezoid &trap) = 0;
+
+private:
+ friend class QTessellatorPrivate;
+ QTessellatorPrivate *d;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp
new file mode 100644
index 0000000000..ccb421d868
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxcbconnection.h"
+#include "qcolormap_x11_p.h"
+#include "qxcbnativepainting.h"
+#include "qt_x11_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QXcbX11Data *qt_x11Data = Q_NULLPTR;
+
+void qt_xcb_native_x11_info_init(QXcbConnection *conn)
+{
+ qt_x11Data = new QXcbX11Data;
+ X11->display = static_cast<Display *>(conn->xlib_display());
+ X11->defaultScreen = DefaultScreen(X11->display);
+ X11->screenCount = ScreenCount(X11->display);
+
+ X11->screens = new QX11InfoData[X11->screenCount];
+ X11->argbVisuals = new Visual *[X11->screenCount];
+ X11->argbColormaps = new Colormap[X11->screenCount];
+
+ for (int s = 0; s < X11->screenCount; s++) {
+ QX11InfoData *screen = X11->screens + s;
+ //screen->ref = 1; // ensures it doesn't get deleted
+ screen->screen = s;
+
+ int widthMM = DisplayWidthMM(X11->display, s);
+ if (widthMM != 0) {
+ screen->dpiX = (DisplayWidth(X11->display, s) * 254 + widthMM * 5) / (widthMM * 10);
+ } else {
+ screen->dpiX = 72;
+ }
+
+ int heightMM = DisplayHeightMM(X11->display, s);
+ if (heightMM != 0) {
+ screen->dpiY = (DisplayHeight(X11->display, s) * 254 + heightMM * 5) / (heightMM * 10);
+ } else {
+ screen->dpiY = 72;
+ }
+
+ X11->argbVisuals[s] = 0;
+ X11->argbColormaps[s] = 0;
+ }
+
+ X11->use_xrender = conn->hasXRender() && !qEnvironmentVariableIsSet("QT_XCB_NATIVE_PAINTING_NO_XRENDER");
+
+#if QT_CONFIG(xrender)
+ memset(X11->solid_fills, 0, sizeof(X11->solid_fills));
+ for (int i = 0; i < X11->solid_fill_count; ++i)
+ X11->solid_fills[i].screen = -1;
+ memset(X11->pattern_fills, 0, sizeof(X11->pattern_fills));
+ for (int i = 0; i < X11->pattern_fill_count; ++i)
+ X11->pattern_fills[i].screen = -1;
+#endif
+
+ QXcbColormap::initialize();
+
+#if QT_CONFIG(xrender)
+ if (X11->use_xrender) {
+ // XRender is supported, let's see if we have a PictFormat for the
+ // default visual
+ XRenderPictFormat *format =
+ XRenderFindVisualFormat(X11->display,
+ (Visual *) QXcbX11Info::appVisual(X11->defaultScreen));
+
+ if (!format) {
+ X11->use_xrender = false;
+ }
+ }
+#endif // QT_CONFIG(xrender)
+}
+
+QVector<XRectangle> qt_region_to_xrectangles(const QRegion &r)
+{
+ const int numRects = r.rectCount();
+ const QVector<QRect> input = r.rects();
+ QVector<XRectangle> output(numRects);
+ for (int i = 0; i < numRects; ++i) {
+ const QRect &in = input[i];
+ XRectangle &out = output[i];
+ out.x = qMax(SHRT_MIN, in.x());
+ out.y = qMax(SHRT_MIN, in.y());
+ out.width = qMin((int)USHRT_MAX, in.width());
+ out.height = qMin((int)USHRT_MAX, in.height());
+ }
+ return output;
+}
+
+class QXcbX11InfoData : public QSharedData, public QX11InfoData
+{};
+
+QXcbX11Info::QXcbX11Info()
+ : d(Q_NULLPTR)
+{}
+
+QXcbX11Info::~QXcbX11Info()
+{}
+
+QXcbX11Info::QXcbX11Info(const QXcbX11Info &other)
+ : d(other.d)
+{}
+
+QXcbX11Info &QXcbX11Info::operator=(const QXcbX11Info &other)
+{
+ d = other.d;
+ return *this;
+}
+
+QXcbX11Info QXcbX11Info::fromScreen(int screen)
+{
+ QXcbX11InfoData *xd = new QXcbX11InfoData;
+ xd->screen = screen;
+ xd->depth = QXcbX11Info::appDepth(screen);
+ xd->cells = QXcbX11Info::appCells(screen);
+ xd->colormap = QXcbX11Info::appColormap(screen);
+ xd->defaultColormap = QXcbX11Info::appDefaultColormap(screen);
+ xd->visual = (Visual *)QXcbX11Info::appVisual(screen);
+ xd->defaultVisual = QXcbX11Info::appDefaultVisual(screen);
+
+ QXcbX11Info info;
+ info.d = xd;
+ return info;
+}
+
+void QXcbX11Info::setDepth(int depth)
+{
+ if (!d)
+ *this = fromScreen(appScreen());
+
+ d->depth = depth;
+}
+
+Display *QXcbX11Info::display()
+{
+ return X11 ? X11->display : 0;
+}
+
+int QXcbX11Info::screen() const
+{
+ return d ? d->screen : QXcbX11Info::appScreen();
+}
+
+int QXcbX11Info::depth() const
+{
+ return d ? d->depth : QXcbX11Info::appDepth();
+}
+
+Colormap QXcbX11Info::colormap() const
+{
+ return d ? d->colormap : QXcbX11Info::appColormap();
+}
+
+void *QXcbX11Info::visual() const
+{
+ return d ? d->visual : QXcbX11Info::appVisual();
+}
+
+void QXcbX11Info::setVisual(void *visual)
+{
+ if (!d)
+ *this = fromScreen(appScreen());
+
+ d->visual = (Visual *) visual;
+}
+
+int QXcbX11Info::appScreen()
+{
+ return X11 ? X11->defaultScreen : 0;
+}
+
+int QXcbX11Info::appDepth(int screen)
+{
+ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].depth : 32;
+}
+
+int QXcbX11Info::appCells(int screen)
+{
+ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].cells : 0;
+}
+
+Colormap QXcbX11Info::appColormap(int screen)
+{
+ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].colormap : 0;
+}
+
+void *QXcbX11Info::appVisual(int screen)
+{
+ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].visual : 0;
+}
+
+Window QXcbX11Info::appRootWindow(int screen)
+{
+ return X11 ? RootWindow(X11->display, screen == -1 ? X11->defaultScreen : screen) : 0;
+}
+
+bool QXcbX11Info::appDefaultColormap(int screen)
+{
+ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].defaultColormap : true;
+}
+
+bool QXcbX11Info::appDefaultVisual(int screen)
+{
+ return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].defaultVisual : true;
+}
+
+int QXcbX11Info::appDpiX(int screen)
+{
+ if (!X11)
+ return 75;
+ if (screen < 0)
+ screen = X11->defaultScreen;
+ if (screen > X11->screenCount)
+ return 0;
+ return X11->screens[screen].dpiX;
+}
+
+int QXcbX11Info::appDpiY(int screen)
+{
+ if (!X11)
+ return 75;
+ if (screen < 0)
+ screen = X11->defaultScreen;
+ if (screen > X11->screenCount)
+ return 0;
+ return X11->screens[screen].dpiY;
+}
+
+#if QT_CONFIG(xrender)
+Picture QXcbX11Data::getSolidFill(int screen, const QColor &c)
+{
+ if (!X11->use_xrender)
+ return XNone;
+
+ XRenderColor color = preMultiply(c);
+ for (int i = 0; i < X11->solid_fill_count; ++i) {
+ if (X11->solid_fills[i].screen == screen
+ && X11->solid_fills[i].color.alpha == color.alpha
+ && X11->solid_fills[i].color.red == color.red
+ && X11->solid_fills[i].color.green == color.green
+ && X11->solid_fills[i].color.blue == color.blue)
+ return X11->solid_fills[i].picture;
+ }
+ // none found, replace one
+ int i = qrand() % 16;
+
+ if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) {
+ XRenderFreePicture (X11->display, X11->solid_fills[i].picture);
+ X11->solid_fills[i].picture = 0;
+ }
+
+ if (!X11->solid_fills[i].picture) {
+ Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 1, 1, 32);
+ XRenderPictureAttributes attrs;
+ attrs.repeat = True;
+ X11->solid_fills[i].picture = XRenderCreatePicture (X11->display, pixmap,
+ XRenderFindStandardFormat(X11->display, PictStandardARGB32),
+ CPRepeat, &attrs);
+ XFreePixmap (X11->display, pixmap);
+ }
+
+ X11->solid_fills[i].color = color;
+ X11->solid_fills[i].screen = screen;
+ XRenderFillRectangle (X11->display, PictOpSrc, X11->solid_fills[i].picture, &color, 0, 0, 1, 1);
+ return X11->solid_fills[i].picture;
+}
+
+XRenderColor QXcbX11Data::preMultiply(const QColor &c)
+{
+ XRenderColor color;
+ const uint A = c.alpha(),
+ R = c.red(),
+ G = c.green(),
+ B = c.blue();
+ color.alpha = (A | A << 8);
+ color.red = (R | R << 8) * color.alpha / 0x10000;
+ color.green = (G | G << 8) * color.alpha / 0x10000;
+ color.blue = (B | B << 8) * color.alpha / 0x10000;
+ return color;
+}
+#endif // QT_CONFIG(xrender)
+
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.h b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.h
new file mode 100644
index 0000000000..f3011286c9
--- /dev/null
+++ b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXCBNATIVEPAINTING_H
+#define QXCBNATIVEPAINTING_H
+
+#include <QSharedDataPointer>
+#include "qt_x11_p.h"
+
+typedef struct _FcPattern FcPattern;
+typedef unsigned long XID;
+typedef XID Colormap;
+typedef XID Window;
+typedef struct _XDisplay Display;
+
+QT_BEGIN_NAMESPACE
+
+class QXcbConnection;
+class QPixmap;
+
+void qt_xcb_native_x11_info_init(QXcbConnection *conn);
+QVector<XRectangle> qt_region_to_xrectangles(const QRegion &r);
+
+class QXcbX11InfoData;
+class QXcbX11Info
+{
+public:
+ QXcbX11Info();
+ ~QXcbX11Info();
+ QXcbX11Info(const QXcbX11Info &other);
+ QXcbX11Info &operator=(const QXcbX11Info &other);
+
+ static QXcbX11Info fromScreen(int screen);
+ static Display *display();
+
+ int depth() const;
+ void setDepth(int depth);
+
+ int screen() const;
+ Colormap colormap() const;
+
+ void *visual() const;
+ void setVisual(void *visual);
+
+ static int appScreen();
+ static int appDepth(int screen = -1);
+ static int appCells(int screen = -1);
+ static Colormap appColormap(int screen = -1);
+ static void *appVisual(int screen = -1);
+ static Window appRootWindow(int screen = -1);
+ static bool appDefaultColormap(int screen = -1);
+ static bool appDefaultVisual(int screen = -1);
+ static int appDpiX(int screen = -1);
+ static int appDpiY(int screen = -1);
+
+private:
+ QSharedDataPointer<QXcbX11InfoData> d;
+
+ friend class QX11PaintEngine;
+ friend class QX11PlatformPixmap;
+ friend void qt_x11SetScreen(QPixmap &pixmap, int screen);
+};
+
+QT_END_NAMESPACE
+
+#endif // QXCBNATIVEPAINTING_H
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index a419caf0fc..17927af3e3 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -150,8 +150,6 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
, m_gc_drawable(0)
, m_xcb_pixmap(0)
{
- Q_XCB_NOOP(connection());
-
const xcb_format_t *fmt = connection()->formatForDepth(depth);
Q_ASSERT(fmt);
@@ -206,11 +204,11 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI
if (!hasShm()) {
m_xcb_pixmap = xcb_generate_id(xcb_connection());
- Q_XCB_CALL(xcb_create_pixmap(xcb_connection(),
- m_xcb_image->depth,
- m_xcb_pixmap,
- screen->screen()->root,
- m_xcb_image->width, m_xcb_image->height));
+ xcb_create_pixmap(xcb_connection(),
+ m_xcb_image->depth,
+ m_xcb_pixmap,
+ screen->screen()->root,
+ m_xcb_image->width, m_xcb_image->height);
}
}
@@ -234,13 +232,13 @@ bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy)
const QRect bounds(QPoint(0, 0), size());
for (const QRect &src : area) {
const QRect dst = src.translated(delta).intersected(bounds);
- Q_XCB_CALL(xcb_copy_area(xcb_connection(),
- m_xcb_pixmap,
- m_xcb_pixmap,
- m_gc,
- src.x(), src.y(),
- dst.x(), dst.y(),
- dst.width(), dst.height()));
+ xcb_copy_area(xcb_connection(),
+ m_xcb_pixmap,
+ m_xcb_pixmap,
+ m_gc,
+ src.x(), src.y(),
+ dst.x(), dst.y(),
+ dst.width(), dst.height());
}
}
@@ -251,7 +249,7 @@ void QXcbShmImage::destroy()
{
const int segmentSize = m_xcb_image ? (m_xcb_image->stride * m_xcb_image->height) : 0;
if (segmentSize && m_shm_info.shmaddr)
- Q_XCB_CALL(xcb_shm_detach(xcb_connection(), m_shm_info.shmseg));
+ xcb_shm_detach(xcb_connection(), m_shm_info.shmseg);
if (segmentSize) {
if (m_shm_info.shmaddr) {
@@ -265,12 +263,12 @@ void QXcbShmImage::destroy()
xcb_image_destroy(m_xcb_image);
if (m_gc)
- Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
+ xcb_free_gc(xcb_connection(), m_gc);
delete m_graphics_buffer;
m_graphics_buffer = Q_NULLPTR;
if (m_xcb_pixmap) {
- Q_XCB_CALL(xcb_free_pixmap(xcb_connection(), m_xcb_pixmap));
+ xcb_free_pixmap(xcb_connection(), m_xcb_pixmap);
m_xcb_pixmap = 0;
}
}
@@ -279,13 +277,13 @@ void QXcbShmImage::ensureGC(xcb_drawable_t dst)
{
if (m_gc_drawable != dst) {
if (m_gc)
- Q_XCB_CALL(xcb_free_gc(xcb_connection(), m_gc));
+ xcb_free_gc(xcb_connection(), m_gc);
static const uint32_t mask = XCB_GC_GRAPHICS_EXPOSURES;
static const uint32_t values[] = { 0 };
m_gc = xcb_generate_id(xcb_connection());
- Q_XCB_CALL(xcb_create_gc(xcb_connection(), m_gc, dst, mask, values));
+ xcb_create_gc(xcb_connection(), m_gc, dst, mask, values);
m_gc_drawable = dst;
}
@@ -425,10 +423,7 @@ void QXcbShmImage::setClip(const QRegion &region)
if (region.isEmpty()) {
static const uint32_t mask = XCB_GC_CLIP_MASK;
static const uint32_t values[] = { XCB_NONE };
- Q_XCB_CALL(xcb_change_gc(xcb_connection(),
- m_gc,
- mask,
- values));
+ xcb_change_gc(xcb_connection(), m_gc, mask, values);
} else {
const QVector<QRect> qrects = region.rects();
QVector<xcb_rectangle_t> xcb_rects(qrects.size());
@@ -440,18 +435,16 @@ void QXcbShmImage::setClip(const QRegion &region)
xcb_rects[i].height = qrects[i].height();
}
- Q_XCB_CALL(xcb_set_clip_rectangles(xcb_connection(),
- XCB_CLIP_ORDERING_YX_BANDED,
- m_gc,
- 0, 0,
- xcb_rects.size(), xcb_rects.constData()));
+ xcb_set_clip_rectangles(xcb_connection(),
+ XCB_CLIP_ORDERING_YX_BANDED,
+ m_gc,
+ 0, 0,
+ xcb_rects.size(), xcb_rects.constData());
}
}
void QXcbShmImage::put(xcb_drawable_t dst, const QRegion &region, const QPoint &offset)
{
- Q_XCB_NOOP(connection());
-
ensureGC(dst);
setClip(region);
@@ -460,33 +453,32 @@ void QXcbShmImage::put(xcb_drawable_t dst, const QRegion &region, const QPoint &
const QRect source = bounds.translated(offset);
if (hasShm()) {
- Q_XCB_CALL(xcb_shm_put_image(xcb_connection(),
- dst,
- m_gc,
- m_xcb_image->width,
- m_xcb_image->height,
- source.x(), source.y(),
- source.width(), source.height(),
- target.x(), target.y(),
- m_xcb_image->depth,
- m_xcb_image->format,
- 0, // send event?
- m_shm_info.shmseg,
- m_xcb_image->data - m_shm_info.shmaddr));
+ xcb_shm_put_image(xcb_connection(),
+ dst,
+ m_gc,
+ m_xcb_image->width,
+ m_xcb_image->height,
+ source.x(), source.y(),
+ source.width(), source.height(),
+ target.x(), target.y(),
+ m_xcb_image->depth,
+ m_xcb_image->format,
+ 0, // send event?
+ m_shm_info.shmseg,
+ m_xcb_image->data - m_shm_info.shmaddr);
m_dirtyShm |= region.translated(offset);
} else {
flushPixmap(region);
- Q_XCB_CALL(xcb_copy_area(xcb_connection(),
- m_xcb_pixmap,
- dst,
- m_gc,
- source.x(), source.y(),
- target.x(), target.y(),
- source.width(), source.height()));
+ xcb_copy_area(xcb_connection(),
+ m_xcb_pixmap,
+ dst,
+ m_gc,
+ source.x(), source.y(),
+ target.x(), target.y(),
+ source.width(), source.height());
}
setClip(QRegion());
- Q_XCB_NOOP(connection());
}
void QXcbShmImage::preparePaint(const QRegion &region)
@@ -592,8 +584,6 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
if (bounds.isNull())
return;
- Q_XCB_NOOP(connection());
-
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
if (!platformWindow) {
qWarning("QXcbBackingStore::flush: QWindow has no platform window (QTBUG-32681)");
@@ -602,8 +592,6 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
m_image->put(platformWindow->xcb_window(), clipped, offset);
- Q_XCB_NOOP(connection());
-
if (platformWindow->needsSync())
platformWindow->updateSyncRequestCounter();
else
@@ -617,8 +605,6 @@ void QXcbBackingStore::composeAndFlush(QWindow *window, const QRegion &region, c
{
QPlatformBackingStore::composeAndFlush(window, region, offset, textures, context, translucentBackground);
- Q_XCB_NOOP(connection());
-
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
if (platformWindow->needsSync()) {
platformWindow->updateSyncRequestCounter();
@@ -632,7 +618,6 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &)
{
if (m_image && size == m_image->size())
return;
- Q_XCB_NOOP(connection());
QXcbScreen *screen = static_cast<QXcbScreen *>(window()->screen()->handle());
QPlatformWindow *pw = window()->handle();
@@ -649,7 +634,6 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &)
if (win->imageNeedsRgbSwap()) {
m_rgbImage = QImage(size, win->imageFormat());
}
- Q_XCB_NOOP(connection());
}
bool QXcbBackingStore::scroll(const QRegion &area, int dx, int dy)
diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp
index 01b3bca0d2..30ab669432 100644
--- a/src/plugins/platforms/xcb/qxcbclipboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp
@@ -278,22 +278,22 @@ QXcbClipboard::QXcbClipboard(QXcbConnection *c)
#ifndef QT_NO_DEBUG
QByteArray ba("Qt clipboard window");
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_owner,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData()));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_owner,
+ atom(QXcbAtom::_NET_WM_NAME),
+ atom(QXcbAtom::UTF8_STRING),
+ 8,
+ ba.length(),
+ ba.constData());
#endif
if (connection()->hasXFixes()) {
const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE;
- Q_XCB_CALL(xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, XCB_ATOM_PRIMARY, mask));
- Q_XCB_CALL(xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, atom(QXcbAtom::CLIPBOARD), mask));
+ xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, XCB_ATOM_PRIMARY, mask);
+ xcb_xfixes_select_selection_input_checked(xcb_connection(), m_owner, atom(QXcbAtom::CLIPBOARD), mask);
}
}
@@ -305,8 +305,7 @@ QXcbClipboard::~QXcbClipboard()
m_timestamp[QClipboard::Selection] != XCB_CURRENT_TIME) {
// First we check if there is a clipboard manager.
- xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER));
- xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(xcb_connection(), cookie, 0);
+ auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER));
if (reply && reply->owner != XCB_NONE) {
// we delete the property so the manager saves all TARGETS.
xcb_delete_property(xcb_connection(), m_owner, atom(QXcbAtom::_QT_SELECTION));
@@ -320,7 +319,6 @@ QXcbClipboard::~QXcbClipboard()
"clipboard manager in a reasonable time");
}
}
- free(reply);
}
if (m_clientClipboard[QClipboard::Clipboard] != m_clientClipboard[QClipboard::Selection])
@@ -459,26 +457,26 @@ xcb_window_t QXcbClipboard::requestor() const
QXcbClipboard *that = const_cast<QXcbClipboard *>(this);
xcb_window_t window = xcb_generate_id(xcb_connection());
- Q_XCB_CALL(xcb_create_window(xcb_connection(),
- XCB_COPY_FROM_PARENT, // depth -- same as root
- window, // window id
- platformScreen->screen()->root, // parent window id
- x, y, w, h,
- 0, // border width
- XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
- platformScreen->screen()->root_visual, // visual
- 0, // value mask
- 0)); // value list
+ xcb_create_window(xcb_connection(),
+ XCB_COPY_FROM_PARENT, // depth -- same as root
+ window, // window id
+ platformScreen->screen()->root, // parent window id
+ x, y, w, h,
+ 0, // border width
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
+ platformScreen->screen()->root_visual, // visual
+ 0, // value mask
+ 0); // value list
#ifndef QT_NO_DEBUG
QByteArray ba("Qt clipboard requestor window");
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- window,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData()));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ window,
+ atom(QXcbAtom::_NET_WM_NAME),
+ atom(QXcbAtom::UTF8_STRING),
+ 8,
+ ba.length(),
+ ba.constData());
#endif
uint32_t mask = XCB_EVENT_MASK_PROPERTY_CHANGE;
@@ -759,17 +757,14 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
format = &dummy_format;
// Don't read anything, just get the size of the property data
- xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, 0, 0));
- xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);
+ auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
if (!reply || reply->type == XCB_NONE) {
- free(reply);
buffer->resize(0);
return false;
}
*type = reply->type;
*format = reply->format;
bytes_left = reply->bytes_after;
- free(reply);
int offset = 0, buffer_offset = 0;
@@ -784,17 +779,15 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
while (bytes_left) {
// more to read...
- xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, offset, maxsize/4));
- reply = xcb_get_property_reply(xcb_connection(), cookie, 0);
- if (!reply || reply->type == XCB_NONE) {
- free(reply);
+ reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, win, property, XCB_GET_PROPERTY_TYPE_ANY, offset, maxsize/4);
+ if (!reply || reply->type == XCB_NONE)
break;
- }
+
*type = reply->type;
*format = reply->format;
bytes_left = reply->bytes_after;
- char *data = (char *)xcb_get_property_value(reply);
- int length = xcb_get_property_value_length(reply);
+ char *data = (char *)xcb_get_property_value(reply.get());
+ int length = xcb_get_property_value_length(reply.get());
// Here we check if we get a buffer overflow and tries to
// recover -- this shouldn't normally happen, but it doesn't
@@ -814,7 +807,6 @@ bool QXcbClipboard::clipboardReadProperty(xcb_window_t win, xcb_atom_t property,
// offset is specified in 32-bit multiples
offset += length / 4;
}
- free(reply);
}
}
@@ -891,13 +883,9 @@ xcb_generic_event_t *QXcbClipboard::waitForClipboardEvent(xcb_window_t win, int
return e;
if (checkManager) {
- xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER));
- xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(xcb_connection(), cookie, 0);
- if (!reply || reply->owner == XCB_NONE) {
- free(reply);
+ auto reply = Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom(QXcbAtom::CLIPBOARD_MANAGER));
+ if (!reply || reply->owner == XCB_NONE)
return 0;
- }
- free(reply);
}
// process other clipboard events, since someone is probably requesting data from us
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index e167ba1231..1671bdabb2 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -148,8 +148,18 @@ static const char * const xcbConnectionErrors[] = {
"Error during FD passing" /* XCB_CONN_CLOSED_FDPASSING_FAILED */
};
-static int nullErrorHandler(Display *, XErrorEvent *)
+static int nullErrorHandler(Display *dpy, XErrorEvent *err)
{
+#ifndef Q_XCB_DEBUG
+ Q_UNUSED(dpy);
+ Q_UNUSED(err);
+#else
+ const int buflen = 1024;
+ char buf[buflen];
+
+ XGetErrorText(dpy, err->error_code, buf, buflen);
+ fprintf(stderr, "X Error: serial %lu error %d %s\n", err->serial, (int) err->error_code, buf);
+#endif
return 0;
}
@@ -243,11 +253,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
} else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) {
// New XRandR output is available and it's enabled
if (output.crtc != XCB_NONE && output.mode != XCB_NONE) {
- xcb_randr_get_output_info_cookie_t outputInfoCookie =
- xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp);
- QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
- xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
-
+ auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(),
+ output.output, output.config_timestamp);
// Find a fake screen
const auto scrs = virtualDesktop->screens();
for (QPlatformScreen *scr : scrs) {
@@ -261,12 +268,12 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
if (screen) {
QString nameWas = screen->name();
// Transform the fake screen into a physical screen
- screen->setOutput(output.output, outputInfo.data());
+ screen->setOutput(output.output, outputInfo.get());
updateScreen(screen, output);
qCDebug(lcQpaScreen) << "output" << screen->name()
<< "is connected and enabled; was fake:" << nameWas;
} else {
- screen = createScreen(virtualDesktop, output, outputInfo.data());
+ screen = createScreen(virtualDesktop, output, outputInfo.get());
qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
}
QHighDpiScaling::updateHighDpiScaling();
@@ -274,10 +281,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
} else if (screen) {
if (output.crtc == XCB_NONE && output.mode == XCB_NONE) {
// Screen has been disabled
- xcb_randr_get_output_info_cookie_t outputInfoCookie =
- xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp);
- QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
- xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
+ auto outputInfo = Q_XCB_REPLY(xcb_randr_get_output_info, xcb_connection(),
+ output.output, output.config_timestamp);
if (outputInfo->crtc == XCB_NONE) {
qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled";
destroyScreen(screen);
@@ -299,16 +304,10 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
{
- xcb_generic_error_t *error = 0;
- xcb_randr_get_output_primary_cookie_t primaryCookie =
- xcb_randr_get_output_primary(xcb_connection(), rootWindow);
- QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary (
- xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
- if (!primary || error) {
+ auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, xcb_connection(), rootWindow);
+ if (!primary)
qWarning("failed to get the primary output of the screen");
- free(error);
- error = NULL;
- }
+
const bool isPrimary = primary ? (primary->output == output) : false;
return isPrimary;
@@ -404,72 +403,59 @@ void QXcbConnection::initializeScreens()
m_virtualDesktops.append(virtualDesktop);
QList<QPlatformScreen *> siblings;
if (has_randr_extension) {
- xcb_generic_error_t *error = NULL;
// RRGetScreenResourcesCurrent is fast but it may return nothing if the
// configuration is not initialized wrt to the hardware. We should call
// RRGetScreenResources in this case.
- QScopedPointer<xcb_randr_get_screen_resources_reply_t, QScopedPointerPodDeleter> resources;
- xcb_randr_get_screen_resources_current_cookie_t resourcesCookie =
- xcb_randr_get_screen_resources_current(xcb_connection(), xcbScreen->root);
- QScopedPointer<xcb_randr_get_screen_resources_current_reply_t, QScopedPointerPodDeleter> resources_current(
- xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, &error));
- if (!resources_current || error) {
+ auto resources_current = Q_XCB_REPLY(xcb_randr_get_screen_resources_current,
+ xcb_connection(), xcbScreen->root);
+ if (!resources_current) {
qWarning("failed to get the current screen resources");
- free(error);
} else {
xcb_timestamp_t timestamp = 0;
xcb_randr_output_t *outputs = Q_NULLPTR;
- int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.data());
+ int outputCount = xcb_randr_get_screen_resources_current_outputs_length(resources_current.get());
if (outputCount) {
timestamp = resources_current->config_timestamp;
- outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.data());
+ outputs = xcb_randr_get_screen_resources_current_outputs(resources_current.get());
} else {
- xcb_randr_get_screen_resources_cookie_t resourcesCookie =
- xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root);
- resources.reset(xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error));
- if (!resources || error) {
+ auto resources = Q_XCB_REPLY(xcb_randr_get_screen_resources,
+ xcb_connection(), xcbScreen->root);
+ if (!resources) {
qWarning("failed to get the screen resources");
- free(error);
} else {
timestamp = resources->config_timestamp;
- outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data());
- outputs = xcb_randr_get_screen_resources_outputs(resources.data());
+ outputCount = xcb_randr_get_screen_resources_outputs_length(resources.get());
+ outputs = xcb_randr_get_screen_resources_outputs(resources.get());
}
}
if (outputCount) {
- xcb_randr_get_output_primary_cookie_t primaryCookie =
- xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root);
- QScopedPointer<xcb_randr_get_output_primary_reply_t, QScopedPointerPodDeleter> primary(
- xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error));
- if (!primary || error) {
+ auto primary = Q_XCB_REPLY(xcb_randr_get_output_primary, xcb_connection(), xcbScreen->root);
+ if (!primary) {
qWarning("failed to get the primary output of the screen");
- free(error);
} else {
for (int i = 0; i < outputCount; i++) {
- QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> output(
- xcb_randr_get_output_info_reply(xcb_connection(),
- xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL));
-
+ auto output = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_output_info,
+ xcb_connection(), outputs[i], timestamp);
// Invalid, disconnected or disabled output
- if (output == NULL)
+ if (!output)
continue;
if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) {
qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable(
- QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()),
- xcb_randr_get_output_info_name_length(output.data()))));
+ QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.get()),
+ xcb_randr_get_output_info_name_length(output.get()))));
continue;
}
if (output->crtc == XCB_NONE) {
qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable(
- QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()),
- xcb_randr_get_output_info_name_length(output.data()))));
+ QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.get()),
+ xcb_randr_get_output_info_name_length(output.get()))));
continue;
}
- QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.data());
+ QXcbScreen *screen = new QXcbScreen(this, virtualDesktop, outputs[i], output.get());
siblings << screen;
m_screens << screen;
@@ -492,12 +478,9 @@ void QXcbConnection::initializeScreens()
}
} else if (has_xinerama_extension) {
// Xinerama is available
- xcb_xinerama_query_screens_cookie_t cookie = xcb_xinerama_query_screens(m_connection);
- xcb_xinerama_query_screens_reply_t *screens = xcb_xinerama_query_screens_reply(m_connection,
- cookie,
- Q_NULLPTR);
+ auto screens = Q_XCB_REPLY(xcb_xinerama_query_screens, m_connection);
if (screens) {
- xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens);
+ xcb_xinerama_screen_info_iterator_t it = xcb_xinerama_query_screens_screen_info_iterator(screens.get());
while (it.rem) {
xcb_xinerama_screen_info_t *screen_info = it.data;
QXcbScreen *screen = new QXcbScreen(this, virtualDesktop,
@@ -507,7 +490,6 @@ void QXcbConnection::initializeScreens()
m_screens << screen;
xcb_xinerama_screen_info_next(&it);
}
- free(screens);
}
}
if (siblings.isEmpty()) {
@@ -556,6 +538,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
, m_defaultVisualId(defaultVisualId)
, m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
, m_nativeInterface(nativeInterface)
+ , has_render_extension(false)
{
#if QT_CONFIG(xcb_xlib)
Display *dpy = XOpenDisplay(m_displayName.constData());
@@ -663,11 +646,6 @@ QXcbConnection::~QXcbConnection()
#ifndef QT_NO_DRAGANDDROP
delete m_drag;
#endif
-
-#if QT_CONFIG(xinput2)
- finalizeXInput2();
-#endif
-
if (m_reader->isRunning()) {
sendConnectionEvent(QXcbAtom::_QT_CLOSE_CONNECTION);
m_reader->wait();
@@ -951,18 +929,6 @@ const char *xcb_protocol_request_codes[] =
"Unknown"
};
-#ifdef Q_XCB_DEBUG
-void QXcbConnection::log(const char *file, int line, int sequence)
-{
- QMutexLocker locker(&m_callLogMutex);
- CallInfo info;
- info.sequence = sequence;
- info.file = file;
- info.line = line;
- m_callLog << info;
-}
-#endif
-
void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
{
long result = 0;
@@ -978,26 +944,6 @@ void QXcbConnection::handleXcbError(xcb_generic_error_t *error)
int(error->sequence), int(error->resource_id),
int(error->major_code), xcb_protocol_request_codes[clamped_major_code],
int(error->minor_code));
-#ifdef Q_XCB_DEBUG
- QMutexLocker locker(&m_callLogMutex);
- int i = 0;
- for (; i < m_callLog.size(); ++i) {
- if (m_callLog.at(i).sequence == error->sequence) {
- qDebug("Caused by: %s:%d", m_callLog.at(i).file.constData(), m_callLog.at(i).line);
- break;
- } else if (m_callLog.at(i).sequence > error->sequence) {
- qDebug("Caused some time before: %s:%d", m_callLog.at(i).file.constData(),
- m_callLog.at(i).line);
- if (i > 0)
- qDebug("and after: %s:%d", m_callLog.at(i-1).file.constData(),
- m_callLog.at(i-1).line);
- break;
- }
- }
- if (i == m_callLog.size() && !m_callLog.isEmpty())
- qDebug("Caused some time after: %s:%d", qAsConst(m_callLog).first().file.constData(),
- qAsConst(m_callLog).first().line);
-#endif
}
static Qt::MouseButtons translateMouseButtons(int s)
@@ -1067,17 +1013,6 @@ namespace {
void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
{
-#ifdef Q_XCB_DEBUG
- {
- QMutexLocker locker(&m_callLogMutex);
- int i = 0;
- for (; i < m_callLog.size(); ++i)
- if (m_callLog.at(i).sequence >= event->sequence)
- break;
- m_callLog.remove(0, i);
- }
-#endif
-
long result = 0;
QAbstractEventDispatcher* dispatcher = QAbstractEventDispatcher::instance();
bool handled = dispatcher && dispatcher->filterNativeEvent(m_nativeInterface->genericEventFilterType(), event, &result);
@@ -1095,28 +1030,28 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
m_keyboard->updateXKBStateFromCore(ev->state);
// the event explicitly contains the state of the three first buttons,
// the rest we need to manage ourselves
- m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state);
- m_buttons |= translateMouseButton(ev->detail);
+ m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
+ m_buttonState |= translateMouseButton(ev->detail);
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
- qCDebug(lcQpaXInputEvents, "legacy mouse press, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons));
+ qCDebug(lcQpaXInputEvents, "legacy mouse press, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttonState));
HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent);
}
case XCB_BUTTON_RELEASE: {
xcb_button_release_event_t *ev = (xcb_button_release_event_t *)event;
m_keyboard->updateXKBStateFromCore(ev->state);
- m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state);
- m_buttons &= ~translateMouseButton(ev->detail);
+ m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
+ m_buttonState &= ~translateMouseButton(ev->detail);
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
- qCDebug(lcQpaXInputEvents, "legacy mouse release, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttons));
+ qCDebug(lcQpaXInputEvents, "legacy mouse release, button %d state %X", ev->detail, static_cast<unsigned int>(m_buttonState));
HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent);
}
case XCB_MOTION_NOTIFY: {
xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)event;
m_keyboard->updateXKBStateFromCore(ev->state);
- m_buttons = (m_buttons & ~0x7) | translateMouseButtons(ev->state);
+ m_buttonState = (m_buttonState & ~0x7) | translateMouseButtons(ev->state);
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "legacy mouse move %d,%d button %d state %X", ev->event_x, ev->event_y,
- ev->detail, static_cast<unsigned int>(m_buttons));
+ ev->detail, static_cast<unsigned int>(m_buttonState));
HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent);
}
@@ -1392,10 +1327,10 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
const xcb_window_t eventListener = xcb_generate_id(m_connection);
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
xcb_screen_t *screen = it.data;
- Q_XCB_CALL(xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
- eventListener, screen->root,
- 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
- screen->root_visual, 0, 0));
+ xcb_create_window(m_connection, XCB_COPY_FROM_PARENT,
+ eventListener, screen->root,
+ 0, 0, 1, 1, 0, XCB_WINDOW_CLASS_INPUT_ONLY,
+ screen->root_visual, 0, 0);
event.response_type = XCB_CLIENT_MESSAGE;
event.format = 32;
@@ -1404,8 +1339,8 @@ void QXcbConnection::sendConnectionEvent(QXcbAtom::Atom a, uint id)
event.type = atom(a);
event.data.data32[0] = id;
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event)));
- Q_XCB_CALL(xcb_destroy_window(m_connection, eventListener));
+ xcb_send_event(xcb_connection(), false, eventListener, XCB_EVENT_MASK_NO_EVENT, reinterpret_cast<const char *>(&event));
+ xcb_destroy_window(m_connection, eventListener);
xcb_flush(xcb_connection());
}
@@ -1463,13 +1398,7 @@ xcb_timestamp_t QXcbConnection::getTimestamp()
xcb_window_t QXcbConnection::getSelectionOwner(xcb_atom_t atom) const
{
- xcb_connection_t *c = xcb_connection();
- xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(c, atom);
- xcb_get_selection_owner_reply_t *reply;
- reply = xcb_get_selection_owner_reply(c, cookie, 0);
- xcb_window_t win = reply->owner;
- free(reply);
- return win;
+ return Q_XCB_REPLY(xcb_get_selection_owner, xcb_connection(), atom)->owner;
}
xcb_window_t QXcbConnection::getQtSelectionOwner()
@@ -1479,16 +1408,16 @@ xcb_window_t QXcbConnection::getQtSelectionOwner()
int16_t x = 0, y = 0;
uint16_t w = 3, h = 3;
m_qtSelectionOwner = xcb_generate_id(xcb_connection());
- Q_XCB_CALL(xcb_create_window(xcb_connection(),
- XCB_COPY_FROM_PARENT, // depth -- same as root
- m_qtSelectionOwner, // window id
- xcbScreen->root, // parent window id
- x, y, w, h,
- 0, // border width
- XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
- xcbScreen->root_visual, // visual
- 0, // value mask
- 0)); // value list
+ xcb_create_window(xcb_connection(),
+ XCB_COPY_FROM_PARENT, // depth -- same as root
+ m_qtSelectionOwner, // window id
+ xcbScreen->root, // parent window id
+ x, y, w, h,
+ 0, // border width
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
+ xcbScreen->root_visual, // visual
+ 0, // value mask
+ 0); // value list
}
return m_qtSelectionOwner;
}
@@ -1504,47 +1433,47 @@ xcb_window_t QXcbConnection::clientLeader()
if (m_clientLeader == 0) {
m_clientLeader = xcb_generate_id(xcb_connection());
QXcbScreen *screen = primaryScreen();
- Q_XCB_CALL(xcb_create_window(xcb_connection(),
- XCB_COPY_FROM_PARENT,
- m_clientLeader,
- screen->root(),
- 0, 0, 1, 1,
- 0,
- XCB_WINDOW_CLASS_INPUT_OUTPUT,
- screen->screen()->root_visual,
- 0, 0));
+ xcb_create_window(xcb_connection(),
+ XCB_COPY_FROM_PARENT,
+ m_clientLeader,
+ screen->root(),
+ 0, 0, 1, 1,
+ 0,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT,
+ screen->screen()->root_visual,
+ 0, 0);
#ifndef QT_NO_DEBUG
QByteArray ba("Qt client leader window");
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_clientLeader,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData()));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_clientLeader,
+ atom(QXcbAtom::_NET_WM_NAME),
+ atom(QXcbAtom::UTF8_STRING),
+ 8,
+ ba.length(),
+ ba.constData());
#endif
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_clientLeader,
- atom(QXcbAtom::WM_CLIENT_LEADER),
- XCB_ATOM_WINDOW,
- 32,
- 1,
- &m_clientLeader));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_clientLeader,
+ atom(QXcbAtom::WM_CLIENT_LEADER),
+ XCB_ATOM_WINDOW,
+ 32,
+ 1,
+ &m_clientLeader);
#if QT_CONFIG(xcb_sm)
// If we are session managed, inform the window manager about it
QByteArray session = qGuiApp->sessionId().toLatin1();
if (!session.isEmpty()) {
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_clientLeader,
- atom(QXcbAtom::SM_CLIENT_ID),
- XCB_ATOM_STRING,
- 8,
- session.length(),
- session.constData()));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_clientLeader,
+ atom(QXcbAtom::SM_CLIENT_ID),
+ XCB_ATOM_STRING,
+ 8,
+ session.length(),
+ session.constData());
}
#endif
}
@@ -1566,7 +1495,8 @@ void *QXcbConnection::createVisualInfoForDefaultVisualId() const
info.visualid = m_defaultVisualId;
int count = 0;
- XVisualInfo *retVisual = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &info, &count);
+ Display *dpy = static_cast<Display *>(connection()->xlib_display());
+ XVisualInfo *retVisual = XGetVisualInfo(dpy, VisualIDMask, &info, &count);
Q_ASSERT(count < 2);
return retVisual;
}
@@ -1628,7 +1558,8 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex,
if (isXIType(event, m_xiOpCode, XI_Motion)) {
#if QT_CONFIG(tabletevent)
xXIDeviceEvent *xdev = reinterpret_cast<xXIDeviceEvent *>(event);
- if (const_cast<QXcbConnection *>(this)->tabletDataForDevice(xdev->sourceid))
+ if (!QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents) &&
+ const_cast<QXcbConnection *>(this)->tabletDataForDevice(xdev->sourceid))
return false;
#endif // QT_CONFIG(tabletevent)
for (int j = nextIndex; j < eventqueue->size(); ++j) {
@@ -1995,11 +1926,7 @@ xcb_atom_t QXcbConnection::internAtom(const char *name)
if (!name || *name == 0)
return XCB_NONE;
- xcb_intern_atom_cookie_t cookie = xcb_intern_atom(xcb_connection(), false, strlen(name), name);
- xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(xcb_connection(), cookie, 0);
- int atom = reply->atom;
- free(reply);
- return atom;
+ return Q_XCB_REPLY(xcb_intern_atom, xcb_connection(), false, strlen(name), name)->atom;
}
QByteArray QXcbConnection::atomName(xcb_atom_t atom)
@@ -2007,18 +1934,12 @@ QByteArray QXcbConnection::atomName(xcb_atom_t atom)
if (!atom)
return QByteArray();
- xcb_generic_error_t *error = 0;
- xcb_get_atom_name_cookie_t cookie = Q_XCB_CALL(xcb_get_atom_name(xcb_connection(), atom));
- xcb_get_atom_name_reply_t *reply = xcb_get_atom_name_reply(xcb_connection(), cookie, &error);
- if (error) {
+ auto reply = Q_XCB_REPLY(xcb_get_atom_name, xcb_connection(), atom);
+ if (!reply)
qWarning() << "QXcbConnection::atomName: bad Atom" << atom;
- free(error);
- }
- if (reply) {
- QByteArray result(xcb_get_atom_name_name(reply), xcb_get_atom_name_name_length(reply));
- free(reply);
- return result;
- }
+ else
+ return QByteArray(xcb_get_atom_name_name(reply.get()), xcb_get_atom_name_name_length(reply.get()));
+
return QByteArray();
}
@@ -2040,29 +1961,24 @@ const xcb_format_t *QXcbConnection::formatForDepth(uint8_t depth) const
void QXcbConnection::sync()
{
// from xcb_aux_sync
- xcb_get_input_focus_cookie_t cookie = Q_XCB_CALL(xcb_get_input_focus(xcb_connection()));
+ xcb_get_input_focus_cookie_t cookie = xcb_get_input_focus(xcb_connection());
free(xcb_get_input_focus_reply(xcb_connection(), cookie, 0));
}
void QXcbConnection::initializeXFixes()
{
- xcb_generic_error_t *error = 0;
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_xfixes_id);
if (!reply || !reply->present)
return;
xfixes_first_event = reply->first_event;
- xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection,
- XCB_XFIXES_MAJOR_VERSION,
- XCB_XFIXES_MINOR_VERSION);
- xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection,
- xfixes_query_cookie, &error);
- if (!xfixes_query || error || xfixes_query->major_version < 2) {
+ auto xfixes_query = Q_XCB_REPLY(xcb_xfixes_query_version, m_connection,
+ XCB_XFIXES_MAJOR_VERSION,
+ XCB_XFIXES_MINOR_VERSION);
+ if (!xfixes_query || xfixes_query->major_version < 2) {
qWarning("QXcbConnection: Failed to initialize XFixes");
- free(error);
xfixes_first_event = 0;
}
- free(xfixes_query);
}
void QXcbConnection::initializeXRender()
@@ -2072,17 +1988,14 @@ void QXcbConnection::initializeXRender()
if (!reply || !reply->present)
return;
- xcb_generic_error_t *error = 0;
- xcb_render_query_version_cookie_t xrender_query_cookie = xcb_render_query_version(m_connection,
- XCB_RENDER_MAJOR_VERSION,
- XCB_RENDER_MINOR_VERSION);
- xcb_render_query_version_reply_t *xrender_query = xcb_render_query_version_reply(m_connection,
- xrender_query_cookie, &error);
- if (!xrender_query || error || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) {
+ has_render_extension = true;
+ auto xrender_query = Q_XCB_REPLY(xcb_render_query_version, m_connection,
+ XCB_RENDER_MAJOR_VERSION,
+ XCB_RENDER_MINOR_VERSION);
+ if (!xrender_query || (xrender_query->major_version == 0 && xrender_query->minor_version < 5)) {
qWarning("QXcbConnection: Failed to initialize XRender");
- free(error);
+ has_render_extension = false;
}
- free(xrender_query);
#endif
}
@@ -2094,21 +2007,16 @@ void QXcbConnection::initializeXRandr()
xrandr_first_event = reply->first_event;
- xcb_generic_error_t *error = 0;
- xcb_randr_query_version_cookie_t xrandr_query_cookie = xcb_randr_query_version(m_connection,
- XCB_RANDR_MAJOR_VERSION,
- XCB_RANDR_MINOR_VERSION);
+ auto xrandr_query = Q_XCB_REPLY(xcb_randr_query_version, m_connection,
+ XCB_RANDR_MAJOR_VERSION,
+ XCB_RANDR_MINOR_VERSION);
has_randr_extension = true;
- xcb_randr_query_version_reply_t *xrandr_query = xcb_randr_query_version_reply(m_connection,
- xrandr_query_cookie, &error);
- if (!xrandr_query || error || (xrandr_query->major_version < 1 || (xrandr_query->major_version == 1 && xrandr_query->minor_version < 2))) {
+ if (!xrandr_query || (xrandr_query->major_version < 1 || (xrandr_query->major_version == 1 && xrandr_query->minor_version < 2))) {
qWarning("QXcbConnection: Failed to initialize XRandr");
- free(error);
has_randr_extension = false;
}
- free(xrandr_query);
xcb_screen_iterator_t rootIter = xcb_setup_roots_iterator(m_setup);
for (; rootIter.rem; xcb_screen_next(&rootIter)) {
@@ -2128,14 +2036,8 @@ void QXcbConnection::initializeXinerama()
if (!reply || !reply->present)
return;
- xcb_generic_error_t *error = Q_NULLPTR;
- xcb_xinerama_is_active_cookie_t xinerama_query_cookie = xcb_xinerama_is_active(m_connection);
- xcb_xinerama_is_active_reply_t *xinerama_is_active = xcb_xinerama_is_active_reply(m_connection,
- xinerama_query_cookie,
- &error);
- has_xinerama_extension = xinerama_is_active && !error && xinerama_is_active->state;
- free(error);
- free(xinerama_is_active);
+ auto xinerama_is_active = Q_XCB_REPLY(xcb_xinerama_is_active, m_connection);
+ has_xinerama_extension = xinerama_is_active && xinerama_is_active->state;
}
void QXcbConnection::initializeXShape()
@@ -2145,16 +2047,13 @@ void QXcbConnection::initializeXShape()
return;
has_shape_extension = true;
- xcb_shape_query_version_cookie_t cookie = xcb_shape_query_version(m_connection);
- xcb_shape_query_version_reply_t *shape_query = xcb_shape_query_version_reply(m_connection,
- cookie, NULL);
+ auto shape_query = Q_XCB_REPLY(xcb_shape_query_version, m_connection);
if (!shape_query) {
qWarning("QXcbConnection: Failed to initialize SHAPE extension");
} else if (shape_query->major_version > 1 || (shape_query->major_version == 1 && shape_query->minor_version >= 1)) {
// The input shape is the only thing added in SHAPE 1.1
has_input_shape = true;
}
- free(shape_query);
}
void QXcbConnection::initializeXKB()
@@ -2169,11 +2068,10 @@ void QXcbConnection::initializeXKB()
xkb_first_event = reply->first_event;
xcb_connection_t *c = connection()->xcb_connection();
- xcb_xkb_use_extension_cookie_t xkb_query_cookie;
- xcb_xkb_use_extension_reply_t *xkb_query;
- xkb_query_cookie = xcb_xkb_use_extension(c, XKB_X11_MIN_MAJOR_XKB_VERSION, XKB_X11_MIN_MINOR_XKB_VERSION);
- xkb_query = xcb_xkb_use_extension_reply(c, xkb_query_cookie, 0);
+ auto xkb_query = Q_XCB_REPLY(xcb_xkb_use_extension, c,
+ XKB_X11_MIN_MAJOR_XKB_VERSION,
+ XKB_X11_MIN_MINOR_XKB_VERSION);
if (!xkb_query) {
qWarning("Qt: Failed to initialize XKB extension");
@@ -2182,12 +2080,10 @@ void QXcbConnection::initializeXKB()
qWarning("Qt: Unsupported XKB version (We want %d %d, but X server has %d %d)",
XCB_XKB_MAJOR_VERSION, XCB_XKB_MINOR_VERSION,
xkb_query->serverMajor, xkb_query->serverMinor);
- free(xkb_query);
return;
}
has_xkb = true;
- free(xkb_query);
const uint16_t required_map_parts = (XCB_XKB_MAP_PART_KEY_TYPES |
XCB_XKB_MAP_PART_KEY_SYMS |
@@ -2222,62 +2118,6 @@ void QXcbConnection::initializeXKB()
#endif
}
-#if defined(XCB_USE_XINPUT22)
-bool QXcbConnection::xi2MouseEvents() const
-{
- static bool mouseViaXI2 = !qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE");
- // FIXME: Don't use XInput2 mouse events when Xinerama extension
- // is enabled, because it causes problems with multi-monitor setup.
- return mouseViaXI2 && !has_xinerama_extension;
-}
-#endif
-
-#if QT_CONFIG(xinput2)
-static int xi2ValuatorOffset(const unsigned char *maskPtr, int maskLen, int number)
-{
- int offset = 0;
- for (int i = 0; i < maskLen; i++) {
- if (number < 8) {
- if ((maskPtr[i] & (1 << number)) == 0)
- return -1;
- }
- for (int j = 0; j < 8; j++) {
- if (j == number)
- return offset;
- if (maskPtr[i] & (1 << j))
- offset++;
- }
- number -= 8;
- }
- return -1;
-}
-
-bool QXcbConnection::xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value)
-{
- const xXIDeviceEvent *xideviceevent = static_cast<const xXIDeviceEvent *>(event);
- const unsigned char *buttonsMaskAddr = (const unsigned char*)&xideviceevent[1];
- const unsigned char *valuatorsMaskAddr = buttonsMaskAddr + xideviceevent->buttons_len * 4;
- FP3232 *valuatorsValuesAddr = (FP3232*)(valuatorsMaskAddr + xideviceevent->valuators_len * 4);
-
- int valuatorOffset = xi2ValuatorOffset(valuatorsMaskAddr, xideviceevent->valuators_len, valuatorNum);
- if (valuatorOffset < 0)
- return false;
-
- *value = valuatorsValuesAddr[valuatorOffset].integral;
- *value += ((double)valuatorsValuesAddr[valuatorOffset].frac / (1 << 16) / (1 << 16));
- return true;
-}
-
-void QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event)
-{
- // xcb event structs contain stuff that wasn't on the wire, the full_sequence field
- // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
- // Move this data back to have the same layout in memory as it was on the wire
- // and allow casting, overwriting the full_sequence field.
- memmove((char*) event + 32, (char*) event + 36, event->length * 4);
-}
-#endif // QT_CONFIG(xinput2)
-
QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const
{
if (!m_systemTrayTracker) {
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 1129090eca..13f5cd5842 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -56,6 +56,9 @@
#include <QtCore/QLoggingCategory>
#include <QtCore/private/qglobal_p.h>
+#include <cstdlib>
+#include <memory>
+
// This is needed to make Qt compile together with XKB. xkb.h is using a variable
// which is called 'explicit', this is a reserved keyword in c++
#if QT_CONFIG(xkb)
@@ -76,13 +79,10 @@
#define XCB_USE_XINPUT22 // XI 2.2 adds multi-point touch support
#endif
#endif
-struct XInput2TouchDeviceData;
#endif // QT_CONFIG(xinput2)
struct xcb_randr_get_output_info_reply_t;
-//#define Q_XCB_DEBUG
-
QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQpaXInput)
@@ -429,16 +429,8 @@ public:
#if QT_CONFIG(xinput2)
void xi2Select(xcb_window_t window);
void xi2SelectStateEvents();
-#endif
-#ifdef XCB_USE_XINPUT21
bool isAtLeastXI21() const { return m_xi2Enabled && m_xi2Minor >= 1; }
-#else
- bool isAtLeastXI21() const { return false; }
-#endif
-#ifdef XCB_USE_XINPUT22
bool isAtLeastXI22() const { return m_xi2Enabled && m_xi2Minor >= 2; }
-#else
- bool isAtLeastXI22() const { return false; }
#endif
void sync();
@@ -468,16 +460,16 @@ public:
bool hasXRandr() const { return has_randr_extension; }
bool hasInputShape() const { return has_input_shape; }
bool hasXKB() const { return has_xkb; }
+ bool hasXRender() const { return has_render_extension; }
- bool supportsThreadedRendering() const { return m_reader->isRunning(); }
bool threadedEventHandling() const { return m_reader->isRunning(); }
xcb_timestamp_t getTimestamp();
xcb_window_t getSelectionOwner(xcb_atom_t atom) const;
xcb_window_t getQtSelectionOwner();
- void setButton(Qt::MouseButton button, bool down) { m_buttons.setFlag(button, down); }
- Qt::MouseButtons buttons() const { return m_buttons; }
+ void setButtonState(Qt::MouseButton button, bool down) { m_buttonState.setFlag(button, down); }
+ Qt::MouseButtons buttonState() const { return m_buttonState; }
Qt::MouseButton translateMouseButton(xcb_button_t s);
QXcbWindow *focusWindow() const { return m_focusWindow; }
@@ -501,13 +493,16 @@ public:
static bool xEmbedSystemTrayVisualHasAlphaChannel();
#ifdef XCB_USE_XINPUT21
- void handleEnterEvent();
-#endif
+ void xi2UpdateScrollingDevices();
+#endif // XCB_USE_XINPUT21
#ifdef XCB_USE_XINPUT22
bool startSystemResizeForTouchBegin(xcb_window_t window, const QPoint &point, Qt::Corner corner);
bool xi2SetMouseGrabEnabled(xcb_window_t w, bool grab);
-#endif
+ bool xi2MouseEvents() const;
+ bool isTouchScreen(int id);
+#endif // XCB_USE_XINPUT22
+
Qt::MouseButton xiToQtMouseButton(uint32_t b);
QXcbEventReader *eventReader() const { return m_reader; }
@@ -516,11 +511,6 @@ public:
QXcbGlIntegration *glIntegration() const { return m_glIntegration; }
-#ifdef XCB_USE_XINPUT22
- bool xi2MouseEvents() const;
- bool isTouchScreen(int id) const;
-#endif
-
protected:
bool event(QEvent *e) override;
@@ -554,13 +544,32 @@ private:
bool compressEvent(xcb_generic_event_t *event, int currentIndex, QXcbEventArray *eventqueue) const;
#if QT_CONFIG(xinput2)
bool m_xi2Enabled = false;
- int m_xi2Minor = 2;
+ int m_xi2Minor = -1;
void initializeXInput2();
- void finalizeXInput2();
+ void xi2SetupDevice(void *info, bool removeExisting = true);
void xi2SetupDevices();
- XInput2TouchDeviceData *touchDeviceForId(int id);
+ struct TouchDeviceData {
+ QTouchDevice *qtTouchDevice = nullptr;
+ QHash<int, QWindowSystemInterface::TouchPoint> touchPoints;
+ QHash<int, QPointF> pointPressedPosition; // in screen coordinates where each point was pressed
+ struct ValuatorClassInfo {
+ double min = 0;
+ double max = 0;
+ int number = -1;
+ QXcbAtom::Atom label;
+ };
+ QVector<ValuatorClassInfo> valuatorInfo;
+
+ // Stuff that is relevant only for touchpads
+ QPointF firstPressedPosition; // in screen coordinates where the first point was pressed
+ QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed
+ QSizeF size; // device size in mm
+ bool providesTouchOrientation = false;
+ };
+ TouchDeviceData *populateTouchDevices(void *info);
+ TouchDeviceData *touchDeviceForId(int id);
void xi2HandleEvent(xcb_ge_event_t *event);
- void xi2HandleHierachyEvent(void *event);
+ void xi2HandleHierarchyEvent(void *event);
void xi2HandleDeviceChangedEvent(void *event);
int m_xiOpCode, m_xiEventBase, m_xiErrorBase;
#ifdef XCB_USE_XINPUT22
@@ -599,9 +608,12 @@ private:
Qt::Orientations legacyOrientations = 0;
QPointF lastScrollPosition;
};
- void updateScrollingDevice(ScrollingDevice& scrollingDevice, int num_classes, void *classes);
- void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice);
QHash<int, ScrollingDevice> m_scrollingDevices;
+#ifdef XCB_USE_XINPUT21
+ void xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice);
+ void xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice);
+ ScrollingDevice *scrollingDeviceForId(int id);
+#endif
static bool xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value);
static void xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event);
@@ -637,34 +649,18 @@ private:
void *m_xlib_display = nullptr;
#endif
QXcbEventReader *m_reader = nullptr;
+
#if QT_CONFIG(xinput2)
- QHash<int, XInput2TouchDeviceData*> m_touchDevices;
+ QHash<int, TouchDeviceData> m_touchDevices;
#ifdef XCB_USE_XINPUT22
struct StartSystemResizeInfo {
- xcb_window_t window;
+ xcb_window_t window = XCB_NONE;
uint16_t deviceid;
uint32_t pointid;
Qt::Corner corner;
} m_startSystemResizeInfo;
#endif
#endif
-#ifdef Q_XCB_DEBUG
- struct CallInfo {
- int sequence;
- QByteArray file;
- int line;
- };
- QVector<CallInfo> m_callLog;
- QMutex m_callLogMutex;
- void log(const char *file, int line, int sequence);
- template <typename cookie_t>
- friend cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection,
- const char *file, int line);
- template <typename reply_t>
- friend reply_t *q_xcb_call_template(reply_t *reply, QXcbConnection *connection,
- const char *file, int line);
-#endif
-
WindowMapper m_mapper;
QVector<PeekFunc> m_peekFuncs;
@@ -678,8 +674,9 @@ private:
bool has_randr_extension = false;
bool has_input_shape;
bool has_xkb = false;
+ bool has_render_extension;
- Qt::MouseButtons m_buttons = 0;
+ Qt::MouseButtons m_buttonState = 0;
QXcbWindow *m_focusWindow = nullptr;
QXcbWindow *m_mouseGrabber = nullptr;
@@ -702,9 +699,6 @@ Q_DECLARE_TYPEINFO(QXcbConnection::TabletData, Q_MOVABLE_TYPE);
#endif
#endif
-#define DISPLAY_FROM_XCB(object) (reinterpret_cast<Display *>(object->connection()->xlib_display()))
-#define CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(object) ((XVisualInfo *)(object->connection()->createVisualInfoForDefaultVisualId()))
-
template<typename T>
xcb_generic_event_t *QXcbConnection::checkEvent(T &checker)
{
@@ -732,6 +726,20 @@ private:
QXcbConnection *m_connection;
};
+#define Q_XCB_REPLY_CONNECTION_ARG(connection, ...) connection
+
+#define Q_XCB_REPLY(call, ...) \
+ std::unique_ptr<call##_reply_t, decltype(std::free) *>( \
+ call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call(__VA_ARGS__), nullptr), \
+ std::free \
+ )
+
+#define Q_XCB_REPLY_UNCHECKED(call, ...) \
+ std::unique_ptr<call##_reply_t, decltype(std::free) *>( \
+ call##_reply(Q_XCB_REPLY_CONNECTION_ARG(__VA_ARGS__), call##_unchecked(__VA_ARGS__), nullptr), \
+ std::free \
+ )
+
template <typename T>
union q_padded_xcb_event {
T event;
@@ -745,30 +753,6 @@ union q_padded_xcb_event {
q_padded_xcb_event<event_type> store = {}; \
auto &event_var = store.event;
-#ifdef Q_XCB_DEBUG
-template <typename cookie_t>
-cookie_t q_xcb_call_template(const cookie_t &cookie, QXcbConnection *connection, const char *file,
- int line)
-{
- connection->log(file, line, cookie.sequence);
- return cookie;
-}
-
-template <typename reply_t>
-reply_t *q_xcb_call_template(reply_t *reply, QXcbConnection *connection, const char *file, int line)
-{
- connection->log(file, line, reply->sequence);
- return reply;
-}
-#define Q_XCB_CALL(x) q_xcb_call_template(x, connection(), __FILE__, __LINE__)
-#define Q_XCB_CALL2(x, connection) q_xcb_call_template(x, connection, __FILE__, __LINE__)
-#define Q_XCB_NOOP(c) q_xcb_call_template(xcb_no_operation(c->xcb_connection()), c, __FILE__, __LINE__);
-#else
-#define Q_XCB_CALL(x) x
-#define Q_XCB_CALL2(x, connection) x
-#define Q_XCB_NOOP(c) (void)c;
-#endif
-
QT_END_NAMESPACE
#endif
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index 38ea2d9ab9..8ed6909990 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -50,19 +50,6 @@
#include <X11/extensions/XInput2.h>
#include <X11/extensions/XI2proto.h>
-struct XInput2TouchDeviceData {
- XIDeviceInfo *xiDeviceInfo = nullptr;
- QTouchDevice *qtTouchDevice = nullptr;
- QHash<int, QWindowSystemInterface::TouchPoint> touchPoints;
- QHash<int, QPointF> pointPressedPosition; // in screen coordinates where each point was pressed
-
- // Stuff that is relevant only for touchpads
- QPointF firstPressedPosition; // in screen coordinates where the first point was pressed
- QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed
- QSizeF size; // device size in mm
- bool providesTouchOrientation = false;
-};
-
void QXcbConnection::initializeXInput2()
{
// TODO Qt 6 (or perhaps earlier): remove these redundant env variables
@@ -70,30 +57,37 @@ void QXcbConnection::initializeXInput2()
const_cast<QLoggingCategory&>(lcQpaXInput()).setEnabled(QtDebugMsg, true);
if (qEnvironmentVariableIsSet("QT_XCB_DEBUG_XINPUT_DEVICES"))
const_cast<QLoggingCategory&>(lcQpaXInputDevices()).setEnabled(QtDebugMsg, true);
+
Display *xDisplay = static_cast<Display *>(m_xlib_display);
if (XQueryExtension(xDisplay, "XInputExtension", &m_xiOpCode, &m_xiEventBase, &m_xiErrorBase)) {
int xiMajor = 2;
- // try 2.2 first, needed for TouchBegin/Update/End
- if (XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) == BadRequest) {
- m_xi2Minor = 1; // for smooth scrolling 2.1 is enough
- if (XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) == BadRequest) {
- m_xi2Minor = 0; // for tablet support 2.0 is enough
- m_xi2Enabled = XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor) != BadRequest;
- } else
- m_xi2Enabled = true;
- } else
- m_xi2Enabled = true;
- if (m_xi2Enabled) {
-#ifdef XCB_USE_XINPUT22
- qCDebug(lcQpaXInputDevices, "XInput version %d.%d is available and Qt supports 2.2 or greater", xiMajor, m_xi2Minor);
- m_startSystemResizeInfo.window = XCB_NONE;
+#if defined(XCB_USE_XINPUT22)
+ m_xi2Minor = 2; // for touch support 2.2 is enough
+#elif defined(XCB_USE_XINPUT21)
+ m_xi2Minor = 1; // for smooth scrolling 2.1 is enough
#else
- qCDebug(lcQpaXInputDevices, "XInput version %d.%d is available and Qt supports 2.0", xiMajor, m_xi2Minor);
+ m_xi2Minor = 0; // for tablet support 2.0 is enough
#endif
+ qCDebug(lcQpaXInput, "Plugin build with support for XInput 2 version up "
+ "to %d.%d", xiMajor, m_xi2Minor);
+
+ switch (XIQueryVersion(xDisplay, &xiMajor, &m_xi2Minor)) {
+ case Success:
+ // Server's supported version can be lower than the version we have
+ // announced to support. In this case Qt client will be limited by
+ // X server's supported version.
+ qCDebug(lcQpaXInput, "Using XInput version %d.%d", xiMajor, m_xi2Minor);
+ m_xi2Enabled = true;
+ xi2SetupDevices();
xi2SelectStateEvents();
+ break;
+ case BadRequest: // Must be an X server with XInput 1
+ qCDebug(lcQpaXInput, "X server does not support XInput 2");
+ break;
+ default: // BadValue
+ qCDebug(lcQpaXInput, "Internal error");
+ break;
}
-
- xi2SetupDevices();
}
}
@@ -113,188 +107,196 @@ void QXcbConnection::xi2SelectStateEvents()
XISelectEvents(dpy, DefaultRootWindow(dpy), &xiEventMask, 1);
}
-void QXcbConnection::xi2SetupDevices()
+void QXcbConnection::xi2SetupDevice(void *info, bool removeExisting)
{
+ XIDeviceInfo *deviceInfo = reinterpret_cast<XIDeviceInfo *>(info);
+ if (removeExisting) {
#if QT_CONFIG(tabletevent)
- m_tabletData.clear();
+ for (int i = 0; i < m_tabletData.count(); ++i) {
+ if (m_tabletData.at(i).deviceId == deviceInfo->deviceid) {
+ m_tabletData.remove(i);
+ break;
+ }
+ }
#endif
- m_scrollingDevices.clear();
-
- if (!m_xi2Enabled)
- return;
+ m_scrollingDevices.remove(deviceInfo->deviceid);
+ m_touchDevices.remove(deviceInfo->deviceid);
+ }
- Display *xDisplay = static_cast<Display *>(m_xlib_display);
- int deviceCount = 0;
- XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount);
- for (int i = 0; i < deviceCount; ++i) {
- // Only non-master pointing devices are relevant here.
- if (devices[i].use != XISlavePointer)
- continue;
- qCDebug(lcQpaXInputDevices) << "input device " << devices[i].name << "ID" << devices[i].deviceid;
+ qCDebug(lcQpaXInputDevices) << "input device " << deviceInfo->name << "ID" << deviceInfo->deviceid;
#if QT_CONFIG(tabletevent)
- TabletData tabletData;
+ TabletData tabletData;
#endif
- ScrollingDevice scrollingDevice;
- for (int c = 0; c < devices[i].num_classes; ++c) {
- switch (devices[i].classes[c]->type) {
- case XIValuatorClass: {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(devices[i].classes[c]);
- const int valuatorAtom = qatom(vci->label);
- qCDebug(lcQpaXInputDevices) << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms);
+ ScrollingDevice scrollingDevice;
+ for (int c = 0; c < deviceInfo->num_classes; ++c) {
+ XIAnyClassInfo *classinfo = deviceInfo->classes[c];
+ switch (classinfo->type) {
+ case XIValuatorClass: {
+ XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
+ const int valuatorAtom = qatom(vci->label);
+ qCDebug(lcQpaXInputDevices) << " has valuator" << atomName(vci->label) << "recognized?" << (valuatorAtom < QXcbAtom::NAtoms);
#if QT_CONFIG(tabletevent)
- if (valuatorAtom < QXcbAtom::NAtoms) {
- TabletData::ValuatorClassInfo info;
- info.minVal = vci->min;
- info.maxVal = vci->max;
- info.number = vci->number;
- tabletData.valuatorInfo[valuatorAtom] = info;
- }
-#endif // QT_CONFIG(tabletevent)
- if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
- scrollingDevice.lastScrollPosition.setX(vci->value);
- else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
- scrollingDevice.lastScrollPosition.setY(vci->value);
- break;
+ if (valuatorAtom < QXcbAtom::NAtoms) {
+ TabletData::ValuatorClassInfo info;
+ info.minVal = vci->min;
+ info.maxVal = vci->max;
+ info.number = vci->number;
+ tabletData.valuatorInfo[valuatorAtom] = info;
}
+#endif // QT_CONFIG(tabletevent)
+ if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
+ scrollingDevice.lastScrollPosition.setX(vci->value);
+ else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
+ scrollingDevice.lastScrollPosition.setY(vci->value);
+ break;
+ }
#ifdef XCB_USE_XINPUT21
- case XIScrollClass: {
- XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(devices[i].classes[c]);
- if (sci->scroll_type == XIScrollTypeVertical) {
- scrollingDevice.orientations |= Qt::Vertical;
- scrollingDevice.verticalIndex = sci->number;
- scrollingDevice.verticalIncrement = sci->increment;
- }
- else if (sci->scroll_type == XIScrollTypeHorizontal) {
- scrollingDevice.orientations |= Qt::Horizontal;
- scrollingDevice.horizontalIndex = sci->number;
- scrollingDevice.horizontalIncrement = sci->increment;
- }
- break;
+ case XIScrollClass: {
+ XIScrollClassInfo *sci = reinterpret_cast<XIScrollClassInfo *>(classinfo);
+ if (sci->scroll_type == XIScrollTypeVertical) {
+ scrollingDevice.orientations |= Qt::Vertical;
+ scrollingDevice.verticalIndex = sci->number;
+ scrollingDevice.verticalIncrement = sci->increment;
}
- case XIButtonClass: {
- XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(devices[i].classes[c]);
- if (bci->num_buttons >= 5) {
- Atom label4 = bci->labels[3];
- Atom label5 = bci->labels[4];
- // Some drivers have no labels on the wheel buttons, some have no label on just one and some have no label on
- // button 4 and the wrong one on button 5. So we just check that they are not labelled with unrelated buttons.
- if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp || qatom(label4) == QXcbAtom::ButtonWheelDown) &&
- (!label5 || qatom(label5) == QXcbAtom::ButtonWheelUp || qatom(label5) == QXcbAtom::ButtonWheelDown))
- scrollingDevice.legacyOrientations |= Qt::Vertical;
- }
- if (bci->num_buttons >= 7) {
- Atom label6 = bci->labels[5];
- Atom label7 = bci->labels[6];
- if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight))
- scrollingDevice.legacyOrientations |= Qt::Horizontal;
- }
- qCDebug(lcQpaXInputDevices, " has %d buttons", bci->num_buttons);
- break;
+ else if (sci->scroll_type == XIScrollTypeHorizontal) {
+ scrollingDevice.orientations |= Qt::Horizontal;
+ scrollingDevice.horizontalIndex = sci->number;
+ scrollingDevice.horizontalIncrement = sci->increment;
}
+ break;
+ }
+ case XIButtonClass: {
+ XIButtonClassInfo *bci = reinterpret_cast<XIButtonClassInfo *>(classinfo);
+ if (bci->num_buttons >= 5) {
+ Atom label4 = bci->labels[3];
+ Atom label5 = bci->labels[4];
+ // Some drivers have no labels on the wheel buttons, some have no label on just one and some have no label on
+ // button 4 and the wrong one on button 5. So we just check that they are not labelled with unrelated buttons.
+ if ((!label4 || qatom(label4) == QXcbAtom::ButtonWheelUp || qatom(label4) == QXcbAtom::ButtonWheelDown) &&
+ (!label5 || qatom(label5) == QXcbAtom::ButtonWheelUp || qatom(label5) == QXcbAtom::ButtonWheelDown))
+ scrollingDevice.legacyOrientations |= Qt::Vertical;
+ }
+ if (bci->num_buttons >= 7) {
+ Atom label6 = bci->labels[5];
+ Atom label7 = bci->labels[6];
+ if ((!label6 || qatom(label6) == QXcbAtom::ButtonHorizWheelLeft) && (!label7 || qatom(label7) == QXcbAtom::ButtonHorizWheelRight))
+ scrollingDevice.legacyOrientations |= Qt::Horizontal;
+ }
+ qCDebug(lcQpaXInputDevices, " has %d buttons", bci->num_buttons);
+ break;
+ }
#endif
- case XIKeyClass:
- qCDebug(lcQpaXInputDevices) << " it's a keyboard";
- break;
+ case XIKeyClass:
+ qCDebug(lcQpaXInputDevices) << " it's a keyboard";
+ break;
#ifdef XCB_USE_XINPUT22
- case XITouchClass:
- // will be handled in deviceForId()
- break;
+ case XITouchClass:
+ // will be handled in populateTouchDevices()
+ break;
#endif
- default:
- qCDebug(lcQpaXInputDevices) << " has class" << devices[i].classes[c]->type;
- break;
- }
+ default:
+ qCDebug(lcQpaXInputDevices) << " has class" << classinfo->type;
+ break;
}
- bool isTablet = false;
+ }
+ bool isTablet = false;
#if QT_CONFIG(tabletevent)
- // If we have found the valuators which we expect a tablet to have, it might be a tablet.
- if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) &&
- tabletData.valuatorInfo.contains(QXcbAtom::AbsY) &&
- tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure))
- isTablet = true;
-
- // But we need to be careful not to take the touch and tablet-button devices as tablets.
- QByteArray name = QByteArray(devices[i].name).toLower();
- QString dbgType = QLatin1String("UNKNOWN");
- if (name.contains("eraser")) {
- isTablet = true;
- tabletData.pointerType = QTabletEvent::Eraser;
- dbgType = QLatin1String("eraser");
- } else if (name.contains("cursor")) {
- isTablet = true;
- tabletData.pointerType = QTabletEvent::Cursor;
- dbgType = QLatin1String("cursor");
- } else if (name.contains("wacom") && name.contains("finger touch")) {
- isTablet = false;
- } else if ((name.contains("pen") || name.contains("stylus")) && isTablet) {
- tabletData.pointerType = QTabletEvent::Pen;
- dbgType = QLatin1String("pen");
- } else if (name.contains("wacom") && isTablet && !name.contains("touch")) {
- // combined device (evdev) rather than separate pen/eraser (wacom driver)
- tabletData.pointerType = QTabletEvent::Pen;
- dbgType = QLatin1String("pen");
- } else if (name.contains("aiptek") /* && device == QXcbAtom::KEYBOARD */) {
- // some "Genius" tablets
- isTablet = true;
- tabletData.pointerType = QTabletEvent::Pen;
- dbgType = QLatin1String("pen");
- } else if (name.contains("waltop") && name.contains("tablet")) {
- // other "Genius" tablets
- // WALTOP International Corp. Slim Tablet
- isTablet = true;
- tabletData.pointerType = QTabletEvent::Pen;
- dbgType = QLatin1String("pen");
- } else if (name.contains("uc-logic") && isTablet) {
- tabletData.pointerType = QTabletEvent::Pen;
- dbgType = QLatin1String("pen");
- } else {
- isTablet = false;
- }
+ // If we have found the valuators which we expect a tablet to have, it might be a tablet.
+ if (tabletData.valuatorInfo.contains(QXcbAtom::AbsX) &&
+ tabletData.valuatorInfo.contains(QXcbAtom::AbsY) &&
+ tabletData.valuatorInfo.contains(QXcbAtom::AbsPressure))
+ isTablet = true;
+
+ // But we need to be careful not to take the touch and tablet-button devices as tablets.
+ QByteArray name = QByteArray(deviceInfo->name).toLower();
+ QString dbgType = QLatin1String("UNKNOWN");
+ if (name.contains("eraser")) {
+ isTablet = true;
+ tabletData.pointerType = QTabletEvent::Eraser;
+ dbgType = QLatin1String("eraser");
+ } else if (name.contains("cursor")) {
+ isTablet = true;
+ tabletData.pointerType = QTabletEvent::Cursor;
+ dbgType = QLatin1String("cursor");
+ } else if (name.contains("wacom") && name.contains("finger touch")) {
+ isTablet = false;
+ } else if ((name.contains("pen") || name.contains("stylus")) && isTablet) {
+ tabletData.pointerType = QTabletEvent::Pen;
+ dbgType = QLatin1String("pen");
+ } else if (name.contains("wacom") && isTablet && !name.contains("touch")) {
+ // combined device (evdev) rather than separate pen/eraser (wacom driver)
+ tabletData.pointerType = QTabletEvent::Pen;
+ dbgType = QLatin1String("pen");
+ } else if (name.contains("aiptek") /* && device == QXcbAtom::KEYBOARD */) {
+ // some "Genius" tablets
+ isTablet = true;
+ tabletData.pointerType = QTabletEvent::Pen;
+ dbgType = QLatin1String("pen");
+ } else if (name.contains("waltop") && name.contains("tablet")) {
+ // other "Genius" tablets
+ // WALTOP International Corp. Slim Tablet
+ isTablet = true;
+ tabletData.pointerType = QTabletEvent::Pen;
+ dbgType = QLatin1String("pen");
+ } else if (name.contains("uc-logic") && isTablet) {
+ tabletData.pointerType = QTabletEvent::Pen;
+ dbgType = QLatin1String("pen");
+ } else {
+ isTablet = false;
+ }
- if (isTablet) {
- tabletData.deviceId = devices[i].deviceid;
- m_tabletData.append(tabletData);
- qCDebug(lcQpaXInputDevices) << " it's a tablet with pointer type" << dbgType;
- }
+ if (isTablet) {
+ tabletData.deviceId = deviceInfo->deviceid;
+ m_tabletData.append(tabletData);
+ qCDebug(lcQpaXInputDevices) << " it's a tablet with pointer type" << dbgType;
+ }
#endif // QT_CONFIG(tabletevent)
#ifdef XCB_USE_XINPUT21
- if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) {
- scrollingDevice.deviceId = devices[i].deviceid;
- // Only use legacy wheel button events when we don't have real scroll valuators.
- scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations;
- m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice);
- qCDebug(lcQpaXInputDevices) << " it's a scrolling device";
- }
+ if (scrollingDevice.orientations || scrollingDevice.legacyOrientations) {
+ scrollingDevice.deviceId = deviceInfo->deviceid;
+ // Only use legacy wheel button events when we don't have real scroll valuators.
+ scrollingDevice.legacyOrientations &= ~scrollingDevice.orientations;
+ m_scrollingDevices.insert(scrollingDevice.deviceId, scrollingDevice);
+ qCDebug(lcQpaXInputDevices) << " it's a scrolling device";
+ }
#endif
- if (!isTablet) {
- // touchDeviceForId populates XInput2DeviceData the first time it is called
- // with a new deviceId. On subsequent calls it will return the cached object.
- XInput2TouchDeviceData *dev = touchDeviceForId(devices[i].deviceid);
- if (dev && lcQpaXInputDevices().isDebugEnabled()) {
- if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
- qCDebug(lcQpaXInputDevices, " it's a touchscreen with type %d capabilities 0x%X max touch points %d",
- dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(),
- dev->qtTouchDevice->maximumTouchPoints());
- else if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad)
- qCDebug(lcQpaXInputDevices, " it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f",
- dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(),
- dev->qtTouchDevice->maximumTouchPoints(),
- dev->size.width(), dev->size.height());
- }
+ if (!isTablet) {
+ TouchDeviceData *dev = populateTouchDevices(deviceInfo);
+ if (dev && lcQpaXInputDevices().isDebugEnabled()) {
+ if (dev->qtTouchDevice->type() == QTouchDevice::TouchScreen)
+ qCDebug(lcQpaXInputDevices, " it's a touchscreen with type %d capabilities 0x%X max touch points %d",
+ dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(),
+ dev->qtTouchDevice->maximumTouchPoints());
+ else if (dev->qtTouchDevice->type() == QTouchDevice::TouchPad)
+ qCDebug(lcQpaXInputDevices, " it's a touchpad with type %d capabilities 0x%X max touch points %d size %f x %f",
+ dev->qtTouchDevice->type(), (unsigned int)dev->qtTouchDevice->capabilities(),
+ dev->qtTouchDevice->maximumTouchPoints(),
+ dev->size.width(), dev->size.height());
}
}
- XIFreeDeviceInfo(devices);
+
}
-void QXcbConnection::finalizeXInput2()
+void QXcbConnection::xi2SetupDevices()
{
- for (XInput2TouchDeviceData *dev : qAsConst(m_touchDevices)) {
- if (dev->xiDeviceInfo)
- XIFreeDeviceInfo(dev->xiDeviceInfo);
- delete dev;
+#if QT_CONFIG(tabletevent)
+ m_tabletData.clear();
+#endif
+ m_scrollingDevices.clear();
+ m_touchDevices.clear();
+
+ Display *xDisplay = static_cast<Display *>(m_xlib_display);
+ int deviceCount = 0;
+ XIDeviceInfo *devices = XIQueryDevice(xDisplay, XIAllDevices, &deviceCount);
+ for (int i = 0; i < deviceCount; ++i) {
+ // Only non-master pointing devices are relevant here.
+ if (devices[i].use != XISlavePointer)
+ continue;
+ xi2SetupDevice(&devices[i], false);
}
+ XIFreeDeviceInfo(devices);
}
void QXcbConnection::xi2Select(xcb_window_t window)
@@ -390,100 +392,105 @@ void QXcbConnection::xi2Select(xcb_window_t window)
#endif
}
-XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
+QXcbConnection::TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
{
- XInput2TouchDeviceData *dev = Q_NULLPTR;
- QHash<int, XInput2TouchDeviceData*>::const_iterator devIt = m_touchDevices.constFind(id);
- if (devIt != m_touchDevices.cend()) {
- dev = devIt.value();
- } else {
- int nrDevices = 0;
- QTouchDevice::Capabilities caps = 0;
- dev = new XInput2TouchDeviceData;
- dev->xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), id, &nrDevices);
- if (nrDevices <= 0) {
- delete dev;
- return 0;
- }
- int type = -1;
- int maxTouchPoints = 1;
- bool hasRelativeCoords = false;
- for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
- XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
- switch (classinfo->type) {
+ TouchDeviceData *dev = nullptr;
+ if (m_touchDevices.contains(id))
+ dev = &m_touchDevices[id];
+ return dev;
+}
+
+QXcbConnection::TouchDeviceData *QXcbConnection::populateTouchDevices(void *info)
+{
+ XIDeviceInfo *deviceinfo = reinterpret_cast<XIDeviceInfo *>(info);
+ QTouchDevice::Capabilities caps = 0;
+ int type = -1;
+ int maxTouchPoints = 1;
+ bool isTouchDevice = false;
+ bool hasRelativeCoords = false;
+ TouchDeviceData dev;
+ for (int i = 0; i < deviceinfo->num_classes; ++i) {
+ XIAnyClassInfo *classinfo = deviceinfo->classes[i];
+ switch (classinfo->type) {
#ifdef XCB_USE_XINPUT22
- case XITouchClass: {
- XITouchClassInfo *tci = reinterpret_cast<XITouchClassInfo *>(classinfo);
- maxTouchPoints = tci->num_touches;
- qCDebug(lcQpaXInputDevices, " has touch class with mode %d", tci->mode);
- switch (tci->mode) {
- case XIDependentTouch:
- type = QTouchDevice::TouchPad;
- break;
- case XIDirectTouch:
- type = QTouchDevice::TouchScreen;
- break;
- }
+ case XITouchClass: {
+ XITouchClassInfo *tci = reinterpret_cast<XITouchClassInfo *>(classinfo);
+ maxTouchPoints = tci->num_touches;
+ qCDebug(lcQpaXInputDevices, " has touch class with mode %d", tci->mode);
+ switch (tci->mode) {
+ case XIDependentTouch:
+ type = QTouchDevice::TouchPad;
+ break;
+ case XIDirectTouch:
+ type = QTouchDevice::TouchScreen;
break;
}
+ break;
+ }
#endif // XCB_USE_XINPUT22
- case XIValuatorClass: {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
- // Some devices (mice) report a resolution of 0; they will be excluded later,
- // for now just prevent a division by zero
- const int vciResolution = vci->resolution ? vci->resolution : 1;
- if (vci->label == atom(QXcbAtom::AbsMTPositionX))
- caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
- else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
- caps |= QTouchDevice::Area;
- else if (vci->label == atom(QXcbAtom::AbsMTOrientation))
- dev->providesTouchOrientation = true;
- else if (vci->label == atom(QXcbAtom::AbsMTPressure) || vci->label == atom(QXcbAtom::AbsPressure))
- caps |= QTouchDevice::Pressure;
- else if (vci->label == atom(QXcbAtom::RelX)) {
- hasRelativeCoords = true;
- dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
- } else if (vci->label == atom(QXcbAtom::RelY)) {
- hasRelativeCoords = true;
- dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
- } else if (vci->label == atom(QXcbAtom::AbsX)) {
- caps |= QTouchDevice::Position;
- dev->size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
- } else if (vci->label == atom(QXcbAtom::AbsY)) {
- caps |= QTouchDevice::Position;
- dev->size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
- }
- break;
+ case XIValuatorClass: {
+ XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
+ const QXcbAtom::Atom valuatorAtom = qatom(vci->label);
+ if (valuatorAtom < QXcbAtom::NAtoms) {
+ TouchDeviceData::ValuatorClassInfo info;
+ info.min = vci->min;
+ info.max = vci->max;
+ info.number = vci->number;
+ info.label = valuatorAtom;
+ dev.valuatorInfo.append(info);
}
- default:
- break;
+ // Some devices (mice) report a resolution of 0; they will be excluded later,
+ // for now just prevent a division by zero
+ const int vciResolution = vci->resolution ? vci->resolution : 1;
+ if (valuatorAtom == QXcbAtom::AbsMTPositionX)
+ caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
+ else if (valuatorAtom == QXcbAtom::AbsMTTouchMajor)
+ caps |= QTouchDevice::Area;
+ else if (valuatorAtom == QXcbAtom::AbsMTOrientation)
+ dev.providesTouchOrientation = true;
+ else if (valuatorAtom == QXcbAtom::AbsMTPressure || valuatorAtom == QXcbAtom::AbsPressure)
+ caps |= QTouchDevice::Pressure;
+ else if (valuatorAtom == QXcbAtom::RelX) {
+ hasRelativeCoords = true;
+ dev.size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
+ } else if (valuatorAtom == QXcbAtom::RelY) {
+ hasRelativeCoords = true;
+ dev.size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
+ } else if (valuatorAtom == QXcbAtom::AbsX) {
+ caps |= QTouchDevice::Position;
+ dev.size.setWidth((vci->max - vci->min) * 1000.0 / vciResolution);
+ } else if (valuatorAtom == QXcbAtom::AbsY) {
+ caps |= QTouchDevice::Position;
+ dev.size.setHeight((vci->max - vci->min) * 1000.0 / vciResolution);
}
+ break;
}
- if (type < 0 && caps && hasRelativeCoords) {
- type = QTouchDevice::TouchPad;
- if (dev->size.width() < 10 || dev->size.height() < 10 ||
- dev->size.width() > 10000 || dev->size.height() > 10000)
- dev->size = QSizeF(130, 110);
- }
- if (!isAtLeastXI22() || type == QTouchDevice::TouchPad)
- caps |= QTouchDevice::MouseEmulation;
-
- if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) {
- dev->qtTouchDevice = new QTouchDevice;
- dev->qtTouchDevice->setName(QString::fromUtf8(dev->xiDeviceInfo->name));
- dev->qtTouchDevice->setType((QTouchDevice::DeviceType)type);
- dev->qtTouchDevice->setCapabilities(caps);
- dev->qtTouchDevice->setMaximumTouchPoints(maxTouchPoints);
- if (caps != 0)
- QWindowSystemInterface::registerTouchDevice(dev->qtTouchDevice);
- m_touchDevices[id] = dev;
- } else {
- XIFreeDeviceInfo(dev->xiDeviceInfo);
- delete dev;
- dev = 0;
+ default:
+ break;
}
}
- return dev;
+ if (type < 0 && caps && hasRelativeCoords) {
+ type = QTouchDevice::TouchPad;
+ if (dev.size.width() < 10 || dev.size.height() < 10 ||
+ dev.size.width() > 10000 || dev.size.height() > 10000)
+ dev.size = QSizeF(130, 110);
+ }
+ if (!isAtLeastXI22() || type == QTouchDevice::TouchPad)
+ caps |= QTouchDevice::MouseEmulation;
+
+ if (type >= QTouchDevice::TouchScreen && type <= QTouchDevice::TouchPad) {
+ dev.qtTouchDevice = new QTouchDevice;
+ dev.qtTouchDevice->setName(QString::fromUtf8(deviceinfo->name));
+ dev.qtTouchDevice->setType((QTouchDevice::DeviceType)type);
+ dev.qtTouchDevice->setCapabilities(caps);
+ dev.qtTouchDevice->setMaximumTouchPoints(maxTouchPoints);
+ if (caps != 0)
+ QWindowSystemInterface::registerTouchDevice(dev.qtTouchDevice);
+ m_touchDevices[deviceinfo->deviceid] = dev;
+ isTouchDevice = true;
+ }
+
+ return isTouchDevice ? &m_touchDevices[deviceinfo->deviceid] : nullptr;
}
#if defined(XCB_USE_XINPUT21) || QT_CONFIG(tabletevent)
@@ -525,7 +532,7 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
break;
}
case XI_HierarchyChanged:
- xi2HandleHierachyEvent(xiEvent);
+ xi2HandleHierarchyEvent(xiEvent);
return;
case XI_DeviceChanged:
xi2HandleDeviceChangedEvent(xiEvent);
@@ -549,9 +556,8 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
#endif // QT_CONFIG(tabletevent)
#ifdef XCB_USE_XINPUT21
- QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(sourceDeviceId);
- if (device != m_scrollingDevices.end())
- xi2HandleScrollEvent(xiEvent, device.value());
+ if (ScrollingDevice *device = scrollingDeviceForId(sourceDeviceId))
+ xi2HandleScrollEvent(xiEvent, *device);
#endif // XCB_USE_XINPUT21
#ifdef XCB_USE_XINPUT22
@@ -588,19 +594,24 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
}
#ifdef XCB_USE_XINPUT22
-static qreal valuatorNormalized(double value, XIValuatorClassInfo *vci)
+bool QXcbConnection::xi2MouseEvents() const
+{
+ static bool mouseViaXI2 = !qEnvironmentVariableIsSet("QT_XCB_NO_XI2_MOUSE");
+ // FIXME: Don't use XInput2 mouse events when Xinerama extension
+ // is enabled, because it causes problems with multi-monitor setup.
+ return mouseViaXI2 && isAtLeastXI22() && !has_xinerama_extension;
+}
+
+bool QXcbConnection::isTouchScreen(int id)
{
- if (value > vci->max)
- value = vci->max;
- if (value < vci->min)
- value = vci->min;
- return (value - vci->min) / (vci->max - vci->min);
+ auto device = touchDeviceForId(id);
+ return device && device->qtTouchDevice->type() == QTouchDevice::TouchScreen;
}
void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindow)
{
xXIDeviceEvent *xiDeviceEvent = static_cast<xXIDeviceEvent *>(xiDevEvent);
- XInput2TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid);
+ TouchDeviceData *dev = touchDeviceForId(xiDeviceEvent->sourceid);
Q_ASSERT(dev);
const bool firstTouch = dev->touchPoints.isEmpty();
if (xiDeviceEvent->evtype == XI_TouchBegin) {
@@ -617,53 +628,53 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
qreal nx = -1.0, ny = -1.0;
qreal w = 0.0, h = 0.0;
bool majorAxisIsY = touchPoint.area.height() > touchPoint.area.width();
- for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
- XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
- if (classinfo->type == XIValuatorClass) {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classinfo);
- int n = vci->number;
- double value;
- if (!xi2GetValuatorValueIfSet(xiDeviceEvent, n, &value))
- continue;
- if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
- qCDebug(lcQpaXInputEvents, " valuator %20s value %lf from range %lf -> %lf",
- atomName(vci->label).constData(), value, vci->min, vci->max );
- if (vci->label == atom(QXcbAtom::RelX)) {
- nx = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::RelY)) {
- ny = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::AbsX)) {
- nx = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::AbsY)) {
- ny = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::AbsMTPositionX)) {
- nx = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
- ny = valuatorNormalized(value, vci);
- } else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) {
- const qreal sw = screen->geometry().width();
- const qreal sh = screen->geometry().height();
- w = valuatorNormalized(value, vci) * std::sqrt(sw * sw + sh * sh);
- } else if (vci->label == atom(QXcbAtom::AbsMTTouchMinor)) {
- const qreal sw = screen->geometry().width();
- const qreal sh = screen->geometry().height();
- h = valuatorNormalized(value, vci) * std::sqrt(sw * sw + sh * sh);
- } else if (vci->label == atom(QXcbAtom::AbsMTOrientation)) {
- // Find the closest axis.
- // 0 corresponds to the Y axis, vci->max to the X axis.
- // Flipping over the Y axis and rotating by 180 degrees
- // don't change the result, so normalize value to range
- // [0, vci->max] first.
- value = qAbs(value);
- while (value > vci->max)
- value -= 2 * vci->max;
- value = qAbs(value);
- majorAxisIsY = value < vci->max - value;
- } else if (vci->label == atom(QXcbAtom::AbsMTPressure) ||
- vci->label == atom(QXcbAtom::AbsPressure)) {
- touchPoint.pressure = valuatorNormalized(value, vci);
- }
+ for (const TouchDeviceData::ValuatorClassInfo vci : dev->valuatorInfo) {
+ double value;
+ if (!xi2GetValuatorValueIfSet(xiDeviceEvent, vci.number, &value))
+ continue;
+ if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
+ qCDebug(lcQpaXInputEvents, " valuator %20s value %lf from range %lf -> %lf",
+ atomName(vci.label).constData(), value, vci.min, vci.max);
+ if (value > vci.max)
+ value = vci.max;
+ if (value < vci.min)
+ value = vci.min;
+ qreal valuatorNormalized = (value - vci.min) / (vci.max - vci.min);
+ if (vci.label == QXcbAtom::RelX) {
+ nx = valuatorNormalized;
+ } else if (vci.label == QXcbAtom::RelY) {
+ ny = valuatorNormalized;
+ } else if (vci.label == QXcbAtom::AbsX) {
+ nx = valuatorNormalized;
+ } else if (vci.label == QXcbAtom::AbsY) {
+ ny = valuatorNormalized;
+ } else if (vci.label == QXcbAtom::AbsMTPositionX) {
+ nx = valuatorNormalized;
+ } else if (vci.label == QXcbAtom::AbsMTPositionY) {
+ ny = valuatorNormalized;
+ } else if (vci.label == QXcbAtom::AbsMTTouchMajor) {
+ const qreal sw = screen->geometry().width();
+ const qreal sh = screen->geometry().height();
+ w = valuatorNormalized * std::sqrt(sw * sw + sh * sh);
+ } else if (vci.label == QXcbAtom::AbsMTTouchMinor) {
+ const qreal sw = screen->geometry().width();
+ const qreal sh = screen->geometry().height();
+ h = valuatorNormalized * std::sqrt(sw * sw + sh * sh);
+ } else if (vci.label == QXcbAtom::AbsMTOrientation) {
+ // Find the closest axis.
+ // 0 corresponds to the Y axis, vci.max to the X axis.
+ // Flipping over the Y axis and rotating by 180 degrees
+ // don't change the result, so normalize value to range
+ // [0, vci.max] first.
+ value = qAbs(value);
+ while (value > vci.max)
+ value -= 2 * vci.max;
+ value = qAbs(value);
+ majorAxisIsY = value < vci.max - value;
+ } else if (vci.label == QXcbAtom::AbsMTPressure || vci.label == QXcbAtom::AbsPressure) {
+ touchPoint.pressure = valuatorNormalized;
}
+
}
// If any value was not updated, use the last-known value.
if (nx == -1.0) {
@@ -765,12 +776,12 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
bool QXcbConnection::startSystemResizeForTouchBegin(xcb_window_t window, const QPoint &point, Qt::Corner corner)
{
- QHash<int, XInput2TouchDeviceData*>::const_iterator devIt = m_touchDevices.constBegin();
+ QHash<int, TouchDeviceData>::const_iterator devIt = m_touchDevices.constBegin();
for (; devIt != m_touchDevices.constEnd(); ++devIt) {
- XInput2TouchDeviceData *deviceData = devIt.value();
- if (deviceData->qtTouchDevice->type() == QTouchDevice::TouchScreen) {
- QHash<int, QPointF>::const_iterator pointIt = deviceData->pointPressedPosition.constBegin();
- for (; pointIt != deviceData->pointPressedPosition.constEnd(); ++pointIt) {
+ TouchDeviceData deviceData = devIt.value();
+ if (deviceData.qtTouchDevice->type() == QTouchDevice::TouchScreen) {
+ QHash<int, QPointF>::const_iterator pointIt = deviceData.pointPressedPosition.constBegin();
+ for (; pointIt != deviceData.pointPressedPosition.constEnd(); ++pointIt) {
if (pointIt.value().toPoint() == point) {
m_startSystemResizeInfo.window = window;
m_startSystemResizeInfo.deviceid = devIt.key();
@@ -845,7 +856,7 @@ bool QXcbConnection::xi2SetMouseGrabEnabled(xcb_window_t w, bool grab)
}
#endif // XCB_USE_XINPUT22
-void QXcbConnection::xi2HandleHierachyEvent(void *event)
+void QXcbConnection::xi2HandleHierarchyEvent(void *event)
{
xXIHierarchyEvent *xiEvent = reinterpret_cast<xXIHierarchyEvent *>(event);
// We only care about hotplugged devices
@@ -860,42 +871,47 @@ void QXcbConnection::xi2HandleHierachyEvent(void *event)
void QXcbConnection::xi2HandleDeviceChangedEvent(void *event)
{
xXIDeviceChangedEvent *xiEvent = reinterpret_cast<xXIDeviceChangedEvent *>(event);
-
- // ### If a slave device changes (XIDeviceChange), we should probably run setup on it again.
- if (xiEvent->reason != XISlaveSwitch)
- return;
-
+ switch (xiEvent->reason) {
+ case XIDeviceChange: {
+ int nrDevices = 0;
+ Display *dpy = static_cast<Display *>(m_xlib_display);
+ XIDeviceInfo* deviceInfo = XIQueryDevice(dpy, xiEvent->sourceid, &nrDevices);
+ if (nrDevices <= 0)
+ return;
+ xi2SetupDevice(deviceInfo);
+ XIFreeDeviceInfo(deviceInfo);
+ break;
+ }
+ case XISlaveSwitch: {
#ifdef XCB_USE_XINPUT21
- // This code handles broken scrolling device drivers that reset absolute positions
- // when they are made active. Whenever a new slave device is made active the
- // primary pointer sends a DeviceChanged event with XISlaveSwitch, and the new
- // active slave in sourceid.
-
- QHash<int, ScrollingDevice>::iterator device = m_scrollingDevices.find(xiEvent->sourceid);
- if (device == m_scrollingDevices.end())
- return;
+ if (ScrollingDevice *scrollingDevice = scrollingDeviceForId(xiEvent->sourceid))
+ xi2UpdateScrollingDevice(*scrollingDevice);
+#endif
+ break;
+ }
+ default:
+ qCDebug(lcQpaXInputEvents, "unknown device-changed-event (device %d)", xiEvent->sourceid);
+ break;
+ }
+}
+#ifdef XCB_USE_XINPUT21
+void QXcbConnection::xi2UpdateScrollingDevice(ScrollingDevice &scrollingDevice)
+{
int nrDevices = 0;
- XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), xiEvent->sourceid, &nrDevices);
+ Display *dpy = static_cast<Display *>(m_xlib_display);
+ XIDeviceInfo* deviceInfo = XIQueryDevice(dpy, scrollingDevice.deviceId, &nrDevices);
if (nrDevices <= 0) {
- qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", xiEvent->sourceid);
+ qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", scrollingDevice.deviceId);
return;
}
- updateScrollingDevice(*device, xiDeviceInfo->num_classes, xiDeviceInfo->classes);
- XIFreeDeviceInfo(xiDeviceInfo);
-#endif
-}
-
-void QXcbConnection::updateScrollingDevice(ScrollingDevice &scrollingDevice, int num_classes, void *classInfo)
-{
-#ifdef XCB_USE_XINPUT21
- XIAnyClassInfo **classes = reinterpret_cast<XIAnyClassInfo**>(classInfo);
QPointF lastScrollPosition;
if (lcQpaXInput().isDebugEnabled())
lastScrollPosition = scrollingDevice.lastScrollPosition;
- for (int c = 0; c < num_classes; ++c) {
- if (classes[c]->type == XIValuatorClass) {
- XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classes[c]);
+ for (int c = 0; c < deviceInfo->num_classes; ++c) {
+ XIAnyClassInfo *classInfo = deviceInfo->classes[c];
+ if (classInfo->type == XIValuatorClass) {
+ XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(classInfo);
const int valuatorAtom = qatom(vci->label);
if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
scrollingDevice.lastScrollPosition.setX(vci->value);
@@ -908,37 +924,30 @@ void QXcbConnection::updateScrollingDevice(ScrollingDevice &scrollingDevice, int
lastScrollPosition.x(), lastScrollPosition.y(),
scrollingDevice.lastScrollPosition.x(),
scrollingDevice.lastScrollPosition.y());
-#else
- Q_UNUSED(scrollingDevice);
- Q_UNUSED(num_classes);
- Q_UNUSED(classInfo);
-#endif
+
+ XIFreeDeviceInfo(deviceInfo);
}
-#ifdef XCB_USE_XINPUT21
-void QXcbConnection::handleEnterEvent()
+void QXcbConnection::xi2UpdateScrollingDevices()
{
QHash<int, ScrollingDevice>::iterator it = m_scrollingDevices.begin();
const QHash<int, ScrollingDevice>::iterator end = m_scrollingDevices.end();
while (it != end) {
- ScrollingDevice& scrollingDevice = it.value();
- int nrDevices = 0;
- XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), scrollingDevice.deviceId, &nrDevices);
- if (nrDevices <= 0) {
- qCDebug(lcQpaXInputDevices, "scrolling device %d no longer present", scrollingDevice.deviceId);
- it = m_scrollingDevices.erase(it);
- continue;
- }
- updateScrollingDevice(scrollingDevice, xiDeviceInfo->num_classes, xiDeviceInfo->classes);
- XIFreeDeviceInfo(xiDeviceInfo);
+ xi2UpdateScrollingDevice(it.value());
++it;
}
}
-#endif
+
+QXcbConnection::ScrollingDevice *QXcbConnection::scrollingDeviceForId(int id)
+{
+ ScrollingDevice *dev = nullptr;
+ if (m_scrollingDevices.contains(id))
+ dev = &m_scrollingDevices[id];
+ return dev;
+}
void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice)
{
-#ifdef XCB_USE_XINPUT21
xXIGenericDeviceEvent *xiEvent = reinterpret_cast<xXIGenericDeviceEvent *>(event);
if (xiEvent->evtype == XI_Motion && scrollingDevice.orientations) {
@@ -1008,10 +1017,51 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin
}
}
}
-#else
- Q_UNUSED(event);
- Q_UNUSED(scrollingDevice);
+}
#endif // XCB_USE_XINPUT21
+
+static int xi2ValuatorOffset(const unsigned char *maskPtr, int maskLen, int number)
+{
+ int offset = 0;
+ for (int i = 0; i < maskLen; i++) {
+ if (number < 8) {
+ if ((maskPtr[i] & (1 << number)) == 0)
+ return -1;
+ }
+ for (int j = 0; j < 8; j++) {
+ if (j == number)
+ return offset;
+ if (maskPtr[i] & (1 << j))
+ offset++;
+ }
+ number -= 8;
+ }
+ return -1;
+}
+
+bool QXcbConnection::xi2GetValuatorValueIfSet(const void *event, int valuatorNum, double *value)
+{
+ const xXIDeviceEvent *xideviceevent = static_cast<const xXIDeviceEvent *>(event);
+ const unsigned char *buttonsMaskAddr = (const unsigned char*)&xideviceevent[1];
+ const unsigned char *valuatorsMaskAddr = buttonsMaskAddr + xideviceevent->buttons_len * 4;
+ FP3232 *valuatorsValuesAddr = (FP3232*)(valuatorsMaskAddr + xideviceevent->valuators_len * 4);
+
+ int valuatorOffset = xi2ValuatorOffset(valuatorsMaskAddr, xideviceevent->valuators_len, valuatorNum);
+ if (valuatorOffset < 0)
+ return false;
+
+ *value = valuatorsValuesAddr[valuatorOffset].integral;
+ *value += ((double)valuatorsValuesAddr[valuatorOffset].frac / (1 << 16) / (1 << 16));
+ return true;
+}
+
+void QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *event)
+{
+ // xcb event structs contain stuff that wasn't on the wire, the full_sequence field
+ // adds an extra 4 bytes and generic events cookie data is on the wire right after the standard 32 bytes.
+ // Move this data back to have the same layout in memory as it was on the wire
+ // and allow casting, overwriting the full_sequence field.
+ memmove((char*) event + 32, (char*) event + 36, event->length * 4);
}
Qt::MouseButton QXcbConnection::xiToQtMouseButton(uint32_t b)
@@ -1028,13 +1078,6 @@ Qt::MouseButton QXcbConnection::xiToQtMouseButton(uint32_t b)
return Qt::NoButton;
}
-bool QXcbConnection::isTouchScreen(int id) const
-{
- auto device = m_touchDevices.value(id);
- return device && device->qtTouchDevice
- && device->qtTouchDevice->type() == QTouchDevice::TouchScreen;
-}
-
#if QT_CONFIG(tabletevent)
static QTabletEvent::TabletDevice toolIdToTabletDevice(quint32 toolId) {
// keep in sync with wacom_intuos_inout() in Linux kernel driver wacom_wac.c
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index 7c62c2e2b3..da63360333 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -579,7 +579,7 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
if (cursor)
return cursor;
if (!cursor && cursorId) {
- cursor = XCreateFontCursor(DISPLAY_FROM_XCB(this), cursorId);
+ cursor = XCreateFontCursor(static_cast<Display *>(connection()->xlib_display()), cursorId);
if (cursor)
return cursor;
}
@@ -631,10 +631,9 @@ void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDes
*pos = QPoint();
xcb_window_t root = c->primaryVirtualDesktop()->root();
- xcb_query_pointer_cookie_t cookie = xcb_query_pointer(c->xcb_connection(), root);
- xcb_generic_error_t *err = 0;
- xcb_query_pointer_reply_t *reply = xcb_query_pointer_reply(c->xcb_connection(), cookie, &err);
- if (!err && reply) {
+
+ auto reply = Q_XCB_REPLY(xcb_query_pointer, c->xcb_connection(), root);
+ if (reply) {
if (virtualDesktop) {
const auto virtualDesktops = c->virtualDesktops();
for (QXcbVirtualDesktop *vd : virtualDesktops) {
@@ -648,11 +647,8 @@ void QXcbCursor::queryPointer(QXcbConnection *c, QXcbVirtualDesktop **virtualDes
*pos = QPoint(reply->root_x, reply->root_y);
if (keybMask)
*keybMask = reply->mask;
- free(reply);
return;
}
- free(err);
- free(reply);
}
QPoint QXcbCursor::pos() const
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index 60d142157f..d4521de8e0 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -94,32 +94,27 @@ static xcb_window_t xdndProxy(QXcbConnection *c, xcb_window_t w)
{
xcb_window_t proxy = XCB_NONE;
- xcb_get_property_cookie_t cookie = Q_XCB_CALL2(xcb_get_property(c->xcb_connection(), false, w, c->atom(QXcbAtom::XdndProxy),
- XCB_ATOM_WINDOW, 0, 1), c);
- xcb_get_property_reply_t *reply = xcb_get_property_reply(c->xcb_connection(), cookie, 0);
+ auto reply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(),
+ false, w, c->atom(QXcbAtom::XdndProxy), XCB_ATOM_WINDOW, 0, 1);
if (reply && reply->type == XCB_ATOM_WINDOW)
- proxy = *((xcb_window_t *)xcb_get_property_value(reply));
- free(reply);
+ proxy = *((xcb_window_t *)xcb_get_property_value(reply.get()));
if (proxy == XCB_NONE)
return proxy;
// exists and is real?
- cookie = Q_XCB_CALL2(xcb_get_property(c->xcb_connection(), false, proxy, c->atom(QXcbAtom::XdndProxy),
- XCB_ATOM_WINDOW, 0, 1), c);
- reply = xcb_get_property_reply(c->xcb_connection(), cookie, 0);
+ reply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(),
+ false, proxy, c->atom(QXcbAtom::XdndProxy), XCB_ATOM_WINDOW, 0, 1);
if (reply && reply->type == XCB_ATOM_WINDOW) {
- xcb_window_t p = *((xcb_window_t *)xcb_get_property_value(reply));
+ xcb_window_t p = *((xcb_window_t *)xcb_get_property_value(reply.get()));
if (proxy != p)
proxy = 0;
} else {
proxy = 0;
}
- free(reply);
-
return proxy;
}
@@ -142,7 +137,7 @@ protected:
QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c)
{
- dropData = new QXcbDropData(this);
+ m_dropData = new QXcbDropData(this);
init();
cleanup_timer = -1;
@@ -150,7 +145,7 @@ QXcbDrag::QXcbDrag(QXcbConnection *c) : QXcbObject(c)
QXcbDrag::~QXcbDrag()
{
- delete dropData;
+ delete m_dropData;
}
void QXcbDrag::init()
@@ -172,11 +167,6 @@ void QXcbDrag::init()
drag_types.clear();
}
-QMimeData *QXcbDrag::platformDropData()
-{
- return dropData;
-}
-
bool QXcbDrag::eventFilter(QObject *o, QEvent *e)
{
/* We are setting a mouse grab on the QShapedPixmapWindow in order not to
@@ -228,28 +218,19 @@ void QXcbDrag::endDrag()
initiatorWindow.clear();
}
-static xcb_translate_coordinates_reply_t *
-translateCoordinates(QXcbConnection *c, xcb_window_t from, xcb_window_t to, int x, int y)
-{
- xcb_translate_coordinates_cookie_t cookie =
- xcb_translate_coordinates(c->xcb_connection(), from, to, x, y);
- return xcb_translate_coordinates_reply(c->xcb_connection(), cookie, 0);
-}
-
static
bool windowInteractsWithPosition(xcb_connection_t *connection, const QPoint & pos, xcb_window_t w, xcb_shape_sk_t shapeType)
{
bool interacts = false;
- xcb_shape_get_rectangles_reply_t *reply = xcb_shape_get_rectangles_reply(connection, xcb_shape_get_rectangles(connection, w, shapeType), NULL);
+ auto reply = Q_XCB_REPLY(xcb_shape_get_rectangles, connection, w, shapeType);
if (reply) {
- xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply);
+ xcb_rectangle_t *rectangles = xcb_shape_get_rectangles_rectangles(reply.get());
if (rectangles) {
- const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply);
+ const int nRectangles = xcb_shape_get_rectangles_rectangles_length(reply.get());
for (int i = 0; !interacts && i < nRectangles; ++i) {
interacts = QRect(rectangles[i].x, rectangles[i].y, rectangles[i].width, rectangles[i].height).contains(pos);
}
}
- free(reply);
}
return interacts;
@@ -261,33 +242,25 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
return 0;
if (md) {
- xcb_get_window_attributes_cookie_t cookie = xcb_get_window_attributes(xcb_connection(), w);
- xcb_get_window_attributes_reply_t *reply = xcb_get_window_attributes_reply(xcb_connection(), cookie, 0);
+ auto reply = Q_XCB_REPLY(xcb_get_window_attributes, xcb_connection(), w);
if (!reply)
return 0;
if (reply->map_state != XCB_MAP_STATE_VIEWABLE)
return 0;
- free(reply);
-
- xcb_get_geometry_cookie_t gcookie = xcb_get_geometry(xcb_connection(), w);
- xcb_get_geometry_reply_t *greply = xcb_get_geometry_reply(xcb_connection(), gcookie, 0);
+ auto greply = Q_XCB_REPLY(xcb_get_geometry, xcb_connection(), w);
if (!greply)
return 0;
QRect windowRect(greply->x, greply->y, greply->width, greply->height);
- free(greply);
if (windowRect.contains(pos)) {
bool windowContainsMouse = !ignoreNonXdndAwareWindows;
{
- xcb_get_property_cookie_t cookie =
- Q_XCB_CALL(xcb_get_property(xcb_connection(), false, w, connection()->atom(QXcbAtom::XdndAware),
- XCB_GET_PROPERTY_TYPE_ANY, 0, 0));
- xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);
-
+ auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
+ false, w, connection()->atom(QXcbAtom::XdndAware),
+ XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
bool isAware = reply && reply->type != XCB_NONE;
- free(reply);
if (isAware) {
const QPoint relPos = pos - windowRect.topLeft();
// When ShapeInput and ShapeBounding are not set they return a single rectangle with the geometry of the window, this is why we
@@ -303,19 +276,16 @@ xcb_window_t QXcbDrag::findRealWindow(const QPoint & pos, xcb_window_t w, int md
}
}
- xcb_query_tree_cookie_t cookie = xcb_query_tree (xcb_connection(), w);
- xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, 0);
-
+ auto reply = Q_XCB_REPLY(xcb_query_tree, xcb_connection(), w);
if (!reply)
return 0;
- int nc = xcb_query_tree_children_length(reply);
- xcb_window_t *c = xcb_query_tree_children(reply);
+ int nc = xcb_query_tree_children_length(reply.get());
+ xcb_window_t *c = xcb_query_tree_children(reply.get());
xcb_window_t r = 0;
for (uint i = nc; !r && i--;)
r = findRealWindow(pos - windowRect.topLeft(), c[i], md-1, ignoreNonXdndAwareWindows);
- free(reply);
if (r)
return r;
@@ -356,15 +326,14 @@ void QXcbDrag::move(const QPoint &globalPos)
}
xcb_window_t rootwin = current_virtual_desktop->root();
- xcb_translate_coordinates_reply_t *translate =
- ::translateCoordinates(connection(), rootwin, rootwin, globalPos.x(), globalPos.y());
+ auto translate = Q_XCB_REPLY(xcb_translate_coordinates, connection()->xcb_connection(),
+ rootwin, rootwin, globalPos.x(), globalPos.y());
if (!translate)
return;
xcb_window_t target = translate->child;
int lx = translate->dst_x;
int ly = translate->dst_y;
- free (translate);
if (target && target != rootwin) {
xcb_window_t src = rootwin;
@@ -372,7 +341,8 @@ void QXcbDrag::move(const QPoint &globalPos)
DNDDEBUG << "checking target for XdndAware" << target << lx << ly;
// translate coordinates
- translate = ::translateCoordinates(connection(), src, target, lx, ly);
+ auto translate = Q_XCB_REPLY(xcb_translate_coordinates, connection()->xcb_connection(),
+ src, target, lx, ly);
if (!translate) {
target = 0;
break;
@@ -381,14 +351,11 @@ void QXcbDrag::move(const QPoint &globalPos)
ly = translate->dst_y;
src = target;
xcb_window_t child = translate->child;
- free(translate);
// check if it has XdndAware
- xcb_get_property_cookie_t cookie = Q_XCB_CALL(xcb_get_property(xcb_connection(), false, target,
- atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0));
- xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);
+ auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, target,
+ atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
bool aware = reply && reply->type != XCB_NONE;
- free(reply);
if (aware) {
DNDDEBUG << "Found XdndAware on " << target;
break;
@@ -422,16 +389,14 @@ void QXcbDrag::move(const QPoint &globalPos)
int target_version = 1;
if (proxy_target) {
- xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, proxy_target,
- atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1);
- xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);
+ auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
+ false, proxy_target,
+ atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 1);
if (!reply || reply->type == XCB_NONE)
target = 0;
- target_version = *(uint32_t *)xcb_get_property_value(reply);
+ target_version = *(uint32_t *)xcb_get_property_value(reply.get());
target_version = qMin(xdnd_version, target_version ? target_version : 1);
-
- free(reply);
}
if (target != current_target) {
@@ -714,21 +679,19 @@ void QXcbDrag::handleEnter(QPlatformWindow *window, const xcb_client_message_eve
if (event->data.data32[1] & 1) {
// get the types from XdndTypeList
- xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, xdnd_dragsource,
- atom(QXcbAtom::XdndTypelist), XCB_ATOM_ATOM,
- 0, xdnd_max_type);
- xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, 0);
+ auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, xdnd_dragsource,
+ atom(QXcbAtom::XdndTypelist), XCB_ATOM_ATOM,
+ 0, xdnd_max_type);
if (reply && reply->type != XCB_NONE && reply->format == 32) {
- int length = xcb_get_property_value_length(reply) / 4;
+ int length = xcb_get_property_value_length(reply.get()) / 4;
if (length > xdnd_max_type)
length = xdnd_max_type;
- xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply);
+ xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply.get());
xdnd_types.reserve(length);
for (int i = 0; i < length; ++i)
xdnd_types.append(atoms[i]);
}
- free(reply);
} else {
// get the types from the message
for(int i = 2; i < 5; i++) {
@@ -769,7 +732,7 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message
dropData = currentDrag()->mimeData();
supported_actions = currentDrag()->supportedActions();
} else {
- dropData = platformDropData();
+ dropData = m_dropData;
supported_actions = Qt::DropActions(toDropAction(e->data.data32[4]));
}
@@ -812,8 +775,8 @@ void QXcbDrag::handle_xdnd_position(QPlatformWindow *w, const xcb_client_message
handle_xdnd_status(&response);
else
#endif
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target,
- XCB_EVENT_MASK_NO_EVENT, (const char *)&response));
+ xcb_send_event(xcb_connection(), false, current_proxy_target,
+ XCB_EVENT_MASK_NO_EVENT, (const char *)&response);
}
namespace
@@ -990,7 +953,7 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e
dropData = currentDrag()->mimeData();
supported_drop_actions = Qt::DropActions(l[4]);
} else {
- dropData = platformDropData();
+ dropData = m_dropData;
supported_drop_actions = accepted_drop_action;
// Drop coming from another app? Update keyboard modifiers.
@@ -1017,8 +980,8 @@ void QXcbDrag::handleDrop(QPlatformWindow *, const xcb_client_message_event_t *e
finished.data.data32[0] = currentWindow ? xcb_window(currentWindow.data()) : XCB_NONE;
finished.data.data32[1] = response.isAccepted(); // flags
finished.data.data32[2] = toXdndAction(response.acceptedAction());
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, current_proxy_target,
- XCB_EVENT_MASK_NO_EVENT, (char *)&finished));
+ xcb_send_event(xcb_connection(), false, current_proxy_target,
+ XCB_EVENT_MASK_NO_EVENT, (char *)&finished);
xdnd_dragsource = 0;
currentWindow.clear();
@@ -1132,28 +1095,20 @@ static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window)
xcb_window_t target = 0;
forever {
// check if window has XdndAware
- xcb_get_property_cookie_t gpCookie = Q_XCB_CALL(
- xcb_get_property(c->xcb_connection(), false, window,
- c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0));
- xcb_get_property_reply_t *gpReply = xcb_get_property_reply(
- c->xcb_connection(), gpCookie, 0);
+ auto gpReply = Q_XCB_REPLY(xcb_get_property, c->xcb_connection(), false, window,
+ c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0);
bool aware = gpReply && gpReply->type != XCB_NONE;
- free(gpReply);
if (aware) {
target = window;
break;
}
// try window's parent
- xcb_query_tree_cookie_t qtCookie = Q_XCB_CALL(
- xcb_query_tree_unchecked(c->xcb_connection(), window));
- xcb_query_tree_reply_t *qtReply = xcb_query_tree_reply(
- c->xcb_connection(), qtCookie, NULL);
+ auto qtReply = Q_XCB_REPLY_UNCHECKED(xcb_query_tree, c->xcb_connection(), window);
if (!qtReply)
break;
xcb_window_t root = qtReply->root;
xcb_window_t parent = qtReply->parent;
- free(qtReply);
if (window == root)
break;
window = parent;
diff --git a/src/plugins/platforms/xcb/qxcbdrag.h b/src/plugins/platforms/xcb/qxcbdrag.h
index 2d152edf76..f261cc1322 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.h
+++ b/src/plugins/platforms/xcb/qxcbdrag.h
@@ -74,7 +74,6 @@ public:
QXcbDrag(QXcbConnection *c);
~QXcbDrag();
- QMimeData *platformDropData() override;
bool eventFilter(QObject *o, QEvent *e) override;
void startDrag() override;
@@ -117,7 +116,7 @@ private:
QPointer<QWindow> currentWindow;
QPoint currentPosition;
- QXcbDropData *dropData;
+ QXcbDropData *m_dropData;
Qt::DropAction accepted_drop_action;
QWindow *desktop_proxy;
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
index c0403d589d..8635a03dcb 100644
--- a/src/plugins/platforms/xcb/qxcbimage.cpp
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -91,19 +91,14 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap
{
xcb_connection_t *conn = connection->xcb_connection();
- xcb_get_image_cookie_t get_image_cookie =
- xcb_get_image_unchecked(conn, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap,
- 0, 0, width, height, 0xffffffff);
-
- xcb_get_image_reply_t *image_reply =
- xcb_get_image_reply(conn, get_image_cookie, NULL);
-
+ auto image_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_image, conn, XCB_IMAGE_FORMAT_Z_PIXMAP, pixmap,
+ 0, 0, width, height, 0xffffffff);
if (!image_reply) {
return QPixmap();
}
- uint8_t *data = xcb_get_image_data(image_reply);
- uint32_t length = xcb_get_image_data_length(image_reply);
+ uint8_t *data = xcb_get_image_data(image_reply.get());
+ uint32_t length = xcb_get_image_data_length(image_reply.get());
QPixmap result;
@@ -165,7 +160,6 @@ QPixmap qt_xcb_pixmapFromXPixmap(QXcbConnection *connection, xcb_pixmap_t pixmap
result = QPixmap::fromImage(image.copy());
}
- free(image_reply);
return result;
}
@@ -203,22 +197,15 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
xcb_connection_t *conn = screen->xcb_connection();
const int w = image.width();
const int h = image.height();
- xcb_generic_error_t *error = 0;
- xcb_render_query_pict_formats_cookie_t formatsCookie = xcb_render_query_pict_formats(conn);
- xcb_render_query_pict_formats_reply_t *formatsReply = xcb_render_query_pict_formats_reply(conn,
- formatsCookie,
- &error);
- if (!formatsReply || error) {
+ auto formats = Q_XCB_REPLY(xcb_render_query_pict_formats, conn);
+ if (!formats) {
qWarning("qt_xcb_createCursorXRender: query_pict_formats failed");
- free(formatsReply);
- free(error);
return XCB_NONE;
}
- xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formatsReply,
+ xcb_render_pictforminfo_t *fmt = xcb_render_util_find_standard_format(formats.get(),
XCB_PICT_STANDARD_ARGB_32);
if (!fmt) {
qWarning("qt_xcb_createCursorXRender: Failed to find format PICT_STANDARD_ARGB_32");
- free(formatsReply);
return XCB_NONE;
}
@@ -230,17 +217,15 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
0, 0, 0);
if (!xi) {
qWarning("qt_xcb_createCursorXRender: xcb_image_create failed");
- free(formatsReply);
return XCB_NONE;
}
xi->data = (uint8_t *) malloc(xi->stride * h);
if (!xi->data) {
qWarning("qt_xcb_createCursorXRender: Failed to malloc() image data");
xcb_image_destroy(xi);
- free(formatsReply);
return XCB_NONE;
}
- memcpy(xi->data, img.constBits(), img.byteCount());
+ memcpy(xi->data, img.constBits(), img.sizeInBytes());
xcb_pixmap_t pix = xcb_generate_id(conn);
xcb_create_pixmap(conn, 32, pix, screen->root(), w, h);
@@ -260,7 +245,6 @@ xcb_cursor_t qt_xcb_createCursorXRender(QXcbScreen *screen, const QImage &image,
xcb_image_destroy(xi);
xcb_render_free_picture(conn, pic);
xcb_free_pixmap(conn, pix);
- free(formatsReply);
return cursor;
#else
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index b372ecd7c4..c8efe2fce8 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -65,6 +65,11 @@
#if QT_CONFIG(xcb_xlib)
#include <X11/Xlib.h>
+#if QT_CONFIG(xcb_native_painting)
+#include "qxcbnativepainting.h"
+#include "qpixmap_x11_p.h"
+#include "qbackingstore_x11_p.h"
+#endif
#endif
#include <qpa/qplatforminputcontextfactory_p.h>
@@ -83,6 +88,11 @@
#include <QtCore/QFileInfo>
+#if QT_CONFIG(vulkan)
+#include "qxcbvulkaninstance.h"
+#include "qxcbvulkanwindow.h"
+#endif
+
QT_BEGIN_NAMESPACE
// Find out if our parent process is gdb by looking at the 'exe' symlink under /proc,.
@@ -187,6 +197,13 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
}
m_fontDatabase.reset(new QGenericUnixFontDatabase());
+
+#if QT_CONFIG(xcb_native_painting)
+ if (nativePaintingEnabled()) {
+ qDebug("QXCB USING NATIVE PAINTING");
+ qt_xcb_native_x11_info_init(defaultConnection());
+ }
+#endif
}
QXcbIntegration::~QXcbIntegration()
@@ -195,15 +212,33 @@ QXcbIntegration::~QXcbIntegration()
m_instance = Q_NULLPTR;
}
+QPlatformPixmap *QXcbIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
+{
+#if QT_CONFIG(xcb_native_painting)
+ if (nativePaintingEnabled())
+ return new QX11PlatformPixmap(type);
+#endif
+
+ return QPlatformIntegration::createPlatformPixmap(type);
+}
+
QPlatformWindow *QXcbIntegration::createPlatformWindow(QWindow *window) const
{
QXcbScreen *screen = static_cast<QXcbScreen *>(window->screen()->handle());
QXcbGlIntegration *glIntegration = screen->connection()->glIntegration();
- if (window->type() != Qt::Desktop && window->supportsOpenGL()) {
- if (glIntegration) {
- QXcbWindow *xcbWindow = glIntegration->createWindow(window);
+ if (window->type() != Qt::Desktop) {
+ if (window->supportsOpenGL()) {
+ if (glIntegration) {
+ QXcbWindow *xcbWindow = glIntegration->createWindow(window);
+ xcbWindow->create();
+ return xcbWindow;
+ }
+#if QT_CONFIG(vulkan)
+ } else if (window->surfaceType() == QSurface::VulkanSurface) {
+ QXcbWindow *xcbWindow = new QXcbVulkanWindow(window);
xcbWindow->create();
return xcbWindow;
+#endif
}
}
@@ -234,6 +269,11 @@ QPlatformOpenGLContext *QXcbIntegration::createPlatformOpenGLContext(QOpenGLCont
QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *window) const
{
+#if QT_CONFIG(xcb_native_painting)
+ if (nativePaintingEnabled())
+ return new QXcbNativeBackingStore(window);
+#endif
+
return new QXcbBackingStore(window);
}
@@ -485,4 +525,21 @@ void QXcbIntegration::beep() const
xcb_bell(connection, 0);
}
+bool QXcbIntegration::nativePaintingEnabled() const
+{
+#if QT_CONFIG(xcb_native_painting)
+ static bool enabled = qEnvironmentVariableIsSet("QT_XCB_NATIVE_PAINTING");
+ return enabled;
+#else
+ return false;
+#endif
+}
+
+#if QT_CONFIG(vulkan)
+QPlatformVulkanInstance *QXcbIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
+{
+ return new QXcbVulkanInstance(instance);
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index b3d72c19d0..186b6c5ddd 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -61,6 +61,7 @@ public:
QXcbIntegration(const QStringList &parameters, int &argc, char **argv);
~QXcbIntegration();
+ QPlatformPixmap *createPlatformPixmap(QPlatformPixmap::PixelType type) const override;
QPlatformWindow *createPlatformWindow(QWindow *window) const override;
QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override;
#ifndef QT_NO_OPENGL
@@ -114,6 +115,12 @@ public:
void beep() const override;
+ bool nativePaintingEnabled() const;
+
+#if QT_CONFIG(vulkan)
+ QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override;
+#endif
+
static QXcbIntegration *instance() { return m_instance; }
private:
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 2e29c208c7..891b53d2dc 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -612,23 +612,18 @@ Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) const
void QXcbKeyboard::readXKBConfig()
{
clearXKBConfig();
- xcb_generic_error_t *error;
- xcb_get_property_cookie_t cookie;
- xcb_get_property_reply_t *config_reply;
xcb_connection_t *c = xcb_connection();
xcb_window_t rootWindow = connection()->rootWindow();
- cookie = xcb_get_property(c, 0, rootWindow,
- atom(QXcbAtom::_XKB_RULES_NAMES), XCB_ATOM_STRING, 0, 1024);
-
- config_reply = xcb_get_property_reply(c, cookie, &error);
+ auto config_reply = Q_XCB_REPLY(xcb_get_property, c, 0, rootWindow,
+ atom(QXcbAtom::_XKB_RULES_NAMES), XCB_ATOM_STRING, 0, 1024);
if (!config_reply) {
qWarning("Qt: Couldn't interpret the _XKB_RULES_NAMES property");
return;
}
- char *xkb_config = (char *)xcb_get_property_value(config_reply);
- int length = xcb_get_property_value_length(config_reply);
+ char *xkb_config = (char *)xcb_get_property_value(config_reply.get());
+ int length = xcb_get_property_value_length(config_reply.get());
// on old X servers xkb_config can be 0 even if config_reply indicates a succesfull read
if (!xkb_config || length == 0)
@@ -653,8 +648,6 @@ void QXcbKeyboard::readXKBConfig()
xkb_names.layout = qstrdup(names[2]);
xkb_names.variant = qstrdup(names[3]);
xkb_names.options = qstrdup(names[4]);
-
- free(config_reply);
}
void QXcbKeyboard::clearXKBConfig()
@@ -1172,23 +1165,19 @@ QXcbKeyboard::~QXcbKeyboard()
void QXcbKeyboard::updateVModMapping()
{
#if QT_CONFIG(xkb)
- xcb_xkb_get_names_cookie_t names_cookie;
- xcb_xkb_get_names_reply_t *name_reply;
xcb_xkb_get_names_value_list_t names_list;
memset(&vmod_masks, 0, sizeof(vmod_masks));
- names_cookie = xcb_xkb_get_names(xcb_connection(),
- XCB_XKB_ID_USE_CORE_KBD,
- XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES);
-
- name_reply = xcb_xkb_get_names_reply(xcb_connection(), names_cookie, 0);
+ auto name_reply = Q_XCB_REPLY(xcb_xkb_get_names, xcb_connection(),
+ XCB_XKB_ID_USE_CORE_KBD,
+ XCB_XKB_NAME_DETAIL_VIRTUAL_MOD_NAMES);
if (!name_reply) {
qWarning("Qt: failed to retrieve the virtual modifier names from XKB");
return;
}
- const void *buffer = xcb_xkb_get_names_value_list(name_reply);
+ const void *buffer = xcb_xkb_get_names_value_list(name_reply.get());
xcb_xkb_get_names_value_list_unpack(buffer,
name_reply->nTypes,
name_reply->indicators,
@@ -1233,32 +1222,27 @@ void QXcbKeyboard::updateVModMapping()
else if (qstrcmp(vmod_name, "Hyper") == 0)
vmod_masks.hyper = bit;
}
-
- free(name_reply);
#endif
}
void QXcbKeyboard::updateVModToRModMapping()
{
#if QT_CONFIG(xkb)
- xcb_xkb_get_map_cookie_t map_cookie;
- xcb_xkb_get_map_reply_t *map_reply;
xcb_xkb_get_map_map_t map;
memset(&rmod_masks, 0, sizeof(rmod_masks));
- map_cookie = xcb_xkb_get_map(xcb_connection(),
- XCB_XKB_ID_USE_CORE_KBD,
- XCB_XKB_MAP_PART_VIRTUAL_MODS,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
-
- map_reply = xcb_xkb_get_map_reply(xcb_connection(), map_cookie, 0);
+ auto map_reply = Q_XCB_REPLY(xcb_xkb_get_map,
+ xcb_connection(),
+ XCB_XKB_ID_USE_CORE_KBD,
+ XCB_XKB_MAP_PART_VIRTUAL_MODS,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
if (!map_reply) {
qWarning("Qt: failed to retrieve the virtual modifier map from XKB");
return;
}
- const void *buffer = xcb_xkb_get_map_map(map_reply);
+ const void *buffer = xcb_xkb_get_map_map(map_reply.get());
xcb_xkb_get_map_map_unpack(buffer,
map_reply->nTypes,
map_reply->nKeySyms,
@@ -1301,7 +1285,6 @@ void QXcbKeyboard::updateVModToRModMapping()
rmod_masks.hyper = modmap;
}
- free(map_reply);
resolveMaskConflicts();
#endif
}
@@ -1315,14 +1298,10 @@ void QXcbKeyboard::updateModifiers()
// process for all modifiers whenever any part of the modifier mapping is changed.
memset(&rmod_masks, 0, sizeof(rmod_masks));
- xcb_generic_error_t *error = 0;
xcb_connection_t *conn = xcb_connection();
- xcb_get_modifier_mapping_cookie_t modMapCookie = xcb_get_modifier_mapping(conn);
- xcb_get_modifier_mapping_reply_t *modMapReply =
- xcb_get_modifier_mapping_reply(conn, modMapCookie, &error);
- if (error) {
+ auto modMapReply = Q_XCB_REPLY(xcb_get_modifier_mapping, conn);
+ if (!modMapReply) {
qWarning("Qt: failed to get modifier mapping");
- free(error);
return;
}
@@ -1338,7 +1317,7 @@ void QXcbKeyboard::updateModifiers()
for (size_t i = 0; i < numSymbols; ++i)
modKeyCodes[i] = xcb_key_symbols_get_keycode(m_key_symbols, symbols[i]);
- xcb_keycode_t *modMap = xcb_get_modifier_mapping_keycodes(modMapReply);
+ xcb_keycode_t *modMap = xcb_get_modifier_mapping_keycodes(modMapReply.get());
const int w = modMapReply->keycodes_per_modifier;
for (size_t i = 0; i < numSymbols; ++i) {
for (int bit = 0; bit < 8; ++bit) {
@@ -1366,7 +1345,6 @@ void QXcbKeyboard::updateModifiers()
for (size_t i = 0; i < numSymbols; ++i)
free(modKeyCodes[i]);
- free(modMapReply);
resolveMaskConflicts();
}
@@ -1449,8 +1427,6 @@ private:
void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type, xcb_keycode_t code,
quint16 state, xcb_timestamp_t time)
{
- Q_XCB_NOOP(connection());
-
if (!m_config)
return;
@@ -1471,30 +1447,6 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
updateXKBStateFromState(kb_state, state);
xcb_keysym_t sym = xkb_state_key_get_one_sym(kb_state, code);
-
- QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
- QMetaMethod method;
-
- if (inputContext) {
- int methodIndex = inputContext->metaObject()->indexOfMethod("x11FilterEvent(uint,uint,uint,bool)");
- if (methodIndex != -1)
- method = inputContext->metaObject()->method(methodIndex);
- }
-
- if (method.isValid()) {
- bool retval = false;
- method.invoke(inputContext, Qt::DirectConnection,
- Q_RETURN_ARG(bool, retval),
- Q_ARG(uint, sym),
- Q_ARG(uint, code),
- Q_ARG(uint, state),
- Q_ARG(bool, type == QEvent::KeyPress));
- if (retval) {
- xkb_state_unref(kb_state);
- return;
- }
- }
-
QString string = lookupString(kb_state, code);
// Ιf control modifier is set we should prefer latin character, this is
@@ -1526,6 +1478,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
}
bool filtered = false;
+ QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
if (inputContext) {
QKeyEvent event(type, qtcode, modifiers, code, sym, state, string, isAutoRepeat, string.length());
event.setTimestamp(time);
@@ -1548,16 +1501,7 @@ void QXcbKeyboard::handleKeyEvent(xcb_window_t sourceWindow, QEvent::Type type,
if (isAutoRepeat && type == QEvent::KeyRelease) {
// since we removed it from the event queue using checkEvent we need to send the key press here
filtered = false;
- if (method.isValid()) {
- method.invoke(inputContext, Qt::DirectConnection,
- Q_RETURN_ARG(bool, filtered),
- Q_ARG(uint, sym),
- Q_ARG(uint, code),
- Q_ARG(uint, state),
- Q_ARG(bool, true));
- }
-
- if (!filtered && inputContext) {
+ if (inputContext) {
QKeyEvent event(QEvent::KeyPress, qtcode, modifiers, code, sym, state, string, isAutoRepeat, string.length());
event.setTimestamp(time);
filtered = inputContext->filterEvent(&event);
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 97dcb8f328..76ee8f3fb4 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -63,6 +63,10 @@
#include "qxcbnativeinterfacehandler.h"
+#if QT_CONFIG(vulkan)
+#include "qxcbvulkanwindow.h"
+#endif
+
QT_BEGIN_NAMESPACE
// return QXcbNativeInterface::ResourceType for the key.
@@ -78,7 +82,8 @@ static int resourceType(const QByteArray &key)
QByteArrayLiteral("rootwindow"),
QByteArrayLiteral("subpixeltype"), QByteArrayLiteral("antialiasingenabled"),
QByteArrayLiteral("atspibus"),
- QByteArrayLiteral("compositingenabled")
+ QByteArrayLiteral("compositingenabled"),
+ QByteArrayLiteral("vksurface")
};
const QByteArray *end = names + sizeof(names) / sizeof(names[0]);
const QByteArray *result = std::find(names, end, key);
@@ -117,28 +122,19 @@ xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const
{
if (m_sysTraySelectionAtom == XCB_ATOM_NONE) {
const QByteArray net_sys_tray = QString::fromLatin1("_NET_SYSTEM_TRAY_S%1").arg(screen->screenNumber()).toLatin1();
- xcb_intern_atom_cookie_t intern_c =
- xcb_intern_atom_unchecked(conn, true, net_sys_tray.length(), net_sys_tray);
-
- xcb_intern_atom_reply_t *intern_r = xcb_intern_atom_reply(conn, intern_c, 0);
-
+ auto intern_r = Q_XCB_REPLY_UNCHECKED(xcb_intern_atom, conn,
+ true, net_sys_tray.length(), net_sys_tray);
if (!intern_r)
return XCB_WINDOW_NONE;
m_sysTraySelectionAtom = intern_r->atom;
- free(intern_r);
}
- xcb_get_selection_owner_cookie_t sel_owner_c = xcb_get_selection_owner_unchecked(conn, m_sysTraySelectionAtom);
- xcb_get_selection_owner_reply_t *sel_owner_r = xcb_get_selection_owner_reply(conn, sel_owner_c, 0);
-
+ auto sel_owner_r = Q_XCB_REPLY_UNCHECKED(xcb_get_selection_owner, conn, m_sysTraySelectionAtom);
if (!sel_owner_r)
return XCB_WINDOW_NONE;
- xcb_window_t selection_window = sel_owner_r->owner;
- free(sel_owner_r);
-
- return selection_window;
+ return sel_owner_r->owner;
}
bool QXcbNativeInterface::systrayVisualHasAlphaChannel()
@@ -262,6 +258,14 @@ void *QXcbNativeInterface::nativeResourceForWindow(const QByteArray &resourceStr
case Screen:
result = screenForWindow(window);
break;
+#if QT_CONFIG(vulkan)
+ case VkSurface:
+ if (window->surfaceType() == QSurface::VulkanSurface && window->handle()) {
+ // return a pointer to the VkSurfaceKHR value, not the value itself
+ result = static_cast<QXcbVulkanWindow *>(window->handle())->surface();
+ }
+ break;
+#endif
default:
break;
}
@@ -453,21 +457,13 @@ void *QXcbNativeInterface::atspiBus()
QXcbConnection *defaultConnection = integration->defaultConnection();
if (defaultConnection) {
xcb_atom_t atspiBusAtom = defaultConnection->internAtom("AT_SPI_BUS");
- xcb_get_property_cookie_t cookie = Q_XCB_CALL2(xcb_get_property(
- defaultConnection->xcb_connection(),
- false, defaultConnection->rootWindow(),
- atspiBusAtom, XCB_ATOM_STRING, 0, 128),
- defaultConnection);
- xcb_get_property_reply_t *reply = Q_XCB_CALL2(xcb_get_property_reply(
- defaultConnection->xcb_connection(),
- cookie, 0),
- defaultConnection);
+ auto reply = Q_XCB_REPLY(xcb_get_property, defaultConnection->xcb_connection(),
+ false, defaultConnection->rootWindow(),
+ atspiBusAtom, XCB_ATOM_STRING, 0, 128);
Q_ASSERT(!reply->bytes_after);
- char *data = (char *)xcb_get_property_value(reply);
- int length = xcb_get_property_value_length(reply);
- QByteArray *busAddress = new QByteArray(data, length);
- free(reply);
- return busAddress;
+ char *data = (char *)xcb_get_property_value(reply.get());
+ int length = xcb_get_property_value_length(reply.get());
+ return new QByteArray(data, length);
}
return 0;
}
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h
index 4186d77f4d..b9f1ebcdc6 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.h
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h
@@ -73,7 +73,8 @@ public:
ScreenSubpixelType,
ScreenAntialiasingEnabled,
AtspiBus,
- CompositingEnabled
+ CompositingEnabled,
+ VkSurface
};
QXcbNativeInterface();
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 5e136b5d7e..9d6f19460e 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -65,6 +65,67 @@ QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t
m_compositingActive = connection->getSelectionOwner(m_net_wm_cm_atom);
m_workArea = getWorkArea();
+
+ readXResources();
+
+ auto rootAttribs = Q_XCB_REPLY_UNCHECKED(xcb_get_window_attributes, xcb_connection(),
+ screen->root);
+ const quint32 existingEventMask = !rootAttribs ? 0 : rootAttribs->your_event_mask;
+
+ const quint32 mask = XCB_CW_EVENT_MASK;
+ const quint32 values[] = {
+ // XCB_CW_EVENT_MASK
+ XCB_EVENT_MASK_ENTER_WINDOW
+ | XCB_EVENT_MASK_LEAVE_WINDOW
+ | XCB_EVENT_MASK_PROPERTY_CHANGE
+ | XCB_EVENT_MASK_STRUCTURE_NOTIFY // for the "MANAGER" atom (system tray notification).
+ | existingEventMask // don't overwrite the event mask on the root window
+ };
+
+ xcb_change_window_attributes(xcb_connection(), screen->root, mask, values);
+
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
+ false, screen->root,
+ atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK),
+ XCB_ATOM_WINDOW, 0, 1024);
+ if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) {
+ xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply.get()));
+
+ if (windowManager != XCB_WINDOW_NONE) {
+ auto windowManagerReply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
+ false, windowManager,
+ atom(QXcbAtom::_NET_WM_NAME),
+ atom(QXcbAtom::UTF8_STRING), 0, 1024);
+ if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) {
+ m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply.get()),
+ xcb_get_property_value_length(windowManagerReply.get()));
+ }
+ }
+ }
+
+ const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id);
+ if (!sync_reply || !sync_reply->present)
+ m_syncRequestSupported = false;
+ else
+ m_syncRequestSupported = true;
+
+ xcb_depth_iterator_t depth_iterator =
+ xcb_screen_allowed_depths_iterator(screen);
+
+ while (depth_iterator.rem) {
+ xcb_depth_t *depth = depth_iterator.data;
+ xcb_visualtype_iterator_t visualtype_iterator =
+ xcb_depth_visuals_iterator(depth);
+
+ while (visualtype_iterator.rem) {
+ xcb_visualtype_t *visualtype = visualtype_iterator.data;
+ m_visuals.insert(visualtype->visual_id, *visualtype);
+ m_visualDepths.insert(visualtype->visual_id, depth->depth);
+ xcb_visualtype_next(&visualtype_iterator);
+ }
+
+ xcb_depth_next(&depth_iterator);
+ }
}
QXcbVirtualDesktop::~QXcbVirtualDesktop()
@@ -123,18 +184,33 @@ void QXcbVirtualDesktop::subscribeToXFixesSelectionNotify()
const uint32_t mask = XCB_XFIXES_SELECTION_EVENT_MASK_SET_SELECTION_OWNER |
XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_WINDOW_DESTROY |
XCB_XFIXES_SELECTION_EVENT_MASK_SELECTION_CLIENT_CLOSE;
- Q_XCB_CALL(xcb_xfixes_select_selection_input_checked(xcb_connection(), connection()->getQtSelectionOwner(), m_net_wm_cm_atom, mask));
+ xcb_xfixes_select_selection_input_checked(xcb_connection(), connection()->getQtSelectionOwner(), m_net_wm_cm_atom, mask);
}
}
+/*! \internal
+
+ Using _NET_WORKAREA to calculate the available desktop geometry on multi-head systems (systems
+ with more than one monitor) is unreliable. Different WMs have different interpretations of what
+ _NET_WORKAREA means with multiple attached monitors. This gets worse when monitors have
+ different dimensions and/or screens are not virtually aligned. In Qt we want the available
+ geometry per monitor (QScreen), not desktop (represented by _NET_WORKAREA). WM specification
+ does not have an atom for this. Thus, QScreen is limted by the lack of support from the
+ underlying system.
+
+ One option could be that Qt does WM's job of calculating this by subtracting geometries of
+ _NET_WM_STRUT_PARTIAL and windows where _NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_DOCK.
+ But this won't work on Gnome 3 shell as it seems that on this desktop environment the tool panel
+ is painted directly on the root window. Maybe there is some Gnome/GTK API that could be used
+ to get height of the panel, but I did not find one. Maybe other WMs have their own tricks, so
+ the reliability of this approach is questionable.
+ */
QRect QXcbVirtualDesktop::getWorkArea() const
{
QRect r;
- xcb_get_property_reply_t * workArea =
- xcb_get_property_reply(xcb_connection(),
- xcb_get_property_unchecked(xcb_connection(), false, screen()->root,
- atom(QXcbAtom::_NET_WORKAREA),
- XCB_ATOM_CARDINAL, 0, 1024), NULL);
+ auto workArea = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(), false, screen()->root,
+ atom(QXcbAtom::_NET_WORKAREA),
+ XCB_ATOM_CARDINAL, 0, 1024);
if (workArea && workArea->type == XCB_ATOM_CARDINAL && workArea->format == 32 && workArea->value_len >= 4) {
// If workArea->value_len > 4, the remaining ones seem to be for WM's virtual desktops
// (don't mess with QXcbVirtualDesktop which represents an X screen).
@@ -142,12 +218,11 @@ QRect QXcbVirtualDesktop::getWorkArea() const
// "docked" panel (with _NET_WM_STRUT_PARTIAL atom set) on just one desktop.
// But for now just assume the first 4 values give us the geometry of the
// "work area", AKA "available geometry"
- uint32_t *geom = (uint32_t*)xcb_get_property_value(workArea);
+ uint32_t *geom = (uint32_t*)xcb_get_property_value(workArea.get());
r = QRect(geom[0], geom[1], geom[2], geom[3]);
} else {
r = QRect(QPoint(), size());
}
- free(workArea);
return r;
}
@@ -167,6 +242,170 @@ static inline QSizeF sizeInMillimeters(const QSize &size, const QDpi &dpi)
Q_MM_PER_INCH * size.height() / dpi.second);
}
+bool QXcbVirtualDesktop::xResource(const QByteArray &identifier,
+ const QByteArray &expectedIdentifier,
+ QByteArray& stringValue)
+{
+ if (identifier.startsWith(expectedIdentifier)) {
+ stringValue = identifier.mid(expectedIdentifier.size());
+ return true;
+ }
+ return false;
+}
+
+static bool parseXftInt(const QByteArray& stringValue, int *value)
+{
+ Q_ASSERT(value != 0);
+ bool ok;
+ *value = stringValue.toInt(&ok);
+ return ok;
+}
+
+static QFontEngine::HintStyle parseXftHintStyle(const QByteArray& stringValue)
+{
+ if (stringValue == "hintfull")
+ return QFontEngine::HintFull;
+ else if (stringValue == "hintnone")
+ return QFontEngine::HintNone;
+ else if (stringValue == "hintmedium")
+ return QFontEngine::HintMedium;
+ else if (stringValue == "hintslight")
+ return QFontEngine::HintLight;
+
+ return QFontEngine::HintStyle(-1);
+}
+
+static QFontEngine::SubpixelAntialiasingType parseXftRgba(const QByteArray& stringValue)
+{
+ if (stringValue == "none")
+ return QFontEngine::Subpixel_None;
+ else if (stringValue == "rgb")
+ return QFontEngine::Subpixel_RGB;
+ else if (stringValue == "bgr")
+ return QFontEngine::Subpixel_BGR;
+ else if (stringValue == "vrgb")
+ return QFontEngine::Subpixel_VRGB;
+ else if (stringValue == "vbgr")
+ return QFontEngine::Subpixel_VBGR;
+
+ return QFontEngine::SubpixelAntialiasingType(-1);
+}
+
+void QXcbVirtualDesktop::readXResources()
+{
+ int offset = 0;
+ QByteArray resources;
+ while (true) {
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
+ false, screen()->root,
+ XCB_ATOM_RESOURCE_MANAGER,
+ XCB_ATOM_STRING, offset/4, 8192);
+ bool more = false;
+ if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) {
+ resources += QByteArray((const char *)xcb_get_property_value(reply.get()), xcb_get_property_value_length(reply.get()));
+ offset += xcb_get_property_value_length(reply.get());
+ more = reply->bytes_after != 0;
+ }
+
+ if (!more)
+ break;
+ }
+
+ QList<QByteArray> split = resources.split('\n');
+ for (int i = 0; i < split.size(); ++i) {
+ const QByteArray &r = split.at(i);
+ int value;
+ QByteArray stringValue;
+ if (xResource(r, "Xft.dpi:\t", stringValue)) {
+ if (parseXftInt(stringValue, &value))
+ m_forcedDpi = value;
+ } else if (xResource(r, "Xft.hintstyle:\t", stringValue)) {
+ m_hintStyle = parseXftHintStyle(stringValue);
+ } else if (xResource(r, "Xft.antialias:\t", stringValue)) {
+ if (parseXftInt(stringValue, &value))
+ m_antialiasingEnabled = value;
+ } else if (xResource(r, "Xft.rgba:\t", stringValue)) {
+ m_subpixelType = parseXftRgba(stringValue);
+ }
+ }
+}
+
+QSurfaceFormat QXcbVirtualDesktop::surfaceFormatFor(const QSurfaceFormat &format) const
+{
+ const xcb_visualid_t xcb_visualid = connection()->hasDefaultVisualId() ? connection()->defaultVisualId()
+ : screen()->root_visual;
+ const xcb_visualtype_t *xcb_visualtype = visualForId(xcb_visualid);
+
+ const int redSize = qPopulationCount(xcb_visualtype->red_mask);
+ const int greenSize = qPopulationCount(xcb_visualtype->green_mask);
+ const int blueSize = qPopulationCount(xcb_visualtype->blue_mask);
+
+ QSurfaceFormat result = format;
+
+ if (result.redBufferSize() < 0)
+ result.setRedBufferSize(redSize);
+
+ if (result.greenBufferSize() < 0)
+ result.setGreenBufferSize(greenSize);
+
+ if (result.blueBufferSize() < 0)
+ result.setBlueBufferSize(blueSize);
+
+ return result;
+}
+
+const xcb_visualtype_t *QXcbVirtualDesktop::visualForFormat(const QSurfaceFormat &format) const
+{
+ const xcb_visualtype_t *candidate = nullptr;
+
+ for (const xcb_visualtype_t &xcb_visualtype : m_visuals) {
+
+ const int redSize = qPopulationCount(xcb_visualtype.red_mask);
+ const int greenSize = qPopulationCount(xcb_visualtype.green_mask);
+ const int blueSize = qPopulationCount(xcb_visualtype.blue_mask);
+ const int alphaSize = depthOfVisual(xcb_visualtype.visual_id) - redSize - greenSize - blueSize;
+
+ if (format.redBufferSize() != -1 && redSize != format.redBufferSize())
+ continue;
+
+ if (format.greenBufferSize() != -1 && greenSize != format.greenBufferSize())
+ continue;
+
+ if (format.blueBufferSize() != -1 && blueSize != format.blueBufferSize())
+ continue;
+
+ if (format.alphaBufferSize() != -1 && alphaSize != format.alphaBufferSize())
+ continue;
+
+ // Try to find a RGB visual rather than e.g. BGR or GBR
+ if (qCountTrailingZeroBits(xcb_visualtype.blue_mask) == 0)
+ return &xcb_visualtype;
+
+ // In case we do not find anything we like, just remember the first one
+ // and hope for the best:
+ if (!candidate)
+ candidate = &xcb_visualtype;
+ }
+
+ return candidate;
+}
+
+const xcb_visualtype_t *QXcbVirtualDesktop::visualForId(xcb_visualid_t visualid) const
+{
+ QMap<xcb_visualid_t, xcb_visualtype_t>::const_iterator it = m_visuals.find(visualid);
+ if (it == m_visuals.constEnd())
+ return 0;
+ return &*it;
+}
+
+quint8 QXcbVirtualDesktop::depthOfVisual(xcb_visualid_t visualid) const
+{
+ QMap<xcb_visualid_t, quint8>::const_iterator it = m_visualDepths.find(visualid);
+ if (it == m_visualDepths.constEnd())
+ return 0;
+ return *it;
+}
+
QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
const xcb_xinerama_screen_info_t *xineramaScreenInfo, int xineramaScreenIdx)
@@ -181,14 +420,11 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
{
if (connection->hasXRandr()) {
xcb_randr_select_input(xcb_connection(), screen()->root, true);
- xcb_randr_get_crtc_info_cookie_t crtcCookie =
- xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, output ? output->timestamp : 0);
- xcb_randr_get_crtc_info_reply_t *crtc =
- xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL);
+ auto crtc = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_crtc_info, xcb_connection(),
+ m_crtc, output ? output->timestamp : 0);
if (crtc) {
updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation);
updateRefreshRate(crtc->mode);
- free(crtc);
}
} else if (xineramaScreenInfo) {
m_geometry = QRect(xineramaScreenInfo->x_org, xineramaScreenInfo->y_org,
@@ -208,74 +444,19 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
if (m_sizeMillimeters.isEmpty())
m_sizeMillimeters = m_virtualSizeMillimeters;
- readXResources();
-
- QScopedPointer<xcb_get_window_attributes_reply_t, QScopedPointerPodDeleter> rootAttribs(
- xcb_get_window_attributes_reply(xcb_connection(),
- xcb_get_window_attributes_unchecked(xcb_connection(), screen()->root), NULL));
- const quint32 existingEventMask = rootAttribs.isNull() ? 0 : rootAttribs->your_event_mask;
-
- const quint32 mask = XCB_CW_EVENT_MASK;
- const quint32 values[] = {
- // XCB_CW_EVENT_MASK
- XCB_EVENT_MASK_ENTER_WINDOW
- | XCB_EVENT_MASK_LEAVE_WINDOW
- | XCB_EVENT_MASK_PROPERTY_CHANGE
- | XCB_EVENT_MASK_STRUCTURE_NOTIFY // for the "MANAGER" atom (system tray notification).
- | existingEventMask // don't overwrite the event mask on the root window
- };
-
- xcb_change_window_attributes(xcb_connection(), screen()->root, mask, values);
-
- xcb_get_property_reply_t *reply =
- xcb_get_property_reply(xcb_connection(),
- xcb_get_property_unchecked(xcb_connection(), false, screen()->root,
- atom(QXcbAtom::_NET_SUPPORTING_WM_CHECK),
- XCB_ATOM_WINDOW, 0, 1024), NULL);
-
- if (reply && reply->format == 32 && reply->type == XCB_ATOM_WINDOW) {
- xcb_window_t windowManager = *((xcb_window_t *)xcb_get_property_value(reply));
-
- if (windowManager != XCB_WINDOW_NONE) {
- xcb_get_property_reply_t *windowManagerReply =
- xcb_get_property_reply(xcb_connection(),
- xcb_get_property_unchecked(xcb_connection(), false, windowManager,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING), 0, 1024), NULL);
- if (windowManagerReply && windowManagerReply->format == 8 && windowManagerReply->type == atom(QXcbAtom::UTF8_STRING)) {
- m_windowManagerName = QString::fromUtf8((const char *)xcb_get_property_value(windowManagerReply), xcb_get_property_value_length(windowManagerReply));
- }
-
- free(windowManagerReply);
- }
- }
- free(reply);
+ m_cursor = new QXcbCursor(connection, this);
- const xcb_query_extension_reply_t *sync_reply = xcb_get_extension_data(xcb_connection(), &xcb_sync_id);
- if (!sync_reply || !sync_reply->present)
- m_syncRequestSupported = false;
+ // Parse EDID
+ if (m_edid.parse(getEdid()))
+ qCDebug(lcQpaScreen, "EDID data for output \"%s\": identifier '%s', manufacturer '%s', model '%s', serial '%s', physical size: %.2fx%.2f",
+ name().toLatin1().constData(),
+ m_edid.identifier.toLatin1().constData(),
+ m_edid.manufacturer.toLatin1().constData(),
+ m_edid.model.toLatin1().constData(),
+ m_edid.serialNumber.toLatin1().constData(),
+ m_edid.physicalSize.width(), m_edid.physicalSize.height());
else
- m_syncRequestSupported = true;
-
- xcb_depth_iterator_t depth_iterator =
- xcb_screen_allowed_depths_iterator(screen());
-
- while (depth_iterator.rem) {
- xcb_depth_t *depth = depth_iterator.data;
- xcb_visualtype_iterator_t visualtype_iterator =
- xcb_depth_visuals_iterator(depth);
-
- while (visualtype_iterator.rem) {
- xcb_visualtype_t *visualtype = visualtype_iterator.data;
- m_visuals.insert(visualtype->visual_id, *visualtype);
- m_visualDepths.insert(visualtype->visual_id, depth->depth);
- xcb_visualtype_next(&visualtype_iterator);
- }
-
- xcb_depth_next(&depth_iterator);
- }
-
- m_cursor = new QXcbCursor(connection, this);
+ qCDebug(lcQpaScreen) << "Failed to parse EDID data for output" << name(); // keep this debug, not warning
}
QXcbScreen::~QXcbScreen()
@@ -300,6 +481,21 @@ QString QXcbScreen::getOutputName(xcb_randr_get_output_info_reply_t *outputInfo)
return name;
}
+QString QXcbScreen::manufacturer() const
+{
+ return m_edid.manufacturer;
+}
+
+QString QXcbScreen::model() const
+{
+ return m_edid.model;
+}
+
+QString QXcbScreen::serialNumber() const
+{
+ return m_edid.serialNumber;
+}
+
QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
{
xcb_window_t root = screen()->root;
@@ -311,12 +507,7 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
xcb_window_t child = root;
do {
- xcb_translate_coordinates_cookie_t translate_cookie =
- xcb_translate_coordinates_unchecked(xcb_connection(), parent, child, x, y);
-
- xcb_translate_coordinates_reply_t *translate_reply =
- xcb_translate_coordinates_reply(xcb_connection(), translate_cookie, NULL);
-
+ auto translate_reply = Q_XCB_REPLY_UNCHECKED(xcb_translate_coordinates, xcb_connection(), parent, child, x, y);
if (!translate_reply) {
return 0;
}
@@ -326,8 +517,6 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
x = translate_reply->dst_x;
y = translate_reply->dst_y;
- free(translate_reply);
-
if (!child || child == root)
return 0;
@@ -350,62 +539,12 @@ void QXcbScreen::windowShown(QXcbWindow *window)
QSurfaceFormat QXcbScreen::surfaceFormatFor(const QSurfaceFormat &format) const
{
- const xcb_visualid_t xcb_visualid = connection()->hasDefaultVisualId() ? connection()->defaultVisualId()
- : screen()->root_visual;
- const xcb_visualtype_t *xcb_visualtype = visualForId(xcb_visualid);
-
- const int redSize = qPopulationCount(xcb_visualtype->red_mask);
- const int greenSize = qPopulationCount(xcb_visualtype->green_mask);
- const int blueSize = qPopulationCount(xcb_visualtype->blue_mask);
-
- QSurfaceFormat result = format;
-
- if (result.redBufferSize() < 0)
- result.setRedBufferSize(redSize);
-
- if (result.greenBufferSize() < 0)
- result.setGreenBufferSize(greenSize);
-
- if (result.blueBufferSize() < 0)
- result.setBlueBufferSize(blueSize);
-
- return result;
+ return m_virtualDesktop->surfaceFormatFor(format);
}
-const xcb_visualtype_t *QXcbScreen::visualForFormat(const QSurfaceFormat &format) const
+const xcb_visualtype_t *QXcbScreen::visualForId(xcb_visualid_t visualid) const
{
- const xcb_visualtype_t *candidate = nullptr;
-
- for (const xcb_visualtype_t &xcb_visualtype : m_visuals) {
-
- const int redSize = qPopulationCount(xcb_visualtype.red_mask);
- const int greenSize = qPopulationCount(xcb_visualtype.green_mask);
- const int blueSize = qPopulationCount(xcb_visualtype.blue_mask);
- const int alphaSize = depthOfVisual(xcb_visualtype.visual_id) - redSize - greenSize - blueSize;
-
- if (format.redBufferSize() != -1 && redSize != format.redBufferSize())
- continue;
-
- if (format.greenBufferSize() != -1 && greenSize != format.greenBufferSize())
- continue;
-
- if (format.blueBufferSize() != -1 && blueSize != format.blueBufferSize())
- continue;
-
- if (format.alphaBufferSize() != -1 && alphaSize != format.alphaBufferSize())
- continue;
-
- // Try to find a RGB visual rather than e.g. BGR or GBR
- if (qCountTrailingZeroBits(xcb_visualtype.blue_mask) == 0)
- return &xcb_visualtype;
-
- // In case we do not find anything we like, just remember the first one
- // and hope for the best:
- if (!candidate)
- candidate = &xcb_visualtype;
- }
-
- return candidate;
+ return m_virtualDesktop->visualForId(visualid);
}
void QXcbScreen::sendStartupMessage(const QByteArray &message) const
@@ -434,20 +573,12 @@ void QXcbScreen::sendStartupMessage(const QByteArray &message) const
} while (sent < length);
}
-const xcb_visualtype_t *QXcbScreen::visualForId(xcb_visualid_t visualid) const
+QRect QXcbScreen::availableGeometry() const
{
- QMap<xcb_visualid_t, xcb_visualtype_t>::const_iterator it = m_visuals.find(visualid);
- if (it == m_visuals.constEnd())
- return 0;
- return &*it;
-}
-
-quint8 QXcbScreen::depthOfVisual(xcb_visualid_t visualid) const
-{
- QMap<xcb_visualid_t, quint8>::const_iterator it = m_visualDepths.find(visualid);
- if (it == m_visualDepths.constEnd())
- return 0;
- return *it;
+ static bool enforceNetWorkarea = !qEnvironmentVariableIsEmpty("QT_RELY_ON_NET_WORKAREA_ATOM");
+ bool isMultiHeadSystem = virtualSiblings().length() > 1;
+ bool useScreenGeometry = isMultiHeadSystem && !enforceNetWorkarea;
+ return useScreenGeometry ? m_geometry : m_availableGeometry;
}
QImage::Format QXcbScreen::format() const
@@ -468,8 +599,9 @@ QDpi QXcbScreen::logicalDpi() const
if (overrideDpi)
return QDpi(overrideDpi, overrideDpi);
- if (m_forcedDpi > 0) {
- return QDpi(m_forcedDpi, m_forcedDpi);
+ const int forcedDpi = m_virtualDesktop->forcedDpi();
+ if (forcedDpi > 0) {
+ return QDpi(forcedDpi, forcedDpi);
}
return virtualDpi();
}
@@ -581,14 +713,10 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
if (!connection()->hasXRandr())
return;
- xcb_randr_get_crtc_info_cookie_t crtcCookie =
- xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp);
- xcb_randr_get_crtc_info_reply_t *crtc =
- xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL);
- if (crtc) {
+ auto crtc = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_crtc_info, xcb_connection(),
+ m_crtc, timestamp);
+ if (crtc)
updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation);
- free(crtc);
- }
}
void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation)
@@ -645,13 +773,11 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode)
// we can safely use get_screen_resources_current here, because in order to
// get here, we must have called get_screen_resources before
- xcb_randr_get_screen_resources_current_cookie_t resourcesCookie =
- xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), screen()->root);
- xcb_randr_get_screen_resources_current_reply_t *resources =
- xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, NULL);
+ auto resources = Q_XCB_REPLY_UNCHECKED(xcb_randr_get_screen_resources_current,
+ xcb_connection(), screen()->root);
if (resources) {
xcb_randr_mode_info_iterator_t modesIter =
- xcb_randr_get_screen_resources_current_modes_iterator(resources);
+ xcb_randr_get_screen_resources_current_modes_iterator(resources.get());
for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) {
xcb_randr_mode_info_t *modeInfo = modesIter.data;
if (modeInfo->id == mode) {
@@ -662,29 +788,19 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode)
}
}
- free(resources);
QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), m_refreshRate);
}
}
-static xcb_get_geometry_reply_t *getGeometryUnchecked(xcb_connection_t *connection, xcb_window_t window)
-{
- const xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry_unchecked(connection, window);
- return xcb_get_geometry_reply(connection, geometry_cookie, NULL);
-}
-
static inline bool translate(xcb_connection_t *connection, xcb_window_t child, xcb_window_t parent,
int *x, int *y)
{
- const xcb_translate_coordinates_cookie_t translate_cookie =
- xcb_translate_coordinates_unchecked(connection, child, parent, *x, *y);
- xcb_translate_coordinates_reply_t *translate_reply =
- xcb_translate_coordinates_reply(connection, translate_cookie, NULL);
+ auto translate_reply = Q_XCB_REPLY_UNCHECKED(xcb_translate_coordinates,
+ connection, child, parent, *x, *y);
if (!translate_reply)
return false;
*x = translate_reply->dst_x;
*y = translate_reply->dst_y;
- free(translate_reply);
return true;
}
@@ -698,22 +814,20 @@ QPixmap QXcbScreen::grabWindow(WId window, int xIn, int yIn, int width, int heig
QXcbScreen *screen = const_cast<QXcbScreen *>(this);
xcb_window_t root = screen->root();
- xcb_get_geometry_reply_t *rootReply = getGeometryUnchecked(xcb_connection(), root);
+ auto rootReply = Q_XCB_REPLY_UNCHECKED(xcb_get_geometry, xcb_connection(), root);
if (!rootReply)
return QPixmap();
const quint8 rootDepth = rootReply->depth;
- free(rootReply);
QSize windowSize;
quint8 effectiveDepth = 0;
if (window) {
- xcb_get_geometry_reply_t *windowReply = getGeometryUnchecked(xcb_connection(), window);
+ auto windowReply = Q_XCB_REPLY_UNCHECKED(xcb_get_geometry, xcb_connection(), window);
if (!windowReply)
return QPixmap();
windowSize = QSize(windowReply->width, windowReply->height);
effectiveDepth = windowReply->depth;
- free(windowReply);
if (effectiveDepth == rootDepth) {
// if the depth of the specified window and the root window are the
// same, grab pixels from the root window (so that we get the any
@@ -738,14 +852,12 @@ QPixmap QXcbScreen::grabWindow(WId window, int xIn, int yIn, int width, int heig
if (height < 0)
height = windowSize.height() - yIn;
- xcb_get_window_attributes_reply_t *attributes_reply =
- xcb_get_window_attributes_reply(xcb_connection(), xcb_get_window_attributes_unchecked(xcb_connection(), window), NULL);
+ auto attributes_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_window_attributes, xcb_connection(), window);
if (!attributes_reply)
return QPixmap();
const xcb_visualtype_t *visual = screen->visualForId(attributes_reply->visual);
- free(attributes_reply);
xcb_pixmap_t pixmap = xcb_generate_id(xcb_connection());
xcb_create_pixmap(xcb_connection(), effectiveDepth, pixmap, window, width, height);
@@ -765,101 +877,41 @@ QPixmap QXcbScreen::grabWindow(WId window, int xIn, int yIn, int width, int heig
return result;
}
-static bool parseXftInt(const QByteArray& stringValue, int *value)
+QXcbXSettings *QXcbScreen::xSettings() const
{
- Q_ASSERT(value != 0);
- bool ok;
- *value = stringValue.toInt(&ok);
- return ok;
+ return m_virtualDesktop->xSettings();
}
-static QFontEngine::HintStyle parseXftHintStyle(const QByteArray& stringValue)
+QByteArray QXcbScreen::getOutputProperty(xcb_atom_t atom) const
{
- if (stringValue == "hintfull")
- return QFontEngine::HintFull;
- else if (stringValue == "hintnone")
- return QFontEngine::HintNone;
- else if (stringValue == "hintmedium")
- return QFontEngine::HintMedium;
- else if (stringValue == "hintslight")
- return QFontEngine::HintLight;
-
- return QFontEngine::HintStyle(-1);
-}
+ QByteArray result;
-static QFontEngine::SubpixelAntialiasingType parseXftRgba(const QByteArray& stringValue)
-{
- if (stringValue == "none")
- return QFontEngine::Subpixel_None;
- else if (stringValue == "rgb")
- return QFontEngine::Subpixel_RGB;
- else if (stringValue == "bgr")
- return QFontEngine::Subpixel_BGR;
- else if (stringValue == "vrgb")
- return QFontEngine::Subpixel_VRGB;
- else if (stringValue == "vbgr")
- return QFontEngine::Subpixel_VBGR;
+ auto reply = Q_XCB_REPLY(xcb_randr_get_output_property, xcb_connection(),
+ m_output, atom, XCB_ATOM_ANY, 0, 100, false, false);
+ if (reply && reply->type == XCB_ATOM_INTEGER && reply->format == 8) {
+ quint8 *data = new quint8[reply->num_items];
+ memcpy(data, xcb_randr_get_output_property_data(reply.get()), reply->num_items);
+ result = QByteArray(reinterpret_cast<const char *>(data), reply->num_items);
+ delete[] data;
+ }
- return QFontEngine::SubpixelAntialiasingType(-1);
+ return result;
}
-bool QXcbScreen::xResource(const QByteArray &identifier,
- const QByteArray &expectedIdentifier,
- QByteArray& stringValue)
+QByteArray QXcbScreen::getEdid() const
{
- if (identifier.startsWith(expectedIdentifier)) {
- stringValue = identifier.mid(expectedIdentifier.size());
- return true;
+ // Try a bunch of atoms
+ xcb_atom_t atom = connection()->internAtom("EDID");
+ QByteArray result = getOutputProperty(atom);
+ if (result.isEmpty()) {
+ atom = connection()->internAtom("EDID_DATA");
+ result = getOutputProperty(atom);
}
- return false;
-}
-
-void QXcbScreen::readXResources()
-{
- int offset = 0;
- QByteArray resources;
- while(1) {
- xcb_get_property_reply_t *reply =
- xcb_get_property_reply(xcb_connection(),
- xcb_get_property_unchecked(xcb_connection(), false, screen()->root,
- XCB_ATOM_RESOURCE_MANAGER,
- XCB_ATOM_STRING, offset/4, 8192), NULL);
- bool more = false;
- if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING) {
- resources += QByteArray((const char *)xcb_get_property_value(reply), xcb_get_property_value_length(reply));
- offset += xcb_get_property_value_length(reply);
- more = reply->bytes_after != 0;
- }
-
- if (reply)
- free(reply);
-
- if (!more)
- break;
+ if (result.isEmpty()) {
+ atom = connection()->internAtom("XFree86_DDC_EDID1_RAWDATA");
+ result = getOutputProperty(atom);
}
-
- QList<QByteArray> split = resources.split('\n');
- for (int i = 0; i < split.size(); ++i) {
- const QByteArray &r = split.at(i);
- int value;
- QByteArray stringValue;
- if (xResource(r, "Xft.dpi:\t", stringValue)) {
- if (parseXftInt(stringValue, &value))
- m_forcedDpi = value;
- } else if (xResource(r, "Xft.hintstyle:\t", stringValue)) {
- m_hintStyle = parseXftHintStyle(stringValue);
- } else if (xResource(r, "Xft.antialias:\t", stringValue)) {
- if (parseXftInt(stringValue, &value))
- m_antialiasingEnabled = value;
- } else if (xResource(r, "Xft.rgba:\t", stringValue)) {
- m_subpixelType = parseXftRgba(stringValue);
- }
- }
-}
-
-QXcbXSettings *QXcbScreen::xSettings() const
-{
- return m_virtualDesktop->xSettings();
+ return result;
}
static inline void formatRect(QDebug &debug, const QRect r)
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 4163be2969..22ae0bc61b 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -53,6 +53,8 @@
#include <private/qfontengine_p.h>
+#include <QtEdidSupport/private/qedidparser_p.h>
+
QT_BEGIN_NAMESPACE
class QXcbConnection;
@@ -91,9 +93,28 @@ public:
void handleXFixesSelectionNotify(xcb_xfixes_selection_notify_event_t *notify_event);
void subscribeToXFixesSelectionNotify();
+ int forcedDpi() const { return m_forcedDpi; }
+ QFontEngine::HintStyle hintStyle() const { return m_hintStyle; }
+ QFontEngine::SubpixelAntialiasingType subpixelType() const { return m_subpixelType; }
+ int antialiasingEnabled() const { return m_antialiasingEnabled; }
+
+ QString windowManagerName() const { return m_windowManagerName; }
+ bool syncRequestSupported() const { return m_syncRequestSupported; }
+
+ QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &format) const;
+
+ const xcb_visualtype_t *visualForFormat(const QSurfaceFormat &format) const;
+ const xcb_visualtype_t *visualForId(xcb_visualid_t) const;
+ quint8 depthOfVisual(xcb_visualid_t) const;
+
private:
QRect getWorkArea() const;
+ static bool xResource(const QByteArray &identifier,
+ const QByteArray &expectedIdentifier,
+ QByteArray &stringValue);
+ void readXResources();
+
xcb_screen_t *m_screen;
const int m_number;
QList<QPlatformScreen *> m_screens;
@@ -103,6 +124,15 @@ private:
bool m_compositingActive = false;
QRect m_workArea;
+
+ int m_forcedDpi = -1;
+ QFontEngine::HintStyle m_hintStyle = QFontEngine::HintStyle(-1);
+ QFontEngine::SubpixelAntialiasingType m_subpixelType = QFontEngine::SubpixelAntialiasingType(-1);
+ int m_antialiasingEnabled = -1;
+ QString m_windowManagerName;
+ bool m_syncRequestSupported = false;
+ QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals;
+ QMap<xcb_visualid_t, quint8> m_visualDepths;
};
class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
@@ -119,8 +149,12 @@ public:
QWindow *topLevelAt(const QPoint &point) const override;
+ QString manufacturer() const override;
+ QString model() const override;
+ QString serialNumber() const override;
+
QRect geometry() const override { return m_geometry; }
- QRect availableGeometry() const override {return m_availableGeometry;}
+ QRect availableGeometry() const override;
int depth() const override { return screen()->root_depth; }
QImage::Format format() const override;
QSizeF physicalSize() const override { return m_sizeMillimeters; }
@@ -152,14 +186,14 @@ public:
void setCrtc(xcb_randr_crtc_t crtc) { m_crtc = crtc; }
void windowShown(QXcbWindow *window);
- QString windowManagerName() const { return m_windowManagerName; }
- bool syncRequestSupported() const { return m_syncRequestSupported; }
+ QString windowManagerName() const { return m_virtualDesktop->windowManagerName(); }
+ bool syncRequestSupported() const { return m_virtualDesktop->syncRequestSupported(); }
QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &format) const;
- const xcb_visualtype_t *visualForFormat(const QSurfaceFormat &format) const;
- const xcb_visualtype_t *visualForId(xcb_visualid_t) const;
- quint8 depthOfVisual(xcb_visualid_t) const;
+ const xcb_visualtype_t *visualForFormat(const QSurfaceFormat &format) const { return m_virtualDesktop->visualForFormat(format); }
+ const xcb_visualtype_t *visualForId(xcb_visualid_t visualid) const;
+ quint8 depthOfVisual(xcb_visualid_t visualid) const { return m_virtualDesktop->depthOfVisual(visualid); }
QString name() const override { return m_outputName; }
@@ -169,20 +203,18 @@ public:
void updateAvailableGeometry();
void updateRefreshRate(xcb_randr_mode_t mode);
- void readXResources();
-
- QFontEngine::HintStyle hintStyle() const { return m_hintStyle; }
- QFontEngine::SubpixelAntialiasingType subpixelType() const { return m_subpixelType; }
- int antialiasingEnabled() const { return m_antialiasingEnabled; }
+ QFontEngine::HintStyle hintStyle() const { return m_virtualDesktop->hintStyle(); }
+ QFontEngine::SubpixelAntialiasingType subpixelType() const { return m_virtualDesktop->subpixelType(); }
+ int antialiasingEnabled() const { return m_virtualDesktop->antialiasingEnabled(); }
QXcbXSettings *xSettings() const;
private:
- static bool xResource(const QByteArray &identifier,
- const QByteArray &expectedIdentifier,
- QByteArray &stringValue);
void sendStartupMessage(const QByteArray &message) const;
+ QByteArray getOutputProperty(xcb_atom_t atom) const;
+ QByteArray getEdid() const;
+
QXcbVirtualDesktop *m_virtualDesktop;
xcb_randr_output_t m_output;
xcb_randr_crtc_t m_crtc;
@@ -198,17 +230,10 @@ private:
QSize m_virtualSize;
QSizeF m_virtualSizeMillimeters;
Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
- QString m_windowManagerName;
- bool m_syncRequestSupported = false;
- QMap<xcb_visualid_t, xcb_visualtype_t> m_visuals;
- QMap<xcb_visualid_t, quint8> m_visualDepths;
QXcbCursor *m_cursor;
int m_refreshRate = 60;
- int m_forcedDpi = -1;
int m_pixelDensity = 1;
- QFontEngine::HintStyle m_hintStyle = QFontEngine::HintStyle(-1);
- QFontEngine::SubpixelAntialiasingType m_subpixelType = QFontEngine::SubpixelAntialiasingType(-1);
- int m_antialiasingEnabled = -1;
+ QEdidParser m_edid;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
index fb0a4a3939..c98879c7df 100644
--- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
+++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp
@@ -85,13 +85,10 @@ QXcbSystemTrayTracker::QXcbSystemTrayTracker(QXcbConnection *connection,
xcb_window_t QXcbSystemTrayTracker::locateTrayWindow(const QXcbConnection *connection, xcb_atom_t selection)
{
- xcb_get_selection_owner_cookie_t cookie = xcb_get_selection_owner(connection->xcb_connection(), selection);
- xcb_get_selection_owner_reply_t *reply = xcb_get_selection_owner_reply(connection->xcb_connection(), cookie, 0);
+ auto reply = Q_XCB_REPLY(xcb_get_selection_owner, connection->xcb_connection(), selection);
if (!reply)
return 0;
- const xcb_window_t result = reply->owner;
- free(reply);
- return result;
+ return reply->owner;
}
// API for QPlatformNativeInterface/QPlatformSystemTrayIcon: Request a window
@@ -119,7 +116,7 @@ xcb_window_t QXcbSystemTrayTracker::trayWindow()
m_connection->addWindowEventListener(m_trayWindow, this);
const quint32 mask = XCB_CW_EVENT_MASK;
const quint32 value = XCB_EVENT_MASK_STRUCTURE_NOTIFY;
- Q_XCB_CALL2(xcb_change_window_attributes(m_connection->xcb_connection(), m_trayWindow, mask, &value), m_connection);
+ xcb_change_window_attributes(m_connection->xcb_connection(), m_trayWindow, mask, &value);
}
}
return m_trayWindow;
@@ -130,23 +127,16 @@ xcb_window_t QXcbSystemTrayTracker::trayWindow()
// does not work for the QWindow parented on the tray.
QRect QXcbSystemTrayTracker::systemTrayWindowGlobalGeometry(xcb_window_t window) const
{
-
xcb_connection_t *conn = m_connection->xcb_connection();
- xcb_get_geometry_reply_t *geomReply =
- xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), 0);
+ auto geomReply = Q_XCB_REPLY(xcb_get_geometry, conn, window);
if (!geomReply)
return QRect();
- xcb_translate_coordinates_reply_t *translateReply =
- xcb_translate_coordinates_reply(conn, xcb_translate_coordinates(conn, window, m_connection->rootWindow(), 0, 0), 0);
- if (!translateReply) {
- free(geomReply);
+ auto translateReply = Q_XCB_REPLY(xcb_translate_coordinates, conn, window, m_connection->rootWindow(), 0, 0);
+ if (!translateReply)
return QRect();
- }
- const QRect result(QPoint(translateReply->dst_x, translateReply->dst_y), QSize(geomReply->width, geomReply->height));
- free(translateReply);
- return result;
+ return QRect(QPoint(translateReply->dst_x, translateReply->dst_y), QSize(geomReply->width, geomReply->height));
}
inline void QXcbSystemTrayTracker::emitSystemTrayWindowChanged()
@@ -180,24 +170,18 @@ bool QXcbSystemTrayTracker::visualHasAlphaChannel()
xcb_atom_t tray_atom = m_connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL);
// Get the xcb property for the _NET_SYSTEM_TRAY_VISUAL atom
- xcb_get_property_cookie_t systray_atom_cookie;
- xcb_get_property_reply_t *systray_atom_reply;
-
- systray_atom_cookie = xcb_get_property_unchecked(m_connection->xcb_connection(), false, m_trayWindow,
+ auto systray_atom_reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, m_connection->xcb_connection(),
+ false, m_trayWindow,
tray_atom, XCB_ATOM_VISUALID, 0, 1);
- systray_atom_reply = xcb_get_property_reply(m_connection->xcb_connection(), systray_atom_cookie, 0);
-
if (!systray_atom_reply)
return false;
xcb_visualid_t systrayVisualId = XCB_NONE;
- if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply) > 0) {
- xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply);
+ if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply.get()) > 0) {
+ xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply.get());
systrayVisualId = vids[0];
}
- free(systray_atom_reply);
-
if (systrayVisualId != XCB_NONE) {
quint8 depth = m_connection->primaryScreen()->depthOfVisual(systrayVisualId);
return depth == 32;
diff --git a/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp b/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp
new file mode 100644
index 0000000000..4d540defa9
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbvulkaninstance.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxcbvulkaninstance.h"
+#include "qxcbwindow.h"
+#include "qxcbscreen.h"
+
+QT_BEGIN_NAMESPACE
+
+QXcbVulkanInstance::QXcbVulkanInstance(QVulkanInstance *instance)
+ : m_instance(instance),
+ m_getPhysDevPresSupport(nullptr),
+ m_createSurface(nullptr),
+ m_destroySurface(nullptr)
+{
+ if (qEnvironmentVariableIsSet("QT_VULKAN_LIB"))
+ m_lib.setFileName(QString::fromUtf8(qgetenv("QT_VULKAN_LIB")));
+ else
+ m_lib.setFileName(QStringLiteral("vulkan"));
+
+ if (!m_lib.load()) {
+ qWarning("Failed to load %s: %s", qPrintable(m_lib.fileName()), qPrintable(m_lib.errorString()));
+ return;
+ }
+
+ init(&m_lib);
+}
+
+QXcbVulkanInstance::~QXcbVulkanInstance()
+{
+}
+
+void QXcbVulkanInstance::createOrAdoptInstance()
+{
+ initInstance(m_instance, QByteArrayList() << QByteArrayLiteral("VK_KHR_xcb_surface"));
+
+ if (!m_vkInst)
+ return;
+
+ m_getPhysDevPresSupport = reinterpret_cast<PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkGetPhysicalDeviceXcbPresentationSupportKHR"));
+ if (!m_getPhysDevPresSupport)
+ qWarning("Failed to find vkGetPhysicalDeviceXcbPresentationSupportKHR");
+}
+
+bool QXcbVulkanInstance::supportsPresent(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex,
+ QWindow *window)
+{
+ if (!m_getPhysDevPresSupport || !m_getPhysDevSurfaceSupport)
+ return true;
+
+ QXcbWindow *w = static_cast<QXcbWindow *>(window->handle());
+ if (!w) {
+ qWarning("Attempted to call supportsPresent() without a valid platform window");
+ return false;
+ }
+ xcb_connection_t *connection = w->xcbScreen()->xcb_connection();
+ bool ok = m_getPhysDevPresSupport(physicalDevice, queueFamilyIndex, connection, w->visualId());
+
+ VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(window);
+ VkBool32 supported = false;
+ m_getPhysDevSurfaceSupport(physicalDevice, queueFamilyIndex, surface, &supported);
+ ok &= bool(supported);
+
+ return ok;
+}
+
+VkSurfaceKHR QXcbVulkanInstance::createSurface(QXcbWindow *window)
+{
+ VkSurfaceKHR surface = 0;
+
+ if (!m_createSurface) {
+ m_createSurface = reinterpret_cast<PFN_vkCreateXcbSurfaceKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkCreateXcbSurfaceKHR"));
+ }
+ if (!m_createSurface) {
+ qWarning("Failed to find vkCreateXcbSurfaceKHR");
+ return surface;
+ }
+ if (!m_destroySurface) {
+ m_destroySurface = reinterpret_cast<PFN_vkDestroySurfaceKHR>(
+ m_vkGetInstanceProcAddr(m_vkInst, "vkDestroySurfaceKHR"));
+ }
+ if (!m_destroySurface) {
+ qWarning("Failed to find vkDestroySurfaceKHR");
+ return surface;
+ }
+
+ VkXcbSurfaceCreateInfoKHR surfaceInfo;
+ memset(&surfaceInfo, 0, sizeof(surfaceInfo));
+ surfaceInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+ surfaceInfo.connection = window->xcbScreen()->xcb_connection();
+ surfaceInfo.window = window->xcb_window();
+ VkResult err = m_createSurface(m_vkInst, &surfaceInfo, nullptr, &surface);
+ if (err != VK_SUCCESS)
+ qWarning("Failed to create Vulkan surface: %d", err);
+
+ return surface;
+}
+
+void QXcbVulkanInstance::destroySurface(VkSurfaceKHR surface)
+{
+ if (m_destroySurface && surface)
+ m_destroySurface(m_vkInst, surface, nullptr);
+}
+
+void QXcbVulkanInstance::presentQueued(QWindow *window)
+{
+ QXcbWindow *w = static_cast<QXcbWindow *>(window->handle());
+ if (!w) {
+ qWarning("Attempted to call presentQueued() without a valid platform window");
+ return;
+ }
+
+ if (w->needsSync())
+ w->postSyncWindowRequest();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbvulkaninstance.h b/src/plugins/platforms/xcb/qxcbvulkaninstance.h
new file mode 100644
index 0000000000..dbe057d944
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbvulkaninstance.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXCBVULKANINSTANCE_H
+#define QXCBVULKANINSTANCE_H
+
+#if defined(VULKAN_H_) && !defined(VK_USE_PLATFORM_XCB_KHR)
+#error "vulkan.h included without xcb WSI"
+#endif
+
+#define VK_USE_PLATFORM_XCB_KHR
+
+#include <QtVulkanSupport/private/qbasicvulkanplatforminstance_p.h>
+#include <QLibrary>
+
+QT_BEGIN_NAMESPACE
+
+class QXcbWindow;
+
+class QXcbVulkanInstance : public QBasicPlatformVulkanInstance
+{
+public:
+ QXcbVulkanInstance(QVulkanInstance *instance);
+ ~QXcbVulkanInstance();
+
+ void createOrAdoptInstance() override;
+ bool supportsPresent(VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, QWindow *window) override;
+ void presentQueued(QWindow *window) override;
+
+ VkSurfaceKHR createSurface(QXcbWindow *window);
+ void destroySurface(VkSurfaceKHR surface);
+
+private:
+ QVulkanInstance *m_instance;
+ QLibrary m_lib;
+ PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR m_getPhysDevPresSupport;
+ PFN_vkCreateXcbSurfaceKHR m_createSurface;
+ PFN_vkDestroySurfaceKHR m_destroySurface;
+};
+
+QT_END_NAMESPACE
+
+#endif // QXCBVULKANINSTANCE_H
diff --git a/src/plugins/platforms/xcb/qxcbvulkanwindow.cpp b/src/plugins/platforms/xcb/qxcbvulkanwindow.cpp
new file mode 100644
index 0000000000..25bc340f97
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbvulkanwindow.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qxcbvulkanwindow.h"
+
+QT_BEGIN_NAMESPACE
+
+QXcbVulkanWindow::QXcbVulkanWindow(QWindow *window)
+ : QXcbWindow(window),
+ m_surface(0)
+{
+}
+
+QXcbVulkanWindow::~QXcbVulkanWindow()
+{
+ if (m_surface) {
+ QVulkanInstance *inst = window()->vulkanInstance();
+ if (inst)
+ static_cast<QXcbVulkanInstance *>(inst->handle())->destroySurface(m_surface);
+ }
+}
+
+void QXcbVulkanWindow::resolveFormat(const QSurfaceFormat &format)
+{
+ m_format = format;
+ if (m_format.redBufferSize() <= 0)
+ m_format.setRedBufferSize(8);
+ if (m_format.greenBufferSize() <= 0)
+ m_format.setGreenBufferSize(8);
+ if (m_format.blueBufferSize() <= 0)
+ m_format.setBlueBufferSize(8);
+}
+
+// No createVisual() needed, use the default that picks one based on the R/G/B/A size.
+
+VkSurfaceKHR *QXcbVulkanWindow::surface()
+{
+ if (m_surface)
+ return &m_surface;
+
+ QVulkanInstance *inst = window()->vulkanInstance();
+ if (!inst) {
+ qWarning("Attempted to create Vulkan surface without an instance; was QWindow::setVulkanInstance() called?");
+ return nullptr;
+ }
+ QXcbVulkanInstance *xcbinst = static_cast<QXcbVulkanInstance *>(inst->handle());
+ m_surface = xcbinst->createSurface(this);
+
+ return &m_surface;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbvulkanwindow.h b/src/plugins/platforms/xcb/qxcbvulkanwindow.h
new file mode 100644
index 0000000000..43c96820c5
--- /dev/null
+++ b/src/plugins/platforms/xcb/qxcbvulkanwindow.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QXCBVULKANWINDOW_H
+#define QXCBVULKANWINDOW_H
+
+#include "qxcbwindow.h"
+#include "qxcbvulkaninstance.h"
+
+QT_BEGIN_NAMESPACE
+
+class QXcbVulkanWindow : public QXcbWindow
+{
+public:
+ QXcbVulkanWindow(QWindow *window);
+ ~QXcbVulkanWindow();
+
+ VkSurfaceKHR *surface();
+
+protected:
+ void resolveFormat(const QSurfaceFormat &format) override;
+
+private:
+ VkSurfaceKHR m_surface;
+};
+
+QT_END_NAMESPACE
+
+#endif // QXCBVULKANWINDOW_H
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 4acc827bf6..c3d00b53bf 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -227,6 +227,12 @@ static inline QImage::Format imageFormatForVisual(int depth, quint32 red_mask, q
return QImage::Format_RGB555;
}
break;
+#if QT_CONFIG(xcb_native_painting)
+ case 8:
+ if (QXcbIntegration::instance() && QXcbIntegration::instance()->nativePaintingEnabled())
+ return QImage::Format_Indexed8;
+ break;
+#endif
default:
break;
}
@@ -420,6 +426,19 @@ void QXcbWindow::create()
qWarning() << "Failed to use requested visual id.";
}
+ if (parent()) {
+ // When using a Vulkan QWindow via QWidget::createWindowContainer() we
+ // must make sure the visuals are compatible. Now, the parent will be
+ // of RasterGLSurface which typically chooses a GLX/EGL compatible
+ // visual which may not be what the Vulkan window would choose.
+ // Therefore, take the parent's visual.
+ if (window()->surfaceType() == QSurface::VulkanSurface
+ && parent()->window()->surfaceType() != QSurface::VulkanSurface)
+ {
+ visual = platformScreen->visualForId(static_cast<QXcbWindow *>(parent())->visualId());
+ }
+ }
+
if (!visual)
visual = createVisual();
@@ -445,11 +464,11 @@ void QXcbWindow::create()
if ((window()->supportsOpenGL() && haveOpenGL) || m_format.hasAlpha()) {
m_cmap = xcb_generate_id(xcb_connection());
- Q_XCB_CALL(xcb_create_colormap(xcb_connection(),
- XCB_COLORMAP_ALLOC_NONE,
- m_cmap,
- xcb_parent_id,
- m_visualId));
+ xcb_create_colormap(xcb_connection(),
+ XCB_COLORMAP_ALLOC_NONE,
+ m_cmap,
+ xcb_parent_id,
+ m_visualId);
mask |= XCB_CW_COLORMAP;
}
@@ -465,23 +484,23 @@ void QXcbWindow::create()
};
m_window = xcb_generate_id(xcb_connection());
- Q_XCB_CALL(xcb_create_window(xcb_connection(),
- m_depth,
- m_window, // window id
- xcb_parent_id, // parent window id
- rect.x(),
- rect.y(),
- rect.width(),
- rect.height(),
- 0, // border width
- XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
- m_visualId, // visual
- mask,
- values));
+ xcb_create_window(xcb_connection(),
+ m_depth,
+ m_window, // window id
+ xcb_parent_id, // parent window id
+ rect.x(),
+ rect.y(),
+ rect.width(),
+ rect.height(),
+ 0, // border width
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
+ m_visualId, // visual
+ mask,
+ values);
connection()->addWindowEventListener(m_window, this);
- Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
+ xcb_change_window_attributes(xcb_connection(), m_window, mask, values);
propagateSizeHints();
@@ -499,43 +518,43 @@ void QXcbWindow::create()
if (window()->flags() & Qt::WindowContextHelpButtonHint)
properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP);
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_window,
- atom(QXcbAtom::WM_PROTOCOLS),
- XCB_ATOM_ATOM,
- 32,
- propertyCount,
- properties));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::WM_PROTOCOLS),
+ XCB_ATOM_ATOM,
+ 32,
+ propertyCount,
+ properties);
m_syncValue.hi = 0;
m_syncValue.lo = 0;
const QByteArray wmClass = QXcbIntegration::instance()->wmClass();
if (!wmClass.isEmpty()) {
- Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE,
- m_window, atom(QXcbAtom::WM_CLASS),
- XCB_ATOM_STRING, 8, wmClass.size(), wmClass.constData()));
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE,
+ m_window, atom(QXcbAtom::WM_CLASS),
+ XCB_ATOM_STRING, 8, wmClass.size(), wmClass.constData());
}
if (m_usingSyncProtocol) {
m_syncCounter = xcb_generate_id(xcb_connection());
- Q_XCB_CALL(xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue));
+ xcb_sync_create_counter(xcb_connection(), m_syncCounter, m_syncValue);
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_window,
- atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER),
- XCB_ATOM_CARDINAL,
- 32,
- 1,
- &m_syncCounter));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::_NET_WM_SYNC_REQUEST_COUNTER),
+ XCB_ATOM_CARDINAL,
+ 32,
+ 1,
+ &m_syncCounter);
}
// set the PID to let the WM kill the application if unresponsive
quint32 pid = getpid();
- Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
- 1, &pid));
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32,
+ 1, &pid);
xcb_wm_hints_t hints;
memset(&hints, 0, sizeof(hints));
@@ -546,23 +565,23 @@ void QXcbWindow::create()
xcb_set_wm_hints(xcb_connection(), m_window, &hints);
xcb_window_t leader = connection()->clientLeader();
- Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32,
- 1, &leader));
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::WM_CLIENT_LEADER), XCB_ATOM_WINDOW, 32,
+ 1, &leader);
/* Add XEMBED info; this operation doesn't initiate the embedding. */
quint32 data[] = { XEMBED_VERSION, XEMBED_MAPPED };
- Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::_XEMBED_INFO),
- atom(QXcbAtom::_XEMBED_INFO),
- 32, 2, (void *)data));
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::_XEMBED_INFO),
+ atom(QXcbAtom::_XEMBED_INFO),
+ 32, 2, (void *)data);
#if QT_CONFIG(xinput2)
connection()->xi2Select(m_window);
#endif
- setWindowState(window()->windowState());
+ setWindowState(window()->windowStates());
setWindowFlags(window()->flags());
setWindowTitle(window()->title());
@@ -571,7 +590,7 @@ void QXcbWindow::create()
#if QT_CONFIG(xcb_xlib)
// force sync to read outstanding requests - see QTBUG-29106
- XSync(DISPLAY_FROM_XCB(platformScreen), false);
+ XSync(static_cast<Display*>(platformScreen->connection()->xlib_display()), false);
#endif
#ifndef QT_NO_DRAGANDDROP
@@ -581,6 +600,9 @@ void QXcbWindow::create()
const qreal opacity = qt_window_private(window())->opacity;
if (!qFuzzyCompare(opacity, qreal(1.0)))
setOpacity(opacity);
+
+ setMask(QHighDpi::toNativeLocalRegion(window()->mask(), window()));
+
if (window()->isTopLevel())
setWindowIcon(window()->icon());
@@ -618,7 +640,7 @@ void QXcbWindow::destroy()
connection()->setMouseGrabber(Q_NULLPTR);
if (m_syncCounter && m_usingSyncProtocol)
- Q_XCB_CALL(xcb_sync_destroy_counter(xcb_connection(), m_syncCounter));
+ xcb_sync_destroy_counter(xcb_connection(), m_syncCounter);
if (m_window) {
if (m_netWmUserTimeWindow) {
xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW));
@@ -629,7 +651,7 @@ void QXcbWindow::destroy()
m_netWmUserTimeWindow = XCB_NONE;
}
connection()->removeWindowEventListener(m_window);
- Q_XCB_CALL(xcb_destroy_window(xcb_connection(), m_window));
+ xcb_destroy_window(xcb_connection(), m_window);
m_window = 0;
}
if (m_cmap) {
@@ -664,7 +686,7 @@ void QXcbWindow::setGeometry(const QRect &rect)
qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX),
qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX),
};
- Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values)));
+ xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values));
} else {
const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
const qint32 values[] = {
@@ -673,7 +695,7 @@ void QXcbWindow::setGeometry(const QRect &rect)
qBound<qint32>(1, wmGeometry.width(), XCOORD_MAX),
qBound<qint32>(1, wmGeometry.height(), XCOORD_MAX),
};
- Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values)));
+ xcb_configure_window(xcb_connection(), m_window, mask, reinterpret_cast<const quint32*>(values));
}
xcb_flush(xcb_connection());
@@ -683,12 +705,10 @@ QMargins QXcbWindow::frameMargins() const
{
if (m_dirtyFrameMargins) {
if (connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_FRAME_EXTENTS))) {
- xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, m_window,
- atom(QXcbAtom::_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4);
- QScopedPointer<xcb_get_property_reply_t, QScopedPointerPodDeleter> reply(
- xcb_get_property_reply(xcb_connection(), cookie, NULL));
+ auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, m_window,
+ atom(QXcbAtom::_NET_FRAME_EXTENTS), XCB_ATOM_CARDINAL, 0, 4);
if (reply && reply->type == XCB_ATOM_CARDINAL && reply->format == 32 && reply->value_len == 4) {
- quint32 *data = (quint32 *)xcb_get_property_value(reply.data());
+ quint32 *data = (quint32 *)xcb_get_property_value(reply.get());
// _NET_FRAME_EXTENTS format is left, right, top, bottom
m_frameMargins = QMargins(data[0], data[2], data[1], data[3]);
m_dirtyFrameMargins = false;
@@ -707,9 +727,7 @@ QMargins QXcbWindow::frameMargins() const
connection()->wmSupport()->virtualRoots();
while (!foundRoot) {
- xcb_query_tree_cookie_t cookie = xcb_query_tree_unchecked(xcb_connection(), parent);
-
- xcb_query_tree_reply_t *reply = xcb_query_tree_reply(xcb_connection(), cookie, NULL);
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_query_tree, xcb_connection(), parent);
if (reply) {
if (reply->root == reply->parent || virtualRoots.indexOf(reply->parent) != -1 || reply->parent == XCB_WINDOW_NONE) {
foundRoot = true;
@@ -717,8 +735,6 @@ QMargins QXcbWindow::frameMargins() const
window = parent;
parent = reply->parent;
}
-
- free(reply);
} else {
m_dirtyFrameMargins = false;
m_frameMargins = QMargins();
@@ -728,23 +744,12 @@ QMargins QXcbWindow::frameMargins() const
QPoint offset;
- xcb_translate_coordinates_reply_t *reply =
- xcb_translate_coordinates_reply(
- xcb_connection(),
- xcb_translate_coordinates(xcb_connection(), window, parent, 0, 0),
- NULL);
-
+ auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(), window, parent, 0, 0);
if (reply) {
offset = QPoint(reply->dst_x, reply->dst_y);
- free(reply);
}
- xcb_get_geometry_reply_t *geom =
- xcb_get_geometry_reply(
- xcb_connection(),
- xcb_get_geometry(xcb_connection(), parent),
- NULL);
-
+ auto geom = Q_XCB_REPLY(xcb_get_geometry, xcb_connection(), parent);
if (geom) {
// --
// add the border_width for the window managers frame... some window managers
@@ -761,8 +766,6 @@ QMargins QXcbWindow::frameMargins() const
int bottom = geom->height + geom->border_width - geometry().height() - offset.y();
m_frameMargins = QMargins(left, top, right, bottom);
-
- free(geom);
}
m_dirtyFrameMargins = false;
@@ -789,12 +792,13 @@ static inline bool testShowWithoutActivating(const QWindow *window)
void QXcbWindow::show()
{
if (window()->isTopLevel()) {
+
xcb_get_property_cookie_t cookie = xcb_get_wm_hints_unchecked(xcb_connection(), m_window);
xcb_wm_hints_t hints;
xcb_get_wm_hints_reply(xcb_connection(), cookie, &hints, NULL);
- if (window()->windowState() & Qt::WindowMinimized)
+ if (window()->windowStates() & Qt::WindowMinimized)
xcb_wm_hints_set_iconic(&hints);
else
xcb_wm_hints_set_normal(&hints);
@@ -820,13 +824,13 @@ void QXcbWindow::show()
if (!transientXcbParent)
transientXcbParent = connection()->clientLeader();
if (transientXcbParent) { // ICCCM 4.1.2.6
- Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
- 1, &transientXcbParent));
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32,
+ 1, &transientXcbParent);
}
}
if (!transientXcbParent)
- Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR));
+ xcb_delete_property(xcb_connection(), m_window, XCB_ATOM_WM_TRANSIENT_FOR);
// update _MOTIF_WM_HINTS
updateMotifWmHintsBeforeMap();
@@ -843,7 +847,7 @@ void QXcbWindow::show()
if (window()->objectName() == QLatin1String("QSystemTrayIconSysWindow"))
return; // defer showing until XEMBED_EMBEDDED_NOTIFY
- Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
+ xcb_map_window(xcb_connection(), m_window);
if (QGuiApplication::modalWindow() == window())
requestActivateWindow();
@@ -855,7 +859,7 @@ void QXcbWindow::show()
void QXcbWindow::hide()
{
- Q_XCB_CALL(xcb_unmap_window(xcb_connection(), m_window));
+ xcb_unmap_window(xcb_connection(), m_window);
// send synthetic UnmapNotify event according to icccm 4.1.4
Q_DECLARE_XCB_EVENT(event, xcb_unmap_notify_event_t);
@@ -863,8 +867,8 @@ void QXcbWindow::hide()
event.event = xcbScreen()->root();
event.window = m_window;
event.from_configure = false;
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
- XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
+ xcb_send_event(xcb_connection(), false, xcbScreen()->root(),
+ XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event);
xcb_flush(xcb_connection());
@@ -1012,15 +1016,11 @@ static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window)
{
QtMotifWmHints hints;
- xcb_get_property_cookie_t get_cookie =
- xcb_get_property_unchecked(c->xcb_connection(), 0, window, c->atom(QXcbAtom::_MOTIF_WM_HINTS),
- c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20);
-
- xcb_get_property_reply_t *reply =
- xcb_get_property_reply(c->xcb_connection(), get_cookie, NULL);
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, c->xcb_connection(), 0, window,
+ c->atom(QXcbAtom::_MOTIF_WM_HINTS), c->atom(QXcbAtom::_MOTIF_WM_HINTS), 0, 20);
if (reply && reply->format == 32 && reply->type == c->atom(QXcbAtom::_MOTIF_WM_HINTS)) {
- hints = *((QtMotifWmHints *)xcb_get_property_value(reply));
+ hints = *((QtMotifWmHints *)xcb_get_property_value(reply.get()));
} else {
hints.flags = 0L;
hints.functions = MWM_FUNC_ALL;
@@ -1029,24 +1029,22 @@ static QtMotifWmHints getMotifWmHints(QXcbConnection *c, xcb_window_t window)
hints.status = 0L;
}
- free(reply);
-
return hints;
}
static void setMotifWmHints(QXcbConnection *c, xcb_window_t window, const QtMotifWmHints &hints)
{
if (hints.flags != 0l) {
- Q_XCB_CALL2(xcb_change_property(c->xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- window,
- c->atom(QXcbAtom::_MOTIF_WM_HINTS),
- c->atom(QXcbAtom::_MOTIF_WM_HINTS),
- 32,
- 5,
- &hints), c);
+ xcb_change_property(c->xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ window,
+ c->atom(QXcbAtom::_MOTIF_WM_HINTS),
+ c->atom(QXcbAtom::_MOTIF_WM_HINTS),
+ 32,
+ 5,
+ &hints);
} else {
- Q_XCB_CALL2(xcb_delete_property(c->xcb_connection(), window, c->atom(QXcbAtom::_MOTIF_WM_HINTS)), c);
+ xcb_delete_property(c->xcb_connection(), window, c->atom(QXcbAtom::_MOTIF_WM_HINTS));
}
}
@@ -1054,15 +1052,12 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
{
NetWmStates result(0);
- xcb_get_property_cookie_t get_cookie =
- xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
- XCB_ATOM_ATOM, 0, 1024);
-
- xcb_get_property_reply_t *reply =
- xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
+ 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
+ XCB_ATOM_ATOM, 0, 1024);
if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) {
- const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply));
+ const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get()));
const xcb_atom_t *statesEnd = states + reply->length;
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_ABOVE)))
result |= NetWmStateAbove;
@@ -1080,7 +1075,6 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
result |= NetWmStateStaysOnTop;
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
result |= NetWmStateDemandsAttention;
- free(reply);
} else {
#ifdef NET_WM_STATE_DEBUG
printf("getting net wm state (%x), empty\n", m_window);
@@ -1094,21 +1088,15 @@ void QXcbWindow::setNetWmStates(NetWmStates states)
{
QVector<xcb_atom_t> atoms;
- xcb_get_property_cookie_t get_cookie =
- xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
- XCB_ATOM_ATOM, 0, 1024);
-
- xcb_get_property_reply_t *reply =
- xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
-
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
+ 0, m_window, atom(QXcbAtom::_NET_WM_STATE),
+ XCB_ATOM_ATOM, 0, 1024);
if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM && reply->value_len > 0) {
- const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply));
+ const xcb_atom_t *data = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get()));
atoms.resize(reply->value_len);
memcpy((void *)&atoms.first(), (void *)data, reply->value_len * sizeof(xcb_atom_t));
}
- free(reply);
-
if (states & NetWmStateAbove && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_ABOVE)))
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW)))
@@ -1127,11 +1115,11 @@ void QXcbWindow::setNetWmStates(NetWmStates states)
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
if (atoms.isEmpty()) {
- Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE)));
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE));
} else {
- Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::_NET_WM_STATE), XCB_ATOM_ATOM, 32,
- atoms.count(), atoms.constData()));
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::_NET_WM_STATE), XCB_ATOM_ATOM, 32,
+ atoms.count(), atoms.constData());
}
xcb_flush(xcb_connection());
}
@@ -1254,67 +1242,48 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
event.data.data32[3] = 0;
event.data.data32[4] = 0;
- Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
+ xcb_send_event(xcb_connection(), 0, xcbScreen()->root(),
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
+ (const char *)&event);
}
-void QXcbWindow::setWindowState(Qt::WindowState state)
+void QXcbWindow::setWindowState(Qt::WindowStates state)
{
if (state == m_windowState)
return;
- // unset old state
- switch (m_windowState) {
- case Qt::WindowMinimized:
- Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
- break;
- case Qt::WindowMaximized:
- changeNetWmState(false,
- atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
- atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
- break;
- case Qt::WindowFullScreen:
- changeNetWmState(false, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
- break;
- default:
- break;
+ if ((m_windowState & Qt::WindowMinimized) && !(state & Qt::WindowMinimized)) {
+ xcb_map_window(xcb_connection(), m_window);
+ } else if (!(m_windowState & Qt::WindowMinimized) && (state & Qt::WindowMinimized)) {
+ xcb_client_message_event_t event;
+
+ event.response_type = XCB_CLIENT_MESSAGE;
+ event.format = 32;
+ event.sequence = 0;
+ event.window = m_window;
+ event.type = atom(QXcbAtom::WM_CHANGE_STATE);
+ event.data.data32[0] = XCB_WM_STATE_ICONIC;
+ event.data.data32[1] = 0;
+ event.data.data32[2] = 0;
+ event.data.data32[3] = 0;
+ event.data.data32[4] = 0;
+
+ xcb_send_event(xcb_connection(), 0, xcbScreen()->root(),
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
+ (const char *)&event);
+ m_minimized = true;
}
- // set new state
- switch (state) {
- case Qt::WindowMinimized:
- {
- xcb_client_message_event_t event;
-
- event.response_type = XCB_CLIENT_MESSAGE;
- event.format = 32;
- event.sequence = 0;
- event.window = m_window;
- event.type = atom(QXcbAtom::WM_CHANGE_STATE);
- event.data.data32[0] = XCB_WM_STATE_ICONIC;
- event.data.data32[1] = 0;
- event.data.data32[2] = 0;
- event.data.data32[3] = 0;
- event.data.data32[4] = 0;
-
- Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
- }
- break;
- case Qt::WindowMaximized:
- changeNetWmState(true,
- atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
+ if ((m_windowState ^ state) & Qt::WindowMaximized) {
+ changeNetWmState(state & Qt::WindowMaximized, atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ),
atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT));
- break;
- case Qt::WindowFullScreen:
- changeNetWmState(true, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
- break;
- case Qt::WindowNoState:
- break;
- default:
- break;
}
- connection()->sync();
+ if ((m_windowState ^ state) & Qt::WindowFullScreen) {
+ changeNetWmState(state & Qt::WindowFullScreen, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
+ }
+ connection()->sync();
m_windowState = state;
}
@@ -1386,10 +1355,10 @@ void QXcbWindow::updateNetWmStateBeforeMap()
states |= NetWmStateBelow;
}
- if (window()->windowState() & Qt::WindowFullScreen)
+ if (window()->windowStates() & Qt::WindowFullScreen)
states |= NetWmStateFullScreen;
- if (window()->windowState() & Qt::WindowMaximized) {
+ if (window()->windowStates() & Qt::WindowMaximized) {
states |= NetWmStateMaximizedHorz;
states |= NetWmStateMaximizedVert;
}
@@ -1422,30 +1391,30 @@ void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp)
if (m_netWmUserTimeWindow || isSupportedByWM) {
if (!m_netWmUserTimeWindow) {
m_netWmUserTimeWindow = xcb_generate_id(xcb_connection());
- Q_XCB_CALL(xcb_create_window(xcb_connection(),
- XCB_COPY_FROM_PARENT, // depth -- same as root
- m_netWmUserTimeWindow, // window id
- m_window, // parent window id
- -1, -1, 1, 1,
- 0, // border width
- XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
- m_visualId, // visual
- 0, // value mask
- 0)); // value list
+ xcb_create_window(xcb_connection(),
+ XCB_COPY_FROM_PARENT, // depth -- same as root
+ m_netWmUserTimeWindow, // window id
+ m_window, // parent window id
+ -1, -1, 1, 1,
+ 0, // border width
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
+ m_visualId, // visual
+ 0, // value mask
+ 0); // value list
wid = m_netWmUserTimeWindow;
xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_USER_TIME_WINDOW),
XCB_ATOM_WINDOW, 32, 1, &m_netWmUserTimeWindow);
xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_USER_TIME));
#ifndef QT_NO_DEBUG
QByteArray ba("Qt NET_WM user time window");
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_netWmUserTimeWindow,
- atom(QXcbAtom::_NET_WM_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData()));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_netWmUserTimeWindow,
+ atom(QXcbAtom::_NET_WM_NAME),
+ atom(QXcbAtom::UTF8_STRING),
+ 8,
+ ba.length(),
+ ba.constData());
#endif
} else if (!isSupportedByWM) {
// WM no longer supports it, then we should remove the
@@ -1519,26 +1488,27 @@ void QXcbWindow::setParent(const QPlatformWindow *parent)
xcb_parent_id = xcbScreen()->root();
m_embedded = false;
}
- Q_XCB_CALL(xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y()));
+ xcb_reparent_window(xcb_connection(), xcb_window(), xcb_parent_id, topLeft.x(), topLeft.y());
}
void QXcbWindow::setWindowTitle(const QString &title)
{
QString fullTitle = formatWindowTitle(title, QString::fromUtf8(" \xe2\x80\x94 ")); // unicode character U+2014, EM DASH
const QByteArray ba = std::move(fullTitle).toUtf8();
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
+ xcb_change_property(xcb_connection(),
XCB_PROP_MODE_REPLACE,
m_window,
atom(QXcbAtom::_NET_WM_NAME),
atom(QXcbAtom::UTF8_STRING),
8,
ba.length(),
- ba.constData()));
+ ba.constData());
#if QT_CONFIG(xcb_xlib)
- XTextProperty *text = qstringToXTP(DISPLAY_FROM_XCB(this), title);
+ Display *dpy = static_cast<Display *>(connection()->xlib_display());
+ XTextProperty *text = qstringToXTP(dpy, title);
if (text)
- XSetWMName(DISPLAY_FROM_XCB(this), m_window, text);
+ XSetWMName(dpy, m_window, text);
#endif
xcb_flush(xcb_connection());
}
@@ -1546,14 +1516,14 @@ void QXcbWindow::setWindowTitle(const QString &title)
void QXcbWindow::setWindowIconText(const QString &title)
{
const QByteArray ba = title.toUtf8();
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_window,
- atom(QXcbAtom::_NET_WM_ICON_NAME),
- atom(QXcbAtom::UTF8_STRING),
- 8,
- ba.length(),
- ba.constData()));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::_NET_WM_ICON_NAME),
+ atom(QXcbAtom::UTF8_STRING),
+ 8,
+ ba.length(),
+ ba.constData());
}
void QXcbWindow::setWindowIcon(const QIcon &icon)
@@ -1583,18 +1553,18 @@ void QXcbWindow::setWindowIcon(const QIcon &icon)
}
if (!icon_data.isEmpty()) {
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_window,
- atom(QXcbAtom::_NET_WM_ICON),
- atom(QXcbAtom::CARDINAL),
- 32,
- icon_data.size(),
- (unsigned char *) icon_data.data()));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::_NET_WM_ICON),
+ atom(QXcbAtom::CARDINAL),
+ 32,
+ icon_data.size(),
+ (unsigned char *) icon_data.data());
} else {
- Q_XCB_CALL(xcb_delete_property(xcb_connection(),
- m_window,
- atom(QXcbAtom::_NET_WM_ICON)));
+ xcb_delete_property(xcb_connection(),
+ m_window,
+ atom(QXcbAtom::_NET_WM_ICON));
}
}
@@ -1602,14 +1572,14 @@ void QXcbWindow::raise()
{
const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE;
const quint32 values[] = { XCB_STACK_MODE_ABOVE };
- Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
+ xcb_configure_window(xcb_connection(), m_window, mask, values);
}
void QXcbWindow::lower()
{
const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE;
const quint32 values[] = { XCB_STACK_MODE_BELOW };
- Q_XCB_CALL(xcb_configure_window(xcb_connection(), m_window, mask, values));
+ xcb_configure_window(xcb_connection(), m_window, mask, values);
}
// Adapt the geometry to match the WM expection with regards
@@ -1703,9 +1673,11 @@ void QXcbWindow::requestActivateWindow()
event.data.data32[3] = 0;
event.data.data32[4] = 0;
- Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
+ xcb_send_event(xcb_connection(), 0, xcbScreen()->root(),
+ XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT,
+ (const char *)&event);
} else {
- Q_XCB_CALL(xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time()));
+ xcb_set_input_focus(xcb_connection(), XCB_INPUT_FOCUS_PARENT, m_window, connection()->time());
}
connection()->sync();
@@ -1749,15 +1721,11 @@ QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const
{
QXcbWindowFunctions::WmWindowTypes result(0);
- xcb_get_property_cookie_t get_cookie =
- xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE),
- XCB_ATOM_ATOM, 0, 1024);
-
- xcb_get_property_reply_t *reply =
- xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
-
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property, xcb_connection(),
+ 0, m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE),
+ XCB_ATOM_ATOM, 0, 1024);
if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) {
- const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply));
+ const xcb_atom_t *types = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply.get()));
const xcb_atom_t *types_end = types + reply->length;
for (; types != types_end; types++) {
QXcbAtom::Atom type = connection()->qatom(*types);
@@ -1811,7 +1779,6 @@ QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const
break;
}
}
- free(reply);
}
return result;
}
@@ -1894,20 +1861,20 @@ void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types, Qt::W
atoms.append(atom(QXcbAtom::_NET_WM_WINDOW_TYPE_NORMAL));
if (atoms.isEmpty()) {
- Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE)));
+ xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_WINDOW_TYPE));
} else {
- Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32,
- atoms.count(), atoms.constData()));
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::_NET_WM_WINDOW_TYPE), XCB_ATOM_ATOM, 32,
+ atoms.count(), atoms.constData());
}
xcb_flush(xcb_connection());
}
void QXcbWindow::setWmWindowRole(const QByteArray &role)
{
- Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
- atom(QXcbAtom::WM_WINDOW_ROLE), XCB_ATOM_STRING, 8,
- role.size(), role.constData()));
+ xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window,
+ atom(QXcbAtom::WM_WINDOW_ROLE), XCB_ATOM_STRING, 8,
+ role.size(), role.constData());
}
void QXcbWindow::setParentRelativeBackPixmapStatic(QWindow *window)
@@ -1920,7 +1887,7 @@ void QXcbWindow::setParentRelativeBackPixmap()
{
const quint32 mask = XCB_CW_BACK_PIXMAP;
const quint32 values[] = { XCB_BACK_PIXMAP_PARENT_RELATIVE };
- Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values));
+ xcb_change_window_attributes(xcb_connection(), m_window, mask, values);
}
bool QXcbWindow::requestSystemTrayWindowDockStatic(const QWindow *window)
@@ -2011,11 +1978,7 @@ void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event)
{
QRect rect(event->x, event->y, event->width, event->height);
- if (m_exposeRegion.isEmpty())
- m_exposeRegion = rect;
- else
- m_exposeRegion |= rect;
-
+ m_exposeRegion |= rect;
bool pending = compressExposeEvent(m_exposeRegion);
// if count is non-zero there are more expose events pending
@@ -2097,13 +2060,11 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
QPoint pos(event->x, event->y);
if (!parent() && !fromSendEvent) {
// Do not trust the position, query it instead.
- xcb_translate_coordinates_cookie_t cookie = xcb_translate_coordinates(xcb_connection(), xcb_window(),
- xcbScreen()->root(), 0, 0);
- xcb_translate_coordinates_reply_t *reply = xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL);
+ auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(),
+ xcb_window(), xcbScreen()->root(), 0, 0);
if (reply) {
pos.setX(reply->dst_x);
pos.setY(reply->dst_y);
- free(reply);
}
}
@@ -2112,14 +2073,6 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
if (!newScreen)
return;
- // Persist the actual geometry so that QWindow::geometry() can
- // be queried in the resize event.
- QPlatformWindow::setGeometry(actualGeometry);
-
- // FIXME: In the case of the requestedGeometry not matching the actualGeometry due
- // to e.g. the window manager applying restrictions to the geometry, the application
- // will never see a move/resize event if the actualGeometry is the same as the current
- // geometry, and may think the requested geometry was fulfilled.
QWindowSystemInterface::handleGeometryChange(window(), actualGeometry);
// QPlatformScreen::screen() is updated asynchronously, so we can't compare it
@@ -2158,15 +2111,12 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const
return pos;
QPoint ret;
- xcb_translate_coordinates_cookie_t cookie =
- xcb_translate_coordinates(xcb_connection(), xcb_window(), xcbScreen()->root(),
- pos.x(), pos.y());
- xcb_translate_coordinates_reply_t *reply =
- xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL);
+ auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(),
+ xcb_window(), xcbScreen()->root(),
+ pos.x(), pos.y());
if (reply) {
ret.setX(reply->dst_x);
ret.setY(reply->dst_y);
- free(reply);
}
return ret;
@@ -2178,15 +2128,12 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const
return pos;
QPoint ret;
- xcb_translate_coordinates_cookie_t cookie =
- xcb_translate_coordinates(xcb_connection(), xcbScreen()->root(), xcb_window(),
- pos.x(), pos.y());
- xcb_translate_coordinates_reply_t *reply =
- xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL);
+ auto reply = Q_XCB_REPLY(xcb_translate_coordinates, xcb_connection(),
+ xcbScreen()->root(), xcb_window(),
+ pos.x(), pos.y());
if (reply) {
ret.setX(reply->dst_x);
ret.setY(reply->dst_y);
- free(reply);
}
return ret;
@@ -2238,16 +2185,24 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
QPoint global(root_x, root_y);
if (isWheel) {
+#if QT_CONFIG(xinput2)
if (!connection()->isAtLeastXI21()) {
- // Logic borrowed from qapplication_x11.cpp
- int delta = 120 * ((detail == 4 || detail == 6) ? 1 : -1);
- bool hor = (((detail == 4 || detail == 5)
- && (modifiers & Qt::AltModifier))
- || (detail == 6 || detail == 7));
-
- QWindowSystemInterface::handleWheelEvent(window(), timestamp,
- local, global, delta, hor ? Qt::Horizontal : Qt::Vertical, modifiers);
+#endif
+ QPoint angleDelta;
+ if (detail == 4)
+ angleDelta.setY(120);
+ else if (detail == 5)
+ angleDelta.setY(-120);
+ else if (detail == 6)
+ angleDelta.setX(120);
+ else if (detail == 7)
+ angleDelta.setX(-120);
+ if (modifiers & Qt::AltModifier)
+ std::swap(angleDelta.rx(), angleDelta.ry());
+ QWindowSystemInterface::handleWheelEvent(window(), timestamp, local, global, QPoint(), angleDelta, modifiers);
+#if QT_CONFIG(xinput2)
}
+#endif
return;
}
@@ -2267,7 +2222,7 @@ void QXcbWindow::handleButtonReleaseEvent(int event_x, int event_y, int root_x,
return;
}
- if (connection()->buttons() == Qt::NoButton)
+ if (connection()->buttonState() == Qt::NoButton)
connection()->setMousePressWindow(Q_NULLPTR);
handleMouseEvent(timestamp, local, global, modifiers, source);
@@ -2282,7 +2237,7 @@ static inline bool doCheckUnGrabAncestor(QXcbConnection *conn)
* not pressed, otherwise (e.g. on Alt+Tab) it can igonre important enter/leave events.
*/
if (conn) {
- const bool mouseButtonsPressed = (conn->buttons() != Qt::NoButton);
+ const bool mouseButtonsPressed = (conn->buttonState() != Qt::NoButton);
#ifdef XCB_USE_XINPUT22
return mouseButtonsPressed || (conn->isAtLeastXI22() && conn->xi2MouseEvents());
#else
@@ -2333,7 +2288,8 @@ void QXcbWindow::handleEnterNotifyEvent(int event_x, int event_y, int root_x, in
{
connection()->setTime(timestamp);
#ifdef XCB_USE_XINPUT21
- connection()->handleEnterEvent();
+ // Updates scroll valuators, as user might have done some scrolling outside our X client.
+ connection()->xi2UpdateScrollingDevices();
#endif
const QPoint global = QPoint(root_x, root_y);
@@ -2376,7 +2332,7 @@ void QXcbWindow::handleMotionNotifyEvent(int event_x, int event_y, int root_x, i
// "mousePressWindow" can be NULL i.e. if a window will be grabbed or unmapped, so set it again here.
// Unset "mousePressWindow" when mouse button isn't pressed - in some cases the release event won't arrive.
- const bool isMouseButtonPressed = (connection()->buttons() != Qt::NoButton);
+ const bool isMouseButtonPressed = (connection()->buttonState() != Qt::NoButton);
const bool hasMousePressWindow = (connection()->mousePressWindow() != Q_NULLPTR);
if (isMouseButtonPressed && !hasMousePressWindow)
connection()->setMousePressWindow(this);
@@ -2431,7 +2387,7 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource
return;
}
for (int i = 1; i <= 15; ++i)
- conn->setButton(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i));
+ conn->setButtonState(conn->translateMouseButton(i), XIMaskIsSet(buttonMask, i));
}
const Qt::KeyboardModifiers modifiers = conn->keyboard()->translateModifiers(ev->mods.effective_mods);
@@ -2455,13 +2411,13 @@ void QXcbWindow::handleXIMouseEvent(xcb_ge_event_t *event, Qt::MouseEventSource
case XI_ButtonPress:
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "XI2 mouse press, button %d, time %d, source %s", button, ev->time, sourceName);
- conn->setButton(button, true);
+ conn->setButtonState(button, true);
handleButtonPressEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source);
break;
case XI_ButtonRelease:
if (Q_UNLIKELY(lcQpaXInputEvents().isDebugEnabled()))
qCDebug(lcQpaXInputEvents, "XI2 mouse release, button %d, time %d, source %s", button, ev->time, sourceName);
- conn->setButton(button, false);
+ conn->setButtonState(button, false);
handleButtonReleaseEvent(event_x, event_y, root_x, root_y, ev->detail, modifiers, ev->time, source);
break;
case XI_Motion:
@@ -2495,12 +2451,14 @@ void QXcbWindow::handleXIEnterLeave(xcb_ge_event_t *event)
case XI_Enter: {
const int event_x = fixed1616ToInt(ev->event_x);
const int event_y = fixed1616ToInt(ev->event_y);
- qCDebug(lcQpaXInput, "XI2 mouse enter %d,%d, mode %d, detail %d, time %d", event_x, event_y, ev->mode, ev->detail, ev->time);
+ qCDebug(lcQpaXInputEvents, "XI2 mouse enter %d,%d, mode %d, detail %d, time %d",
+ event_x, event_y, ev->mode, ev->detail, ev->time);
handleEnterNotifyEvent(event_x, event_y, root_x, root_y, ev->mode, ev->detail, ev->time);
break;
}
case XI_Leave:
- qCDebug(lcQpaXInput, "XI2 mouse leave, mode %d, detail %d, time %d", ev->mode, ev->detail, ev->time);
+ qCDebug(lcQpaXInputEvents, "XI2 mouse leave, mode %d, detail %d, time %d",
+ ev->mode, ev->detail, ev->time);
connection()->keyboard()->updateXKBStateFromXI(&ev->mods, &ev->group);
handleLeaveNotifyEvent(root_x, root_y, ev->mode, ev->detail, ev->time);
break;
@@ -2514,7 +2472,7 @@ void QXcbWindow::handleMouseEvent(xcb_timestamp_t time, const QPoint &local, con
Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source)
{
connection()->setTime(time);
- QWindowSystemInterface::handleMouseEvent(window(), time, local, global, connection()->buttons(), modifiers, source);
+ QWindowSystemInterface::handleMouseEvent(window(), time, local, global, connection()->buttonState(), modifiers, source);
}
void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
@@ -2537,44 +2495,33 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
if (propertyDeleted)
return;
- Qt::WindowState newState = Qt::WindowNoState;
- if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'.
- const xcb_get_property_cookie_t get_cookie =
- xcb_get_property(xcb_connection(), 0, m_window, atom(QXcbAtom::WM_STATE),
- XCB_ATOM_ANY, 0, 1024);
-
- xcb_get_property_reply_t *reply =
- xcb_get_property_reply(xcb_connection(), get_cookie, NULL);
+ Qt::WindowStates newState = Qt::WindowNoState;
+ if (event->atom == atom(QXcbAtom::WM_STATE)) { // WM_STATE: Quick check for 'Minimize'.
+ auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
+ 0, m_window, atom(QXcbAtom::WM_STATE),
+ XCB_ATOM_ANY, 0, 1024);
if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) {
- const quint32 *data = (const quint32 *)xcb_get_property_value(reply);
- if (reply->length != 0) {
- if (data[0] == XCB_WM_STATE_ICONIC
- || (data[0] == XCB_WM_STATE_WITHDRAWN
- && m_lastWindowStateEvent == Qt::WindowMinimized)) {
- newState = Qt::WindowMinimized;
- }
- }
+ const quint32 *data = (const quint32 *)xcb_get_property_value(reply.get());
+ if (reply->length != 0)
+ m_minimized = (data[0] == XCB_WM_STATE_ICONIC
+ || (data[0] == XCB_WM_STATE_WITHDRAWN && m_minimized));
}
- free(reply);
- } else { // _NET_WM_STATE can't change minimized state
- if (m_lastWindowStateEvent == Qt::WindowMinimized)
- newState = Qt::WindowMinimized;
- }
-
- if (newState != Qt::WindowMinimized) { // Something else changed, get _NET_WM_STATE.
- const NetWmStates states = netWmStates();
- if (states & NetWmStateFullScreen)
- newState = Qt::WindowFullScreen;
- else if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert))
- newState = Qt::WindowMaximized;
}
+ if (m_minimized)
+ newState = Qt::WindowMinimized;
+
+ const NetWmStates states = netWmStates();
+ if (states & NetWmStateFullScreen)
+ newState |= Qt::WindowFullScreen;
+ if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert))
+ newState |= Qt::WindowMaximized;
// Send Window state, compress events in case other flags (modality, etc) are changed.
if (m_lastWindowStateEvent != newState) {
QWindowSystemInterface::handleWindowStateChanged(window(), newState);
m_lastWindowStateEvent = newState;
m_windowState = newState;
- if (m_windowState == Qt::WindowMinimized && connection()->mouseGrabber() == this)
+ if ((m_windowState & Qt::WindowMinimized) && connection()->mouseGrabber() == this)
connection()->setMouseGrabber(Q_NULLPTR);
}
return;
@@ -2609,7 +2556,7 @@ void QXcbWindow::updateSyncRequestCounter()
return;
}
if (m_usingSyncProtocol && (m_syncValue.lo != 0 || m_syncValue.hi != 0)) {
- Q_XCB_CALL(xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue));
+ xcb_sync_set_counter(xcb_connection(), m_syncCounter, m_syncValue);
xcb_flush(xcb_connection());
m_syncValue.lo = 0;
@@ -2633,13 +2580,11 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
xcb_ungrab_keyboard(xcb_connection(), XCB_TIME_CURRENT_TIME);
return true;
}
- xcb_grab_keyboard_cookie_t cookie = xcb_grab_keyboard(xcb_connection(), false,
- m_window, XCB_TIME_CURRENT_TIME,
- XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
- xcb_grab_keyboard_reply_t *reply = xcb_grab_keyboard_reply(xcb_connection(), cookie, NULL);
- bool result = !(!reply || reply->status != XCB_GRAB_STATUS_SUCCESS);
- free(reply);
- return result;
+
+ auto reply = Q_XCB_REPLY(xcb_grab_keyboard, xcb_connection(), false,
+ m_window, XCB_TIME_CURRENT_TIME,
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC);
+ return reply && reply->status == XCB_GRAB_STATUS_SUCCESS;
}
bool QXcbWindow::setMouseGrabEnabled(bool grab)
@@ -2661,16 +2606,16 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME);
return true;
}
- xcb_grab_pointer_cookie_t cookie = xcb_grab_pointer(xcb_connection(), false, m_window,
- (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
- | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW
- | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION),
- XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
- XCB_WINDOW_NONE, XCB_CURSOR_NONE,
- XCB_TIME_CURRENT_TIME);
- xcb_grab_pointer_reply_t *reply = xcb_grab_pointer_reply(xcb_connection(), cookie, NULL);
- bool result = !(!reply || reply->status != XCB_GRAB_STATUS_SUCCESS);
- free(reply);
+
+ auto reply = Q_XCB_REPLY(xcb_grab_pointer, xcb_connection(),
+ false, m_window,
+ (XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
+ | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW
+ | XCB_EVENT_MASK_LEAVE_WINDOW | XCB_EVENT_MASK_POINTER_MOTION),
+ XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_ASYNC,
+ XCB_WINDOW_NONE, XCB_CURSOR_NONE,
+ XCB_TIME_CURRENT_TIME);
+ bool result = reply && reply->status == XCB_GRAB_STATUS_SUCCESS;
if (result)
connection()->setMouseGrabber(this);
return result;
@@ -2778,8 +2723,7 @@ void QXcbWindow::sendXEmbedMessage(xcb_window_t window, quint32 message,
event.data.data32[2] = detail;
event.data.data32[3] = data1;
event.data.data32[4] = data2;
- Q_XCB_CALL(xcb_send_event(xcb_connection(), false, window,
- XCB_EVENT_MASK_NO_EVENT, (const char *)&event));
+ xcb_send_event(xcb_connection(), false, window, XCB_EVENT_MASK_NO_EVENT, (const char *)&event);
}
static bool activeWindowChangeQueued(const QWindow *window)
@@ -2801,12 +2745,12 @@ void QXcbWindow::handleXEmbedMessage(const xcb_client_message_event_t *event)
case XEMBED_WINDOW_DEACTIVATE:
break;
case XEMBED_EMBEDDED_NOTIFY:
- Q_XCB_CALL(xcb_map_window(xcb_connection(), m_window));
+ xcb_map_window(xcb_connection(), m_window);
xcbScreen()->windowShown(this);
// Without Qt::WA_TranslucentBackground, we use a ParentRelative BackPixmap.
// Clear the whole tray icon window to its background color as early as possible
// so that we can get a clean result from grabWindow() later.
- Q_XCB_CALL(xcb_clear_area(xcb_connection(), false, m_window, 0, 0, geometry().width(), geometry().height()));
+ xcb_clear_area(xcb_connection(), false, m_window, 0, 0, geometry().width(), geometry().height());
xcb_flush(xcb_connection());
break;
case XEMBED_FOCUS_IN:
@@ -2853,14 +2797,14 @@ void QXcbWindow::setOpacity(qreal level)
quint32 value = qRound64(qBound(qreal(0), level, qreal(1)) * 0xffffffff);
- Q_XCB_CALL(xcb_change_property(xcb_connection(),
- XCB_PROP_MODE_REPLACE,
- m_window,
- atom(QXcbAtom::_NET_WM_WINDOW_OPACITY),
- XCB_ATOM_CARDINAL,
- 32,
- 1,
- (uchar *)&value));
+ xcb_change_property(xcb_connection(),
+ XCB_PROP_MODE_REPLACE,
+ m_window,
+ atom(QXcbAtom::_NET_WM_WINDOW_OPACITY),
+ XCB_ATOM_CARDINAL,
+ 32,
+ 1,
+ (uchar *)&value);
}
void QXcbWindow::setMask(const QRegion &region)
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index f38343b6c2..b5bf33520f 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -82,7 +82,7 @@ public:
void setVisible(bool visible) override;
void setWindowFlags(Qt::WindowFlags flags) override;
- void setWindowState(Qt::WindowState state) override;
+ void setWindowState(Qt::WindowStates state) override;
WId winId() const override;
void setParent(const QPlatformWindow *window) override;
@@ -244,7 +244,7 @@ protected:
xcb_sync_int64_t m_syncValue;
xcb_sync_counter_t m_syncCounter = 0;
- Qt::WindowState m_windowState = Qt::WindowNoState;
+ Qt::WindowStates m_windowState = Qt::WindowNoState;
xcb_gravity_t m_gravity = XCB_GRAVITY_STATIC;
@@ -254,6 +254,7 @@ protected:
bool m_deferredActivation = false;
bool m_embedded = false;
bool m_alertState = false;
+ bool m_minimized = false;
xcb_window_t m_netWmUserTimeWindow = XCB_NONE;
QSurfaceFormat m_format;
@@ -265,7 +266,8 @@ protected:
QSize m_oldWindowSize;
xcb_visualid_t m_visualId = 0;
- int m_lastWindowStateEvent = -1;
+ // Last sent state. Initialized to an invalid state, on purpose.
+ Qt::WindowStates m_lastWindowStateEvent = Qt::WindowActive;
enum SyncState {
NoSyncNeeded,
diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
index 470f021314..2619892b19 100644
--- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp
+++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
@@ -66,16 +66,15 @@ void QXcbWMSupport::updateNetWMAtoms()
int offset = 0;
int remaining = 0;
do {
- xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_SUPPORTED), XCB_ATOM_ATOM, offset, 1024);
- xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, NULL);
+ auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(), false, root, atom(QXcbAtom::_NET_SUPPORTED), XCB_ATOM_ATOM, offset, 1024);
if (!reply)
break;
remaining = 0;
if (reply->type == XCB_ATOM_ATOM && reply->format == 32) {
- int len = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t);
- xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply);
+ int len = xcb_get_property_value_length(reply.get())/sizeof(xcb_atom_t);
+ xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply.get());
int s = net_wm_atoms.size();
net_wm_atoms.resize(s + len);
memcpy(net_wm_atoms.data() + s, atoms, len*sizeof(xcb_atom_t));
@@ -83,8 +82,6 @@ void QXcbWMSupport::updateNetWMAtoms()
remaining = reply->bytes_after;
offset += len;
}
-
- free(reply);
} while (remaining > 0);
}
@@ -100,16 +97,16 @@ void QXcbWMSupport::updateVirtualRoots()
int offset = 0;
int remaining = 0;
do {
- xcb_get_property_cookie_t cookie = xcb_get_property(xcb_connection(), false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024);
- xcb_get_property_reply_t *reply = xcb_get_property_reply(xcb_connection(), cookie, NULL);
+ auto reply = Q_XCB_REPLY(xcb_get_property, xcb_connection(),
+ false, root, atom(QXcbAtom::_NET_VIRTUAL_ROOTS), XCB_ATOM_WINDOW, offset, 1024);
if (!reply)
break;
remaining = 0;
if (reply->type == XCB_ATOM_WINDOW && reply->format == 32) {
- int len = xcb_get_property_value_length(reply)/sizeof(xcb_window_t);
- xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply);
+ int len = xcb_get_property_value_length(reply.get())/sizeof(xcb_window_t);
+ xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply.get());
int s = net_virtual_roots.size();
net_virtual_roots.resize(s + len);
memcpy(net_virtual_roots.data() + s, roots, len*sizeof(xcb_window_t));
@@ -118,10 +115,10 @@ void QXcbWMSupport::updateVirtualRoots()
offset += len;
}
- free(reply);
} while (remaining > 0);
-#ifdef Q_XCB_DEBUG
+//#define VIRTUAL_ROOTS_DEBUG
+#ifdef VIRTUAL_ROOTS_DEBUG
qDebug("======== updateVirtualRoots");
for (int i = 0; i < net_virtual_roots.size(); ++i)
qDebug() << connection()->atomName(net_virtual_roots.at(i));
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
index 88933c6c22..bd398ea049 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.cpp
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
@@ -106,26 +106,23 @@ public:
QByteArray settings;
xcb_atom_t _xsettings_atom = screen->connection()->atom(QXcbAtom::_XSETTINGS_SETTINGS);
while (1) {
- xcb_get_property_cookie_t get_prop_cookie =
- xcb_get_property_unchecked(screen->xcb_connection(),
+ auto reply = Q_XCB_REPLY_UNCHECKED(xcb_get_property,
+ screen->xcb_connection(),
false,
x_settings_window,
_xsettings_atom,
_xsettings_atom,
offset/4,
8192);
- xcb_get_property_reply_t *reply = xcb_get_property_reply(screen->xcb_connection(), get_prop_cookie, NULL);
bool more = false;
if (!reply)
return settings;
- const auto property_value_length = xcb_get_property_value_length(reply);
- settings.append(static_cast<const char *>(xcb_get_property_value(reply)), property_value_length);
+ const auto property_value_length = xcb_get_property_value_length(reply.get());
+ settings.append(static_cast<const char *>(xcb_get_property_value(reply.get())), property_value_length);
offset += property_value_length;
more = reply->bytes_after != 0;
- free(reply);
-
if (!more)
break;
}
@@ -228,34 +225,24 @@ QXcbXSettings::QXcbXSettings(QXcbVirtualDesktop *screen)
{
QByteArray settings_atom_for_screen("_XSETTINGS_S");
settings_atom_for_screen.append(QByteArray::number(screen->number()));
- xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(screen->xcb_connection(),
- true,
- settings_atom_for_screen.length(),
- settings_atom_for_screen.constData());
- xcb_generic_error_t *error = 0;
- xcb_intern_atom_reply_t *atom_reply = xcb_intern_atom_reply(screen->xcb_connection(),atom_cookie,&error);
- if (error) {
- free(error);
+ auto atom_reply = Q_XCB_REPLY(xcb_intern_atom,
+ screen->xcb_connection(),
+ true,
+ settings_atom_for_screen.length(),
+ settings_atom_for_screen.constData());
+ if (!atom_reply)
return;
- }
- xcb_atom_t selection_owner_atom = atom_reply->atom;
- free(atom_reply);
- xcb_get_selection_owner_cookie_t selection_cookie =
- xcb_get_selection_owner(screen->xcb_connection(), selection_owner_atom);
+ xcb_atom_t selection_owner_atom = atom_reply->atom;
- xcb_get_selection_owner_reply_t *selection_result =
- xcb_get_selection_owner_reply(screen->xcb_connection(), selection_cookie, &error);
- if (error) {
- free(error);
+ auto selection_result = Q_XCB_REPLY(xcb_get_selection_owner,
+ screen->xcb_connection(), selection_owner_atom);
+ if (!selection_result)
return;
- }
d_ptr->x_settings_window = selection_result->owner;
- free(selection_result);
- if (!d_ptr->x_settings_window) {
+ if (!d_ptr->x_settings_window)
return;
- }
const uint32_t event = XCB_CW_EVENT_MASK;
const uint32_t event_mask[] = { XCB_EVENT_MASK_STRUCTURE_NOTIFY|XCB_EVENT_MASK_PROPERTY_CHANGE };
diff --git a/src/plugins/platforms/xcb/xcb_qpa_lib.pro b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
index 1c76b49650..6956d04083 100644
--- a/src/plugins/platforms/xcb/xcb_qpa_lib.pro
+++ b/src/plugins/platforms/xcb/xcb_qpa_lib.pro
@@ -5,11 +5,14 @@ DEFINES += QT_NO_FOREACH
QT += \
core-private gui-private \
service_support-private theme_support-private \
- eventdispatcher_support-private fontdatabase_support-private
+ eventdispatcher_support-private fontdatabase_support-private \
+ edid_support-private
qtHaveModule(linuxaccessibility_support-private): \
QT += linuxaccessibility_support-private
+qtConfig(vulkan): QT += vulkan_support-private
+
SOURCES = \
qxcbclipboard.cpp \
qxcbconnection.cpp \
@@ -65,6 +68,17 @@ qtConfig(xcb-sm) {
}
include(gl_integrations/gl_integrations.pri)
+include(nativepainting/nativepainting.pri)
+
+qtConfig(vulkan) {
+ SOURCES += \
+ qxcbvulkaninstance.cpp \
+ qxcbvulkanwindow.cpp
+
+ HEADERS += \
+ qxcbvulkaninstance.h \
+ qxcbvulkanwindow.h
+}
!qtConfig(system-xcb) {
QMAKE_USE += xcb-static xcb
diff --git a/src/plugins/platformthemes/gtk3/qgtk3menu.cpp b/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
index f48e00ab8e..0b67739095 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
+++ b/src/plugins/platformthemes/gtk3/qgtk3menu.cpp
@@ -86,7 +86,6 @@ QGtk3MenuItem::QGtk3MenuItem()
m_enabled(true),
m_underline(false),
m_invalid(true),
- m_tag(reinterpret_cast<quintptr>(this)),
m_menu(nullptr),
m_item(nullptr)
{
@@ -149,16 +148,6 @@ GtkWidget *QGtk3MenuItem::handle() const
return m_item;
}
-quintptr QGtk3MenuItem::tag() const
-{
- return m_tag;
-}
-
-void QGtk3MenuItem::setTag(quintptr tag)
-{
- m_tag = tag;
-}
-
QString QGtk3MenuItem::text() const
{
return m_text;
@@ -347,7 +336,6 @@ void QGtk3MenuItem::onToggle(GtkCheckMenuItem *check, void *data)
}
QGtk3Menu::QGtk3Menu()
- : m_tag(reinterpret_cast<quintptr>(this))
{
m_menu = gtk_menu_new();
@@ -408,16 +396,6 @@ void QGtk3Menu::syncSeparatorsCollapsible(bool enable)
Q_UNUSED(enable);
}
-quintptr QGtk3Menu::tag() const
-{
- return m_tag;
-}
-
-void QGtk3Menu::setTag(quintptr tag)
-{
- m_tag = tag;
-}
-
void QGtk3Menu::setEnabled(bool enabled)
{
gtk_widget_set_sensitive(m_menu, enabled);
diff --git a/src/plugins/platformthemes/gtk3/qgtk3menu.h b/src/plugins/platformthemes/gtk3/qgtk3menu.h
index c4dd89cefc..cce800fbd8 100644
--- a/src/plugins/platformthemes/gtk3/qgtk3menu.h
+++ b/src/plugins/platformthemes/gtk3/qgtk3menu.h
@@ -61,9 +61,6 @@ public:
GtkWidget *create();
GtkWidget *handle() const;
- quintptr tag() const override;
- void setTag(quintptr tag) override;
-
QString text() const;
void setText(const QString &text) override;
@@ -112,7 +109,6 @@ private:
bool m_exclusive;
bool m_underline;
bool m_invalid;
- quintptr m_tag;
QGtk3Menu *m_menu;
GtkWidget *m_item;
QString m_text;
@@ -136,9 +132,6 @@ public:
void syncMenuItem(QPlatformMenuItem *item) override;
void syncSeparatorsCollapsible(bool enable) override;
- quintptr tag() const override;
- void setTag(quintptr tag) override;
-
void setEnabled(bool enabled) override;
void setVisible(bool visible) override;
@@ -161,7 +154,6 @@ protected:
static void onHide(GtkWidget *menu, void *data);
private:
- quintptr m_tag;
GtkWidget *m_menu;
QPoint m_targetPos;
QVector<QGtk3MenuItem *> m_items;
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index 6d62420bd6..cd4d301194 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -8,6 +8,7 @@ qtHaveModule(gui) {
qtConfig(imageformatplugin): SUBDIRS *= imageformats
!android:qtConfig(library): SUBDIRS *= generic
}
+qtHaveModule(widgets): SUBDIRS += styles
!winrt:qtHaveModule(printsupport): \
SUBDIRS += printsupport
diff --git a/src/plugins/sqldrivers/db2/qsql_db2.cpp b/src/plugins/sqldrivers/db2/qsql_db2.cpp
index 27d0e7001a..1a9631f1eb 100644
--- a/src/plugins/sqldrivers/db2/qsql_db2.cpp
+++ b/src/plugins/sqldrivers/db2/qsql_db2.cpp
@@ -66,6 +66,10 @@
QT_BEGIN_NAMESPACE
static const int COLNAMESIZE = 255;
+// Based on what is mentioned in the documentation here:
+// https://www.ibm.com/support/knowledgecenter/en/SSEPEK_10.0.0/sqlref/src/tpc/db2z_limits.html
+// The limit is 128 bytes for table names
+static const SQLSMALLINT TABLENAMESIZE = 128;
static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT };
class QDB2DriverPrivate : public QSqlDriverPrivate
@@ -297,6 +301,12 @@ static QSqlField qMakeFieldInfo(const QDB2ResultPrivate* d, int i)
f.setLength(colSize == 0 ? -1 : int(colSize));
f.setPrecision(colScale == 0 ? -1 : int(colScale));
f.setSqlType(int(colType));
+ SQLTCHAR tableName[TABLENAMESIZE];
+ SQLSMALLINT tableNameLen;
+ r = SQLColAttribute(d->hStmt, i + 1, SQL_DESC_BASE_TABLE_NAME, tableName,
+ TABLENAMESIZE, &tableNameLen, 0);
+ if (r == SQL_SUCCESS)
+ f.setTableName(qFromTChar(tableName));
return f;
}
@@ -1394,7 +1404,9 @@ QSqlRecord QDB2Driver::record(const QString& tableName) const
SQL_FETCH_NEXT,
0);
while (r == SQL_SUCCESS) {
- fil.append(qMakeFieldInfo(hStmt));
+ QSqlField fld = qMakeFieldInfo(hStmt);
+ fld.setTableName(tableName);
+ fil.append(fld);
r = SQLFetchScroll(hStmt,
SQL_FETCH_NEXT,
0);
diff --git a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
index 2b75f3c964..c50fc7916a 100644
--- a/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
+++ b/src/plugins/sqldrivers/ibase/qsql_ibase.cpp
@@ -1383,7 +1383,8 @@ QSqlRecord QIBaseResult::record() const
for (int i = 0; i < d->sqlda->sqld; ++i) {
v = d->sqlda->sqlvar[i];
QSqlField f(QString::fromLatin1(v.aliasname, v.aliasname_length).simplified(),
- qIBaseTypeName2(v.sqltype, v.sqlscale < 0));
+ qIBaseTypeName2(v.sqltype, v.sqlscale < 0),
+ QString::fromLatin1(v.relname, v.relname_length));
f.setLength(v.sqllen);
f.setPrecision(qAbs(v.sqlscale));
f.setRequiredStatus((v.sqltype & 1) == 0 ? QSqlField::Required : QSqlField::Optional);
@@ -1686,7 +1687,7 @@ QSqlRecord QIBaseDriver::record(const QString& tablename) const
while (q.next()) {
int type = q.value(1).toInt();
bool hasScale = q.value(3).toInt() < 0;
- QSqlField f(q.value(0).toString().simplified(), qIBaseTypeName(type, hasScale));
+ QSqlField f(q.value(0).toString().simplified(), qIBaseTypeName(type, hasScale), tablename);
if(hasScale) {
f.setLength(q.value(4).toInt());
f.setPrecision(qAbs(q.value(3).toInt()));
@@ -1727,7 +1728,9 @@ QSqlIndex QIBaseDriver::primaryIndex(const QString &table) const
"ORDER BY b.RDB$FIELD_POSITION"));
while (q.next()) {
- QSqlField field(q.value(1).toString().simplified(), qIBaseTypeName(q.value(2).toInt(), q.value(3).toInt() < 0));
+ QSqlField field(q.value(1).toString().simplified(),
+ qIBaseTypeName(q.value(2).toInt(), q.value(3).toInt() < 0),
+ tablename);
index.append(field); //TODO: asc? desc?
index.setName(q.value(0).toString());
}
diff --git a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
index ee439fa33e..3dc0e73af5 100644
--- a/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
+++ b/src/plugins/sqldrivers/mysql/qsql_mysql.cpp
@@ -331,7 +331,8 @@ static QVariant::Type qDecodeMYSQLType(int mysqltype, uint flags)
static QSqlField qToField(MYSQL_FIELD *field, QTextCodec *tc)
{
QSqlField f(toUnicode(tc, field->name),
- qDecodeMYSQLType(int(field->type), field->flags));
+ qDecodeMYSQLType(int(field->type), field->flags),
+ toUnicode(tc, field->table));
f.setRequired(IS_NOT_NULL(field->flags));
f.setLength(field->length);
f.setPrecision(field->decimals);
diff --git a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
index 59ef42d609..c32a29c5e7 100644
--- a/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
+++ b/src/plugins/sqldrivers/odbc/qsql_odbc.cpp
@@ -64,6 +64,7 @@ QT_BEGIN_NAMESPACE
#define ODBC_CHECK_DRIVER
static const int COLNAMESIZE = 256;
+static const SQLSMALLINT TABLENAMESIZE = 128;
//Map Qt parameter types to ODBC types
static const SQLSMALLINT qParamType[4] = { SQL_PARAM_INPUT, SQL_PARAM_INPUT, SQL_PARAM_OUTPUT, SQL_PARAM_INPUT_OUTPUT };
@@ -730,6 +731,12 @@ static QSqlField qMakeFieldInfo(const SQLHANDLE hStmt, int i, QString *errorMess
f.setRequired(false);
// else we don't know
f.setAutoValue(isAutoValue(hStmt, i));
+ QVarLengthArray<SQLTCHAR> tableName(TABLENAMESIZE);
+ SQLSMALLINT tableNameLen;
+ r = SQLColAttribute(hStmt, i + 1, SQL_DESC_BASE_TABLE_NAME, tableName.data(),
+ TABLENAMESIZE, &tableNameLen, 0);
+ if (r == SQL_SUCCESS)
+ f.setTableName(fromSQLTCHAR(tableName, tableNameLen));
return f;
}
diff --git a/src/plugins/sqldrivers/psql/qsql_psql.cpp b/src/plugins/sqldrivers/psql/qsql_psql.cpp
index acadc830b2..a3aa0f6593 100644
--- a/src/plugins/sqldrivers/psql/qsql_psql.cpp
+++ b/src/plugins/sqldrivers/psql/qsql_psql.cpp
@@ -552,6 +552,11 @@ QSqlRecord QPSQLResult::record() const
f.setName(QString::fromUtf8(PQfname(d->result, i)));
else
f.setName(QString::fromLocal8Bit(PQfname(d->result, i)));
+ QSqlQuery qry(driver()->createResult());
+ if (qry.exec(QStringLiteral("SELECT relname FROM pg_class WHERE pg_class.oid = %1")
+ .arg(PQftable(d->result, i))) && qry.next()) {
+ f.setTableName(qry.value(0).toString());
+ }
int ptype = PQftype(d->result, i);
f.setType(qDecodePSQLType(ptype));
int len = PQfsize(d->result, i);
@@ -1132,7 +1137,7 @@ QSqlIndex QPSQLDriver::primaryIndex(const QString& tablename) const
i.exec(stmt.arg(tbl));
while (i.isActive() && i.next()) {
- QSqlField f(i.value(0).toString(), qDecodePSQLType(i.value(1).toInt()));
+ QSqlField f(i.value(0).toString(), qDecodePSQLType(i.value(1).toInt()), tablename);
idx.append(f);
idx.setName(i.value(2).toString());
}
@@ -1237,7 +1242,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
QString defVal = query.value(5).toString();
if (!defVal.isEmpty() && defVal.at(0) == QLatin1Char('\''))
defVal = defVal.mid(1, defVal.length() - 2);
- QSqlField f(query.value(0).toString(), qDecodePSQLType(query.value(1).toInt()));
+ QSqlField f(query.value(0).toString(), qDecodePSQLType(query.value(1).toInt()), tablename);
f.setRequired(query.value(2).toBool());
f.setLength(len);
f.setPrecision(precision);
@@ -1264,7 +1269,7 @@ QSqlRecord QPSQLDriver::record(const QString& tablename) const
len = precision - 4;
precision = -1;
}
- QSqlField f(query.value(0).toString(), qDecodePSQLType(query.value(1).toInt()));
+ QSqlField f(query.value(0).toString(), qDecodePSQLType(query.value(1).toInt()), tablename);
f.setRequired(query.value(2).toBool());
f.setLength(len);
f.setPrecision(precision);
@@ -1419,6 +1424,7 @@ bool QPSQLDriver::subscribeToNotification(const QString &name)
QString query = QLatin1String("LISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
PGresult *result = d->exec(query);
if (PQresultStatus(result) != PGRES_COMMAND_OK) {
+ d->seid.removeLast();
setLastError(qMakeError(tr("Unable to subscribe"), QSqlError::StatementError, d, result));
PQclear(result);
return false;
diff --git a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
index 13ec024924..e9f5ee9508 100644
--- a/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
+++ b/src/plugins/sqldrivers/sqlite/qsql_sqlite.cpp
@@ -51,6 +51,10 @@
#include <qstringlist.h>
#include <qvector.h>
#include <qdebug.h>
+#ifndef QT_NO_REGULAREXPRESSION
+#include <qcache.h>
+#include <qregularexpression.h>
+#endif
#include <QTimeZone>
#if defined Q_OS_WIN
@@ -209,7 +213,9 @@ void QSQLiteResultPrivate::initColumns(bool emptyResultset)
QString colName = QString(reinterpret_cast<const QChar *>(
sqlite3_column_name16(stmt, i))
).remove(QLatin1Char('"'));
-
+ const QString tableName = QString(reinterpret_cast<const QChar *>(
+ sqlite3_column_table_name16(stmt, i))
+ ).remove(QLatin1Char('"'));
// must use typeName for resolving the type to match QSqliteDriver::record
QString typeName = QString(reinterpret_cast<const QChar *>(
sqlite3_column_decltype16(stmt, i)));
@@ -242,7 +248,7 @@ void QSQLiteResultPrivate::initColumns(bool emptyResultset)
}
}
- QSqlField fld(colName, fieldType);
+ QSqlField fld(colName, fieldType, tableName);
fld.setSqlType(stp);
rInf.append(fld);
}
@@ -455,8 +461,27 @@ bool QSQLiteResult::exec()
d->finalize();
return false;
}
+
int paramCount = sqlite3_bind_parameter_count(d->stmt);
- if (paramCount == values.count()) {
+ bool paramCountIsValid = paramCount == values.count();
+
+#if (SQLITE_VERSION_NUMBER >= 3003011)
+ // In the case of the reuse of a named placeholder
+ if (!paramCountIsValid) {
+ const auto countIndexes = [](int counter, const QList<int>& indexList) {
+ return counter + indexList.length();
+ };
+
+ const int bindParamCount = std::accumulate(d->indexes.cbegin(),
+ d->indexes.cend(),
+ 0,
+ countIndexes);
+
+ paramCountIsValid = bindParamCount == values.count();
+ }
+#endif
+
+ if (paramCountIsValid) {
for (int i = 0; i < paramCount; ++i) {
res = SQLITE_OK;
const QVariant value = values.at(i);
@@ -483,14 +508,14 @@ bool QSQLiteResult::exec()
break;
case QVariant::DateTime: {
const QDateTime dateTime = value.toDateTime();
- const QString str = dateTime.toString(QStringLiteral("yyyy-MM-ddThh:mm:ss.zzz") + timespecToString(dateTime));
+ const QString str = dateTime.toString(QLatin1String("yyyy-MM-ddThh:mm:ss.zzz") + timespecToString(dateTime));
res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
str.size() * sizeof(ushort), SQLITE_TRANSIENT);
break;
}
case QVariant::Time: {
const QTime time = value.toTime();
- const QString str = time.toString(QStringLiteral("hh:mm:ss.zzz"));
+ const QString str = time.toString(QStringViewLiteral("hh:mm:ss.zzz"));
res = sqlite3_bind_text16(d->stmt, i + 1, str.utf16(),
str.size() * sizeof(ushort), SQLITE_TRANSIENT);
break;
@@ -583,6 +608,40 @@ QVariant QSQLiteResult::handle() const
/////////////////////////////////////////////////////////
+#ifndef QT_NO_REGULAREXPRESSION
+static void _q_regexp(sqlite3_context* context, int argc, sqlite3_value** argv)
+{
+ if (Q_UNLIKELY(argc != 2)) {
+ sqlite3_result_int(context, 0);
+ return;
+ }
+
+ const QString pattern = QString::fromUtf8(
+ reinterpret_cast<const char*>(sqlite3_value_text(argv[0])));
+ const QString subject = QString::fromUtf8(
+ reinterpret_cast<const char*>(sqlite3_value_text(argv[1])));
+
+ auto cache = static_cast<QCache<QString, QRegularExpression>*>(sqlite3_user_data(context));
+ auto regexp = cache->object(pattern);
+ const bool wasCached = regexp;
+
+ if (!wasCached)
+ regexp = new QRegularExpression(pattern, QRegularExpression::DontCaptureOption | QRegularExpression::OptimizeOnFirstUsageOption);
+
+ const bool found = subject.contains(*regexp);
+
+ if (!wasCached)
+ cache->insert(pattern, regexp);
+
+ sqlite3_result_int(context, int(found));
+}
+
+static void _q_regexp_cleanup(void *cache)
+{
+ delete static_cast<QCache<QString, QRegularExpression>*>(cache);
+}
+#endif
+
QSQLiteDriver::QSQLiteDriver(QObject * parent)
: QSqlDriver(*new QSQLiteDriverPrivate, parent)
{
@@ -618,11 +677,17 @@ bool QSQLiteDriver::hasFeature(DriverFeature f) const
case EventNotifications:
return true;
case QuerySize:
- case NamedPlaceholders:
case BatchOperations:
case MultipleResultSets:
case CancelQuery:
return false;
+ case NamedPlaceholders:
+#if (SQLITE_VERSION_NUMBER < 3003011)
+ return false;
+#else
+ return true;
+#endif
+
}
return false;
}
@@ -642,6 +707,11 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c
bool sharedCache = false;
bool openReadOnlyOption = false;
bool openUriOption = false;
+#ifndef QT_NO_REGULAREXPRESSION
+ static const QLatin1String regexpConnectOption = QLatin1String("QSQLITE_ENABLE_REGEXP");
+ bool defineRegexp = false;
+ int regexpCacheSize = 25;
+#endif
const auto opts = conOpts.splitRef(QLatin1Char(';'));
for (auto option : opts) {
@@ -661,18 +731,42 @@ bool QSQLiteDriver::open(const QString & db, const QString &, const QString &, c
} else if (option == QLatin1String("QSQLITE_ENABLE_SHARED_CACHE")) {
sharedCache = true;
}
+#ifndef QT_NO_REGULAREXPRESSION
+ else if (option.startsWith(regexpConnectOption)) {
+ option = option.mid(regexpConnectOption.size()).trimmed();
+ if (option.isEmpty()) {
+ defineRegexp = true;
+ } else if (option.startsWith(QLatin1Char('='))) {
+ bool ok = false;
+ const int cacheSize = option.mid(1).trimmed().toInt(&ok);
+ if (ok) {
+ defineRegexp = true;
+ if (cacheSize > 0)
+ regexpCacheSize = cacheSize;
+ }
+ }
+ }
+#endif
}
int openMode = (openReadOnlyOption ? SQLITE_OPEN_READONLY : (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE));
+ openMode |= (sharedCache ? SQLITE_OPEN_SHAREDCACHE : SQLITE_OPEN_PRIVATECACHE);
if (openUriOption)
openMode |= SQLITE_OPEN_URI;
- sqlite3_enable_shared_cache(sharedCache);
+ openMode |= SQLITE_OPEN_NOMUTEX;
if (sqlite3_open_v2(db.toUtf8().constData(), &d->access, openMode, NULL) == SQLITE_OK) {
sqlite3_busy_timeout(d->access, timeOut);
setOpen(true);
setOpenError(false);
+#ifndef QT_NO_REGULAREXPRESSION
+ if (defineRegexp) {
+ auto cache = new QCache<QString, QRegularExpression>(regexpCacheSize);
+ sqlite3_create_function_v2(d->access, "regexp", 2, SQLITE_UTF8, cache, &_q_regexp, NULL,
+ NULL, &_q_regexp_cleanup);
+ }
+#endif
return true;
} else {
if (d->access) {
@@ -807,7 +901,7 @@ static QSqlIndex qGetTableInfo(QSqlQuery &q, const QString &tableName, bool only
if (onlyPIndex && !isPk)
continue;
QString typeName = q.value(2).toString().toLower();
- QSqlField fld(q.value(1).toString(), qGetColumnType(typeName));
+ QSqlField fld(q.value(1).toString(), qGetColumnType(typeName), tableName);
if (isPk && (typeName == QLatin1String("integer")))
// INTEGER PRIMARY KEY fields are auto-generated in sqlite
// INT PRIMARY KEY is not the same as INTEGER PRIMARY KEY!
diff --git a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp
index 67c24e4168..93f47e3f13 100644
--- a/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp
+++ b/src/plugins/sqldrivers/sqlite2/qsql_sqlite2.cpp
@@ -576,7 +576,7 @@ QSqlIndex QSQLite2Driver::primaryIndex(const QString &tblname) const
QVariant::Type type = QVariant::Invalid;
if (rec.contains(name))
type = rec.field(name).type();
- index.append(QSqlField(name, type));
+ index.append(QSqlField(name, type, tblname));
}
return index;
}
diff --git a/src/plugins/sqldrivers/tds/qsql_tds.cpp b/src/plugins/sqldrivers/tds/qsql_tds.cpp
index 6ebd09a572..670198af81 100644
--- a/src/plugins/sqldrivers/tds/qsql_tds.cpp
+++ b/src/plugins/sqldrivers/tds/qsql_tds.cpp
@@ -767,7 +767,7 @@ QSqlRecord QTDSDriver::record(const QString& tablename) const
"where id = (select id from sysobjects where name = '%1')"));
t.exec(stmt.arg(table));
while (t.next()) {
- QSqlField f(t.value(0).toString().simplified(), qDecodeTDSType(t.value(1).toInt()));
+ QSqlField f(t.value(0).toString().simplified(), qDecodeTDSType(t.value(1).toInt()), tablename);
f.setLength(t.value(2).toInt());
f.setPrecision(t.value(3).toInt());
f.setSqlType(t.value(1).toInt());
@@ -853,7 +853,7 @@ QSqlIndex QTDSDriver::primaryIndex(const QString& tablename) const
QRegExp regx(QLatin1String("\\s*(\\S+)(?:\\s+(DESC|desc))?\\s*"));
for(QStringList::Iterator it = fNames.begin(); it != fNames.end(); ++it) {
regx.indexIn(*it);
- QSqlField f(regx.cap(1), rec.field(regx.cap(1)).type());
+ QSqlField f(regx.cap(1), rec.field(regx.cap(1)).type(), tablename);
if (regx.cap(2).toLower() == QLatin1String("desc")) {
idx.append(f, true);
} else {
diff --git a/src/plugins/styles/android/android.pro b/src/plugins/styles/android/android.pro
new file mode 100644
index 0000000000..4ca35d8046
--- /dev/null
+++ b/src/plugins/styles/android/android.pro
@@ -0,0 +1,16 @@
+TARGET = qandroidstyle
+
+QT += widgets-private
+
+SOURCES += \
+ main.cpp \
+ qandroidstyle.cpp
+
+HEADERS += \
+ qandroidstyle_p.h
+
+DISTFILES += androidstyle.json
+
+PLUGIN_TYPE = styles
+PLUGIN_CLASS_NAME = QAndroidStylePlugin
+load(qt_plugin)
diff --git a/src/plugins/styles/android/androidstyle.json b/src/plugins/styles/android/androidstyle.json
new file mode 100644
index 0000000000..6843bd3301
--- /dev/null
+++ b/src/plugins/styles/android/androidstyle.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "android" ]
+}
diff --git a/src/plugins/styles/android/main.cpp b/src/plugins/styles/android/main.cpp
new file mode 100644
index 0000000000..2121538b0a
--- /dev/null
+++ b/src/plugins/styles/android/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtWidgets/qstyleplugin.h>
+#include "qandroidstyle_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAndroidStylePlugin : public QStylePlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "androidstyle.json")
+public:
+ QStyle *create(const QString &key);
+};
+
+QStyle *QAndroidStylePlugin::create(const QString &key)
+{
+ if (key.compare(QLatin1String("android"), Qt::CaseInsensitive) == 0)
+ return new QAndroidStyle();
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
+
diff --git a/src/widgets/styles/qandroidstyle.cpp b/src/plugins/styles/android/qandroidstyle.cpp
index 55f125c6b5..086df92322 100644
--- a/src/widgets/styles/qandroidstyle.cpp
+++ b/src/plugins/styles/android/qandroidstyle.cpp
@@ -39,8 +39,6 @@
#include "qandroidstyle_p.h"
-#if QT_CONFIG(style_android) || defined(QT_PLUGIN)
-
#include <QFile>
#include <QFont>
#include <QApplication>
@@ -1816,5 +1814,3 @@ QRect QAndroidStyle::AndroidSpinnerControl::subControlRect(const QStyleOptionCom
}
QT_END_NAMESPACE
-
-#endif // QT_CONFIG(style_android) || defined(QT_PLUGIN)
diff --git a/src/widgets/styles/qandroidstyle_p.h b/src/plugins/styles/android/qandroidstyle_p.h
index caff0afada..3faa08afb9 100644
--- a/src/widgets/styles/qandroidstyle_p.h
+++ b/src/plugins/styles/android/qandroidstyle_p.h
@@ -52,16 +52,14 @@
//
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include <QtWidgets/private/qfusionstyle_p.h>
#include <QtCore/QList>
#include <QtCore/QMargins>
#include <QtCore/QHash>
#include <QtCore/QVariantMap>
-#include "qfusionstyle_p.h"
QT_BEGIN_NAMESPACE
-#if QT_CONFIG(style_android)
-
class Q_WIDGETS_EXPORT QAndroidStyle : public QFusionStyle
{
Q_OBJECT
@@ -388,8 +386,6 @@ private:
AndroidCompoundButtonControl *checkBoxControl;
};
-#endif // style_android
-
QT_END_NAMESPACE
#endif // QANDROIDSTYLE_P_H
diff --git a/src/plugins/styles/mac/mac.pro b/src/plugins/styles/mac/mac.pro
new file mode 100644
index 0000000000..f3c7c1c067
--- /dev/null
+++ b/src/plugins/styles/mac/mac.pro
@@ -0,0 +1,19 @@
+TARGET = qmacstyle
+
+QT += widgets-private
+
+SOURCES += \
+ main.mm \
+ qmacstyle_mac.mm
+
+HEADERS += \
+ qmacstyle_mac_p.h \
+ qmacstyle_mac_p_p.h
+
+LIBS_PRIVATE += -framework AppKit -framework ApplicationServices -framework Carbon
+
+DISTFILES += macstyle.json
+
+PLUGIN_TYPE = styles
+PLUGIN_CLASS_NAME = QMacStylePlugin
+load(qt_plugin)
diff --git a/src/plugins/styles/mac/macstyle.json b/src/plugins/styles/mac/macstyle.json
new file mode 100644
index 0000000000..5897815eec
--- /dev/null
+++ b/src/plugins/styles/mac/macstyle.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "macintosh" ]
+}
diff --git a/src/plugins/styles/mac/main.mm b/src/plugins/styles/mac/main.mm
new file mode 100644
index 0000000000..ae31bb95fb
--- /dev/null
+++ b/src/plugins/styles/mac/main.mm
@@ -0,0 +1,65 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtWidgets/qstyleplugin.h>
+#include "qmacstyle_mac_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QMacStylePlugin : public QStylePlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "macstyle.json")
+public:
+ QStyle *create(const QString &key);
+};
+
+QStyle *QMacStylePlugin::create(const QString &key)
+{
+ QMacAutoReleasePool pool;
+ if (key.compare(QLatin1String("macintosh"), Qt::CaseInsensitive) == 0)
+ return new QMacStyle();
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
+
diff --git a/src/widgets/styles/qmacstyle.qdoc b/src/plugins/styles/mac/qmacstyle.qdoc
index a77843a4dd..fcbc813844 100644
--- a/src/widgets/styles/qmacstyle.qdoc
+++ b/src/plugins/styles/mac/qmacstyle.qdoc
@@ -82,7 +82,7 @@
documentation.
\image qmacstyle.png
- \sa QWindowsXPStyle, QWindowsStyle, QFusionStyle
+ \sa QWindowsVistaStyle, QWindowsStyle, QFusionStyle
*/
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 6117ea22c7..a6ece7632a 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -43,6 +43,7 @@
*/
#include <AppKit/AppKit.h>
+#include <ApplicationServices/ApplicationServices.h>
#include "qmacstyle_mac_p.h"
#include "qmacstyle_mac_p_p.h"
@@ -156,6 +157,68 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(NotificationReceiver);
}
@end
+@interface QT_MANGLE_NAMESPACE(QIndeterminateProgressIndicator) : NSProgressIndicator
+
+@property (readonly, nonatomic) NSInteger animators;
+
+- (instancetype)init;
+
+- (void)startAnimation;
+- (void)stopAnimation;
+
+- (void)drawWithFrame:(CGRect)rect inView:(NSView *)view;
+
+@end
+
+QT_NAMESPACE_ALIAS_OBJC_CLASS(QIndeterminateProgressIndicator);
+
+@implementation QIndeterminateProgressIndicator
+
+- (instancetype)init
+{
+ if ((self = [super init])) {
+ _animators = 0;
+ self.indeterminate = YES;
+ self.usesThreadedAnimation = NO;
+ self.alphaValue = 0.0;
+ }
+
+ return self;
+}
+
+- (void)startAnimation
+{
+ if (_animators == 0) {
+ self.hidden = NO;
+ [super startAnimation:self];
+ }
+ ++_animators;
+}
+
+- (void)stopAnimation
+{
+ --_animators;
+ if (_animators == 0) {
+ [super stopAnimation:self];
+ self.hidden = YES;
+ [self removeFromSuperviewWithoutNeedingDisplay];
+ }
+}
+
+- (void)drawWithFrame:(CGRect)rect inView:(NSView *)view
+{
+ // The alphaValue change is not strictly necessary, but feels safer.
+ self.alphaValue = 1.0;
+ if (self.superview != view)
+ [view addSubview:self];
+ if (!CGRectEqualToRect(self.frame, rect))
+ self.frame = rect;
+ [self drawRect:rect];
+ self.alphaValue = 0.0;
+}
+
+@end
+
QT_BEGIN_NAMESPACE
// The following constants are used for adjusting the size
@@ -230,10 +293,6 @@ static const QColor tabBarCloseButtonCrossSelected(115, 115, 115);
static const int closeButtonSize = 14;
static const qreal closeButtonCornerRadius = 2.0;
-// Resolve these at run-time, since the functions was moved in Leopard.
-typedef HIRect * (*PtrHIShapeGetBounds)(HIShapeRef, HIRect *);
-static PtrHIShapeGetBounds ptrHIShapeGetBounds = 0;
-
#if QT_CONFIG(tabbar)
static bool isVerticalTabs(const QTabBar::Shape shape) {
return (shape == QTabBar::RoundedEast
@@ -243,6 +302,23 @@ static bool isVerticalTabs(const QTabBar::Shape shape) {
}
#endif
+static bool setupScroller(NSScroller *scroller, const QStyleOptionSlider *sb)
+{
+ const qreal length = sb->maximum - sb->minimum + sb->pageStep;
+ if (qFuzzyIsNull(length))
+ return false;
+ const qreal proportion = sb->pageStep / length;
+ const qreal range = qreal(sb->maximum - sb->minimum);
+ qreal value = range ? qreal(sb->sliderValue - sb->minimum) / range : 0;
+ if (sb->orientation == Qt::Horizontal && sb->direction == Qt::RightToLeft)
+ value = 1.0 - value;
+
+ scroller.frame = sb->rect.toCGRect();
+ scroller.floatValue = value;
+ scroller.knobProportion = proportion;
+ return true;
+}
+
static bool isInMacUnifiedToolbarArea(QWindow *window, int windowY)
{
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
@@ -414,19 +490,14 @@ void drawTabBase(QPainter *p, const QStyleOptionTabBarBase *tbb, const QWidget *
}
#endif
-static int getControlSize(const QStyleOption *option, const QWidget *widget)
+static QStyleHelper::WidgetSizePolicy getControlSize(const QStyleOption *option, const QWidget *widget)
{
- switch (QMacStyle::widgetSizePolicy(widget, option)) {
- case QMacStyle::SizeSmall:
- return QAquaSizeSmall;
- case QMacStyle::SizeMini:
- return QAquaSizeMini;
- default:
- break;
- }
- return QAquaSizeLarge;
-}
+ const auto wsp = QStyleHelper::widgetSizePolicy(widget, option);
+ if (wsp == QStyleHelper::SizeDefault)
+ return QStyleHelper::SizeLarge;
+ return wsp;
+}
#if QT_CONFIG(treeview)
static inline bool isTreeView(const QWidget *widget)
@@ -587,46 +658,103 @@ static inline int qt_mac_hitheme_tab_version()
return 1;
}
-static inline HIRect qt_hirectForQRect(const QRect &convertRect, const QRect &rect = QRect())
-{
- return CGRectMake(convertRect.x() + rect.x(), convertRect.y() + rect.y(),
- convertRect.width() - rect.width(), convertRect.height() - rect.height());
-}
-
-static inline const QRect qt_qrectForHIRect(const HIRect &hirect)
-{
- return QRect(QPoint(int(hirect.origin.x), int(hirect.origin.y)),
- QSize(int(hirect.size.width), int(hirect.size.height)));
-}
-
-inline bool qt_mac_is_metal(const QWidget *w)
-{
- for (; w; w = w->parentWidget()) {
- if (w->testAttribute(Qt::WA_MacBrushedMetal))
- return true;
- if (w->isWindow() && w->testAttribute(Qt::WA_WState_Created)) { // If not created will fall through to the opaque check and be fine anyway.
- return qt_macWindowIsTextured(w);
- }
-#ifndef QT_NO_ACCESSIBILITY
- if (w->d_func()->isOpaque)
- break;
-#endif
- }
- return false;
-}
-
-static int qt_mac_aqua_get_metric(ThemeMetric met)
+enum QAquaMetric {
+ // Prepend kThemeMetric to get the HIToolBox constant.
+ // Represents the values already used in QMacStyle.
+ CheckBoxHeight = 0,
+ CheckBoxWidth,
+ EditTextFrameOutset,
+ FocusRectOutset,
+ HSliderHeight,
+ HSliderTickHeight,
+ LargeProgressBarThickness,
+ ListHeaderHeight,
+ MenuSeparatorHeight, // GetThemeMenuSeparatorHeight
+ MiniCheckBoxHeight,
+ MiniCheckBoxWidth,
+ MiniHSliderHeight,
+ MiniHSliderTickHeight,
+ MiniPopupButtonHeight,
+ MiniPushButtonHeight,
+ MiniRadioButtonHeight,
+ MiniRadioButtonWidth,
+ MiniVSliderTickWidth,
+ MiniVSliderWidth,
+ NormalProgressBarThickness,
+ PopupButtonHeight,
+ ProgressBarShadowOutset,
+ PushButtonHeight,
+ RadioButtonHeight,
+ RadioButtonWidth,
+ SeparatorSize,
+ SmallCheckBoxHeight,
+ SmallCheckBoxWidth,
+ SmallHSliderHeight,
+ SmallHSliderTickHeight,
+ SmallPopupButtonHeight,
+ SmallProgressBarShadowOutset,
+ SmallPushButtonHeight,
+ SmallRadioButtonHeight,
+ SmallRadioButtonWidth,
+ SmallVSliderTickWidth,
+ SmallVSliderWidth,
+ VSliderTickWidth,
+ VSliderWidth
+};
+
+static const int qt_mac_aqua_metrics[] = {
+ // Values as of macOS 10.12.4 and Xcode 8.3.1
+ 18 /* CheckBoxHeight */,
+ 18 /* CheckBoxWidth */,
+ 1 /* EditTextFrameOutset */,
+ 4 /* FocusRectOutset */,
+ 22 /* HSliderHeight */,
+ 5 /* HSliderTickHeight */,
+ 16 /* LargeProgressBarThickness */,
+ 17 /* ListHeaderHeight */,
+ 12 /* MenuSeparatorHeight, aka GetThemeMenuSeparatorHeight */,
+ 11 /* MiniCheckBoxHeight */,
+ 10 /* MiniCheckBoxWidth */,
+ 12 /* MiniHSliderHeight */,
+ 4 /* MiniHSliderTickHeight */,
+ 15 /* MiniPopupButtonHeight */,
+ 16 /* MiniPushButtonHeight */,
+ 11 /* MiniRadioButtonHeight */,
+ 10 /* MiniRadioButtonWidth */,
+ 4 /* MiniVSliderTickWidth */,
+ 12 /* MiniVSliderWidth */,
+ 12 /* NormalProgressBarThickness */,
+ 20 /* PopupButtonHeight */,
+ 4 /* ProgressBarShadowOutset */,
+ 20 /* PushButtonHeight */,
+ 18 /* RadioButtonHeight */,
+ 18 /* RadioButtonWidth */,
+ 1 /* SeparatorSize */,
+ 16 /* SmallCheckBoxHeight */,
+ 14 /* SmallCheckBoxWidth */,
+ 15 /* SmallHSliderHeight */,
+ 4 /* SmallHSliderTickHeight */,
+ 17 /* SmallPopupButtonHeight */,
+ 2 /* SmallProgressBarShadowOutset */,
+ 17 /* SmallPushButtonHeight */,
+ 15 /* SmallRadioButtonHeight */,
+ 14 /* SmallRadioButtonWidth */,
+ 4 /* SmallVSliderTickWidth */,
+ 15 /* SmallVSliderWidth */,
+ 5 /* VSliderTickWidth */,
+ 22 /* VSliderWidth */
+};
+
+static inline int qt_mac_aqua_get_metric(QAquaMetric m)
{
- SInt32 ret;
- GetThemeMetric(met, &ret);
- return ret;
+ return qt_mac_aqua_metrics[m];
}
static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg, QSize szHint,
- QAquaWidgetSize sz)
+ QStyleHelper::WidgetSizePolicy sz)
{
QSize ret(-1, -1);
- if (sz != QAquaSizeSmall && sz != QAquaSizeLarge && sz != QAquaSizeMini) {
+ if (sz != QStyleHelper::SizeSmall && sz != QStyleHelper::SizeLarge && sz != QStyleHelper::SizeMini) {
qDebug("Not sure how to return this...");
return ret;
}
@@ -692,12 +820,12 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
QString buttonText = qt_mac_removeMnemonics(psh->text());
if (buttonText.contains(QLatin1Char('\n')))
ret = QSize(-1, -1);
- else if (sz == QAquaSizeLarge)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight));
- else if (sz == QAquaSizeSmall)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPushButtonHeight));
- else if (sz == QAquaSizeMini)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight));
+ else if (sz == QStyleHelper::SizeLarge)
+ ret = QSize(-1, qt_mac_aqua_get_metric(PushButtonHeight));
+ else if (sz == QStyleHelper::SizeSmall)
+ ret = QSize(-1, qt_mac_aqua_get_metric(SmallPushButtonHeight));
+ else if (sz == QStyleHelper::SizeMini)
+ ret = QSize(-1, qt_mac_aqua_get_metric(MiniPushButtonHeight));
if (!psh->icon().isNull()){
// If the button got an icon, and the icon is larger than the
@@ -715,15 +843,15 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
}
} else {
// The only sensible thing to do is to return whatever the style suggests...
- if (sz == QAquaSizeLarge)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight));
- else if (sz == QAquaSizeSmall)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPushButtonHeight));
- else if (sz == QAquaSizeMini)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPushButtonHeight));
+ if (sz == QStyleHelper::SizeLarge)
+ ret = QSize(-1, qt_mac_aqua_get_metric(PushButtonHeight));
+ else if (sz == QStyleHelper::SizeSmall)
+ ret = QSize(-1, qt_mac_aqua_get_metric(SmallPushButtonHeight));
+ else if (sz == QStyleHelper::SizeMini)
+ ret = QSize(-1, qt_mac_aqua_get_metric(MiniPushButtonHeight));
else
// Since there's no default size we return the large size...
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPushButtonHeight));
+ ret = QSize(-1, qt_mac_aqua_get_metric(PushButtonHeight));
}
#endif
#if 0 //Not sure we are applying the rules correctly for RadioButtons/CheckBoxes --Sam
@@ -732,33 +860,33 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
// Exception for case where multiline radio button text requires no size constrainment
if (rdo->text().find('\n') != -1)
return ret;
- if (sz == QAquaSizeLarge)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricRadioButtonHeight));
- else if (sz == QAquaSizeSmall)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallRadioButtonHeight));
- else if (sz == QAquaSizeMini)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniRadioButtonHeight));
+ if (sz == QStyleHelper::SizeLarge)
+ ret = QSize(-1, qt_mac_aqua_get_metric(RadioButtonHeight));
+ else if (sz == QStyleHelper::SizeSmall)
+ ret = QSize(-1, qt_mac_aqua_get_metric(SmallRadioButtonHeight));
+ else if (sz == QStyleHelper::SizeMini)
+ ret = QSize(-1, qt_mac_aqua_get_metric(MiniRadioButtonHeight));
} else if (ct == QStyle::CT_CheckBox) {
- if (sz == QAquaSizeLarge)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricCheckBoxHeight));
- else if (sz == QAquaSizeSmall)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallCheckBoxHeight));
- else if (sz == QAquaSizeMini)
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniCheckBoxHeight));
+ if (sz == QStyleHelper::SizeLarge)
+ ret = QSize(-1, qt_mac_aqua_get_metric(CheckBoxHeight));
+ else if (sz == QStyleHelper::SizeSmall)
+ ret = QSize(-1, qt_mac_aqua_get_metric(SmallCheckBoxHeight));
+ else if (sz == QStyleHelper::SizeMini)
+ ret = QSize(-1, qt_mac_aqua_get_metric(MiniCheckBoxHeight));
#endif
break;
}
case QStyle::CT_SizeGrip:
- if (sz == QAquaSizeLarge || sz == QAquaSizeSmall) {
- HIRect r;
- HIPoint p = { 0, 0 };
+ if (sz == QStyleHelper::SizeLarge || sz == QStyleHelper::SizeSmall) {
+ CGRect r;
+ CGPoint p = { 0, 0 };
HIThemeGrowBoxDrawInfo gbi;
gbi.version = 0;
gbi.state = kThemeStateActive;
gbi.kind = kHIThemeGrowBoxKindNormal;
gbi.direction = QApplication::isRightToLeft() ? kThemeGrowLeft | kThemeGrowDown
: kThemeGrowRight | kThemeGrowDown;
- gbi.size = sz == QAquaSizeSmall ? kHIThemeGrowBoxSizeSmall : kHIThemeGrowBoxSizeNormal;
+ gbi.size = sz == QStyleHelper::SizeSmall ? kHIThemeGrowBoxSizeSmall : kHIThemeGrowBoxSizeNormal;
if (HIThemeGetGrowBoxBounds(&p, &gbi, &r) == noErr) {
int width = 0;
#ifndef QT_NO_MDIAREA
@@ -771,21 +899,21 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
break;
case QStyle::CT_ComboBox:
switch (sz) {
- case QAquaSizeLarge:
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricPopupButtonHeight));
+ case QStyleHelper::SizeLarge:
+ ret = QSize(-1, qt_mac_aqua_get_metric(PopupButtonHeight));
break;
- case QAquaSizeSmall:
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricSmallPopupButtonHeight));
+ case QStyleHelper::SizeSmall:
+ ret = QSize(-1, qt_mac_aqua_get_metric(SmallPopupButtonHeight));
break;
- case QAquaSizeMini:
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricMiniPopupButtonHeight));
+ case QStyleHelper::SizeMini:
+ ret = QSize(-1, qt_mac_aqua_get_metric(MiniPopupButtonHeight));
break;
default:
break;
}
break;
case QStyle::CT_ToolButton:
- if (sz == QAquaSizeSmall) {
+ if (sz == QStyleHelper::SizeSmall) {
int width = 0, height = 0;
if (szHint == QSize(-1, -1)) { //just 'guess'..
#ifndef QT_NO_TOOLBUTTON
@@ -830,35 +958,35 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
const QSlider *sld = qobject_cast<const QSlider *>(widg);
// If this conversion fails then the widget was not what it claimed to be.
if(sld) {
- if (sz == QAquaSizeLarge) {
+ if (sz == QStyleHelper::SizeLarge) {
if (sld->orientation() == Qt::Horizontal) {
- w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight);
+ w = qt_mac_aqua_get_metric(HSliderHeight);
if (sld->tickPosition() != QSlider::NoTicks)
- w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight);
+ w += qt_mac_aqua_get_metric(HSliderTickHeight);
} else {
- w = qt_mac_aqua_get_metric(kThemeMetricVSliderWidth);
+ w = qt_mac_aqua_get_metric(VSliderWidth);
if (sld->tickPosition() != QSlider::NoTicks)
- w += qt_mac_aqua_get_metric(kThemeMetricVSliderTickWidth);
+ w += qt_mac_aqua_get_metric(VSliderTickWidth);
}
- } else if (sz == QAquaSizeSmall) {
+ } else if (sz == QStyleHelper::SizeSmall) {
if (sld->orientation() == Qt::Horizontal) {
- w = qt_mac_aqua_get_metric(kThemeMetricSmallHSliderHeight);
+ w = qt_mac_aqua_get_metric(SmallHSliderHeight);
if (sld->tickPosition() != QSlider::NoTicks)
- w += qt_mac_aqua_get_metric(kThemeMetricSmallHSliderTickHeight);
+ w += qt_mac_aqua_get_metric(SmallHSliderTickHeight);
} else {
- w = qt_mac_aqua_get_metric(kThemeMetricSmallVSliderWidth);
+ w = qt_mac_aqua_get_metric(SmallVSliderWidth);
if (sld->tickPosition() != QSlider::NoTicks)
- w += qt_mac_aqua_get_metric(kThemeMetricSmallVSliderTickWidth);
+ w += qt_mac_aqua_get_metric(SmallVSliderTickWidth);
}
- } else if (sz == QAquaSizeMini) {
+ } else if (sz == QStyleHelper::SizeMini) {
if (sld->orientation() == Qt::Horizontal) {
- w = qt_mac_aqua_get_metric(kThemeMetricMiniHSliderHeight);
+ w = qt_mac_aqua_get_metric(MiniHSliderHeight);
if (sld->tickPosition() != QSlider::NoTicks)
- w += qt_mac_aqua_get_metric(kThemeMetricMiniHSliderTickHeight);
+ w += qt_mac_aqua_get_metric(MiniHSliderTickHeight);
} else {
- w = qt_mac_aqua_get_metric(kThemeMetricMiniVSliderWidth);
+ w = qt_mac_aqua_get_metric(MiniVSliderWidth);
if (sld->tickPosition() != QSlider::NoTicks)
- w += qt_mac_aqua_get_metric(kThemeMetricMiniVSliderTickWidth);
+ w += qt_mac_aqua_get_metric(MiniVSliderTickWidth);
}
}
} else {
@@ -866,8 +994,8 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
// a slider. We don't know if this is vertical or horizontal or if we need to
// have tick marks or not.
// For this case we will return an horizontal slider without tick marks.
- w = qt_mac_aqua_get_metric(kThemeMetricHSliderHeight);
- w += qt_mac_aqua_get_metric(kThemeMetricHSliderTickHeight);
+ w = qt_mac_aqua_get_metric(HSliderHeight);
+ w += qt_mac_aqua_get_metric(HSliderTickHeight);
}
if (sld->orientation() == Qt::Horizontal)
ret.setHeight(w);
@@ -882,12 +1010,12 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
if (const QProgressBar *pb = qobject_cast<const QProgressBar *>(widg))
orient = pb->orientation();
- if (sz == QAquaSizeLarge)
- finalValue = qt_mac_aqua_get_metric(kThemeMetricLargeProgressBarThickness)
- + qt_mac_aqua_get_metric(kThemeMetricProgressBarShadowOutset);
+ if (sz == QStyleHelper::SizeLarge)
+ finalValue = qt_mac_aqua_get_metric(LargeProgressBarThickness)
+ + qt_mac_aqua_get_metric(ProgressBarShadowOutset);
else
- finalValue = qt_mac_aqua_get_metric(kThemeMetricNormalProgressBarThickness)
- + qt_mac_aqua_get_metric(kThemeMetricSmallProgressBarShadowOutset);
+ finalValue = qt_mac_aqua_get_metric(NormalProgressBarThickness)
+ + qt_mac_aqua_get_metric(SmallProgressBarShadowOutset);
if (orient == Qt::Horizontal)
ret.setHeight(finalValue);
else
@@ -899,7 +1027,7 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
case QStyle::CT_LineEdit:
if (!widg || !qobject_cast<QComboBox *>(widg->parentWidget())) {
//should I take into account the font dimentions of the lineedit? -Sam
- if (sz == QAquaSizeLarge)
+ if (sz == QStyleHelper::SizeLarge)
ret = QSize(-1, 21);
else
ret = QSize(-1, 19);
@@ -909,11 +1037,11 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
case QStyle::CT_HeaderSection:
#if QT_CONFIG(treeview)
if (isTreeView(widg))
- ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricListHeaderHeight));
+ ret = QSize(-1, qt_mac_aqua_get_metric(ListHeaderHeight));
#endif
break;
case QStyle::CT_MenuBar:
- if (sz == QAquaSizeLarge) {
+ if (sz == QStyleHelper::SizeLarge) {
ret = QSize(-1, [[NSApp mainMenu] menuBarHeight]);
// In the qt_mac_set_native_menubar(false) case,
// we come it here with a zero-height main menu,
@@ -931,30 +1059,30 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
#if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT)
-static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSize small, QSize mini)
+static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QSize large, QSize small, QSize mini)
{
Q_UNUSED(widg);
if (large == QSize(-1, -1)) {
if (small != QSize(-1, -1))
- return QAquaSizeSmall;
+ return QStyleHelper::SizeSmall;
if (mini != QSize(-1, -1))
- return QAquaSizeMini;
- return QAquaSizeUnknown;
+ return QStyleHelper::SizeMini;
+ return QStyleHelper::SizeDefault;
} else if (small == QSize(-1, -1)) {
if (mini != QSize(-1, -1))
- return QAquaSizeMini;
- return QAquaSizeLarge;
+ return QStyleHelper::SizeMini;
+ return QStyleHelper::SizeLarge;
} else if (mini == QSize(-1, -1)) {
- return QAquaSizeLarge;
+ return QStyleHelper::SizeLarge;
}
#ifndef QT_NO_MAINWINDOW
if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL")) {
//if (small.width() != -1 || small.height() != -1)
- return QAquaSizeSmall;
+ return QStyleHelper::SizeSmall;
} else if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI")) {
- return QAquaSizeMini;
+ return QStyleHelper::SizeMini;
}
#endif
@@ -990,11 +1118,11 @@ static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz
mini_delta += delta * delta;
}
if (mini_delta < small_delta && mini_delta < large_delta)
- return QAquaSizeMini;
+ return QStyleHelper::SizeMini;
else if (small_delta < large_delta)
- return QAquaSizeSmall;
+ return QStyleHelper::SizeSmall;
#endif
- return QAquaSizeLarge;
+ return QStyleHelper::SizeLarge;
}
#endif
@@ -1014,12 +1142,11 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h
const CGFloat focusRingWidth = radius > 0 ? 3.5 : 6;
QMacAutoReleasePool pool;
QMacCGContext ctx(&focusRingPixmap);
+ setupNSGraphicsContext(ctx, NO);
+
CGContextBeginTransparencyLayer(ctx, NULL);
CGContextSetAlpha(ctx, 0.5); // As applied to the stroke color below
- [NSGraphicsContext saveGraphicsState];
- [NSGraphicsContext setCurrentContext:[NSGraphicsContext graphicsContextWithCGContext:ctx
- flipped:NO]];
CGRect focusRingRect = CGRectMake(hMargin, vMargin, size, size);
NSBezierPath *focusRingPath;
if (radius > 0) {
@@ -1043,7 +1170,7 @@ void QMacStylePrivate::drawFocusRing(QPainter *p, const QRect &targetRect, int h
[focusRingPath stroke];
CGContextEndTransparencyLayer(ctx);
- [NSGraphicsContext restoreGraphicsState];
+ restoreNSGraphicsContext(ctx);
}
QPixmapCache::insert(key, focusRingPixmap);
}
@@ -1144,62 +1271,61 @@ void QMacStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widg
}
#endif // QT_CONFIG(tabbar)
-QAquaWidgetSize QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption *option,
+QStyleHelper::WidgetSizePolicy QMacStylePrivate::effectiveAquaSizeConstrain(const QStyleOption *option,
const QWidget *widg,
QStyle::ContentsType ct,
QSize szHint, QSize *insz) const
{
- QAquaWidgetSize sz = aquaSizeConstrain(option, widg, ct, szHint, insz);
- if (sz == QAquaSizeUnknown)
- return QAquaSizeLarge;
+ QStyleHelper::WidgetSizePolicy sz = aquaSizeConstrain(option, widg, ct, szHint, insz);
+ if (sz == QStyleHelper::SizeDefault)
+ return QStyleHelper::SizeLarge;
return sz;
}
-QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
+QStyleHelper::WidgetSizePolicy QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
QStyle::ContentsType ct, QSize szHint, QSize *insz) const
{
#if defined(QMAC_QAQUASTYLE_SIZE_CONSTRAIN) || defined(DEBUG_SIZE_CONSTRAINT)
if (option) {
if (option->state & QStyle::State_Small)
- return QAquaSizeSmall;
+ return QStyleHelper::SizeSmall;
if (option->state & QStyle::State_Mini)
- return QAquaSizeMini;
+ return QStyleHelper::SizeMini;
}
if (!widg) {
if (insz)
*insz = QSize();
if (qEnvironmentVariableIsSet("QWIDGET_ALL_SMALL"))
- return QAquaSizeSmall;
+ return QStyleHelper::SizeSmall;
if (qEnvironmentVariableIsSet("QWIDGET_ALL_MINI"))
- return QAquaSizeMini;
- return QAquaSizeUnknown;
+ return QStyleHelper::SizeMini;
+ return QStyleHelper::SizeDefault;
}
- Q_Q(const QMacStyle);
- QSize large = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeLarge),
- small = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeSmall),
- mini = qt_aqua_get_known_size(ct, widg, szHint, QAquaSizeMini);
+ QSize large = qt_aqua_get_known_size(ct, widg, szHint, QStyleHelper::SizeLarge),
+ small = qt_aqua_get_known_size(ct, widg, szHint, QStyleHelper::SizeSmall),
+ mini = qt_aqua_get_known_size(ct, widg, szHint, QStyleHelper::SizeMini);
bool guess_size = false;
- QAquaWidgetSize ret = QAquaSizeUnknown;
- QMacStyle::WidgetSizePolicy wsp = q->widgetSizePolicy(widg);
- if (wsp == QMacStyle::SizeDefault)
+ QStyleHelper::WidgetSizePolicy ret = QStyleHelper::SizeDefault;
+ QStyleHelper::WidgetSizePolicy wsp = QStyleHelper::widgetSizePolicy(widg);
+ if (wsp == QStyleHelper::SizeDefault)
guess_size = true;
- else if (wsp == QMacStyle::SizeMini)
- ret = QAquaSizeMini;
- else if (wsp == QMacStyle::SizeSmall)
- ret = QAquaSizeSmall;
- else if (wsp == QMacStyle::SizeLarge)
- ret = QAquaSizeLarge;
+ else if (wsp == QStyleHelper::SizeMini)
+ ret = QStyleHelper::SizeMini;
+ else if (wsp == QStyleHelper::SizeSmall)
+ ret = QStyleHelper::SizeSmall;
+ else if (wsp == QStyleHelper::SizeLarge)
+ ret = QStyleHelper::SizeLarge;
if (guess_size)
ret = qt_aqua_guess_size(widg, large, small, mini);
QSize *sz = 0;
- if (ret == QAquaSizeSmall)
+ if (ret == QStyleHelper::SizeSmall)
sz = &small;
- else if (ret == QAquaSizeLarge)
+ else if (ret == QStyleHelper::SizeLarge)
sz = &large;
- else if (ret == QAquaSizeMini)
+ else if (ret == QStyleHelper::SizeMini)
sz = &mini;
if (insz)
*insz = sz ? *sz : QSize(-1, -1);
@@ -1225,7 +1351,7 @@ QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option,
Q_UNUSED(widg);
Q_UNUSED(ct);
Q_UNUSED(szHint);
- return QAquaSizeUnknown;
+ return QStyleHelper::SizeDefault;
#endif
}
@@ -1233,10 +1359,10 @@ QAquaWidgetSize QMacStylePrivate::aquaSizeConstrain(const QStyleOption *option,
Returns the free space awailable for contents inside the
button (and not the size of the contents itself)
*/
-HIRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn,
+CGRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn,
const HIThemeButtonDrawInfo *bdi) const
{
- HIRect outerBounds = qt_hirectForQRect(btn->rect);
+ CGRect outerBounds = btn->rect.toCGRect();
// Adjust the bounds to correct for
// carbon not calculating the content bounds fully correct
if (bdi->kind == kThemePushButton || bdi->kind == kThemePushButtonSmall){
@@ -1246,7 +1372,7 @@ HIRect QMacStylePrivate::pushButtonContentBounds(const QStyleOptionButton *btn,
outerBounds.origin.y += QMacStylePrivate::PushButtonTopOffset;
}
- HIRect contentBounds;
+ CGRect contentBounds;
HIThemeGetButtonContentBounds(&outerBounds, bdi, &contentBounds);
return contentBounds;
}
@@ -1282,7 +1408,7 @@ bool QMacStylePrivate::contentFitsInPushButton(const QStyleOptionButton *btn,
ThemeButtonKind tmp = bdi->kind;
bdi->kind = buttonKindToCheck;
QSize contentSize = pushButtonSizeFromContents(btn);
- QRect freeContentRect = qt_qrectForHIRect(pushButtonContentBounds(btn, bdi));
+ QRect freeContentRect = QRectF::fromCGRect(pushButtonContentBounds(btn, bdi)).toRect();
bdi->kind = tmp;
return freeContentRect.contains(QRect(freeContentRect.x(), freeContentRect.y(),
contentSize.width(), contentSize.height()));
@@ -1318,19 +1444,19 @@ void QMacStylePrivate::initHIThemePushButton(const QStyleOptionButton *btn,
bdi->kind = kThemeBevelButton;
} else {
switch (aquaSizeConstrain(btn, widget)) {
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
bdi->kind = kThemePushButtonSmall;
break;
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
bdi->kind = kThemePushButtonMini;
break;
- case QAquaSizeLarge:
+ case QStyleHelper::SizeLarge:
// ... We should honor if the user is explicit about using the
// large button. But right now Qt will specify the large button
- // as default rather than QAquaSizeUnknown.
- // So we treat it like QAquaSizeUnknown
+ // as default rather than QStyleHelper::SizeDefault.
+ // So we treat it like QStyleHelper::SizeDefault
// to get the dynamic choosing of button kind.
- case QAquaSizeUnknown:
+ case QStyleHelper::SizeDefault:
// Choose the button kind that closest match the button rect, but at the
// same time displays the button contents without clipping.
bdi->kind = kThemeBevelButton;
@@ -1384,18 +1510,18 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem
else
bdi->state = tds;
- QAquaWidgetSize aSize = aquaSizeConstrain(combo, widget);
+ QStyleHelper::WidgetSizePolicy aSize = aquaSizeConstrain(combo, widget);
switch (aSize) {
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxMini)
: ThemeButtonKind(kThemePopupButtonMini);
break;
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
bdi->kind = combo->editable ? ThemeButtonKind(kThemeComboBoxSmall)
: ThemeButtonKind(kThemePopupButtonSmall);
break;
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
+ case QStyleHelper::SizeLarge:
+ case QStyleHelper::SizeDefault:
// Unless the user explicitly specified large buttons, determine the
// kind by looking at the combox size.
// ... specifying small and mini-buttons it not a current feature of
@@ -1451,9 +1577,9 @@ void QMacStylePrivate::initComboboxBdi(const QStyleOptionComboBox *combo, HIThem
Carbon draws comboboxes (and other views) outside the rect given as argument. Use this function to obtain
the corresponding inner rect for drawing the same combobox so that it stays inside the given outerBounds.
*/
-HIRect QMacStylePrivate::comboboxInnerBounds(const HIRect &outerBounds, int buttonKind)
+CGRect QMacStylePrivate::comboboxInnerBounds(const CGRect &outerBounds, int buttonKind)
{
- HIRect innerBounds = outerBounds;
+ CGRect innerBounds = outerBounds;
// Carbon draw parts of the view outside the rect.
// So make the rect a bit smaller to compensate
// (I wish HIThemeGetButtonBackgroundBounds worked)
@@ -1497,6 +1623,7 @@ HIRect QMacStylePrivate::comboboxInnerBounds(const HIRect &outerBounds, int butt
default:
break;
}
+
return innerBounds;
}
@@ -1538,17 +1665,17 @@ QRect QMacStylePrivate::comboboxEditBounds(const QRect &outerBounds, const HIThe
create it manually by drawing a small Carbon combo onto a pixmap (use pixmap cache), chop
it up, and copy it back onto the widget. Othervise, draw the combobox supplied by Carbon directly.
*/
-void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p)
+void QMacStylePrivate::drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p)
{
if (!(bdi.kind == kThemeComboBox && outerBounds.size.height > 28)){
// We have an unscaled combobox, or popup-button; use Carbon directly.
- HIRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, bdi.kind);
+ const CGRect innerBounds = QMacStylePrivate::comboboxInnerBounds(outerBounds, bdi.kind);
HIThemeDrawButton(&innerBounds, &bdi, QMacCGContext(p), kHIThemeOrientationNormal, 0);
} else {
QPixmap buffer;
QString key = QString(QLatin1String("$qt_cbox%1-%2")).arg(int(bdi.state)).arg(int(bdi.adornment));
if (!QPixmapCache::find(key, buffer)) {
- HIRect innerBoundsSmallCombo = {{3, 3}, {29, 25}};
+ CGRect innerBoundsSmallCombo = {{3, 3}, {29, 25}};
buffer = QPixmap(35, 28);
buffer.fill(Qt::transparent);
QPainter buffPainter(&buffer);
@@ -1589,17 +1716,15 @@ void QMacStylePrivate::drawCombobox(const HIRect &outerBounds, const HIThemeButt
Carbon tableheaders don't scale (sight). So create it manually by drawing a small Carbon header
onto a pixmap (use pixmap cache), chop it up, and copy it back onto the widget.
*/
-void QMacStylePrivate::drawTableHeader(const HIRect &outerBounds,
+void QMacStylePrivate::drawTableHeader(const CGRect &outerBounds,
bool drawTopBorder, bool drawLeftBorder, const HIThemeButtonDrawInfo &bdi, QPainter *p)
{
- static SInt32 headerHeight = 0;
- static OSStatus err = GetThemeMetric(kThemeMetricListHeaderHeight, &headerHeight);
- Q_UNUSED(err);
+ static SInt32 headerHeight = qt_mac_aqua_get_metric(ListHeaderHeight);
QPixmap buffer;
QString key = QString(QLatin1String("$qt_tableh%1-%2-%3")).arg(int(bdi.state)).arg(int(bdi.adornment)).arg(int(bdi.value));
if (!QPixmapCache::find(key, buffer)) {
- HIRect headerNormalRect = {{0., 0.}, {16., CGFloat(headerHeight)}};
+ CGRect headerNormalRect = {{0., 0.}, {16., CGFloat(headerHeight)}};
buffer = QPixmap(headerNormalRect.size.width, headerNormalRect.size.height);
buffer.fill(Qt::transparent);
QPainter buffPainter(&buffer);
@@ -1650,148 +1775,85 @@ void QMacStylePrivate::drawTableHeader(const HIRect &outerBounds,
p->translate(-outerBounds.origin.x, -outerBounds.origin.y);
}
-/*
- Returns cutoff sizes for scroll bars.
- thumbIndicatorCutoff is the smallest size where the thumb indicator is drawn.
- scrollButtonsCutoff is the smallest size where the up/down buttons is drawn.
-*/
-enum ScrollBarCutoffType { thumbIndicatorCutoff = 0, scrollButtonsCutoff = 1 };
-static int scrollButtonsCutoffSize(ScrollBarCutoffType cutoffType, QMacStyle::WidgetSizePolicy widgetSize)
-{
- // Mini scroll bars do not exist as of version 10.4.
- if (widgetSize == QMacStyle::SizeMini)
- return 0;
-
- const int sizeIndex = (widgetSize == QMacStyle::SizeSmall) ? 1 : 0;
- static const int sizeTable[2][2] = { { 61, 56 }, { 49, 44 } };
- return sizeTable[sizeIndex][cutoffType];
-}
-
void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider,
HIThemeTrackDrawInfo *tdi, const QWidget *needToRemoveMe) const
{
+ Q_UNUSED(cc);
memset(tdi, 0, sizeof(HIThemeTrackDrawInfo)); // We don't get it all for some reason or another...
tdi->version = qt_mac_hitheme_version;
tdi->reserved = 0;
tdi->filler1 = 0;
- bool isScrollbar = (cc == QStyle::CC_ScrollBar);
switch (aquaSizeConstrain(slider, needToRemoveMe)) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- if (isScrollbar)
- tdi->kind = kThemeMediumScrollBar;
- else
- tdi->kind = kThemeMediumSlider;
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
+ tdi->kind = kThemeMediumSlider;
break;
- case QAquaSizeMini:
- if (isScrollbar)
- tdi->kind = kThemeSmallScrollBar; // should be kThemeMiniScrollBar, but not implemented
- else
- tdi->kind = kThemeMiniSlider;
+ case QStyleHelper::SizeMini:
+ tdi->kind = kThemeMiniSlider;
break;
- case QAquaSizeSmall:
- if (isScrollbar)
- tdi->kind = kThemeSmallScrollBar;
- else
- tdi->kind = kThemeSmallSlider;
+ case QStyleHelper::SizeSmall:
+ tdi->kind = kThemeSmallSlider;
break;
}
bool usePlainKnob = slider->tickPosition == QSlider::NoTicks
|| slider->tickPosition == QSlider::TicksBothSides;
- tdi->bounds = qt_hirectForQRect(slider->rect);
- if (isScrollbar) {
- tdi->min = slider->minimum;
- tdi->max = slider->maximum;
- tdi->value = slider->sliderPosition;
+ tdi->bounds = slider->rect.toCGRect();
+ // Fix min and max positions. HITheme seems confused when it comes to rendering
+ // a slider at those positions. We give it a hand by extending and offsetting
+ // the slider range accordingly. See also comment for CC_Slider in drawComplexControl()
+ tdi->min = 0;
+ if (slider->orientation == Qt::Horizontal)
+ tdi->max = 10 * slider->rect.width();
+ else
+ tdi->max = 10 * slider->rect.height();
+
+ int range = slider->maximum - slider->minimum;
+ if (range == 0) {
+ tdi->value = 0;
+ } else if (usePlainKnob || slider->orientation == Qt::Horizontal) {
+ int endsCorrection = usePlainKnob ? 25 : 10;
+ tdi->value = (tdi->max + 2 * endsCorrection) * (slider->sliderPosition - slider->minimum) / range - endsCorrection;
} else {
- // Fix min and max positions. HITheme seems confused when it comes to rendering
- // a slider at those positions. We give it a hand by extending and offsetting
- // the slider range accordingly. See also comment for CC_Slider in drawComplexControl()
- tdi->min = 0;
- if (slider->orientation == Qt::Horizontal)
- tdi->max = 10 * slider->rect.width();
- else
- tdi->max = 10 * slider->rect.height();
-
- int range = slider->maximum - slider->minimum;
- if (range == 0) {
- tdi->value = 0;
- } else if (usePlainKnob || slider->orientation == Qt::Horizontal) {
- int endsCorrection = usePlainKnob ? 25 : 10;
- tdi->value = (tdi->max + 2 * endsCorrection) * (slider->sliderPosition - slider->minimum) / range - endsCorrection;
- } else {
- tdi->value = (tdi->max + 30) * (slider->sliderPosition - slider->minimum) / range - 20;
- }
+ tdi->value = (tdi->max + 30) * (slider->sliderPosition - slider->minimum) / range - 20;
}
+
tdi->attributes = kThemeTrackShowThumb;
if (slider->upsideDown)
tdi->attributes |= kThemeTrackRightToLeft;
if (slider->orientation == Qt::Horizontal) {
tdi->attributes |= kThemeTrackHorizontal;
- if (isScrollbar && slider->direction == Qt::RightToLeft) {
- if (!slider->upsideDown)
- tdi->attributes |= kThemeTrackRightToLeft;
- else
- tdi->attributes &= ~kThemeTrackRightToLeft;
- }
- }
-
- // Tiger broke reverse scroll bars so put them back and "fake it"
- if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft)) {
- tdi->attributes &= ~kThemeTrackRightToLeft;
- tdi->value = tdi->max - tdi->value;
}
tdi->enableState = (slider->state & QStyle::State_Enabled) ? kThemeTrackActive
: kThemeTrackDisabled;
- if (!isScrollbar) {
- if (slider->state & QStyle::QStyle::State_HasFocus)
- tdi->attributes |= kThemeTrackHasFocus;
- if (usePlainKnob)
- tdi->trackInfo.slider.thumbDir = kThemeThumbPlain;
- else if (slider->tickPosition == QSlider::TicksAbove)
- tdi->trackInfo.slider.thumbDir = kThemeThumbUpward;
- else
- tdi->trackInfo.slider.thumbDir = kThemeThumbDownward;
- } else {
- tdi->trackInfo.scrollbar.viewsize = slider->pageStep;
- }
-}
-
-void QMacStylePrivate::setAutoDefaultButton(QObject *button) const
-{
- if (autoDefaultButton != button) {
- if (QStyleAnimation *anim = animation(autoDefaultButton)) {
- anim->updateTarget();
- stopAnimation(autoDefaultButton);
- }
- autoDefaultButton = button;
- }
- if (autoDefaultButton && !animation(autoDefaultButton))
- startAnimation(new QStyleAnimation(autoDefaultButton));
+ if (slider->state & QStyle::QStyle::State_HasFocus)
+ tdi->attributes |= kThemeTrackHasFocus;
+ if (usePlainKnob)
+ tdi->trackInfo.slider.thumbDir = kThemeThumbPlain;
+ else if (slider->tickPosition == QSlider::TicksAbove)
+ tdi->trackInfo.slider.thumbDir = kThemeThumbUpward;
+ else
+ tdi->trackInfo.slider.thumbDir = kThemeThumbDownward;
}
QMacStylePrivate::QMacStylePrivate()
- : mouseDown(false), backingStoreNSView(nil)
+ : backingStoreNSView(nil)
{
- defaultButtonStart = CFAbsoluteTimeGetCurrent();
- memset(&buttonState, 0, sizeof(ButtonState));
-
- if (ptrHIShapeGetBounds == 0) {
- QLibrary library(QLatin1String("/System/Library/Frameworks/Carbon.framework/Carbon"));
- library.setLoadHints(QLibrary::ExportExternalSymbolsHint);
- ptrHIShapeGetBounds = reinterpret_cast<PtrHIShapeGetBounds>(library.resolve("HIShapeGetBounds"));
- }
-
+ if (auto *ssf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::SmallFont))
+ smallSystemFont = *ssf;
+ if (auto *msf = QGuiApplicationPrivate::platformTheme()->font(QPlatformTheme::MiniFont))
+ miniSystemFont = *msf;
}
QMacStylePrivate::~QMacStylePrivate()
{
QMacAutoReleasePool pool;
- Q_FOREACH (NSView *b, cocoaControls)
+ for (NSView *b : cocoaControls)
[b release];
+ for (NSCell *cell : cocoaCells)
+ [cell release];
}
ThemeDrawState QMacStylePrivate::getDrawState(QStyle::State flags)
@@ -1825,7 +1887,7 @@ static QCocoaWidget cocoaWidgetFromHIThemeButtonKind(ThemeButtonKind kind)
w.first = QCocoaComboBox;
break;
case kThemeArrowButton:
- w.first = QCocoaArrowButton;
+ w.first = QCocoaDisclosureButton;
break;
case kThemeCheckBox:
case kThemeCheckBoxSmall:
@@ -1851,16 +1913,16 @@ static QCocoaWidget cocoaWidgetFromHIThemeButtonKind(ThemeButtonKind kind)
case kThemePopupButtonSmall:
case kThemeCheckBoxSmall:
case kThemeRadioButtonSmall:
- w.second = QAquaSizeSmall;
+ w.second = QStyleHelper::SizeSmall;
break;
case kThemePushButtonMini:
case kThemePopupButtonMini:
case kThemeCheckBoxMini:
case kThemeRadioButtonMini:
- w.second = QAquaSizeMini;
+ w.second = QStyleHelper::SizeMini;
break;
default:
- w.second = QAquaSizeLarge;
+ w.second = QStyleHelper::SizeLarge;
break;
}
@@ -1877,6 +1939,16 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const
bv = [[NSPopUpButton alloc] init];
else if (widget.first == QCocoaComboBox)
bv = [[NSComboBox alloc] init];
+ else if (widget.first == QCocoaProgressIndicator)
+ bv = [[NSProgressIndicator alloc] init];
+ else if (widget.first == QCocoaIndeterminateProgressIndicator)
+ bv = [[QIndeterminateProgressIndicator alloc] init];
+ else if (widget.first == QCocoaHorizontalScroller)
+ bv = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)];
+ else if (widget.first == QCocoaVerticalScroller)
+ // Cocoa sets the orientation from the view's frame
+ // at construction time, and it cannot be changed later.
+ bv = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)];
else if (widget.first == QCocoaHorizontalSlider)
bv = [[NSSlider alloc] init];
else if (widget.first == QCocoaVerticalSlider)
@@ -1887,7 +1959,7 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const
bv = [[NSButton alloc] init];
switch (widget.first) {
- case QCocoaArrowButton: {
+ case QCocoaDisclosureButton: {
NSButton *bc = (NSButton *)bv;
bc.buttonType = NSOnOffButton;
bc.bezelStyle = NSDisclosureBezelStyle;
@@ -1926,15 +1998,28 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const
if ([bv isKindOfClass:[NSControl class]]) {
NSCell *bcell = [(NSControl *)bv cell];
switch (widget.second) {
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
bcell.controlSize = NSSmallControlSize;
break;
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
bcell.controlSize = NSMiniControlSize;
break;
default:
break;
}
+ } else if ([bv isKindOfClass:[NSProgressIndicator class]]) {
+ auto *pi = static_cast<NSProgressIndicator *>(bv);
+ pi.indeterminate = (widget.first == QCocoaIndeterminateProgressIndicator);
+ switch (widget.second) {
+ case QStyleHelper::SizeSmall:
+ pi.controlSize = NSSmallControlSize;
+ break;
+ case QStyleHelper::SizeMini:
+ pi.controlSize = NSMiniControlSize;
+ break;
+ default:
+ break;
+ }
}
const_cast<QMacStylePrivate *>(this)->cocoaControls.insert(widget, bv);
@@ -1943,53 +2028,85 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget) const
return bv;
}
+NSCell *QMacStylePrivate::cocoaCell(QCocoaWidget widget) const
+{
+ NSCell *cell = cocoaCells[widget];
+ if (!cell) {
+ switch (widget.first) {
+ case QCocoaStepper:
+ cell = [[NSStepperCell alloc] init];
+ break;
+ case QCocoaDisclosureButton: {
+ NSButtonCell *bc = [[NSButtonCell alloc] init];
+ bc.buttonType = NSOnOffButton;
+ bc.bezelStyle = NSDisclosureBezelStyle;
+ cell = bc;
+ break;
+ }
+ default:
+ break;
+ }
+
+ switch (widget.second) {
+ case QStyleHelper::SizeSmall:
+ cell.controlSize = NSSmallControlSize;
+ break;
+ case QStyleHelper::SizeMini:
+ cell.controlSize = NSMiniControlSize;
+ break;
+ default:
+ break;
+ }
+
+ const_cast<QMacStylePrivate *>(this)->cocoaCells.insert(widget, cell);
+ }
+
+ return cell;
+}
+
void QMacStylePrivate::drawNSViewInRect(QCocoaWidget widget, NSView *view, const QRect &qtRect, QPainter *p, bool isQWidget, QCocoaDrawRectBlock drawRectBlock) const
{
QPoint offset;
- if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeLarge))
+ if (widget == QCocoaWidget(QCocoaRadioButton, QStyleHelper::SizeLarge))
offset.setY(2);
- else if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeSmall))
+ else if (widget == QCocoaWidget(QCocoaRadioButton, QStyleHelper::SizeSmall))
offset = QPoint(-1, 2);
- else if (widget == QCocoaWidget(QCocoaRadioButton, QAquaSizeMini))
+ else if (widget == QCocoaWidget(QCocoaRadioButton, QStyleHelper::SizeMini))
offset.setY(2);
- else if (widget == QCocoaWidget(QCocoaPopupButton, QAquaSizeSmall)
- || widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeLarge))
+ else if (widget == QCocoaWidget(QCocoaPopupButton, QStyleHelper::SizeSmall)
+ || widget == QCocoaWidget(QCocoaCheckBox, QStyleHelper::SizeLarge))
offset.setY(1);
- else if (widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeSmall))
+ else if (widget == QCocoaWidget(QCocoaCheckBox, QStyleHelper::SizeSmall))
offset.setX(-1);
- else if (widget == QCocoaWidget(QCocoaCheckBox, QAquaSizeMini))
+ else if (widget == QCocoaWidget(QCocoaCheckBox, QStyleHelper::SizeMini))
offset = QPoint(7, 5);
- else if (widget == QCocoaWidget(QCocoaPopupButton, QAquaSizeMini))
+ else if (widget == QCocoaWidget(QCocoaPopupButton, QStyleHelper::SizeMini))
offset = QPoint(2, -1);
- else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeLarge))
+ else if (widget == QCocoaWidget(QCocoaPullDownButton, QStyleHelper::SizeLarge))
offset = isQWidget ? QPoint(3, -1) : QPoint(-1, -3);
- else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeSmall))
+ else if (widget == QCocoaWidget(QCocoaPullDownButton, QStyleHelper::SizeSmall))
offset = QPoint(2, 1);
- else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeMini))
+ else if (widget == QCocoaWidget(QCocoaPullDownButton, QStyleHelper::SizeMini))
offset = QPoint(5, 0);
- else if (widget == QCocoaWidget(QCocoaComboBox, QAquaSizeLarge))
+ else if (widget == QCocoaWidget(QCocoaComboBox, QStyleHelper::SizeLarge))
offset = QPoint(3, 0);
QMacCGContext ctx(p);
- CGContextSaveGState(ctx);
- CGContextTranslateCTM(ctx, offset.x(), offset.y());
+ setupNSGraphicsContext(ctx, YES);
- [NSGraphicsContext saveGraphicsState];
- [NSGraphicsContext setCurrentContext:[NSGraphicsContext
- graphicsContextWithGraphicsPort:ctx flipped:YES]];
+ CGContextTranslateCTM(ctx, offset.x(), offset.y());
- NSRect rect = NSMakeRect(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height());
+ const CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height());
[backingStoreNSView addSubview:view];
view.frame = rect;
if (drawRectBlock)
- drawRectBlock(rect, (CGContextRef)ctx);
+ drawRectBlock(ctx, rect);
else
[view drawRect:rect];
[view removeFromSuperviewWithoutNeedingDisplay];
- [NSGraphicsContext restoreGraphicsState];
- CGContextRestoreGState(ctx);
+ restoreNSGraphicsContext(ctx);
}
void QMacStylePrivate::resolveCurrentNSView(QWindow *window)
@@ -1997,7 +2114,7 @@ void QMacStylePrivate::resolveCurrentNSView(QWindow *window)
backingStoreNSView = window ? (NSView *)window->winId() : nil;
}
-void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi,
+void QMacStylePrivate::drawColorlessButton(const CGRect &macRect, HIThemeButtonDrawInfo *bdi,
QPainter *p, const QStyleOption *opt) const
{
int xoff = 0,
@@ -2048,7 +2165,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD
QMacStylePrivate::drawCombobox(macRect, *bdi, &tmpPainter);
} else {
QMacCGContext cg(&activePixmap);
- HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height);
+ CGRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height);
if (button && pressed)
bdi->state = kThemeStateActive;
else if (viewItem)
@@ -2106,7 +2223,7 @@ void QMacStylePrivate::drawColorlessButton(const HIRect &macRect, HIThemeButtonD
colorlessPixmap.fill(Qt::transparent);
QMacCGContext cg(&colorlessPixmap);
- HIRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height);
+ CGRect newRect = CGRectMake(xoff, yoff, macRect.size.width, macRect.size.height);
int oldValue = bdi->value;
bdi->value = kThemeButtonOff;
HIThemeDrawButton(&newRect, bdi, cg, kHIThemeOrientationNormal, 0);
@@ -2146,20 +2263,10 @@ QMacStyle::QMacStyle()
QMacAutoReleasePool pool;
d->receiver = [[NotificationReceiver alloc] initWithPrivate:d];
- NotificationReceiver *receiver = static_cast<NotificationReceiver *>(d->receiver);
-
- [[NSNotificationCenter defaultCenter] addObserver:receiver
- selector:@selector(scrollBarStyleDidChange:)
- name:NSPreferredScrollerStyleDidChangeNotification
- object:nil];
-
- // Create scroller objects. Scroller internal direction setup happens
- // on initWithFrame and cannot be changed later on. Create two scrollers
- // initialized with fake geometry. Correct geometry is set at draw time.
- d->horizontalScroller = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 200, 20)];
- d->verticalScroller = [[NSScroller alloc] initWithFrame:NSMakeRect(0, 0, 20, 200)];
-
- d->indicatorBranchButtonCell = nil;
+ [[NSNotificationCenter defaultCenter] addObserver:d->receiver
+ selector:@selector(scrollBarStyleDidChange:)
+ name:NSPreferredScrollerStyleDidChangeNotification
+ object:nil];
}
QMacStyle::~QMacStyle()
@@ -2167,12 +2274,8 @@ QMacStyle::~QMacStyle()
Q_D(QMacStyle);
QMacAutoReleasePool pool;
- [d->horizontalScroller release];
- [d->verticalScroller release];
-
- NotificationReceiver *receiver = static_cast<NotificationReceiver *>(d->receiver);
- [[NSNotificationCenter defaultCenter] removeObserver:receiver];
- [receiver release];
+ [[NSNotificationCenter defaultCenter] removeObserver:d->receiver];
+ [d->receiver release];
delete qt_mac_backgroundPattern;
qt_mac_backgroundPattern = 0;
@@ -2258,16 +2361,6 @@ void QMacStyle::unpolish(QApplication *)
void QMacStyle::polish(QWidget* w)
{
- if (qt_mac_is_metal(w) && !w->testAttribute(Qt::WA_SetPalette)) {
- // Set a clear brush so that the metal shines through.
- QPalette pal = w->palette();
- QBrush background(Qt::transparent);
- pal.setBrush(QPalette::All, QPalette::Window, background);
- pal.setBrush(QPalette::All, QPalette::Button, background);
- w->setPalette(pal);
- w->setAttribute(Qt::WA_SetPalette, false);
- }
-
#ifndef QT_NO_MENU
if (qobject_cast<QMenu*>(w)
#if QT_CONFIG(combobox)
@@ -2326,12 +2419,11 @@ void QMacStyle::polish(QWidget* w)
void QMacStyle::unpolish(QWidget* w)
{
- if ((
+ if (
#ifndef QT_NO_MENU
- qobject_cast<QMenu*>(w) ||
+ qobject_cast<QMenu*>(w) &&
#endif
- qt_mac_is_metal(w)
- ) && !w->testAttribute(Qt::WA_SetPalette)) {
+ !w->testAttribute(Qt::WA_SetPalette)) {
QPalette pal = qApp->palette(w);
w->setPalette(pal);
w->setAttribute(Qt::WA_SetPalette, false);
@@ -2377,7 +2469,7 @@ void QMacStyle::unpolish(QWidget* w)
int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QWidget *widget) const
{
Q_D(const QMacStyle);
- int controlSize = getControlSize(opt, widget);
+ const int controlSize = getControlSize(opt, widget);
SInt32 ret = 0;
switch (metric) {
@@ -2390,7 +2482,7 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
break;
case PM_FocusFrameVMargin:
case PM_FocusFrameHMargin:
- GetThemeMetric(kThemeMetricFocusRectOutset, &ret);
+ ret = qt_mac_aqua_get_metric(FocusRectOutset);
break;
case PM_DialogButtonsSeparator:
ret = -5;
@@ -2433,13 +2525,7 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
ret = 2;
break;
case PM_MenuScrollerHeight:
-#if 0
- SInt16 ash, asw;
- GetThemeMenuItemExtra(kThemeMenuItemScrollUpArrow, &ash, &asw);
- ret = ash;
-#else
ret = 15; // I hate having magic numbers in here...
-#endif
break;
case PM_DefaultFrameWidth:
#ifndef QT_NO_MAINWINDOW
@@ -2463,14 +2549,14 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
ret = 24;
break;
case PM_SpinBoxFrameWidth:
- GetThemeMetric(kThemeMetricEditTextFrameOutset, &ret);
+ ret = qt_mac_aqua_get_metric(EditTextFrameOutset);
switch (d->aquaSizeConstrain(opt, widget)) {
+ case QStyleHelper::SizeMini:
+ ret += 1;
+ break;
default:
ret += 2;
break;
- case QAquaSizeMini:
- ret += 1;
- break;
}
break;
case PM_ButtonShiftHorizontal:
@@ -2533,16 +2619,16 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
break; }
case QStyle::PM_TabBarTabHSpace:
switch (d->aquaSizeConstrain(opt, widget)) {
- case QAquaSizeLarge:
+ case QStyleHelper::SizeLarge:
ret = QCommonStyle::pixelMetric(metric, opt, widget);
break;
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
ret = 20;
break;
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
ret = 16;
break;
- case QAquaSizeUnknown:
+ case QStyleHelper::SizeDefault:
const QStyleOptionTab *tb = qstyleoption_cast<const QStyleOptionTab *>(opt);
if (tb && tb->documentMode)
ret = 30;
@@ -2566,78 +2652,78 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
break;
case PM_TabBarBaseOverlap:
switch (d->aquaSizeConstrain(opt, widget)) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
ret = 11;
break;
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
ret = 8;
break;
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
ret = 7;
break;
}
break;
case PM_ScrollBarExtent: {
- const QAquaWidgetSize size = d->effectiveAquaSizeConstrain(opt, widget);
+ const QStyleHelper::WidgetSizePolicy size = d->effectiveAquaSizeConstrain(opt, widget);
ret = static_cast<SInt32>([NSScroller
scrollerWidthForControlSize:static_cast<NSControlSize>(size)
scrollerStyle:[NSScroller preferredScrollerStyle]]);
break; }
case PM_IndicatorHeight: {
switch (d->aquaSizeConstrain(opt, widget)) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- GetThemeMetric(kThemeMetricCheckBoxHeight, &ret);
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
+ ret = qt_mac_aqua_get_metric(CheckBoxHeight);
break;
- case QAquaSizeMini:
- GetThemeMetric(kThemeMetricMiniCheckBoxHeight, &ret);
+ case QStyleHelper::SizeMini:
+ ret = qt_mac_aqua_get_metric(MiniCheckBoxHeight);
break;
- case QAquaSizeSmall:
- GetThemeMetric(kThemeMetricSmallCheckBoxHeight, &ret);
+ case QStyleHelper::SizeSmall:
+ ret = qt_mac_aqua_get_metric(SmallCheckBoxHeight);
break;
}
break; }
case PM_IndicatorWidth: {
switch (d->aquaSizeConstrain(opt, widget)) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- GetThemeMetric(kThemeMetricCheckBoxWidth, &ret);
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
+ ret = qt_mac_aqua_get_metric(CheckBoxWidth);
break;
- case QAquaSizeMini:
- GetThemeMetric(kThemeMetricMiniCheckBoxWidth, &ret);
+ case QStyleHelper::SizeMini:
+ ret = qt_mac_aqua_get_metric(MiniCheckBoxWidth);
break;
- case QAquaSizeSmall:
- GetThemeMetric(kThemeMetricSmallCheckBoxWidth, &ret);
+ case QStyleHelper::SizeSmall:
+ ret = qt_mac_aqua_get_metric(SmallCheckBoxWidth);
break;
}
++ret;
break; }
case PM_ExclusiveIndicatorHeight: {
switch (d->aquaSizeConstrain(opt, widget)) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- GetThemeMetric(kThemeMetricRadioButtonHeight, &ret);
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
+ ret = qt_mac_aqua_get_metric(RadioButtonHeight);
break;
- case QAquaSizeMini:
- GetThemeMetric(kThemeMetricMiniRadioButtonHeight, &ret);
+ case QStyleHelper::SizeMini:
+ ret = qt_mac_aqua_get_metric(MiniRadioButtonHeight);
break;
- case QAquaSizeSmall:
- GetThemeMetric(kThemeMetricSmallRadioButtonHeight, &ret);
+ case QStyleHelper::SizeSmall:
+ ret = qt_mac_aqua_get_metric(SmallRadioButtonHeight);
break;
}
break; }
case PM_ExclusiveIndicatorWidth: {
switch (d->aquaSizeConstrain(opt, widget)) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- GetThemeMetric(kThemeMetricRadioButtonWidth, &ret);
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
+ ret = qt_mac_aqua_get_metric(RadioButtonWidth);
break;
- case QAquaSizeMini:
- GetThemeMetric(kThemeMetricMiniRadioButtonWidth, &ret);
+ case QStyleHelper::SizeMini:
+ ret = qt_mac_aqua_get_metric(MiniRadioButtonWidth);
break;
- case QAquaSizeSmall:
- GetThemeMetric(kThemeMetricSmallRadioButtonWidth, &ret);
+ case QStyleHelper::SizeSmall:
+ ret = qt_mac_aqua_get_metric(SmallRadioButtonWidth);
break;
}
++ret;
@@ -2652,11 +2738,11 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
ret = 0;
break;
case PM_SizeGripSize: {
- QAquaWidgetSize aSize;
+ QStyleHelper::WidgetSizePolicy aSize;
if (widget && widget->window()->windowType() == Qt::Tool)
- aSize = QAquaSizeSmall;
+ aSize = QStyleHelper::SizeSmall;
else
- aSize = QAquaSizeLarge;
+ aSize = QStyleHelper::SizeLarge;
const QSize size = qt_aqua_get_known_size(CT_SizeGrip, widget, QSize(), aSize);
ret = size.width();
break; }
@@ -2697,24 +2783,13 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
}
if (isWindow) {
- bool isMetal = widget && widget->testAttribute(Qt::WA_MacBrushedMetal);
- if (isMetal) {
- if (metric == PM_LayoutTopMargin) {
- return_SIZE(9 /* AHIG */, 6 /* guess */, 6 /* guess */);
- } else if (metric == PM_LayoutBottomMargin) {
- return_SIZE(18 /* AHIG */, 15 /* guess */, 13 /* guess */);
- } else {
- return_SIZE(14 /* AHIG */, 11 /* guess */, 9 /* guess */);
- }
- } else {
- /*
- AHIG would have (20, 8, 10) here but that makes
- no sense. It would also have 14 for the top margin
- but this contradicts both Builder and most
- applications.
- */
- return_SIZE(20, 10, 10); // AHIG
- }
+ /*
+ AHIG would have (20, 8, 10) here but that makes
+ no sense. It would also have 14 for the top margin
+ but this contradicts both Builder and most
+ applications.
+ */
+ return_SIZE(20, 10, 10); // AHIG
} else {
// hack to detect QTabWidget
if (widget && widget->parentWidget()
@@ -3062,7 +3137,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
if (opt) {
if (QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
ret = true;
- HIRect menuRect = CGRectMake(opt->rect.x(), opt->rect.y() + 4,
+ CGRect menuRect = CGRectMake(opt->rect.x(), opt->rect.y() + 4,
opt->rect.width(), opt->rect.height() - 8);
HIThemeMenuDrawInfo mdi;
mdi.version = 0;
@@ -3103,6 +3178,10 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
case SH_ItemView_ScrollMode:
ret = QAbstractItemView::ScrollPerPixel;
break;
+ case SH_TitleBar_ShowToolTipsOnButtons:
+ // min/max/close buttons on windows don't show tool tips
+ ret = false;
+ break;
default:
ret = QCommonStyle::styleHint(sh, opt, w, hret);
break;
@@ -3166,35 +3245,6 @@ QPixmap QMacStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOpt
return icon.pixmap(qt_getWindow(widget), QSize(size, size));
}
-void QMacStyle::setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy)
-{
- QWidget *wadget = const_cast<QWidget *>(widget);
- wadget->setAttribute(Qt::WA_MacNormalSize, policy == SizeLarge);
- wadget->setAttribute(Qt::WA_MacSmallSize, policy == SizeSmall);
- wadget->setAttribute(Qt::WA_MacMiniSize, policy == SizeMini);
-}
-
-QMacStyle::WidgetSizePolicy QMacStyle::widgetSizePolicy(const QWidget *widget, const QStyleOption *opt)
-{
- while (widget) {
- if (widget->testAttribute(Qt::WA_MacMiniSize)) {
- return SizeMini;
- } else if (widget->testAttribute(Qt::WA_MacSmallSize)) {
- return SizeSmall;
- } else if (widget->testAttribute(Qt::WA_MacNormalSize)) {
- return SizeLarge;
- }
- widget = widget->parentWidget();
- }
-
- if (opt && opt->state & State_Mini)
- return SizeMini;
- else if (opt && opt->state & State_Small)
- return SizeSmall;
-
- return SizeDefault;
-}
-
void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPainter *p,
const QWidget *w) const
{
@@ -3292,8 +3342,8 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
else
#endif
gdi.kind = kHIThemeGroupBoxKindPrimary;
- HIRect hirect = qt_hirectForQRect(opt->rect);
- HIThemeDrawGroupBox(&hirect, &gdi, cg, kHIThemeOrientationNormal);
+ CGRect cgRect = opt->rect.toCGRect();
+ HIThemeDrawGroupBox(&cgRect, &gdi, cg, kHIThemeOrientationNormal);
}
}
break;
@@ -3435,20 +3485,20 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
bdi.adornment |= kThemeAdornmentFocus;
bool isRadioButton = (pe == PE_IndicatorRadioButton);
switch (d->aquaSizeConstrain(opt, w)) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
if (isRadioButton)
bdi.kind = kThemeRadioButton;
else
bdi.kind = kThemeCheckBox;
break;
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
if (isRadioButton)
bdi.kind = kThemeMiniRadioButton;
else
bdi.kind = kThemeMiniCheckBox;
break;
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
if (isRadioButton)
bdi.kind = kThemeSmallRadioButton;
else
@@ -3461,7 +3511,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
bdi.value = kThemeButtonOn;
else
bdi.value = kThemeButtonOff;
- HIRect macRect = qt_hirectForQRect(opt->rect);
+ CGRect macRect = opt->rect.toCGRect();
if (!drawColorless)
HIThemeDrawButton(&macRect, &bdi, cg, kHIThemeOrientationNormal, 0);
else
@@ -3473,20 +3523,12 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
case PE_IndicatorBranch: {
if (!(opt->state & State_Children))
break;
- if (!d->indicatorBranchButtonCell)
- const_cast<QMacStylePrivate *>(d)->indicatorBranchButtonCell = (void *)[[NSButtonCell alloc] init];
- NSButtonCell *triangleCell = (NSButtonCell *)d->indicatorBranchButtonCell;
- [triangleCell setButtonType:NSOnOffButton];
+ NSButtonCell *triangleCell = static_cast<NSButtonCell *>(d->cocoaCell(QCocoaWidget(QCocoaDisclosureButton, QStyleHelper::SizeLarge)));
[triangleCell setState:(opt->state & State_Open) ? NSOnState : NSOffState];
- [triangleCell setBezelStyle:NSDisclosureBezelStyle];
bool viewHasFocus = (w && w->hasFocus()) || (opt->state & State_HasFocus);
[triangleCell setBackgroundStyle:((opt->state & State_Selected) && viewHasFocus) ? NSBackgroundStyleDark : NSBackgroundStyleLight];
- CGContextSaveGState(cg);
- [NSGraphicsContext saveGraphicsState];
-
- [NSGraphicsContext setCurrentContext:[NSGraphicsContext
- graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]];
+ d->setupNSGraphicsContext(cg, NO);
QRect qtRect = opt->rect.adjusted(DisclosureOffset, 0, -DisclosureOffset, 0);
CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height());
@@ -3496,8 +3538,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
[triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
- [NSGraphicsContext restoreGraphicsState];
- CGContextRestoreGState(cg);
+ d->restoreNSGraphicsContext(cg);
break; }
case PE_Frame: {
@@ -3519,7 +3560,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
SInt32 frame_size;
fdi.kind = frame->features & QStyleOptionFrame::Rounded ? kHIThemeFrameTextFieldRound :
kHIThemeFrameTextFieldSquare;
- GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size);
+ frame_size = qt_mac_aqua_get_metric(EditTextFrameOutset);
if ((frame->state & State_ReadOnly) || !(frame->state & State_Enabled))
fdi.state = kThemeStateInactive;
else if (fdi.state == kThemeStatePressed)
@@ -3537,11 +3578,10 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
p->drawRect(frame->rect);
p->restore();
}
- HIRect hirect = qt_hirectForQRect(frame->rect,
- QRect(frame_size, frame_size,
- frame_size * 2, frame_size * 2));
+ const auto frameMargins = QMargins(frame_size, frame_size, frame_size, frame_size);
+ const CGRect cgRect = frame->rect.marginsRemoved(frameMargins).toCGRect();
- HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal);
+ HIThemeDrawFrame(&cgRect, &fdi, cg, kHIThemeOrientationNormal);
} else {
QCommonStyle::drawPrimitive(pe, opt, p, w);
}
@@ -3568,7 +3608,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
case PE_FrameTabWidget:
if (const QStyleOptionTabWidgetFrame *twf
= qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
- HIRect hirect = qt_hirectForQRect(twf->rect);
+ CGRect cgRect = twf->rect.toCGRect();
HIThemeTabPaneDrawInfo tpdi;
tpdi.version = qt_mac_hitheme_tab_version();
tpdi.state = tds;
@@ -3576,7 +3616,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
tpdi.size = kHIThemeTabSizeNormal;
tpdi.kind = kHIThemeTabKindNormal;
tpdi.adornment = kHIThemeTabPaneAdornmentNormal;
- HIThemeDrawTabPane(&hirect, &tpdi, cg, kHIThemeOrientationNormal);
+ HIThemeDrawTabPane(&cgRect, &tpdi, cg, kHIThemeOrientationNormal);
}
break;
#endif
@@ -3659,6 +3699,18 @@ static inline QPixmap darkenPixmap(const QPixmap &pixmap)
+void QMacStylePrivate::setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const
+{
+ if (vertical) {
+ CGContextTranslateCTM(cg, rect.size.height, 0);
+ CGContextRotateCTM(cg, M_PI_2);
+ }
+ if (vertical != reverse) {
+ CGContextTranslateCTM(cg, rect.size.width, 0);
+ CGContextScaleCTM(cg, -1, 1);
+ }
+}
+
void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter *p,
const QWidget *w) const
{
@@ -3729,7 +3781,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
bdi.adornment = kThemeAdornmentFocus;
ir = visualRect(header->direction, header->rect, ir);
- HIRect bounds = qt_hirectForQRect(ir);
+ CGRect bounds = ir.toCGRect();
bool noVerticalHeader = true;
#if QT_CONFIG(tableview)
@@ -3881,36 +3933,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
break;
}
- // No default button pulsating animation on Yosemite,
- // so we have to do few things differently.
-
// a focused auto-default button within an active window
// takes precedence over a normal default button
- if (btn->features & QStyleOptionButton::AutoDefaultButton
- && opt->state & State_Active && opt->state & State_HasFocus) {
+ if ((btn->features & QStyleOptionButton::AutoDefaultButton)
+ && (opt->state & State_Active)
+ && (opt->state & State_HasFocus))
d->autoDefaultButton = opt->styleObject;
- } else if (d->autoDefaultButton == opt->styleObject) {
- d->setAutoDefaultButton(0);
- }
-
- if (!d->autoDefaultButton) {
- if (btn->features & QStyleOptionButton::DefaultButton && opt->state & State_Active) {
- d->defaultButton = opt->styleObject;
- } else if (d->defaultButton == opt->styleObject) {
- if (QStyleAnimation *animation = d->animation(opt->styleObject)) {
- animation->updateTarget();
- d->stopAnimation(opt->styleObject);
- }
- d->defaultButton = 0;
- }
- }
-
- // TODO: find out the pressed button in a qwidget independent way
- extern QWidget *qt_button_down; // qwidgetwindow.cpp
- if (opt->styleObject == qt_button_down)
- d->pressedButton = opt->styleObject;
- else if (d->pressedButton == opt->styleObject)
- d->pressedButton = 0;
+ else if (d->autoDefaultButton == opt->styleObject)
+ d->autoDefaultButton = nullptr;
bool hasMenu = btn->features & QStyleOptionButton::HasMenu;
HIThemeButtonDrawInfo bdi;
@@ -3933,7 +3963,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// Unlike Carbon, we want the button to always be drawn inside its bounds.
// Therefore, make the button a bit smaller, so that even if it got focus,
// the focus 'shadow' will be inside.
- HIRect newRect = qt_hirectForQRect(btn->rect);
+ CGRect newRect = btn->rect.toCGRect();
if (bdi.kind == kThemePushButton || bdi.kind == kThemePushButtonSmall) {
newRect.origin.x += QMacStylePrivate::PushButtonLeftOffset;
newRect.origin.y += QMacStylePrivate::PushButtonTopOffset;
@@ -3952,7 +3982,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
[pdb highlight:(bdi.state == kThemeStatePressed)];
pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive;
QRect rect = opt->rect;
- rect.adjust(0, 0, cw.second == QAquaSizeSmall ? -4 : cw.second == QAquaSizeMini ? -9 : -6, 0);
+ rect.adjust(0, 0, cw.second == QStyleHelper::SizeSmall ? -4 : cw.second == QStyleHelper::SizeMini ? -9 : -6, 0);
d->drawNSViewInRect(cw, pdb, rect, p, w != 0);
} else if (hasMenu && bdi.state == kThemeStatePressed)
d->drawColorlessButton(newRect, &bdi, p, opt);
@@ -4005,7 +4035,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QRect ar = QRect(ir.right() - mbi - QMacStylePrivate::PushButtonRightOffset,
ir.height() / 2 - arrowYOffset, mbi, ir.height() / 2);
ar = visualRect(btn->direction, ir, ar);
- HIRect arrowRect = CGRectMake(ar.x() + arrowXOffset, ar.y(), ar.width(), ar.height());
+ CGRect arrowRect = CGRectMake(ar.x() + arrowXOffset, ar.y(), ar.width(), ar.height());
HIThemePopupArrowDrawInfo pdi;
pdi.version = qt_mac_hitheme_version;
@@ -4026,9 +4056,9 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// windows style if it has an icon and text, then it should be more like a
// tab. So, cheat a little here. However, if it *is* only an icon
// the windows style works great, so just use that implementation.
- bool hasMenu = btn.features & QStyleOptionButton::HasMenu;
- bool hasIcon = !btn.icon.isNull();
- bool hasText = !btn.text.isEmpty();
+ const bool hasMenu = btn.features & QStyleOptionButton::HasMenu;
+ const bool hasIcon = !btn.icon.isNull();
+ const bool hasText = !btn.text.isEmpty();
if (!hasMenu) {
if (tds == kThemeStatePressed
@@ -4038,94 +4068,45 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
btn.palette.setColor(QPalette::ButtonText, Qt::white);
}
- if (!hasIcon && !hasMenu) {
- // ### this is really overly difficult, simplify.
- // It basically tries to get the right font for "small" and "mini" icons.
- QFont oldFont = p->font();
- QFont newFont = qt_app_fonts_hash()->value("QPushButton", QFont());
- ThemeFontID themeId = kThemePushButtonFont;
- if (oldFont == newFont) { // Yes, use HITheme to draw the text for small sizes.
- switch (d->aquaSizeConstrain(opt, w)) {
- default:
- break;
- case QAquaSizeSmall:
- themeId = kThemeSmallSystemFont;
- break;
- case QAquaSizeMini:
- themeId = kThemeMiniSystemFont;
- break;
- }
+ if ((!hasIcon && !hasMenu) || (hasIcon && !hasText)) {
+ QCommonStyle::drawControl(ce, &btn, p, w);
+ } else {
+ QRect freeContentRect = btn.rect;
+ QRect textRect = itemTextRect(
+ btn.fontMetrics, freeContentRect, Qt::AlignCenter, btn.state & State_Enabled, btn.text);
+ if (hasMenu) {
+ textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls
}
-
- if (themeId == kThemePushButtonFont) {
- QCommonStyle::drawControl(ce, &btn, p, w);
- } else {
- p->save();
- CGContextSetShouldAntialias(cg, true);
- CGContextSetShouldSmoothFonts(cg, true);
- HIThemeTextInfo tti;
- tti.version = qt_mac_hitheme_version;
- tti.state = tds;
- QColor textColor;
- textColor = btn.palette.buttonText().color();
- CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()),
- static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) };
- CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace());
- CGContextSetFillColor(cg, colorComp);
- tti.fontID = themeId;
- tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter;
- tti.verticalFlushness = kHIThemeTextVerticalFlushCenter;
- tti.options = kHIThemeTextBoxOptionNone;
- tti.truncationPosition = kHIThemeTextTruncationNone;
- tti.truncationMaxLines = 1 + btn.text.count(QLatin1Char('\n'));
- QCFString buttonText = qt_mac_removeMnemonics(btn.text);
- QRect r = btn.rect;
- HIRect bounds = qt_hirectForQRect(r);
- HIThemeDrawTextBox(buttonText, &bounds, &tti,
- cg, kHIThemeOrientationNormal);
- p->restore();
+ // Draw the icon:
+ if (hasIcon) {
+ int contentW = textRect.width();
+ if (hasMenu)
+ contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4;
+ QIcon::Mode mode = btn.state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
+ if (mode == QIcon::Normal && btn.state & State_HasFocus)
+ mode = QIcon::Active;
+ // Decide if the icon is should be on or off:
+ QIcon::State state = QIcon::Off;
+ if (btn.state & State_On)
+ state = QIcon::On;
+ QPixmap pixmap = btn.icon.pixmap(window, btn.iconSize, mode, state);
+ int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
+ int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
+ contentW += pixmapWidth + QMacStylePrivate::PushButtonContentPadding;
+ int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2;
+ int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmapHeight) / 2;
+ QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmapWidth, pixmapHeight);
+ QRect visualIconDestRect = visualRect(btn.direction, freeContentRect, iconDestRect);
+ proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap);
+ int newOffset = iconDestRect.x() + iconDestRect.width()
+ + QMacStylePrivate::PushButtonContentPadding - textRect.x();
+ textRect.adjust(newOffset, 0, newOffset, 0);
}
- } else {
- if (hasIcon && !hasText) {
- QCommonStyle::drawControl(ce, &btn, p, w);
- } else {
- QRect freeContentRect = btn.rect;
- QRect textRect = itemTextRect(
- btn.fontMetrics, freeContentRect, Qt::AlignCenter, btn.state & State_Enabled, btn.text);
- if (hasMenu) {
- textRect.moveTo(w ? 15 : 11, textRect.top()); // Supports Qt Quick Controls
- }
- // Draw the icon:
- if (hasIcon) {
- int contentW = textRect.width();
- if (hasMenu)
- contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4;
- QIcon::Mode mode = btn.state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
- if (mode == QIcon::Normal && btn.state & State_HasFocus)
- mode = QIcon::Active;
- // Decide if the icon is should be on or off:
- QIcon::State state = QIcon::Off;
- if (btn.state & State_On)
- state = QIcon::On;
- QPixmap pixmap = btn.icon.pixmap(window, btn.iconSize, mode, state);
- int pixmapWidth = pixmap.width() / pixmap.devicePixelRatio();
- int pixmapHeight = pixmap.height() / pixmap.devicePixelRatio();
- contentW += pixmapWidth + QMacStylePrivate::PushButtonContentPadding;
- int iconLeftOffset = freeContentRect.x() + (freeContentRect.width() - contentW) / 2;
- int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmapHeight) / 2;
- QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmapWidth, pixmapHeight);
- QRect visualIconDestRect = visualRect(btn.direction, freeContentRect, iconDestRect);
- proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap);
- int newOffset = iconDestRect.x() + iconDestRect.width()
- + QMacStylePrivate::PushButtonContentPadding - textRect.x();
- textRect.adjust(newOffset, 0, newOffset, 0);
- }
- // Draw the text:
- if (hasText) {
- textRect = visualRect(btn.direction, freeContentRect, textRect);
- proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn.palette,
- (btn.state & State_Enabled), btn.text, QPalette::ButtonText);
- }
+ // Draw the text:
+ if (hasText) {
+ textRect = visualRect(btn.direction, freeContentRect, textRect);
+ proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn.palette,
+ (btn.state & State_Enabled), btn.text, QPalette::ButtonText);
}
}
}
@@ -4161,15 +4142,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
tdi.style = kThemeTabNonFront;
tdi.direction = getTabDirection(tabOpt->shape);
switch (d->aquaSizeConstrain(opt, w)) {
- default:
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
tdi.size = kHIThemeTabSizeNormal;
break;
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
tdi.size = kHIThemeTabSizeSmall;
break;
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
tdi.size = kHIThemeTabSizeMini;
break;
}
@@ -4241,85 +4221,49 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
// HITheme doesn't stretch its tabs. Therefore we have to cheat and do the job ourselves.
if (stretchTabs) {
- HIRect hirect = CGRectMake(0, 0, 23, 23);
+ CGRect cgRect = CGRectMake(0, 0, 23, 23);
QPixmap pm(23, 23);
pm.fill(Qt::transparent);
{
QMacCGContext pmcg(&pm);
- HIThemeDrawTab(&hirect, &tdi, pmcg, kHIThemeOrientationNormal, 0);
+ HIThemeDrawTab(&cgRect, &tdi, pmcg, kHIThemeOrientationNormal, 0);
}
QStyleHelper::drawBorderPixmap(pm, p, tabRect, 7, 7, 7, 7);
} else {
- HIRect hirect = qt_hirectForQRect(tabRect);
- HIThemeDrawTab(&hirect, &tdi, cg, kHIThemeOrientationNormal, 0);
+ CGRect cgRect = tabRect.toCGRect();
+ HIThemeDrawTab(&cgRect, &tdi, cg, kHIThemeOrientationNormal, 0);
}
}
break;
case CE_TabBarTabLabel:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
QStyleOptionTab myTab = *tab;
- ThemeTabDirection ttd = getTabDirection(myTab.shape);
- bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast;
+ const bool verticalTabs = tab->shape == QTabBar::RoundedWest
+ || tab->shape == QTabBar::RoundedEast
+ || tab->shape == QTabBar::TriangularWest
+ || tab->shape == QTabBar::TriangularEast;
// Check to see if we use have the same as the system font
// (QComboMenuItem is internal and should never be seen by the
// outside world, unless they read the source, in which case, it's
// their own fault).
- bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value("QComboMenuItem");
+ const bool nonDefaultFont = p->font() != qt_app_fonts_hash()->value("QComboMenuItem");
if (!myTab.documentMode && (myTab.state & State_Selected) && (myTab.state & State_Active))
if (const auto *tabBar = qobject_cast<const QTabBar *>(w))
if (!tabBar->tabTextColor(tabBar->currentIndex()).isValid())
myTab.palette.setColor(QPalette::WindowText, Qt::white);
- if (verticalTabs || nonDefaultFont || !tab->icon.isNull()
- || !myTab.leftButtonSize.isEmpty() || !myTab.rightButtonSize.isEmpty()) {
- int heightOffset = 0;
- if (verticalTabs) {
- heightOffset = -1;
- } else if (nonDefaultFont) {
- if (p->fontMetrics().height() == myTab.rect.height())
- heightOffset = 2;
- }
- myTab.rect.setHeight(myTab.rect.height() + heightOffset);
-
- QCommonStyle::drawControl(ce, &myTab, p, w);
- } else {
- p->save();
- CGContextSetShouldAntialias(cg, true);
- CGContextSetShouldSmoothFonts(cg, true);
- HIThemeTextInfo tti;
- tti.version = qt_mac_hitheme_version;
- tti.state = tds;
- QColor textColor = myTab.palette.windowText().color();
- CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()),
- static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) };
- CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace());
- CGContextSetFillColor(cg, colorComp);
- switch (d->aquaSizeConstrain(opt, w)) {
- default:
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- tti.fontID = kThemeSystemFont;
- break;
- case QAquaSizeSmall:
- tti.fontID = kThemeSmallSystemFont;
- break;
- case QAquaSizeMini:
- tti.fontID = kThemeMiniSystemFont;
- break;
- }
- tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter;
- tti.verticalFlushness = kHIThemeTextVerticalFlushCenter;
- tti.options = verticalTabs ? kHIThemeTextBoxOptionStronglyVertical : kHIThemeTextBoxOptionNone;
- tti.truncationPosition = kHIThemeTextTruncationNone;
- tti.truncationMaxLines = 1 + myTab.text.count(QLatin1Char('\n'));
- QCFString tabText = qt_mac_removeMnemonics(myTab.text);
- QRect r = myTab.rect.adjusted(0, 0, 0, -1);
- HIRect bounds = qt_hirectForQRect(r);
- HIThemeDrawTextBox(tabText, &bounds, &tti, cg, kHIThemeOrientationNormal);
- p->restore();
+ int heightOffset = 0;
+ if (verticalTabs) {
+ heightOffset = -1;
+ } else if (nonDefaultFont) {
+ if (p->fontMetrics().height() == myTab.rect.height())
+ heightOffset = 2;
}
+ myTab.rect.setHeight(myTab.rect.height() + heightOffset);
+
+ QCommonStyle::drawControl(ce, &myTab, p, w);
}
break;
#endif
@@ -4337,15 +4281,15 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
wdi.titleWidth = opt->rect.width();
wdi.attributes = 0;
- HIRect titleBarRect;
- HIRect tmpRect = qt_hirectForQRect(opt->rect);
+ CGRect titleBarRect;
+ CGRect tmpRect = opt->rect.toCGRect();
{
QCFType<HIShapeRef> titleRegion;
QRect newr = opt->rect.adjusted(0, 0, 2, 0);
HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion);
- ptrHIShapeGetBounds(titleRegion, &tmpRect);
+ HIShapeGetBounds(titleRegion, &tmpRect);
newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y));
- titleBarRect = qt_hirectForQRect(newr);
+ titleBarRect = newr.toCGRect();
}
QMacCGContext cg(p);
HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0);
@@ -4406,53 +4350,65 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
d->drawFocusRing(p, opt->rect, hMargin, vMargin);
break; }
case CE_MenuItem:
+ case CE_MenuHMargin:
+ case CE_MenuVMargin:
case CE_MenuEmptyArea:
+ case CE_MenuTearoff:
+ case CE_MenuScroller:
if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
- p->fillRect(mi->rect, opt->palette.background());
- QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, w);
- int tabwidth = mi->tabWidth;
- int maxpmw = mi->maxIconWidth;
- bool active = mi->state & State_Selected;
- bool enabled = mi->state & State_Enabled;
- HIRect menuRect = qt_hirectForQRect(mi->menuRect);
- HIRect itemRect = qt_hirectForQRect(mi->rect);
- HIThemeMenuItemDrawInfo mdi;
- mdi.version = qt_mac_hitheme_version;
- mdi.itemType = kThemeMenuItemPlain;
- if (!mi->icon.isNull())
- mdi.itemType |= kThemeMenuItemHasIcon;
- if (mi->menuItemType == QStyleOptionMenuItem::SubMenu)
- mdi.itemType |= kThemeMenuItemHierarchical | kThemeMenuItemHierBackground;
- else
- mdi.itemType |= kThemeMenuItemPopUpBackground;
- if (enabled)
- mdi.state = kThemeMenuActive;
- else
- mdi.state = kThemeMenuDisabled;
- if (active)
- mdi.state |= kThemeMenuSelected;
- QRect contentRect;
+ const bool active = mi->state & State_Selected;
+ const QBrush bg = active ? mi->palette.highlight() : mi->palette.background();
+ p->fillRect(mi->rect, bg);
+
+ const QStyleHelper::WidgetSizePolicy widgetSize = d->aquaSizeConstrain(opt, w);
+
+ if (ce == CE_MenuTearoff) {
+ p->setPen(QPen(mi->palette.dark().color(), 1, Qt::DashLine));
+ p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2 - 1,
+ mi->rect.x() + mi->rect.width() - 4,
+ mi->rect.y() + mi->rect.height() / 2 - 1);
+ p->setPen(QPen(mi->palette.light().color(), 1, Qt::DashLine));
+ p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2,
+ mi->rect.x() + mi->rect.width() - 4,
+ mi->rect.y() + mi->rect.height() / 2);
+ } else if (ce == CE_MenuScroller) {
+ const QSize scrollerSize = QSize(10, 8);
+ const int scrollerVOffset = 5;
+ const int left = mi->rect.x() + (mi->rect.width() - scrollerSize.width()) / 2;
+ const int right = left + scrollerSize.width();
+ int top;
+ int bottom;
+ if (opt->state & State_DownArrow) {
+ bottom = mi->rect.y() + scrollerVOffset;
+ top = bottom + scrollerSize.height();
+ } else {
+ bottom = mi->rect.bottom() - scrollerVOffset;
+ top = bottom - scrollerSize.height();
+ }
+ p->save();
+ p->setRenderHint(QPainter::Antialiasing);
+ QPainterPath path;
+ path.moveTo(left, bottom);
+ path.lineTo(right, bottom);
+ path.lineTo((left + right) / 2, top);
+ p->fillPath(path, opt->palette.buttonText());
+ p->restore();
+ } else if (ce != CE_MenuItem) {
+ break;
+ }
+
if (mi->menuItemType == QStyleOptionMenuItem::Separator) {
- // First arg should be &menurect, but wacky stuff happens then.
- HIThemeDrawMenuSeparator(&itemRect, &itemRect, &mdi,
- cg, kHIThemeOrientationNormal);
+ CGColorRef separatorColor = [NSColor quaternaryLabelColor].CGColor;
+ const QRect separatorRect = QRect(mi->rect.left(), mi->rect.center().y(), mi->rect.width(), 2);
+ p->fillRect(separatorRect, qt_mac_toQColor(separatorColor));
break;
- } else {
- HIRect cr;
- bool needAlpha = mi->palette.color(QPalette::Button) == Qt::transparent;
- if (needAlpha) {
- CGContextSaveGState(cg);
- CGContextSetAlpha(cg, 0.0);
- }
- HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi,
- cg, kHIThemeOrientationNormal, &cr);
- if (needAlpha)
- CGContextRestoreGState(cg);
- if (ce == CE_MenuEmptyArea)
- break;
- contentRect = qt_qrectForHIRect(cr);
}
- int xpos = contentRect.x() + 18;
+
+ const int tabwidth = mi->tabWidth;
+ const int maxpmw = mi->maxIconWidth;
+ const bool enabled = mi->state & State_Enabled;
+
+ int xpos = mi->rect.x() + 18;
int checkcol = maxpmw;
if (!enabled)
p->setPen(mi->palette.text().color());
@@ -4466,16 +4422,16 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
checkmarkOpt.initFrom(w);
const int mw = checkcol + macItemFrame;
- const int mh = contentRect.height() + macItemFrame;
- const int xp = contentRect.x() + macItemFrame;
- checkmarkOpt.rect = QRect(xp, contentRect.y() - checkmarkOpt.fontMetrics.descent(), mw, mh);
+ const int mh = mi->rect.height() + macItemFrame;
+ const int xp = mi->rect.x() + macItemFrame;
+ checkmarkOpt.rect = QRect(xp, mi->rect.y() - checkmarkOpt.fontMetrics.descent(), mw, mh);
checkmarkOpt.state |= State_On; // Always on. Never rendered when off.
checkmarkOpt.state.setFlag(State_Selected, active);
checkmarkOpt.state.setFlag(State_Enabled, enabled);
- if (widgetSize == QAquaSizeMini)
+ if (widgetSize == QStyleHelper::SizeMini)
checkmarkOpt.state |= State_Mini;
- else if (widgetSize == QAquaSizeSmall)
+ else if (widgetSize == QStyleHelper::SizeSmall)
checkmarkOpt.state |= State_Small;
// We let drawPrimitive(PE_IndicatorMenuCheckMark) pick the right color
@@ -4498,7 +4454,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QPixmap pixmap = mi->icon.pixmap(window, iconSize, mode);
int pixw = pixmap.width() / pixmap.devicePixelRatio();
int pixh = pixmap.height() / pixmap.devicePixelRatio();
- QRect cr(xpos, contentRect.y(), checkcol, contentRect.height());
+ QRect cr(xpos, mi->rect.y(), checkcol, mi->rect.height());
QRect pmr(0, 0, pixw, pixh);
pmr.moveCenter(cr.center());
p->drawPixmap(pmr.topLeft(), pixmap);
@@ -4510,16 +4466,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
int t = s.indexOf(QLatin1Char('\t'));
int text_flags = Qt::AlignRight | Qt::AlignVCenter | Qt::TextHideMnemonic
| Qt::TextSingleLine | Qt::AlignAbsolute;
- int yPos = contentRect.y();
- if (widgetSize == QAquaSizeMini)
+ int yPos = mi->rect.y();
+ if (widgetSize == QStyleHelper::SizeMini)
yPos += 1;
p->save();
if (t >= 0) {
p->setFont(qt_app_fonts_hash()->value("QMenuItem", p->font()));
- int xp = contentRect.right() - tabwidth - macRightBorder
- - macItemHMargin - macItemFrame + 1;
- p->drawText(xp, yPos, tabwidth, contentRect.height(), text_flags,
- s.mid(t + 1));
+ int xp = mi->rect.right() - tabwidth - macRightBorder - macItemHMargin - macItemFrame + 1;
+ p->drawText(xp, yPos, tabwidth, mi->rect.height(), text_flags, s.mid(t + 1));
s = s.left(t);
}
@@ -4532,73 +4486,21 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// is very, very weak. This makes it stonger.
myFont.setPointSizeF(QFontInfo(mi->font).pointSizeF());
p->setFont(myFont);
- p->drawText(xpos, yPos, contentRect.width() - xm - tabwidth + 1,
- contentRect.height(), text_flags ^ Qt::AlignRight, s);
+ p->drawText(xpos, yPos, mi->rect.width() - xm - tabwidth + 1,
+ mi->rect.height(), text_flags ^ Qt::AlignRight, s);
p->restore();
}
}
break;
- case CE_MenuHMargin:
- case CE_MenuVMargin:
- case CE_MenuTearoff:
- case CE_MenuScroller:
- if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
- p->fillRect(mi->rect, opt->palette.background());
-
- HIRect menuRect = qt_hirectForQRect(mi->menuRect);
- HIRect itemRect = qt_hirectForQRect(mi->rect);
- HIThemeMenuItemDrawInfo mdi;
- mdi.version = qt_mac_hitheme_version;
- if (!(opt->state & State_Enabled))
- mdi.state = kThemeMenuDisabled;
- else if (opt->state & State_Selected)
- mdi.state = kThemeMenuSelected;
- else
- mdi.state = kThemeMenuActive;
- if (ce == CE_MenuScroller) {
- if (opt->state & State_DownArrow)
- mdi.itemType = kThemeMenuItemScrollDownArrow;
- else
- mdi.itemType = kThemeMenuItemScrollUpArrow;
- } else {
- mdi.itemType = kThemeMenuItemPlain;
- }
- HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi,
- cg,
- kHIThemeOrientationNormal, 0);
- if (ce == CE_MenuTearoff) {
- p->setPen(QPen(mi->palette.dark().color(), 1, Qt::DashLine));
- p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2 - 1,
- mi->rect.x() + mi->rect.width() - 4,
- mi->rect.y() + mi->rect.height() / 2 - 1);
- p->setPen(QPen(mi->palette.light().color(), 1, Qt::DashLine));
- p->drawLine(mi->rect.x() + 2, mi->rect.y() + mi->rect.height() / 2,
- mi->rect.x() + mi->rect.width() - 4,
- mi->rect.y() + mi->rect.height() / 2);
- }
- }
- break;
case CE_MenuBarItem:
+ case CE_MenuBarEmptyArea:
if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
- HIRect menuRect = qt_hirectForQRect(mi->menuRect);
- HIRect itemRect = qt_hirectForQRect(mi->rect);
-
const bool selected = (opt->state & State_Selected) && (opt->state & State_Enabled) && (opt->state & State_Sunken);
- if (selected) {
- // Draw a selected menu item background:
- HIThemeMenuItemDrawInfo mdi;
- mdi.version = qt_mac_hitheme_version;
- mdi.state = kThemeMenuSelected;
- mdi.itemType = kThemeMenuItemPlain;
- HIThemeDrawMenuItem(&menuRect, &itemRect, &mdi, cg, kHIThemeOrientationNormal, 0);
- } else {
- // Draw the toolbar background:
- HIThemeMenuBarDrawInfo bdi;
- bdi.version = qt_mac_hitheme_version;
- bdi.state = kThemeMenuBarNormal;
- bdi.attributes = 0;
- HIThemeDrawMenuBarBackground(&menuRect, &bdi, cg, kHIThemeOrientationNormal);
- }
+ const QBrush bg = selected ? mi->palette.highlight() : mi->palette.background();
+ p->fillRect(mi->rect, bg);
+
+ if (ce != CE_MenuBarItem)
+ break;
if (!mi->icon.isNull()) {
int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
@@ -4616,77 +4518,68 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
}
break;
- case CE_MenuBarEmptyArea:
- if (const QStyleOptionMenuItem *mi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
- HIThemeMenuBarDrawInfo bdi;
- bdi.version = qt_mac_hitheme_version;
- bdi.state = kThemeMenuBarNormal;
- bdi.attributes = 0;
- HIRect hirect = qt_hirectForQRect(mi->rect);
- HIThemeDrawMenuBarBackground(&hirect, &bdi, cg,
- kHIThemeOrientationNormal);
- break;
- }
+ case CE_ProgressBarLabel:
+ case CE_ProgressBarGroove:
+ // Do nothing. All done in CE_ProgressBarContents. Only keep these for proxy style overrides.
+ break;
case CE_ProgressBarContents:
if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
- HIThemeTrackDrawInfo tdi;
- tdi.version = qt_mac_hitheme_version;
- tdi.reserved = 0;
- bool isIndeterminate = (pb->minimum == 0 && pb->maximum == 0);
+ QMacAutoReleasePool pool;
+ const bool isIndeterminate = (pb->minimum == 0 && pb->maximum == 0);
const bool vertical = pb->orientation == Qt::Vertical;
const bool inverted = pb->invertedAppearance;
bool reverse = (!vertical && (pb->direction == Qt::RightToLeft));
if (inverted)
reverse = !reverse;
- switch (d->aquaSizeConstrain(opt, w)) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- tdi.kind = !isIndeterminate ? kThemeLargeProgressBar
- : kThemeLargeIndeterminateBar;
- break;
- case QAquaSizeMini:
- case QAquaSizeSmall:
- tdi.kind = !isIndeterminate ? kThemeProgressBar : kThemeIndeterminateBar;
- break;
- }
- tdi.bounds = qt_hirectForQRect(pb->rect);
- tdi.max = pb->maximum;
- tdi.min = pb->minimum;
- tdi.value = pb->progress;
- tdi.attributes = vertical ? 0 : kThemeTrackHorizontal;
+ QRect rect = pb->rect;
+ if (vertical)
+ rect = rect.transposed();
+ const CGRect cgRect = rect.toCGRect();
+
+ const auto aquaSize = d->effectiveAquaSizeConstrain(opt, w);
+ const QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject));
+ QIndeterminateProgressIndicator *ipi = nil;
+ if (isIndeterminate || animation)
+ ipi = static_cast<QIndeterminateProgressIndicator *>(d->cocoaControl({ QCocoaIndeterminateProgressIndicator, aquaSize }));
if (isIndeterminate) {
- if (QProgressStyleAnimation *animation = qobject_cast<QProgressStyleAnimation*>(d->animation(opt->styleObject)))
- tdi.trackInfo.progress.phase = animation->animationStep();
- else if (opt->styleObject)
- d->startAnimation(new QProgressStyleAnimation(d->animateSpeed(QMacStylePrivate::AquaProgressBar), opt->styleObject));
+ // QIndeterminateProgressIndicator derives from NSProgressIndicator. We use a single
+ // instance that we start animating as soon as one of the progress bars is indeterminate.
+ // Since they will be in sync (as it's the case in Cocoa), we just need to draw it with
+ // the right geometry when the animation triggers an update. However, we can't hide it
+ // entirely between frames since that would stop the animation, so we just set its alpha
+ // value to 0. Same if we remove it from its superview. See QIndeterminateProgressIndicator
+ // implementation for details.
+ if (!animation && opt->styleObject) {
+ auto *animation = new QProgressStyleAnimation(d->animateSpeed(QMacStylePrivate::AquaProgressBar), opt->styleObject);
+ // NSProgressIndicator is heavier to draw than the HITheme API, so we reduce the frame rate a couple notches.
+ animation->setFrameRate(QStyleAnimation::FifteenFps);
+ d->startAnimation(animation);
+ [ipi startAnimation];
+ }
+
+ d->setupNSGraphicsContext(cg, NO);
+ d->setupVerticalInvertedXform(cg, reverse, vertical, cgRect);
+ [ipi drawWithFrame:cgRect inView:d->backingStoreNSView];
+ d->restoreNSGraphicsContext(cg);
} else {
- d->stopAnimation(opt->styleObject);
- }
- if (!(pb->state & State_Active))
- tdi.enableState = kThemeTrackInactive;
- else if (!(pb->state & State_Enabled))
- tdi.enableState = kThemeTrackDisabled;
- else
- tdi.enableState = kThemeTrackActive;
- HIThemeOrientation drawOrientation = kHIThemeOrientationNormal;
- if (reverse) {
- if (vertical) {
- drawOrientation = kHIThemeOrientationInverted;
- } else {
- CGContextSaveGState(cg);
- CGContextTranslateCTM(cg, pb->rect.width(), 0);
- CGContextScaleCTM(cg, -1, 1);
+ if (animation) {
+ d->stopAnimation(opt->styleObject);
+ [ipi stopAnimation];
}
+
+ const QCocoaWidget cw = { QCocoaProgressIndicator, aquaSize };
+ auto *pi = static_cast<NSProgressIndicator *>(d->cocoaControl(cw));
+ d->drawNSViewInRect(cw, pi, rect, p, w != nullptr, ^(CGContextRef ctx, const CGRect &rect) {
+ d->setupVerticalInvertedXform(ctx, reverse, vertical, rect);
+ pi.minValue = pb->minimum;
+ pi.maxValue = pb->maximum;
+ pi.doubleValue = pb->progress;
+ [pi drawRect:rect];
+ });
}
- HIThemeDrawTrack(&tdi, 0, cg, drawOrientation);
- if (reverse && !vertical)
- CGContextRestoreGState(cg);
}
break;
- case CE_ProgressBarLabel:
- case CE_ProgressBarGroove:
- break;
case CE_SizeGrip: {
if (w && w->testAttribute(Qt::WA_MacOpaqueSizeGrip)) {
HIThemeGrowBoxDrawInfo gdi;
@@ -4695,22 +4588,20 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
gdi.kind = kHIThemeGrowBoxKindNormal;
gdi.direction = kThemeGrowRight | kThemeGrowDown;
gdi.size = kHIThemeGrowBoxSizeNormal;
- HIPoint pt = CGPointMake(opt->rect.x(), opt->rect.y());
+ CGPoint pt = CGPointMake(opt->rect.x(), opt->rect.y());
HIThemeDrawGrowBox(&pt, &gdi, cg, kHIThemeOrientationNormal);
} else {
// It isn't possible to draw a transparent size grip with the
// native API, so we do it ourselves here.
- const bool metal = qt_mac_is_metal(w);
- QPen lineColor = metal ? QColor(236, 236, 236) : QColor(82, 82, 82, 192);
- QPen metalHighlight = QColor(5, 5, 5, 192);
+ QPen lineColor = QColor(82, 82, 82, 192);
lineColor.setWidth(1);
p->save();
p->setRenderHint(QPainter::Antialiasing);
p->setPen(lineColor);
const Qt::LayoutDirection layoutDirection = w ? w->layoutDirection() : qApp->layoutDirection();
- const int NumLines = metal ? 4 : 3;
+ const int NumLines = 3;
for (int l = 0; l < NumLines; ++l) {
- const int offset = (l * 4 + (metal ? 2 : 3));
+ const int offset = (l * 4 + 3);
QPoint start, end;
if (layoutDirection == Qt::LeftToRight) {
start = QPoint(opt->rect.width() - offset, opt->rect.height() - 1);
@@ -4720,13 +4611,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
end = QPoint(1, opt->rect.height() - offset);
}
p->drawLine(start, end);
- if (metal) {
- p->setPen(metalHighlight);
- p->setRenderHint(QPainter::Antialiasing, false);
- p->drawLine(start + QPoint(0, -1), end + QPoint(0, -1));
- p->setRenderHint(QPainter::Antialiasing, true);
- p->setPen(lineColor);
- }
}
p->restore();
}
@@ -4738,8 +4622,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
sdi.version = qt_mac_hitheme_version;
sdi.state = tds;
sdi.adornment = kHIThemeSplitterAdornmentMetal;
- HIRect hirect = qt_hirectForQRect(opt->rect);
- HIThemeDrawPaneSplitter(&hirect, &sdi, cg, kHIThemeOrientationNormal);
+ CGRect cgRect = opt->rect.toCGRect();
+ HIThemeDrawPaneSplitter(&cgRect, &sdi, cg, kHIThemeOrientationNormal);
} else {
QPen oldPen = p->pen();
p->setPen(opt->palette.dark().color());
@@ -4804,7 +4688,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
bool isEndOfUnifiedArea = !isInMacUnifiedToolbarArea(w->window()->windowHandle(), windowToolbarEnd.y() + 1);
if (isEndOfUnifiedArea) {
SInt32 margin;
- GetThemeMetric(kThemeMetricSeparatorSize, &margin);
+ margin = qt_mac_aqua_get_metric(SeparatorSize);
CGRect separatorRect = CGRectMake(opt->rect.left(), opt->rect.bottom(), opt->rect.width(), margin);
HIThemeSeparatorDrawInfo separatorDrawInfo;
separatorDrawInfo.version = 0;
@@ -4867,7 +4751,7 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
{
Q_D(const QMacStyle);
QRect rect;
- int controlSize = getControlSize(opt, widget);
+ const int controlSize = getControlSize(opt, widget);
switch (sr) {
case SE_ItemViewItemText:
@@ -4889,8 +4773,8 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
// the focus 'shadow' will be inside. Adjust the content rect likewise.
HIThemeButtonDrawInfo bdi;
d->initHIThemePushButton(btn, widget, d->getDrawState(opt->state), &bdi);
- HIRect contentRect = d->pushButtonContentBounds(btn, &bdi);
- rect = qt_qrectForHIRect(contentRect);
+ CGRect contentRect = d->pushButtonContentBounds(btn, &bdi);
+ rect = QRectF::fromCGRect(contentRect).toRect();
}
break;
case SE_HeaderLabel: {
@@ -4919,7 +4803,7 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
rect = opt->rect;
break;
case SE_TreeViewDisclosureItem: {
- HIRect inRect = CGRectMake(opt->rect.x(), opt->rect.y(),
+ CGRect inRect = CGRectMake(opt->rect.x(), opt->rect.y(),
opt->rect.width(), opt->rect.height());
HIThemeButtonDrawInfo bdi;
bdi.version = qt_mac_hitheme_version;
@@ -4927,12 +4811,12 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
bdi.kind = kThemeDisclosureButton;
bdi.value = kThemeDisclosureRight;
bdi.adornment = kThemeAdornmentNone;
- HIRect contentRect;
+ CGRect contentRect;
HIThemeGetButtonContentBounds(&inRect, &bdi, &contentRect);
QCFType<HIShapeRef> shape;
- HIRect outRect;
+ CGRect outRect;
HIThemeGetButtonShape(&inRect, &bdi, &shape);
- ptrHIShapeGetBounds(shape, &outRect);
+ HIShapeGetBounds(shape, &outRect);
rect = QRect(int(outRect.origin.x + DisclosureOffset), int(outRect.origin.y),
int(contentRect.origin.x - outRect.origin.x + DisclosureOffset),
int(outRect.size.height));
@@ -5080,9 +4964,9 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
case SE_CheckBoxLayoutItem:
rect = opt->rect;
- if (controlSize == QAquaSizeLarge) {
+ if (controlSize == QStyleHelper::SizeLarge) {
setLayoutItemMargins(+2, +3, -9, -4, &rect, opt->direction);
- } else if (controlSize == QAquaSizeSmall) {
+ } else if (controlSize == QStyleHelper::SizeSmall) {
setLayoutItemMargins(+1, +5, 0 /* fix */, -6, &rect, opt->direction);
} else {
setLayoutItemMargins(0, +7, 0 /* fix */, -6, &rect, opt->direction);
@@ -5099,9 +4983,9 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
#endif
{
rect = opt->rect;
- if (controlSize == QAquaSizeLarge) {
+ if (controlSize == QStyleHelper::SizeLarge) {
rect.adjust(+3, +2, -3, -4);
- } else if (controlSize == QAquaSizeSmall) {
+ } else if (controlSize == QStyleHelper::SizeSmall) {
setLayoutItemMargins(+2, +1, -3, -4, &rect, opt->direction);
} else {
setLayoutItemMargins(+1, 0, -2, 0, &rect, opt->direction);
@@ -5129,9 +5013,9 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break; // leave rect alone
}
rect = opt->rect;
- if (controlSize == QAquaSizeLarge) {
+ if (controlSize == QStyleHelper::SizeLarge) {
rect.adjust(+6, +4, -6, -8);
- } else if (controlSize == QAquaSizeSmall) {
+ } else if (controlSize == QStyleHelper::SizeSmall) {
rect.adjust(+5, +4, -5, -6);
} else {
rect.adjust(+1, 0, -1, -2);
@@ -5139,10 +5023,10 @@ QRect QMacStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
case SE_RadioButtonLayoutItem:
rect = opt->rect;
- if (controlSize == QAquaSizeLarge) {
+ if (controlSize == QStyleHelper::SizeLarge) {
setLayoutItemMargins(+2, +2 /* SHOULD BE +3, done for alignment */,
0, -4 /* SHOULD BE -3, done for alignment */, &rect, opt->direction);
- } else if (controlSize == QAquaSizeSmall) {
+ } else if (controlSize == QStyleHelper::SizeSmall) {
rect.adjust(0, +6, 0 /* fix */, -5);
} else {
rect.adjust(0, +6, 0 /* fix */, -7);
@@ -5342,8 +5226,23 @@ static inline void drawToolbarButtonArrow(const QRect &toolButtonRect, ThemeDraw
padi.state = tds;
padi.orientation = kThemeArrowDown;
padi.size = kThemeArrow7pt;
- HIRect hirect = qt_hirectForQRect(arrowRect);
- HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal);
+ CGRect cgRect = arrowRect.toCGRect();
+ HIThemeDrawPopupArrow(&cgRect, &padi, cg, kHIThemeOrientationNormal);
+}
+
+void QMacStylePrivate::setupNSGraphicsContext(CGContextRef cg, bool flipped) const
+{
+ CGContextSaveGState(cg);
+ [NSGraphicsContext saveGraphicsState];
+
+ [NSGraphicsContext setCurrentContext:
+ [NSGraphicsContext graphicsContextWithCGContext:cg flipped:flipped]];
+}
+
+void QMacStylePrivate::restoreNSGraphicsContext(CGContextRef cg) const
+{
+ [NSGraphicsContext restoreGraphicsState];
+ CGContextRestoreGState(cg);
}
void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p,
@@ -5356,389 +5255,328 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
QStyleHelper::styleObjectWindow(opt->styleObject);
const_cast<QMacStylePrivate *>(d)->resolveCurrentNSView(window);
switch (cc) {
- case CC_Slider:
case CC_ScrollBar:
- if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- HIThemeTrackDrawInfo tdi;
- d->getSliderInfo(cc, slider, &tdi, widget);
- if (slider->state & State_Sunken) {
- if (cc == CC_Slider) {
- if (slider->activeSubControls == SC_SliderHandle)
- tdi.trackInfo.slider.pressState = kThemeThumbPressed;
- else if (slider->activeSubControls == SC_SliderGroove)
- tdi.trackInfo.slider.pressState = kThemeLeftTrackPressed;
- } else {
- if (slider->activeSubControls == SC_ScrollBarSubLine
- || slider->activeSubControls == SC_ScrollBarAddLine) {
- // This test looks complex but it basically boils down
- // to the following: The "RTL look" on the mac also
- // changed the directions of the controls, that's not
- // what people expect (an arrow is an arrow), so we
- // kind of fake and say the opposite button is hit.
- // This works great, up until 10.4 which broke the
- // scroll bars, so I also have actually do something
- // similar when I have an upside down scroll bar
- // because on Tiger I only "fake" the reverse stuff.
- bool reverseHorizontal = (slider->direction == Qt::RightToLeft
- && slider->orientation == Qt::Horizontal);
-
- if ((reverseHorizontal
- && slider->activeSubControls == SC_ScrollBarAddLine)
- || (!reverseHorizontal
- && slider->activeSubControls == SC_ScrollBarSubLine)) {
- tdi.trackInfo.scrollbar.pressState = kThemeRightInsideArrowPressed
- | kThemeLeftOutsideArrowPressed;
- } else {
- tdi.trackInfo.scrollbar.pressState = kThemeLeftInsideArrowPressed
- | kThemeRightOutsideArrowPressed;
- }
- } else if (slider->activeSubControls == SC_ScrollBarAddPage) {
- tdi.trackInfo.scrollbar.pressState = kThemeRightTrackPressed;
- } else if (slider->activeSubControls == SC_ScrollBarSubPage) {
- tdi.trackInfo.scrollbar.pressState = kThemeLeftTrackPressed;
- } else if (slider->activeSubControls == SC_ScrollBarSlider) {
- tdi.trackInfo.scrollbar.pressState = kThemeThumbPressed;
- }
- }
- }
- HIRect macRect;
- bool tracking = slider->sliderPosition == slider->sliderValue;
- if (!tracking) {
- // Small optimization, the same as q->subControlRect
- QCFType<HIShapeRef> shape;
- HIThemeGetTrackThumbShape(&tdi, &shape);
- ptrHIShapeGetBounds(shape, &macRect);
- tdi.value = slider->sliderValue;
- }
+ if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- // Remove controls from the scroll bar if it is to short to draw them correctly.
- // This is done in two stages: first the thumb indicator is removed when it is
- // no longer possible to move it, second the up/down buttons are removed when
- // there is not enough space for them.
- if (cc == CC_ScrollBar) {
- if (opt && opt->styleObject && !QMacStylePrivate::scrollBars.contains(opt->styleObject))
- QMacStylePrivate::scrollBars.append(QPointer<QObject>(opt->styleObject));
- const int scrollBarLength = (slider->orientation == Qt::Horizontal)
- ? slider->rect.width() : slider->rect.height();
- const QMacStyle::WidgetSizePolicy sizePolicy = widgetSizePolicy(widget, opt);
- if (scrollBarLength < scrollButtonsCutoffSize(thumbIndicatorCutoff, sizePolicy))
- tdi.attributes &= ~kThemeTrackShowThumb;
- if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, sizePolicy))
- tdi.enableState = kThemeTrackNothingToScroll;
- } else {
- if (!(slider->subControls & SC_SliderHandle))
- tdi.attributes &= ~kThemeTrackShowThumb;
- if (!(slider->subControls & SC_SliderGroove))
- tdi.attributes |= kThemeTrackHideTrack;
- }
+ const bool isHorizontal = sb->orientation == Qt::Horizontal;
- const bool isHorizontal = slider->orientation == Qt::Horizontal;
+ if (opt && opt->styleObject && !QMacStylePrivate::scrollBars.contains(opt->styleObject))
+ QMacStylePrivate::scrollBars.append(QPointer<QObject>(opt->styleObject));
- if (cc == CC_ScrollBar && proxy()->styleHint(SH_ScrollBar_Transient, opt, widget)) {
- bool wasActive = false;
- CGFloat opacity = 0.0;
- CGFloat expandScale = 1.0;
- CGFloat expandOffset = -1.0;
- bool shouldExpand = false;
- const CGFloat maxExpandScale = tdi.kind == kThemeSmallScrollBar ? 11.0 / 7.0 : 13.0 / 9.0;
-
- if (QObject *styleObject = opt->styleObject) {
- int oldPos = styleObject->property("_q_stylepos").toInt();
- int oldMin = styleObject->property("_q_stylemin").toInt();
- int oldMax = styleObject->property("_q_stylemax").toInt();
- QRect oldRect = styleObject->property("_q_stylerect").toRect();
- QStyle::State oldState = static_cast<QStyle::State>(styleObject->property("_q_stylestate").value<QStyle::State::Int>());
- uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt();
-
- // a scrollbar is transient when the scrollbar itself and
- // its sibling are both inactive (ie. not pressed/hovered/moved)
- bool transient = !opt->activeSubControls && !(slider->state & State_On);
-
- if (!transient ||
- oldPos != slider->sliderPosition ||
- oldMin != slider->minimum ||
- oldMax != slider->maximum ||
- oldRect != slider->rect ||
- oldState != slider->state ||
- oldActiveControls != slider->activeSubControls) {
-
- // if the scrollbar is transient or its attributes, geometry or
- // state has changed, the opacity is reset back to 100% opaque
- opacity = 1.0;
-
- styleObject->setProperty("_q_stylepos", slider->sliderPosition);
- styleObject->setProperty("_q_stylemin", slider->minimum);
- styleObject->setProperty("_q_stylemax", slider->maximum);
- styleObject->setProperty("_q_stylerect", slider->rect);
- styleObject->setProperty("_q_stylestate", static_cast<QStyle::State::Int>(slider->state));
- styleObject->setProperty("_q_stylecontrols", static_cast<uint>(slider->activeSubControls));
-
- QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject));
- if (transient) {
- if (!anim) {
- anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating, styleObject);
- d->startAnimation(anim);
- } else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) {
- // the scrollbar was already fading out while the
- // state changed -> restart the fade out animation
- anim->setCurrentTime(0);
- }
- } else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
- d->stopAnimation(styleObject);
+ static const CGFloat knobWidths[] = { 7.0, 5.0, 5.0 };
+ static const CGFloat expandedKnobWidths[] = { 11.0, 9.0, 9.0 };
+ const auto cocoaSize = d->effectiveAquaSizeConstrain(opt, widget);
+ const CGFloat maxExpandScale = expandedKnobWidths[cocoaSize] / knobWidths[cocoaSize];
+
+ const bool isTransient = proxy()->styleHint(SH_ScrollBar_Transient, opt, widget);
+ if (!isTransient)
+ d->stopAnimation(opt->styleObject);
+ bool wasActive = false;
+ CGFloat opacity = 0.0;
+ CGFloat expandScale = 1.0;
+ CGFloat expandOffset = 0.0;
+ bool shouldExpand = false;
+
+ if (QObject *styleObject = opt->styleObject) {
+ const int oldPos = styleObject->property("_q_stylepos").toInt();
+ const int oldMin = styleObject->property("_q_stylemin").toInt();
+ const int oldMax = styleObject->property("_q_stylemax").toInt();
+ const QRect oldRect = styleObject->property("_q_stylerect").toRect();
+ const QStyle::State oldState = static_cast<QStyle::State>(styleObject->property("_q_stylestate").value<QStyle::State::Int>());
+ const uint oldActiveControls = styleObject->property("_q_stylecontrols").toUInt();
+
+ // a scrollbar is transient when the scrollbar itself and
+ // its sibling are both inactive (ie. not pressed/hovered/moved)
+ const bool transient = isTransient && !opt->activeSubControls && !(sb->state & State_On);
+
+ if (!transient ||
+ oldPos != sb->sliderPosition ||
+ oldMin != sb->minimum ||
+ oldMax != sb->maximum ||
+ oldRect != sb->rect ||
+ oldState != sb->state ||
+ oldActiveControls != sb->activeSubControls) {
+
+ // if the scrollbar is transient or its attributes, geometry or
+ // state has changed, the opacity is reset back to 100% opaque
+ opacity = 1.0;
+
+ styleObject->setProperty("_q_stylepos", sb->sliderPosition);
+ styleObject->setProperty("_q_stylemin", sb->minimum);
+ styleObject->setProperty("_q_stylemax", sb->maximum);
+ styleObject->setProperty("_q_stylerect", sb->rect);
+ styleObject->setProperty("_q_stylestate", static_cast<QStyle::State::Int>(sb->state));
+ styleObject->setProperty("_q_stylecontrols", static_cast<uint>(sb->activeSubControls));
+
+ QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject));
+ if (transient) {
+ if (!anim) {
+ anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Deactivating, styleObject);
+ d->startAnimation(anim);
+ } else if (anim->mode() == QScrollbarStyleAnimation::Deactivating) {
+ // the scrollbar was already fading out while the
+ // state changed -> restart the fade out animation
+ anim->setCurrentTime(0);
}
+ } else if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
+ d->stopAnimation(styleObject);
}
+ }
- QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject));
- if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
- // once a scrollbar was active (hovered/pressed), it retains
- // the active look even if it's no longer active while fading out
- if (oldActiveControls)
- anim->setActive(true);
+ QScrollbarStyleAnimation *anim = qobject_cast<QScrollbarStyleAnimation *>(d->animation(styleObject));
+ if (anim && anim->mode() == QScrollbarStyleAnimation::Deactivating) {
+ // once a scrollbar was active (hovered/pressed), it retains
+ // the active look even if it's no longer active while fading out
+ if (oldActiveControls)
+ anim->setActive(true);
- wasActive = anim->wasActive();
- opacity = anim->currentValue();
- }
+ wasActive = anim->wasActive();
+ opacity = anim->currentValue();
+ }
- shouldExpand = (opt->activeSubControls || wasActive);
- if (shouldExpand) {
- if (!anim && !oldActiveControls) {
- // Start expand animation only once and when entering
- anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating, styleObject);
- d->startAnimation(anim);
- }
- if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) {
- expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue();
- expandOffset = 5.5 * anim->currentValue() - 1;
- } else {
- // Keep expanded state after the animation ends, and when fading out
- expandScale = maxExpandScale;
- expandOffset = 4.5;
- }
+ shouldExpand = isTransient && (opt->activeSubControls || wasActive);
+ if (shouldExpand) {
+ if (!anim && !oldActiveControls) {
+ // Start expand animation only once and when entering
+ anim = new QScrollbarStyleAnimation(QScrollbarStyleAnimation::Activating, styleObject);
+ d->startAnimation(anim);
+ }
+ if (anim && anim->mode() == QScrollbarStyleAnimation::Activating) {
+ expandScale = 1.0 + (maxExpandScale - 1.0) * anim->currentValue();
+ expandOffset = 5.5 * (1.0 - anim->currentValue());
+ } else {
+ // Keep expanded state after the animation ends, and when fading out
+ expandScale = maxExpandScale;
+ expandOffset = 0.0;
}
}
+ }
+
+ d->setupNSGraphicsContext(cg, NO /* flipped */);
- CGContextSaveGState(cg);
- [NSGraphicsContext saveGraphicsState];
+ const QCocoaWidget cw(isHorizontal ? QCocoaHorizontalScroller : QCocoaVerticalScroller, cocoaSize);
+ NSScroller *scroller = static_cast<NSScroller *>(d->cocoaControl(cw));
- [NSGraphicsContext setCurrentContext:[NSGraphicsContext
- graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]];
- NSScroller *scroller = isHorizontal ? d->horizontalScroller : d-> verticalScroller;
- // mac os behaviour: as soon as one color channel is >= 128,
- // the bg is considered bright, scroller is dark
+ if (isTransient) {
+ // macOS behavior: as soon as one color channel is >= 128,
+ // the background is considered bright, scroller is dark.
const QColor bgColor = QStyleHelper::backgroundColor(opt->palette, widget);
- const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 &&
- bgColor.blue() < 128;
- if (isDarkBg)
- [scroller setKnobStyle:NSScrollerKnobStyleLight];
- else
- [scroller setKnobStyle:NSScrollerKnobStyleDefault];
+ const bool hasDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128;
+ scroller.knobStyle = hasDarkBg? NSScrollerKnobStyleLight : NSScrollerKnobStyleDark;
+ } else {
+ scroller.knobStyle = NSScrollerKnobStyleDefault;
+ }
- [scroller setControlSize:(tdi.kind == kThemeSmallScrollBar ? NSMiniControlSize
- : NSRegularControlSize)];
- [scroller setBounds:NSMakeRect(0, 0, slider->rect.width(), slider->rect.height())];
- [scroller setScrollerStyle:NSScrollerStyleOverlay];
+ scroller.scrollerStyle = isTransient ? NSScrollerStyleOverlay : NSScrollerStyleLegacy;
+ if (!setupScroller(scroller, sb))
+ break;
+
+ if (isTransient) {
CGContextBeginTransparencyLayer(cg, NULL);
CGContextSetAlpha(cg, opacity);
+ }
- // Draw the track when hovering
- if (opt->activeSubControls || wasActive) {
- NSRect rect = [scroller bounds];
- if (shouldExpand) {
- if (isHorizontal)
- rect.origin.y += 4.5 - expandOffset;
- else
- rect.origin.x += 4.5 - expandOffset;
- }
- [scroller drawKnobSlotInRect:rect highlight:YES];
- }
-
- const qreal length = slider->maximum - slider->minimum + slider->pageStep;
- const qreal proportion = slider->pageStep / length;
- qreal value = (slider->sliderValue - slider->minimum) / length;
- if (isHorizontal && slider->direction == Qt::RightToLeft)
- value = 1.0 - value - proportion;
-
- [scroller setKnobProportion:1.0];
-
- const int minKnobWidth = 26;
+ // Draw the track when hovering. Expand by shifting the track rect.
+ if (!isTransient || opt->activeSubControls || wasActive) {
+ CGRect trackRect = scroller.bounds;
+ if (isHorizontal)
+ trackRect.origin.y += expandOffset;
+ else
+ trackRect.origin.x += expandOffset;
+ [scroller drawKnobSlotInRect:trackRect highlight:NO];
+ }
- if (isHorizontal) {
- const qreal plannedWidth = proportion * slider->rect.width();
- const qreal width = qMax<qreal>(minKnobWidth, plannedWidth);
- const qreal totalWidth = slider->rect.width() + plannedWidth - width;
- [scroller setFrame:NSMakeRect(0, 0, width, slider->rect.height())];
- if (shouldExpand) {
- CGContextScaleCTM(cg, 1, expandScale);
- CGContextTranslateCTM(cg, value * totalWidth, -expandOffset);
- } else {
- CGContextTranslateCTM(cg, value * totalWidth, 1);
- }
- } else {
- const qreal plannedHeight = proportion * slider->rect.height();
- const qreal height = qMax<qreal>(minKnobWidth, plannedHeight);
- const qreal totalHeight = slider->rect.height() + plannedHeight - height;
- [scroller setFrame:NSMakeRect(0, 0, slider->rect.width(), height)];
- if (shouldExpand) {
- CGContextScaleCTM(cg, expandScale, 1);
- CGContextTranslateCTM(cg, -expandOffset, value * totalHeight);
- } else {
- CGContextTranslateCTM(cg, 1, value * totalHeight);
- }
- }
- if (length > 0.0) {
- [scroller layout];
+ if (shouldExpand) {
+ // -[NSScroller drawKnob] is not useful here because any scaling applied
+ // will only be used to draw the hi-DPI artwork. And even if did scale,
+ // the stretched knob would look wrong, actually. So we need to draw the
+ // scroller manually when it's being hovered.
+ const CGFloat scrollerWidth = [NSScroller scrollerWidthForControlSize:scroller.controlSize scrollerStyle:scroller.scrollerStyle];
+ const CGFloat knobWidth = knobWidths[cocoaSize] * expandScale;
+ // Cocoa can help get the exact knob length in the current orientation
+ const CGRect scrollerKnobRect = CGRectInset([scroller rectForPart:NSScrollerKnob], 1, 1);
+ const CGFloat knobLength = isHorizontal ? scrollerKnobRect.size.width : scrollerKnobRect.size.height;
+ const CGFloat knobPos = isHorizontal ? scrollerKnobRect.origin.x : scrollerKnobRect.origin.y;
+ const CGFloat knobOffset = qRound((scrollerWidth + expandOffset - knobWidth) / 2.0);
+ const CGFloat knobRadius = knobWidth / 2.0;
+ CGRect knobRect;
+ if (isHorizontal)
+ knobRect = CGRectMake(knobPos, knobOffset, knobLength, knobWidth);
+ else
+ knobRect = CGRectMake(knobOffset, knobPos, knobWidth, knobLength);
+ QCFType<CGPathRef> knobPath = CGPathCreateWithRoundedRect(knobRect, knobRadius, knobRadius, nullptr);
+ CGContextAddPath(cg, knobPath);
+ CGContextSetAlpha(cg, 0.5);
+ CGContextSetFillColorWithColor(cg, NSColor.blackColor.CGColor);
+ CGContextFillPath(cg);
+ } else {
+ [scroller drawKnob];
+
+ if (!isTransient && opt->activeSubControls) {
+ // The knob should appear darker (going from 0.76 down to 0.49).
+ // But no blending mode can help darken enough in a single pass,
+ // so we resort to drawing the knob twice with a small help from
+ // blending. This brings the gray level to a close enough 0.53.
+ CGContextSetBlendMode(cg, kCGBlendModePlusDarker);
[scroller drawKnob];
}
+ }
+ if (isTransient)
CGContextEndTransparencyLayer(cg);
- [NSGraphicsContext restoreGraphicsState];
- CGContextRestoreGState(cg);
- } else {
- d->stopAnimation(opt->styleObject);
-
- if (cc == CC_Slider) {
- // Fix min and max positions. (See also getSliderInfo()
- // for the slider values adjustments.)
- // HITheme seems to have forgotten how to render
- // a slide at those positions, leaving a gap between
- // the knob and the ends of the track.
- // We fix this by rendering the track first, and then
- // the knob on top. However, in order to not clip the
- // knob, we reduce the the drawing rect for the track.
- HIRect bounds = tdi.bounds;
- if (isHorizontal) {
- tdi.bounds.size.width -= 2;
- tdi.bounds.origin.x += 1;
- if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward)
- tdi.bounds.origin.y -= 2;
- else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward)
- tdi.bounds.origin.y += 3;
- } else {
- tdi.bounds.size.height -= 2;
- tdi.bounds.origin.y += 1;
- if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right
- tdi.bounds.origin.x -= 4;
- else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left
- tdi.bounds.origin.x += 2;
- }
+ d->restoreNSGraphicsContext(cg);
+ }
+ break;
+ case CC_Slider:
+ if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
+ const bool isHorizontal = slider->orientation == Qt::Horizontal;
- // Yosemite demands its blue progress track when no tickmarks are present
- if (!(slider->subControls & SC_SliderTickmarks)) {
- QCocoaWidgetKind sliderKind = slider->orientation == Qt::Horizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider;
- QCocoaWidget cw = QCocoaWidget(sliderKind, QAquaSizeLarge);
- NSSlider *sl = (NSSlider *)d->cocoaControl(cw);
- sl.minValue = slider->minimum;
- sl.maxValue = slider->maximum;
- sl.intValue = slider->sliderValue;
- sl.enabled = slider->state & QStyle::State_Enabled;
- d->drawNSViewInRect(cw, sl, opt->rect, p, widget != 0, ^(NSRect rect, CGContextRef ctx) {
- const bool isSierraOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra;
- if (slider->upsideDown) {
- if (isHorizontal) {
- CGContextTranslateCTM(ctx, rect.size.width, 0);
- CGContextScaleCTM(ctx, -1, 1);
- }
- } else if (!isHorizontal && !isSierraOrLater) {
- CGContextTranslateCTM(ctx, 0, rect.size.height);
- CGContextScaleCTM(ctx, 1, -1);
- }
- const bool shouldFlip = isHorizontal || (slider->upsideDown && isSierraOrLater);
- [sl.cell drawBarInside:NSRectFromCGRect(tdi.bounds) flipped:shouldFlip];
- // No need to restore the CTM later, the context has been saved
- // and will be restored at the end of drawNSViewInRect()
- });
- tdi.attributes |= kThemeTrackHideTrack;
- } else {
- tdi.attributes &= ~(kThemeTrackShowThumb | kThemeTrackHasFocus);
- HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg,
- kHIThemeOrientationNormal);
- tdi.attributes |= kThemeTrackHideTrack | kThemeTrackShowThumb;
- }
- tdi.bounds = bounds;
+ HIThemeTrackDrawInfo tdi;
+ d->getSliderInfo(cc, slider, &tdi, widget);
+ if (slider->state & State_Sunken) {
+ if (cc == CC_Slider) {
+ if (slider->activeSubControls == SC_SliderHandle)
+ tdi.trackInfo.slider.pressState = kThemeThumbPressed;
+ else if (slider->activeSubControls == SC_SliderGroove)
+ tdi.trackInfo.slider.pressState = kThemeLeftTrackPressed;
}
+ }
+ CGRect macRect;
+ bool tracking = slider->sliderPosition == slider->sliderValue;
+ if (!tracking) {
+ // Small optimization, the same as q->subControlRect
+ QCFType<HIShapeRef> shape;
+ HIThemeGetTrackThumbShape(&tdi, &shape);
+ HIShapeGetBounds(shape, &macRect);
+ tdi.value = slider->sliderValue;
+ }
- if (cc == CC_Slider && slider->subControls & SC_SliderTickmarks) {
-
- HIRect bounds;
- // As part of fixing the min and max positions,
- // we need to adjust the tickmarks as well
- bounds = tdi.bounds;
- if (slider->orientation == Qt::Horizontal) {
- tdi.bounds.size.width += 2;
- tdi.bounds.origin.x -= 1;
- if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward)
- tdi.bounds.origin.y -= 2;
- } else {
- tdi.bounds.size.height += 3;
- tdi.bounds.origin.y -= 3;
- tdi.bounds.origin.y += 1;
- if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left
- tdi.bounds.origin.x -= 2;
- }
+ if (!(slider->subControls & SC_SliderHandle))
+ tdi.attributes &= ~kThemeTrackShowThumb;
+ if (!(slider->subControls & SC_SliderGroove))
+ tdi.attributes |= kThemeTrackHideTrack;
+
+ // Fix min and max positions. (See also getSliderInfo()
+ // for the slider values adjustments.)
+ // HITheme seems to have forgotten how to render
+ // a slide at those positions, leaving a gap between
+ // the knob and the ends of the track.
+ // We fix this by rendering the track first, and then
+ // the knob on top. However, in order to not clip the
+ // knob, we reduce the the drawing rect for the track.
+ CGRect bounds = tdi.bounds;
+ if (isHorizontal) {
+ tdi.bounds.size.width -= 2;
+ tdi.bounds.origin.x += 1;
+ if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward)
+ tdi.bounds.origin.y -= 2;
+ else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward)
+ tdi.bounds.origin.y += 3;
+ } else {
+ tdi.bounds.size.height -= 2;
+ tdi.bounds.origin.y += 1;
+ if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right
+ tdi.bounds.origin.x -= 4;
+ else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left
+ tdi.bounds.origin.x += 2;
+ }
- if (qt_mac_is_metal(widget)) {
- if (tdi.enableState == kThemeTrackInactive)
- tdi.enableState = kThemeTrackActive; // Looks more Cocoa-like
- }
- int interval = slider->tickInterval;
- if (interval == 0) {
- interval = slider->pageStep;
- if (interval == 0)
- interval = slider->singleStep;
- if (interval == 0)
- interval = 1;
- }
- int numMarks = 1 + ((slider->maximum - slider->minimum) / interval);
-
- if (tdi.trackInfo.slider.thumbDir == kThemeThumbPlain) {
- // They asked for both, so we'll give it to them.
- tdi.trackInfo.slider.thumbDir = kThemeThumbDownward;
- HIThemeDrawTrackTickMarks(&tdi, numMarks,
- cg,
- kHIThemeOrientationNormal);
- tdi.trackInfo.slider.thumbDir = kThemeThumbUpward;
- // 10.10 and above need a slight shift
- if (slider->orientation == Qt::Vertical)
- tdi.bounds.origin.x -= 2;
- HIThemeDrawTrackTickMarks(&tdi, numMarks,
- cg,
- kHIThemeOrientationNormal);
- // Reset to plain thumb to be drawn further down
- tdi.trackInfo.slider.thumbDir = kThemeThumbPlain;
- } else {
- HIThemeDrawTrackTickMarks(&tdi, numMarks,
- cg,
- kHIThemeOrientationNormal);
- }
+ // Yosemite demands its blue progress track when no tickmarks are present
+ if (!(slider->subControls & SC_SliderTickmarks)) {
+ QCocoaWidgetKind sliderKind = slider->orientation == Qt::Horizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider;
+ QCocoaWidget cw = QCocoaWidget(sliderKind, QStyleHelper::SizeLarge);
+ NSSlider *sl = (NSSlider *)d->cocoaControl(cw);
+ sl.minValue = slider->minimum;
+ sl.maxValue = slider->maximum;
+ sl.intValue = slider->sliderValue;
+ sl.enabled = slider->state & QStyle::State_Enabled;
+ d->drawNSViewInRect(cw, sl, opt->rect, p, widget != 0, ^(CGContextRef ctx, const CGRect &rect) {
+ const bool isSierraOrLater = QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSSierra;
+ if (slider->upsideDown) {
+ if (isHorizontal) {
+ CGContextTranslateCTM(ctx, rect.size.width, 0);
+ CGContextScaleCTM(ctx, -1, 1);
+ }
+ } else if (!isHorizontal && !isSierraOrLater) {
+ CGContextTranslateCTM(ctx, 0, rect.size.height);
+ CGContextScaleCTM(ctx, 1, -1);
+ }
+ const bool shouldFlip = isHorizontal || (slider->upsideDown && isSierraOrLater);
+ [sl.cell drawBarInside:NSRectFromCGRect(tdi.bounds) flipped:shouldFlip];
+ // No need to restore the CTM later, the context has been saved
+ // and will be restored at the end of drawNSViewInRect()
+ });
+ tdi.attributes |= kThemeTrackHideTrack;
+
+ tdi.bounds = bounds;
+ }
- tdi.bounds = bounds;
+ if (slider->subControls & SC_SliderTickmarks) {
+
+ CGRect bounds;
+ // As part of fixing the min and max positions,
+ // we need to adjust the tickmarks as well
+ bounds = tdi.bounds;
+ if (slider->orientation == Qt::Horizontal) {
+ tdi.bounds.size.width += 2;
+ tdi.bounds.origin.x -= 1;
+ if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward)
+ tdi.bounds.origin.y -= 2;
+ } else {
+ tdi.bounds.size.height += 3;
+ tdi.bounds.origin.y -= 3;
+ tdi.bounds.origin.y += 1;
+ if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left
+ tdi.bounds.origin.x -= 2;
}
- if (cc == CC_Slider) {
- // Still as part of fixing the min and max positions,
- // we also adjust the knob position. We can do this
- // because it's rendered separately from the track.
- if (slider->orientation == Qt::Vertical) {
- if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right
- tdi.bounds.origin.x -= 2;
- }
+ int interval = slider->tickInterval;
+ if (interval == 0) {
+ interval = slider->pageStep;
+ if (interval == 0)
+ interval = slider->singleStep;
+ if (interval == 0)
+ interval = 1;
+ }
+ int numMarks = 1 + ((slider->maximum - slider->minimum) / interval);
+
+ if (tdi.trackInfo.slider.thumbDir == kThemeThumbPlain) {
+ // They asked for both, so we'll give it to them.
+ tdi.trackInfo.slider.thumbDir = kThemeThumbDownward;
+ HIThemeDrawTrackTickMarks(&tdi, numMarks,
+ cg,
+ kHIThemeOrientationNormal);
+ tdi.trackInfo.slider.thumbDir = kThemeThumbUpward;
+ // 10.10 and above need a slight shift
+ if (slider->orientation == Qt::Vertical)
+ tdi.bounds.origin.x -= 2;
+ HIThemeDrawTrackTickMarks(&tdi, numMarks,
+ cg,
+ kHIThemeOrientationNormal);
+ // Reset to plain thumb to be drawn further down
+ tdi.trackInfo.slider.thumbDir = kThemeThumbPlain;
+ } else {
+ HIThemeDrawTrackTickMarks(&tdi, numMarks,
+ cg,
+ kHIThemeOrientationNormal);
}
- HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg,
- kHIThemeOrientationNormal);
+ tdi.bounds = bounds;
}
+
+ HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg,
+ kHIThemeOrientationNormal);
}
break;
#ifndef QT_NO_SPINBOX
case CC_SpinBox:
if (const QStyleOptionSpinBox *sb = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
- QStyleOptionSpinBox newSB = *sb;
if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) {
SInt32 frame_size;
- GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size);
+ frame_size = qt_mac_aqua_get_metric(EditTextFrameOutset);
QRect lineeditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget);
lineeditRect.adjust(-frame_size, -frame_size, +frame_size, +frame_size);
@@ -5748,58 +5586,36 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
fdi.state = tds == kThemeStateInactive ? kThemeStateActive : tds;
fdi.kind = kHIThemeFrameTextFieldSquare;
fdi.isFocused = false;
- HIRect hirect = qt_hirectForQRect(lineeditRect);
- HIThemeDrawFrame(&hirect, &fdi, cg, kHIThemeOrientationNormal);
+ CGRect cgRect = lineeditRect.toCGRect();
+ HIThemeDrawFrame(&cgRect, &fdi, cg, kHIThemeOrientationNormal);
}
if (sb->subControls & (SC_SpinBoxUp | SC_SpinBoxDown)) {
- HIThemeButtonDrawInfo bdi;
- bdi.version = qt_mac_hitheme_version;
- QAquaWidgetSize aquaSize = d->aquaSizeConstrain(opt, widget);
- switch (aquaSize) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- bdi.kind = kThemeIncDecButton;
- break;
- case QAquaSizeMini:
- bdi.kind = kThemeIncDecButtonMini;
- break;
- case QAquaSizeSmall:
- bdi.kind = kThemeIncDecButtonSmall;
- break;
- }
- if (!(sb->stepEnabled & (QAbstractSpinBox::StepUpEnabled
- | QAbstractSpinBox::StepDownEnabled)))
- tds = kThemeStateUnavailable;
- if (sb->activeSubControls == SC_SpinBoxDown
- && (sb->state & State_Sunken))
- tds = kThemeStatePressedDown;
- else if (sb->activeSubControls == SC_SpinBoxUp
- && (sb->state & State_Sunken))
- tds = kThemeStatePressedUp;
- if (tds == kThemeStateInactive)
- bdi.state = kThemeStateActive;
- else
- bdi.state = tds;
- bdi.value = kThemeButtonOff;
- bdi.adornment = kThemeAdornmentNone;
-
- QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
-
- updown |= proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
- HIRect newRect = qt_hirectForQRect(updown);
- QRect off_rct;
- HIRect outRect;
- HIThemeGetButtonBackgroundBounds(&newRect, &bdi, &outRect);
- off_rct.setRect(int(newRect.origin.x - outRect.origin.x),
- int(newRect.origin.y - outRect.origin.y),
- int(outRect.size.width - newRect.size.width),
- int(outRect.size.height - newRect.size.height));
-
- newRect = qt_hirectForQRect(updown, off_rct);
- if (tds == kThemeStateInactive)
- d->drawColorlessButton(newRect, &bdi, p, sb);
- else
- HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0);
+ const QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget)
+ | proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
+
+ d->setupNSGraphicsContext(cg, NO);
+
+ const auto aquaSize = d->effectiveAquaSizeConstrain(opt, widget);
+ NSStepperCell *cell = static_cast<NSStepperCell *>(d->cocoaCell(QCocoaWidget(QCocoaStepper, aquaSize)));
+ cell.enabled = (sb->state & State_Enabled);
+
+ const CGRect newRect = [cell drawingRectForBounds:updown.toCGRect()];
+
+ const bool upPressed = sb->activeSubControls == SC_SpinBoxUp && (sb->state & State_Sunken);
+ const bool downPressed = sb->activeSubControls == SC_SpinBoxDown && (sb->state & State_Sunken);
+ const CGFloat x = CGRectGetMidX(newRect);
+ const CGFloat y = upPressed ? -3 : 3; // FIXME Weird coordinate shift going on
+ // Pretend we're pressing the mouse on the right button. Unfortunately, NSStepperCell has no
+ // API to highlight a specific button. The highlighted property works only on the down button.
+ if (upPressed || downPressed)
+ [cell startTrackingAt:CGPointMake(x, y) inView:d->backingStoreNSView];
+
+ [cell drawWithFrame:newRect inView:d->backingStoreNSView];
+
+ if (upPressed || downPressed)
+ [cell stopTracking:CGPointMake(x, y) at:CGPointMake(x, y) inView:d->backingStoreNSView mouseIsUp:NO];
+
+ d->restoreNSGraphicsContext(cg);
}
}
break;
@@ -5808,7 +5624,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){
HIThemeButtonDrawInfo bdi;
d->initComboboxBdi(combo, &bdi, widget, tds);
- HIRect rect = qt_hirectForQRect(combo->rect);
+ CGRect rect = combo->rect.toCGRect();
if (combo->editable)
rect.origin.y += tds == kThemeStateInactive ? 1 : 2;
if (tds != kThemeStateInactive)
@@ -5846,15 +5662,15 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
if (widget && widget->isWindowModified() && titlebar->subControls & SC_TitleBarCloseButton)
wdi.attributes |= kThemeWindowHasCloseBox | kThemeWindowHasDirty;
- HIRect titleBarRect;
- HIRect tmpRect = qt_hirectForQRect(titlebar->rect);
+ CGRect titleBarRect;
+ CGRect tmpRect = titlebar->rect.toCGRect();
{
QCFType<HIShapeRef> titleRegion;
QRect newr = titlebar->rect.adjusted(0, 0, 2, 0);
HIThemeGetWindowShape(&tmpRect, &wdi, kWindowTitleBarRgn, &titleRegion);
- ptrHIShapeGetBounds(titleRegion, &tmpRect);
+ HIShapeGetBounds(titleRegion, &tmpRect);
newr.translate(newr.x() - int(tmpRect.origin.x), newr.y() - int(tmpRect.origin.y));
- titleBarRect = qt_hirectForQRect(newr);
+ titleBarRect = newr.toCGRect();
}
HIThemeDrawWindowFrame(&titleBarRect, &wdi, cg, kHIThemeOrientationNormal, 0);
if (titlebar->subControls & (SC_TitleBarCloseButton
@@ -5904,7 +5720,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
QCFType<HIShapeRef> titleRegion2;
HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleProxyIconRgn,
&titleRegion2);
- ptrHIShapeGetBounds(titleRegion2, &tmpRect);
+ HIShapeGetBounds(titleRegion2, &tmpRect);
if (tmpRect.size.width != 1) {
int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
iw = titlebar->icon.actualSize(QSize(iconExtent, iconExtent)).width();
@@ -5914,8 +5730,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
p->save();
QCFType<HIShapeRef> titleRegion3;
HIThemeGetWindowShape(&titleBarRect, &wdi, kWindowTitleTextRgn, &titleRegion3);
- ptrHIShapeGetBounds(titleRegion3, &tmpRect);
- p->setClipRect(qt_qrectForHIRect(tmpRect));
+ HIShapeGetBounds(titleRegion3, &tmpRect);
+ p->setClipRect(QRectF::fromCGRect(tmpRect).toRect());
QRect br = p->clipRegion().boundingRect();
int x = br.x(),
y = br.y() + (titlebar->rect.height() / 2 - p->fontMetrics().height() / 2);
@@ -5946,36 +5762,21 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
else
groupBox.subControls = groupBox.subControls & ~SC_GroupBoxFrame; // We don't like frames and ugly lines
- bool didModifySubControls = false;
- if ((!widget || !widget->testAttribute(Qt::WA_SetFont))
- && QApplication::desktopSettingsAware()) {
+ const bool didSetFont = widget && widget->testAttribute(Qt::WA_SetFont);
+ const bool didModifySubControls = !didSetFont && QApplication::desktopSettingsAware();
+ if (didModifySubControls)
groupBox.subControls = groupBox.subControls & ~SC_GroupBoxLabel;
- didModifySubControls = true;
- }
QCommonStyle::drawComplexControl(cc, &groupBox, p, widget);
if (didModifySubControls) {
- p->save();
- CGContextSetShouldAntialias(cg, true);
- CGContextSetShouldSmoothFonts(cg, true);
- HIThemeTextInfo tti;
- tti.version = qt_mac_hitheme_version;
- tti.state = tds;
- QColor textColor = groupBox.palette.windowText().color();
- CGFloat colorComp[] = { static_cast<CGFloat>(textColor.redF()), static_cast<CGFloat>(textColor.greenF()),
- static_cast<CGFloat>(textColor.blueF()), static_cast<CGFloat>(textColor.alphaF()) };
- CGContextSetFillColorSpace(cg, qt_mac_genericColorSpace());
- CGContextSetFillColor(cg, colorComp);
- tti.fontID = flat ? kThemeSystemFont : kThemeSmallSystemFont;
- tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter;
- tti.verticalFlushness = kHIThemeTextVerticalFlushCenter;
- tti.options = kHIThemeTextBoxOptionNone;
- tti.truncationPosition = kHIThemeTextTruncationNone;
- tti.truncationMaxLines = 1 + groupBox.text.count(QLatin1Char('\n'));
- QCFString groupText = qt_mac_removeMnemonics(groupBox.text);
- QRect r = proxy()->subControlRect(CC_GroupBox, &groupBox, SC_GroupBoxLabel, widget);
- HIRect bounds = qt_hirectForQRect(r);
- HIThemeDrawTextBox(groupText, &bounds, &tti, cg, kHIThemeOrientationNormal);
- p->restore();
+ const QRect rect = proxy()->subControlRect(CC_GroupBox, &groupBox, SC_GroupBoxLabel, widget);
+ const bool rtl = groupBox.direction == Qt::RightToLeft;
+ const int alignment = Qt::TextHideMnemonic | (rtl ? Qt::AlignRight : Qt::AlignLeft);
+ const QFont savedFont = p->font();
+ if (!flat)
+ p->setFont(d->smallSystemFont);
+ proxy()->drawItemText(p, rect, alignment, groupBox.palette, groupBox.state & State_Enabled, groupBox.text, QPalette::WindowText);
+ if (!flat)
+ p->setFont(savedFont);
}
}
break;
@@ -6017,12 +5818,12 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
} else {
ThemeButtonKind bkind = kThemeBevelButton;
switch (d->aquaSizeConstrain(opt, widget)) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
bkind = kThemeBevelButton;
break;
- case QAquaSizeMini:
- case QAquaSizeSmall:
+ case QStyleHelper::SizeMini:
+ case QStyleHelper::SizeSmall:
bkind = kThemeSmallBevelButton;
break;
}
@@ -6052,17 +5853,16 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
if (tb->state & State_On)
bdi.value = kThemeButtonOn;
- QRect off_rct(0, 0, 0, 0);
- HIRect myRect, macRect;
+ CGRect myRect, macRect;
myRect = CGRectMake(tb->rect.x(), tb->rect.y(),
tb->rect.width(), tb->rect.height());
HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect);
- off_rct.setRect(int(myRect.origin.x - macRect.origin.x),
- int(myRect.origin.y - macRect.origin.y),
- int(macRect.size.width - myRect.size.width),
- int(macRect.size.height - myRect.size.height));
- myRect = qt_hirectForQRect(button, off_rct);
+ const auto offMargins = QMargins(int(myRect.origin.x - macRect.origin.x),
+ int(myRect.origin.y - macRect.origin.y),
+ int(macRect.size.width - myRect.size.width),
+ int(macRect.size.height - myRect.size.height));
+ myRect = button.marginsRemoved(offMargins).toCGRect();
HIThemeDrawButton(&myRect, &bdi, cg, kHIThemeOrientationNormal, 0);
}
}
@@ -6079,16 +5879,16 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
if (tb->state & (State_On | State_Sunken)
|| (tb->activeSubControls & SC_ToolButtonMenu))
bdi.state = kThemeStatePressed;
- HIRect hirect = qt_hirectForQRect(menuarea);
- HIThemeDrawButton(&hirect, &bdi, cg, kHIThemeOrientationNormal, 0);
+ CGRect cgRect = menuarea.toCGRect();
+ HIThemeDrawButton(&cgRect, &bdi, cg, kHIThemeOrientationNormal, 0);
QRect r(menuarea.x() + ((menuarea.width() / 2) - 3), menuarea.height() - 8, 8, 8);
HIThemePopupArrowDrawInfo padi;
padi.version = qt_mac_hitheme_version;
padi.state = tds;
padi.orientation = kThemeArrowDown;
padi.size = kThemeArrow7pt;
- hirect = qt_hirectForQRect(r);
- HIThemeDrawPopupArrow(&hirect, &padi, cg, kHIThemeOrientationNormal);
+ cgRect = r.toCGRect();
+ HIThemeDrawPopupArrow(&cgRect, &padi, cg, kHIThemeOrientationNormal);
} else if (tb->features & QStyleOptionToolButton::HasMenu) {
drawToolbarButtonArrow(tb->rect, tds, cg);
}
@@ -6132,7 +5932,7 @@ QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc,
HIThemeTrackDrawInfo tdi;
d->getSliderInfo(cc, slider, &tdi, widget);
ControlPartCode part;
- HIPoint pos = CGPointMake(pt.x(), pt.y());
+ CGPoint pos = CGPointMake(pt.x(), pt.y());
if (HIThemeHitTestTrack(&tdi, &pos, &part)) {
if (part == kControlPageUpPart || part == kControlPageDownPart)
sc = SC_SliderGroove;
@@ -6143,50 +5943,39 @@ QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc,
break;
case CC_ScrollBar:
if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- HIScrollBarTrackInfo sbi;
- sbi.version = qt_mac_hitheme_version;
- if (!(sb->state & State_Active))
- sbi.enableState = kThemeTrackInactive;
- else if (sb->state & State_Enabled)
- sbi.enableState = kThemeTrackActive;
- else
- sbi.enableState = kThemeTrackDisabled;
-
- // The arrow buttons are not drawn if the scroll bar is to short,
- // exclude them from the hit test.
- const int scrollBarLength = (sb->orientation == Qt::Horizontal)
- ? sb->rect.width() : sb->rect.height();
- if (scrollBarLength < scrollButtonsCutoffSize(scrollButtonsCutoff, widgetSizePolicy(widget, opt)))
- sbi.enableState = kThemeTrackNothingToScroll;
+ if (!sb->rect.contains(pt)) {
+ sc = SC_None;
+ break;
+ }
- sbi.viewsize = sb->pageStep;
- HIPoint pos = CGPointMake(pt.x(), pt.y());
+ const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget);
+ const bool isHorizontal = sb->orientation == Qt::Horizontal;
+ const auto cw = QCocoaWidget(isHorizontal ? QCocoaHorizontalScroller : QCocoaVerticalScroller, controlSize);
+ auto *scroller = static_cast<NSScroller *>(d->cocoaControl(cw));
+ if (!setupScroller(scroller, sb)) {
+ sc = SC_None;
+ break;
+ }
- HIRect macSBRect = qt_hirectForQRect(sb->rect);
- ControlPartCode part;
- bool reverseHorizontal = (sb->direction == Qt::RightToLeft
- && sb->orientation == Qt::Horizontal);
- if (HIThemeHitTestScrollBarArrows(&macSBRect, &sbi, sb->orientation == Qt::Horizontal,
- &pos, 0, &part)) {
- if (part == kControlUpButtonPart)
- sc = reverseHorizontal ? SC_ScrollBarAddLine : SC_ScrollBarSubLine;
- else if (part == kControlDownButtonPart)
- sc = reverseHorizontal ? SC_ScrollBarSubLine : SC_ScrollBarAddLine;
+ // Since -[NSScroller testPart:] doesn't want to cooperate, we do it the
+ // straightforward way. In any case, macOS doesn't return line-sized changes
+ // with NSScroller since 10.7, according to the aforementioned method's doc.
+ const auto knobRect = QRectF::fromCGRect([scroller rectForPart:NSScrollerKnob]);
+ if (isHorizontal) {
+ const bool isReverse = sb->direction == Qt::RightToLeft;
+ if (pt.x() < knobRect.left())
+ sc = isReverse ? SC_ScrollBarAddPage : SC_ScrollBarSubPage;
+ else if (pt.x() > knobRect.right())
+ sc = isReverse ? SC_ScrollBarSubPage : SC_ScrollBarAddPage;
+ else
+ sc = SC_ScrollBarSlider;
} else {
- HIThemeTrackDrawInfo tdi;
- d->getSliderInfo(cc, sb, &tdi, widget);
- if(tdi.enableState == kThemeTrackInactive)
- tdi.enableState = kThemeTrackActive;
- if (HIThemeHitTestTrack(&tdi, &pos, &part)) {
- if (part == kControlPageUpPart)
- sc = reverseHorizontal ? SC_ScrollBarAddPage
- : SC_ScrollBarSubPage;
- else if (part == kControlPageDownPart)
- sc = reverseHorizontal ? SC_ScrollBarSubPage
- : SC_ScrollBarAddPage;
- else
- sc = SC_ScrollBarSlider;
- }
+ if (pt.y() < knobRect.top())
+ sc = SC_ScrollBarSubPage;
+ else if (pt.y() > knobRect.bottom())
+ sc = SC_ScrollBarAddPage;
+ else
+ sc = SC_ScrollBarSlider;
}
}
break;
@@ -6209,10 +5998,10 @@ QStyle::SubControl QMacStyle::hitTestComplexControl(ComplexControl cc,
wdi.attributes |= kThemeWindowHasCloseBox;
QRect tmpRect = tbar->rect;
tmpRect.setHeight(tmpRect.height() + 100);
- HIRect hirect = qt_hirectForQRect(tmpRect);
+ CGRect cgRect = tmpRect.toCGRect();
WindowRegionCode hit;
- HIPoint hipt = CGPointMake(pt.x(), pt.y());
- if (HIThemeGetWindowRegionHit(&hirect, &wdi, &hipt, &hit)) {
+ CGPoint hipt = CGPointMake(pt.x(), pt.y());
+ if (HIThemeGetWindowRegionHit(&cgRect, &wdi, &hipt, &hit)) {
switch (hit) {
case kWindowCloseBoxRgn:
sc = QStyle::SC_TitleBarCloseButton;
@@ -6247,41 +6036,48 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
Q_D(const QMacStyle);
QRect ret;
switch (cc) {
- case CC_Slider:
case CC_ScrollBar:
+ if (const QStyleOptionSlider *sb = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
+ const bool isHorizontal = sb->orientation == Qt::Horizontal;
+ const bool isReverseHorizontal = isHorizontal && (sb->direction == Qt::RightToLeft);
+
+ NSScrollerPart part = NSScrollerNoPart;
+ if (sc == SC_ScrollBarSlider) {
+ part = NSScrollerKnob;
+ } else if (sc == SC_ScrollBarGroove) {
+ part = NSScrollerKnobSlot;
+ } else if (sc == SC_ScrollBarSubPage || sc == SC_ScrollBarAddPage) {
+ if ((!isReverseHorizontal && sc == SC_ScrollBarSubPage)
+ || (isReverseHorizontal && sc == SC_ScrollBarAddPage))
+ part = NSScrollerDecrementPage;
+ else
+ part = NSScrollerIncrementPage;
+ }
+ // And nothing else since 10.7
+
+ if (part != NSScrollerNoPart) {
+ const auto controlSize = d->effectiveAquaSizeConstrain(opt, widget);
+ const auto cw = QCocoaWidget(isHorizontal ? QCocoaHorizontalScroller : QCocoaVerticalScroller, controlSize);
+ auto *scroller = static_cast<NSScroller *>(d->cocoaControl(cw));
+ if (setupScroller(scroller, sb))
+ ret = QRectF::fromCGRect([scroller rectForPart:part]).toRect();
+ }
+ }
+ break;
+ case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
HIThemeTrackDrawInfo tdi;
d->getSliderInfo(cc, slider, &tdi, widget);
- HIRect macRect;
+ CGRect macRect;
QCFType<HIShapeRef> shape;
- bool scrollBar = cc == CC_ScrollBar;
- if ((scrollBar && sc == SC_ScrollBarSlider)
- || (!scrollBar && sc == SC_SliderHandle)) {
+ if (sc == SC_SliderHandle) {
HIThemeGetTrackThumbShape(&tdi, &shape);
- ptrHIShapeGetBounds(shape, &macRect);
- } else if (!scrollBar && sc == SC_SliderGroove) {
+ HIShapeGetBounds(shape, &macRect);
+ } else if (sc == SC_SliderGroove) {
HIThemeGetTrackBounds(&tdi, &macRect);
- } else if (sc == SC_ScrollBarGroove) { // Only scroll bar parts available...
- HIThemeGetTrackDragRect(&tdi, &macRect);
- } else {
- ControlPartCode cpc;
- if (sc == SC_ScrollBarSubPage || sc == SC_ScrollBarAddPage) {
- cpc = sc == SC_ScrollBarSubPage ? kControlPageDownPart
- : kControlPageUpPart;
- } else {
- cpc = sc == SC_ScrollBarSubLine ? kControlUpButtonPart
- : kControlDownButtonPart;
- if (slider->direction == Qt::RightToLeft
- && slider->orientation == Qt::Horizontal) {
- if (cpc == kControlDownButtonPart)
- cpc = kControlUpButtonPart;
- else if (cpc == kControlUpButtonPart)
- cpc = kControlDownButtonPart;
- }
- }
- HIThemeGetTrackPartBounds(&tdi, cpc, &macRect);
}
- ret = qt_qrectForHIRect(macRect);
+ // FIXME No SC_SliderTickmarks?
+ ret = QRectF::fromCGRect(macRect).toRect();
// Tweak: the dark line between the sub/add line buttons belong to only one of the buttons
// when doing hit-testing, but both of them have to repaint it. Extend the rect to cover
@@ -6330,16 +6126,16 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
if (wrc != kWindowGlobalPortRgn) {
QCFType<HIShapeRef> region;
QRect tmpRect = titlebar->rect;
- HIRect titleRect = qt_hirectForQRect(tmpRect);
+ CGRect titleRect = tmpRect.toCGRect();
HIThemeGetWindowShape(&titleRect, &wdi, kWindowTitleBarRgn, &region);
- ptrHIShapeGetBounds(region, &titleRect);
+ HIShapeGetBounds(region, &titleRect);
CFRelease(region);
tmpRect.translate(tmpRect.x() - int(titleRect.origin.x),
tmpRect.y() - int(titleRect.origin.y));
- titleRect = qt_hirectForQRect(tmpRect);
+ titleRect = tmpRect.toCGRect();
HIThemeGetWindowShape(&titleRect, &wdi, wrc, &region);
- ptrHIShapeGetBounds(region, &titleRect);
- ret = qt_qrectForHIRect(titleRect);
+ HIShapeGetBounds(region, &titleRect);
+ ret = QRectF::fromCGRect(titleRect).toRect();
}
}
break;
@@ -6361,7 +6157,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
break; }
case SC_ComboBoxListBoxPopup:{
if (combo->editable) {
- HIRect inner = QMacStylePrivate::comboboxInnerBounds(qt_hirectForQRect(combo->rect), bdi.kind);
+ const CGRect inner = QMacStylePrivate::comboboxInnerBounds(combo->rect.toCGRect(), bdi.kind);
QRect editRect = QMacStylePrivate::comboboxEditBounds(combo->rect, bdi);
const int comboTop = combo->rect.top();
ret = QRect(qRound(inner.origin.x),
@@ -6390,35 +6186,16 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
case SC_GroupBoxLabel:
case SC_GroupBoxCheckBox: {
// Cheat and use the smaller font if we need to
- bool checkable = groupBox->subControls & SC_GroupBoxCheckBox;
- bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont))
- || !QApplication::desktopSettingsAware();
- int tw;
- int h;
- int margin = flat || hasNoText ? 0 : 9;
+ const bool checkable = groupBox->subControls & SC_GroupBoxCheckBox;
+ const bool fontIsSet = (widget && widget->testAttribute(Qt::WA_SetFont))
+ || !QApplication::desktopSettingsAware();
+ const int margin = flat || hasNoText ? 0 : 9;
ret = groupBox->rect.adjusted(margin, 0, -margin, 0);
- if (!fontIsSet) {
- HIThemeTextInfo tti;
- tti.version = qt_mac_hitheme_version;
- tti.state = kThemeStateActive;
- tti.fontID = flat ? kThemeSystemFont : kThemeSmallSystemFont;
- tti.horizontalFlushness = kHIThemeTextHorizontalFlushCenter;
- tti.verticalFlushness = kHIThemeTextVerticalFlushCenter;
- tti.options = kHIThemeTextBoxOptionNone;
- tti.truncationPosition = kHIThemeTextTruncationNone;
- tti.truncationMaxLines = 1 + groupBox->text.count(QLatin1Char('\n'));
- CGFloat width;
- CGFloat height;
- QCFString groupText = qt_mac_removeMnemonics(groupBox->text);
- HIThemeGetTextDimensions(groupText, 0, &tti, &width, &height, 0);
- tw = qRound(width);
- h = qCeil(height);
- } else {
- QFontMetricsF fm = QFontMetricsF(groupBox->fontMetrics);
- h = qCeil(fm.height());
- tw = qCeil(fm.size(Qt::TextShowMnemonic, groupBox->text).width());
- }
+ const QFontMetricsF fm = flat || fontIsSet ? QFontMetricsF(groupBox->fontMetrics) : QFontMetricsF(d->smallSystemFont);
+ const QSizeF s = fm.size(Qt::AlignHCenter | Qt::AlignVCenter, qt_mac_removeMnemonics(groupBox->text), 0, nullptr);
+ const int tw = qCeil(s.width());
+ const int h = qCeil(fm.height());
ret.setHeight(h);
QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment,
@@ -6487,25 +6264,25 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
#ifndef QT_NO_SPINBOX
case CC_SpinBox:
if (const QStyleOptionSpinBox *spin = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
- QAquaWidgetSize aquaSize = d->aquaSizeConstrain(spin, widget);
+ QStyleHelper::WidgetSizePolicy aquaSize = d->effectiveAquaSizeConstrain(spin, widget);
int spinner_w;
int spinBoxSep;
int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, spin, widget);
switch (aquaSize) {
- default:
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
+ case QStyleHelper::SizeLarge:
spinner_w = 14;
spinBoxSep = 2;
break;
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
spinner_w = 12;
spinBoxSep = 2;
break;
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
spinner_w = 10;
spinBoxSep = 1;
break;
+ default:
+ Q_UNREACHABLE();
}
switch (sc) {
@@ -6517,34 +6294,25 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
const int y = fw;
const int x = spin->rect.width() - spinner_w;
ret.setRect(x + spin->rect.x(), y + spin->rect.y(), spinner_w, spin->rect.height() - y * 2);
- HIThemeButtonDrawInfo bdi;
- bdi.version = qt_mac_hitheme_version;
- bdi.kind = kThemeIncDecButton;
int hackTranslateX;
switch (aquaSize) {
- default:
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
- bdi.kind = kThemeIncDecButton;
+ case QStyleHelper::SizeLarge:
hackTranslateX = 0;
break;
- case QAquaSizeSmall:
- bdi.kind = kThemeIncDecButtonSmall;
+ case QStyleHelper::SizeSmall:
hackTranslateX = -2;
break;
- case QAquaSizeMini:
- bdi.kind = kThemeIncDecButtonMini;
+ case QStyleHelper::SizeMini:
hackTranslateX = -1;
break;
+ default:
+ Q_UNREACHABLE();
}
- bdi.state = kThemeStateActive;
- bdi.value = kThemeButtonOff;
- bdi.adornment = kThemeAdornmentNone;
- HIRect hirect = qt_hirectForQRect(ret);
- HIRect outRect;
- HIThemeGetButtonBackgroundBounds(&hirect, &bdi, &outRect);
- ret = qt_qrectForHIRect(outRect);
+ NSStepperCell *cell = static_cast<NSStepperCell *>(d->cocoaCell(QCocoaWidget(QCocoaStepper, aquaSize)));
+ const CGRect outRect = [cell drawingRectForBounds:ret.toCGRect()];
+ ret = QRectF::fromCGRect(outRect).toRect();
+
switch (sc) {
case SC_SpinBoxUp:
ret.setHeight(ret.height() / 2);
@@ -6668,7 +6436,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
#if QT_CONFIG(tabbar)
case QStyle::CT_TabBarTab:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
- const QAquaWidgetSize AquaSize = d->aquaSizeConstrain(opt, widget);
+ const QStyleHelper::WidgetSizePolicy AquaSize = d->aquaSizeConstrain(opt, widget);
const bool differentFont = (widget && widget->testAttribute(Qt::WA_SetFont))
|| !QApplication::desktopSettingsAware();
ThemeTabDirection ttd = getTabDirection(tab->shape);
@@ -6679,17 +6447,17 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
int extraHSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget);
QFontMetrics fm = opt->fontMetrics;
switch (AquaSize) {
- case QAquaSizeUnknown:
- case QAquaSizeLarge:
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
if (tab->documentMode)
defaultTabHeight = 24;
else
defaultTabHeight = 21;
break;
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
defaultTabHeight = 18;
break;
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
defaultTabHeight = 16;
break;
}
@@ -6755,9 +6523,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
h = sz.height();
if (mi->menuItemType == QStyleOptionMenuItem::Separator) {
w = 10;
- SInt16 ash;
- GetThemeMenuSeparatorHeight(&ash);
- h = ash;
+ h = qt_mac_aqua_get_metric(MenuSeparatorHeight);
} else {
h = mi->fontMetrics.height() + 2;
if (!mi->icon.isNull()) {
@@ -6835,7 +6601,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case CT_ScrollBar :
// Make sure that the scroll bar is large enough to display the thumb indicator.
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- const int minimumSize = scrollButtonsCutoffSize(thumbIndicatorCutoff, widgetSizePolicy(widget, opt));
+ const int minimumSize = 24; // Smallest knob size, but Cocoa doesn't seem to care
if (slider->orientation == Qt::Horizontal)
sz = sz.expandedTo(QSize(minimumSize, sz.height()));
else
@@ -6855,7 +6621,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
if (useAquaGuideline){
QSize macsz;
- if (d->aquaSizeConstrain(opt, widget, ct, sz, &macsz) != QAquaSizeUnknown) {
+ if (d->aquaSizeConstrain(opt, widget, ct, sz, &macsz) != QStyleHelper::SizeDefault) {
if (macsz.width() != -1)
sz.setWidth(macsz.width());
if (macsz.height() != -1)
@@ -6866,27 +6632,26 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
// The sizes that Carbon and the guidelines gives us excludes the focus frame.
// We compensate for this by adding some extra space here to make room for the frame when drawing:
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(opt)){
- QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget);
+ const auto widgetSize = d->aquaSizeConstrain(opt, widget);
int bkind = 0;
switch (widgetSize) {
default:
- case QAquaSizeLarge:
+ case QStyleHelper::SizeLarge:
bkind = combo->editable ? kThemeComboBox : kThemePopupButton;
break;
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
bkind = combo->editable ? int(kThemeComboBoxSmall) : int(kThemePopupButtonSmall);
break;
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
bkind = combo->editable ? kThemeComboBoxMini : kThemePopupButtonMini;
break;
}
- HIRect tmpRect = {{0, 0}, {0, 0}};
- HIRect diffRect = QMacStylePrivate::comboboxInnerBounds(tmpRect, bkind);
+ const CGRect diffRect = QMacStylePrivate::comboboxInnerBounds(CGRectZero, bkind);
sz.rwidth() -= qRound(diffRect.size.width);
sz.rheight() -= qRound(diffRect.size.height);
} else if (ct == CT_PushButton || ct == CT_ToolButton){
ThemeButtonKind bkind;
- QAquaWidgetSize widgetSize = d->aquaSizeConstrain(opt, widget);
+ QStyleHelper::WidgetSizePolicy widgetSize = d->aquaSizeConstrain(opt, widget);
switch (ct) {
default:
case CT_PushButton:
@@ -6897,26 +6662,26 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
}
switch (widgetSize) {
- default:
- case QAquaSizeLarge:
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
bkind = kThemePushButton;
break;
- case QAquaSizeSmall:
+ case QStyleHelper::SizeSmall:
bkind = kThemePushButtonSmall;
break;
- case QAquaSizeMini:
+ case QStyleHelper::SizeMini:
bkind = kThemePushButtonMini;
break;
}
break;
case CT_ToolButton:
switch (widgetSize) {
- default:
- case QAquaSizeLarge:
+ case QStyleHelper::SizeDefault:
+ case QStyleHelper::SizeLarge:
bkind = kThemeLargeBevelButton;
break;
- case QAquaSizeMini:
- case QAquaSizeSmall:
+ case QStyleHelper::SizeMini:
+ case QStyleHelper::SizeSmall:
bkind = kThemeSmallBevelButton;
}
break;
@@ -6928,7 +6693,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
bdi.kind = bkind;
bdi.value = kThemeButtonOff;
bdi.adornment = kThemeAdornmentNone;
- HIRect macRect, myRect;
+ CGRect macRect, myRect;
myRect = CGRectMake(0, 0, sz.width(), sz.height());
HIThemeGetButtonBackgroundBounds(&myRect, &bdi, &macRect);
// Mini buttons only return their actual size in HIThemeGetButtonBackgroundBounds, so help them out a bit (guess),
@@ -7030,8 +6795,7 @@ int QMacStyle::layoutSpacing(QSizePolicy::ControlType control1,
const QWidget *widget) const
{
const int ButtonMask = QSizePolicy::ButtonBox | QSizePolicy::PushButton;
- bool isMetal = (widget && widget->testAttribute(Qt::WA_MacBrushedMetal));
- int controlSize = getControlSize(option, widget);
+ const int controlSize = getControlSize(option, widget);
if (control2 == QSizePolicy::ButtonBox) {
/*
@@ -7039,11 +6803,10 @@ int QMacStyle::layoutSpacing(QSizePolicy::ControlType control1,
boxes and the row of buttons. The 20 pixel comes from
Builder.
*/
- if (isMetal // (AHIG, guess, guess)
- || (control1 & (QSizePolicy::Frame // guess
- | QSizePolicy::GroupBox // (AHIG, guess, guess)
- | QSizePolicy::TabWidget // guess
- | ButtonMask))) { // AHIG
+ if (control1 & (QSizePolicy::Frame // guess
+ | QSizePolicy::GroupBox // (AHIG, guess, guess)
+ | QSizePolicy::TabWidget // guess
+ | ButtonMask)) { // AHIG
return_SIZE(14, 8, 8);
} else if (control1 == QSizePolicy::LineEdit) {
return_SIZE(8, 8, 8); // Interface Builder
diff --git a/src/widgets/styles/qmacstyle_mac_p.h b/src/plugins/styles/mac/qmacstyle_mac_p.h
index 7296539356..6011baeea2 100644
--- a/src/widgets/styles/qmacstyle_mac_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p.h
@@ -56,9 +56,6 @@
QT_BEGIN_NAMESPACE
-
-#if QT_CONFIG(style_mac)
-
class QPalette;
class QPushButton;
@@ -100,12 +97,6 @@ public:
virtual int styleHint(StyleHint sh, const QStyleOption *opt = 0, const QWidget *w = 0,
QStyleHintReturn *shret = 0) const;
- enum WidgetSizePolicy { SizeSmall, SizeLarge, SizeMini, SizeDefault
- };
-
- static void setWidgetSizePolicy(const QWidget *w, WidgetSizePolicy policy);
- static WidgetSizePolicy widgetSizePolicy(const QWidget *w, const QStyleOption *opt = 0);
-
QPixmap standardPixmap(StandardPixmap sp, const QStyleOption *opt,
const QWidget *widget = 0) const;
@@ -132,8 +123,6 @@ private:
#endif
};
-#endif
-
QT_END_NAMESPACE
#endif // QMACSTYLE_MAC_P_H
diff --git a/src/widgets/styles/qmacstyle_mac_p_p.h b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
index 50596e572d..8574a52a87 100644
--- a/src/widgets/styles/qmacstyle_mac_p_p.h
+++ b/src/plugins/styles/mac/qmacstyle_mac_p_p.h
@@ -45,8 +45,8 @@
#undef check
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include <QtWidgets/private/qcommonstyle_p.h>
#include "qmacstyle_mac_p.h"
-#include "qcommonstyle_p.h"
#include <private/qapplication_p.h>
#if QT_CONFIG(combobox)
#include <private/qcombobox_p.h>
@@ -128,8 +128,11 @@
// We mean it.
//
+Q_FORWARD_DECLARE_MUTABLE_CG_TYPE(CGContext);
+
Q_FORWARD_DECLARE_OBJC_CLASS(NSView);
-Q_FORWARD_DECLARE_OBJC_CLASS(NSScroller);
+Q_FORWARD_DECLARE_OBJC_CLASS(NSCell);
+Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(NotificationReceiver));
QT_BEGIN_NAMESPACE
@@ -146,27 +149,29 @@ QT_BEGIN_NAMESPACE
#define CT1(c) CT2(c, c)
#define CT2(c1, c2) ((uint(c1) << 16) | uint(c2))
-enum QAquaWidgetSize { QAquaSizeLarge = 0, QAquaSizeSmall = 1, QAquaSizeMini = 2,
- QAquaSizeUnknown = -1 };
-
enum QCocoaWidgetKind {
- QCocoaArrowButton, // Disclosure triangle, like in QTreeView
QCocoaCheckBox,
QCocoaComboBox, // Editable QComboBox
+ QCocoaDisclosureButton, // Disclosure triangle, like in QTreeView
QCocoaPopupButton, // Non-editable QComboBox
+ QCocoaProgressIndicator,
+ QCocoaIndeterminateProgressIndicator,
QCocoaPullDownButton, // QPushButton with menu
QCocoaPushButton,
QCocoaRadioButton,
+ QCocoaHorizontalScroller,
+ QCocoaVerticalScroller,
QCocoaHorizontalSlider,
- QCocoaVerticalSlider
+ QCocoaVerticalSlider,
+ QCocoaStepper // QSpinBox buttons
};
-typedef QPair<QCocoaWidgetKind, QAquaWidgetSize> QCocoaWidget;
+typedef QPair<QCocoaWidgetKind, QStyleHelper::WidgetSizePolicy> QCocoaWidget;
-typedef void (^QCocoaDrawRectBlock)(NSRect, CGContextRef);
+typedef void (^QCocoaDrawRectBlock)(CGContextRef, const CGRect &);
#define SIZE(large, small, mini) \
- (controlSize == QAquaSizeLarge ? (large) : controlSize == QAquaSizeSmall ? (small) : (mini))
+ (controlSize == QStyleHelper::SizeLarge ? (large) : controlSize == QStyleHelper::SizeSmall ? (small) : (mini))
// same as return SIZE(...) but optimized
#define return_SIZE(large, small, mini) \
@@ -199,10 +204,10 @@ public:
enum Animates { AquaPushButton, AquaProgressBar, AquaListViewItemOpen, AquaScrollBar };
static ThemeDrawState getDrawState(QStyle::State flags);
- QAquaWidgetSize aquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
+ QStyleHelper::WidgetSizePolicy aquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
QStyle::ContentsType ct = QStyle::CT_CustomBase,
QSize szHint=QSize(-1, -1), QSize *insz = 0) const;
- QAquaWidgetSize effectiveAquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
+ QStyleHelper::WidgetSizePolicy effectiveAquaSizeConstrain(const QStyleOption *option, const QWidget *widg,
QStyle::ContentsType ct = QStyle::CT_CustomBase,
QSize szHint=QSize(-1, -1), QSize *insz = 0) const;
void getSliderInfo(QStyle::ComplexControl cc, const QStyleOptionSlider *slider,
@@ -210,23 +215,23 @@ public:
inline int animateSpeed(Animates) const { return 33; }
// Utility functions
- void drawColorlessButton(const HIRect &macRect, HIThemeButtonDrawInfo *bdi,
+ void drawColorlessButton(const CGRect &macRect, HIThemeButtonDrawInfo *bdi,
QPainter *p, const QStyleOption *opt) const;
QSize pushButtonSizeFromContents(const QStyleOptionButton *btn) const;
- HIRect pushButtonContentBounds(const QStyleOptionButton *btn,
+ CGRect pushButtonContentBounds(const QStyleOptionButton *btn,
const HIThemeButtonDrawInfo *bdi) const;
void initComboboxBdi(const QStyleOptionComboBox *combo, HIThemeButtonDrawInfo *bdi,
const QWidget *widget, const ThemeDrawState &tds) const;
- static HIRect comboboxInnerBounds(const HIRect &outerBounds, int buttonKind);
+ static CGRect comboboxInnerBounds(const CGRect &outerBounds, int buttonKind);
static QRect comboboxEditBounds(const QRect &outerBounds, const HIThemeButtonDrawInfo &bdi);
- static void drawCombobox(const HIRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p);
- static void drawTableHeader(const HIRect &outerBounds, bool drawTopBorder, bool drawLeftBorder,
+ static void drawCombobox(const CGRect &outerBounds, const HIThemeButtonDrawInfo &bdi, QPainter *p);
+ static void drawTableHeader(const CGRect &outerBounds, bool drawTopBorder, bool drawLeftBorder,
const HIThemeButtonDrawInfo &bdi, QPainter *p);
bool contentFitsInPushButton(const QStyleOptionButton *btn, HIThemeButtonDrawInfo *bdi,
ThemeButtonKind buttonKindToCheck) const;
@@ -238,6 +243,12 @@ public:
void setAutoDefaultButton(QObject *button) const;
NSView *cocoaControl(QCocoaWidget widget) const;
+ NSCell *cocoaCell(QCocoaWidget widget) const;
+
+ void setupNSGraphicsContext(CGContextRef cg, bool flipped) const;
+ void restoreNSGraphicsContext(CGContextRef cg) const;
+
+ void setupVerticalInvertedXform(CGContextRef cg, bool reverse, bool vertical, const CGRect &rect) const;
void drawNSViewInRect(QCocoaWidget widget, NSView *view, const QRect &rect, QPainter *p, bool isQWidget = true, QCocoaDrawRectBlock drawRectBlock = nil) const;
void resolveCurrentNSView(QWindow *window);
@@ -249,24 +260,17 @@ public:
#endif
public:
- mutable QPointer<QObject> pressedButton;
- mutable QPointer<QObject> defaultButton;
mutable QPointer<QObject> autoDefaultButton;
static QVector<QPointer<QObject> > scrollBars;
- struct ButtonState {
- int frame;
- enum { ButtonDark, ButtonLight } dir;
- } buttonState;
mutable QPointer<QFocusFrame> focusWidget;
- CFAbsoluteTime defaultButtonStart;
- bool mouseDown;
- void* receiver;
- NSScroller *horizontalScroller;
- NSScroller *verticalScroller;
- void *indicatorBranchButtonCell;
+ QT_MANGLE_NAMESPACE(NotificationReceiver) *receiver;
NSView *backingStoreNSView;
QHash<QCocoaWidget, NSView *> cocoaControls;
+ QHash<QCocoaWidget, NSCell *> cocoaCells;
+
+ QFont smallSystemFont;
+ QFont miniSystemFont;
};
QT_END_NAMESPACE
diff --git a/src/plugins/styles/styles.pro b/src/plugins/styles/styles.pro
new file mode 100644
index 0000000000..542ad1329a
--- /dev/null
+++ b/src/plugins/styles/styles.pro
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+QT_FOR_CONFIG += widgets-private
+
+qtConfig(style-android): SUBDIRS += android
+
+qtConfig(style-mac): SUBDIRS += mac
+
+qtConfig(style-windowsvista): SUBDIRS += windowsvista
diff --git a/src/plugins/styles/windowsvista/main.cpp b/src/plugins/styles/windowsvista/main.cpp
new file mode 100644
index 0000000000..d5048e45b7
--- /dev/null
+++ b/src/plugins/styles/windowsvista/main.cpp
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include <QtWidgets/qstyleplugin.h>
+#include "qwindowsvistastyle_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsVistaStylePlugin : public QStylePlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QStyleFactoryInterface" FILE "windowsvistastyle.json")
+public:
+ QStyle *create(const QString &key);
+};
+
+QStyle *QWindowsVistaStylePlugin::create(const QString &key)
+{
+ if (key.compare(QLatin1String("windowsvista"), Qt::CaseInsensitive) == 0)
+ return new QWindowsVistaStyle();
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
index 8ab4a61f5f..60a5c25b1f 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle.cpp
@@ -47,8 +47,6 @@
#include <private/qapplication_p.h>
#include <qpa/qplatformnativeinterface.h>
-#if QT_CONFIG(style_windowsvista) || defined(QT_PLUGIN)
-
QT_BEGIN_NAMESPACE
static const int windowsItemFrame = 2; // menu item frame width
@@ -2488,5 +2486,3 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon,
}
QT_END_NAMESPACE
-
-#endif //QT_NO_WINDOWSVISTA
diff --git a/src/widgets/styles/qwindowsvistastyle_p.h b/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h
index 8fbd1dc380..5ffcbc6aa9 100644
--- a/src/widgets/styles/qwindowsvistastyle_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle_p.h
@@ -52,13 +52,10 @@
//
#include <QtWidgets/private/qtwidgetsglobal_p.h>
-#include <private/qwindowsxpstyle_p.h>
+#include "qwindowsxpstyle_p.h"
QT_BEGIN_NAMESPACE
-
-#if QT_CONFIG(style_windowsvista)
-
class QWindowsVistaStylePrivate;
class QWindowsVistaStyle : public QWindowsXPStyle
{
@@ -103,7 +100,6 @@ private:
Q_DECLARE_PRIVATE(QWindowsVistaStyle)
friend class QStyleFactory;
};
-#endif // style_windowsvista
QT_END_NAMESPACE
diff --git a/src/widgets/styles/qwindowsvistastyle_p_p.h b/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h
index 5e2200b876..14af2c6bbc 100644
--- a/src/widgets/styles/qwindowsvistastyle_p_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsvistastyle_p_p.h
@@ -53,9 +53,7 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include "qwindowsvistastyle_p.h"
-
-#if QT_CONFIG(style_windowsvista)
-#include <private/qwindowsxpstyle_p_p.h>
+#include "qwindowsxpstyle_p_p.h"
#include <private/qstyleanimation_p.h>
#include <private/qpaintengine_raster_p.h>
#include <qpaintengine.h>
@@ -189,6 +187,4 @@ public:
QT_END_NAMESPACE
-#endif // style_windowsvista
-
#endif // QWINDOWSVISTASTYLE_P_P_H
diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
index bb2c0688c4..a3a665f22b 100644
--- a/src/widgets/styles/qwindowsxpstyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
@@ -39,8 +39,6 @@
#include "qwindowsxpstyle_p.h"
#include "qwindowsxpstyle_p_p.h"
-#if QT_CONFIG(style_windowsxp) || defined(QT_PLUGIN)
-
#include <private/qobject_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qapplication_p.h>
@@ -673,6 +671,13 @@ static inline TransformType transformType(const QTransform &transform, qreal dev
? HighDpiScalingTransform : ComplexTransform;
}
+// QTBUG-60571: Exclude known fully opaque theme parts which produce values
+// invalid in ARGB32_Premultiplied (for example, 0x00ffffff).
+static inline bool isFullyOpaque(const XPThemeData &themeData)
+{
+ return themeData.theme == QWindowsXPStylePrivate::TaskDialogTheme && themeData.partId == TDLG_PRIMARYPANEL;
+}
+
/*! \internal
Main theme drawing function.
Determines the correct lowlevel drawing method depending on several
@@ -711,6 +716,7 @@ bool QWindowsXPStylePrivate::drawBackground(XPThemeData &themeData)
bool canDrawDirectly = false;
if (themeData.widget && painter->opacity() == 1.0 && !themeData.rotate
+ && !isFullyOpaque(themeData)
&& tt != ComplexTransform && !themeData.mirrorVertically
&& !translucentToplevel) {
// Draw on backing store DC only for real widgets or backing store images.
@@ -4228,5 +4234,3 @@ void QWindowsXPStylePrivate::showProperties(XPThemeData &themeData)
QT_END_NAMESPACE
-
-#endif //QT_NO_WINDOWSXP
diff --git a/src/widgets/styles/qwindowsxpstyle_p.h b/src/plugins/styles/windowsvista/qwindowsxpstyle_p.h
index 62e3af927c..d00620eefa 100644
--- a/src/widgets/styles/qwindowsxpstyle_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle_p.h
@@ -52,13 +52,10 @@
//
#include <QtWidgets/private/qtwidgetsglobal_p.h>
-#include <private/qwindowsstyle_p.h>
+#include <QtWidgets/private/qwindowsstyle_p.h>
QT_BEGIN_NAMESPACE
-
-#if QT_CONFIG(style_windowsxp)
-
class QWindowsXPStylePrivate;
class QWindowsXPStyle : public QWindowsStyle
{
@@ -102,8 +99,6 @@ private:
friend class QStyleFactory;
};
-#endif // style_windowsxp
-
QT_END_NAMESPACE
#endif // QWINDOWSXPSTYLE_P_H
diff --git a/src/widgets/styles/qwindowsxpstyle_p_p.h b/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
index fb5210cb07..721a734829 100644
--- a/src/widgets/styles/qwindowsxpstyle_p_p.h
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle_p_p.h
@@ -53,7 +53,7 @@
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include "qwindowsxpstyle_p.h"
-#include "qwindowsstyle_p_p.h"
+#include <QtWidgets/private/qwindowsstyle_p_p.h>
#include <qmap.h>
#include <qt_windows.h>
@@ -94,8 +94,6 @@ QT_BEGIN_NAMESPACE
// Uncomment define below to build debug assisting code, and output
// #define DEBUG_XP_STYLE
-#if QT_CONFIG(style_windowsxp)
-
// Declarations -----------------------------------------------------------------------------------
class XPThemeData
{
@@ -338,8 +336,6 @@ inline QMarginsF XPThemeData::themeMargins(const QWidget *w, QPainter *p, int th
return theme.margins(propId);
}
-#endif // style_windows
-
QT_END_NAMESPACE
#endif //QWINDOWSXPSTYLE_P_P_H
diff --git a/src/plugins/styles/windowsvista/windowsvista.pro b/src/plugins/styles/windowsvista/windowsvista.pro
new file mode 100644
index 0000000000..f82bcfc91b
--- /dev/null
+++ b/src/plugins/styles/windowsvista/windowsvista.pro
@@ -0,0 +1,22 @@
+TARGET = qwindowsvistastyle
+
+QT += widgets-private
+
+SOURCES += main.cpp
+
+HEADERS += qwindowsvistastyle_p.h qwindowsvistastyle_p_p.h
+SOURCES += qwindowsvistastyle.cpp
+
+HEADERS += qwindowsxpstyle_p.h qwindowsxpstyle_p_p.h
+SOURCES += qwindowsxpstyle.cpp
+
+LIBS_PRIVATE += -lgdi32 -luser32
+
+# DEFINES/LIBS needed for qwizard_win.cpp and the styles
+include(../../../widgets/kernel/win.pri)
+
+DISTFILES += windowsvistastyle.json
+
+PLUGIN_TYPE = styles
+PLUGIN_CLASS_NAME = QWindowsVistaStylePlugin
+load(qt_plugin)
diff --git a/src/plugins/styles/windowsvista/windowsvistastyle.json b/src/plugins/styles/windowsvista/windowsvistastyle.json
new file mode 100644
index 0000000000..771aa0c600
--- /dev/null
+++ b/src/plugins/styles/windowsvista/windowsvistastyle.json
@@ -0,0 +1,3 @@
+{
+ "Keys": [ "windowsvista" ]
+}
diff --git a/src/printsupport/kernel/qcups.cpp b/src/printsupport/kernel/qcups.cpp
index 48ab71eea4..1c9d522c1c 100644
--- a/src/printsupport/kernel/qcups.cpp
+++ b/src/printsupport/kernel/qcups.cpp
@@ -96,7 +96,7 @@ static inline QString jobHoldToString(const QCUPSSupport::JobHoldUntil jobHold,
if (holdUntilTime < localDateTime.time())
localDateTime = localDateTime.addDays(1);
localDateTime.setTime(holdUntilTime);
- return localDateTime.toUTC().time().toString(QStringLiteral("HH:mm"));
+ return localDateTime.toUTC().time().toString(QStringViewLiteral("HH:mm"));
}
// else fall through:
Q_FALLTHROUGH();
diff --git a/src/printsupport/kernel/qprintengine_pdf.cpp b/src/printsupport/kernel/qprintengine_pdf.cpp
index 278bb044e1..080ff7ccf4 100644
--- a/src/printsupport/kernel/qprintengine_pdf.cpp
+++ b/src/printsupport/kernel/qprintengine_pdf.cpp
@@ -58,10 +58,12 @@
QT_BEGIN_NAMESPACE
-QPdfPrintEngine::QPdfPrintEngine(QPrinter::PrinterMode m)
+QPdfPrintEngine::QPdfPrintEngine(QPrinter::PrinterMode m, QPdfEngine::PdfVersion version)
: QPdfEngine(*new QPdfPrintEnginePrivate(m))
{
state = QPrinter::Idle;
+
+ setPdfVersion(version);
}
QPdfPrintEngine::QPdfPrintEngine(QPdfPrintEnginePrivate &p)
diff --git a/src/printsupport/kernel/qprintengine_pdf_p.h b/src/printsupport/kernel/qprintengine_pdf_p.h
index b964885bbf..e9e81bdf68 100644
--- a/src/printsupport/kernel/qprintengine_pdf_p.h
+++ b/src/printsupport/kernel/qprintengine_pdf_p.h
@@ -83,7 +83,7 @@ class Q_PRINTSUPPORT_EXPORT QPdfPrintEngine : public QPdfEngine, public QPrintEn
{
Q_DECLARE_PRIVATE(QPdfPrintEngine)
public:
- QPdfPrintEngine(QPrinter::PrinterMode m);
+ QPdfPrintEngine(QPrinter::PrinterMode m, QPdfEngine::PdfVersion version = QPdfEngine::Version_1_4);
virtual ~QPdfPrintEngine();
// reimplementations QPaintEngine
diff --git a/src/printsupport/kernel/qprinter.cpp b/src/printsupport/kernel/qprinter.cpp
index 83ebb15a12..d59db444e4 100644
--- a/src/printsupport/kernel/qprinter.cpp
+++ b/src/printsupport/kernel/qprinter.cpp
@@ -149,7 +149,8 @@ void QPrinterPrivate::initEngines(QPrinter::OutputFormat format, const QPrinterI
printEngine = ps->createNativePrintEngine(printerMode);
paintEngine = ps->createPaintEngine(printEngine, printerMode);
} else {
- QPdfPrintEngine *pdfEngine = new QPdfPrintEngine(printerMode);
+ const auto pdfEngineVersion = (pdfVersion == QPrinter::PdfVersion_1_4 ? QPdfEngine::Version_1_4 : QPdfEngine::Version_A1b);
+ QPdfPrintEngine *pdfEngine = new QPdfPrintEngine(printerMode, pdfEngineVersion);
paintEngine = pdfEngine;
printEngine = pdfEngine;
}
@@ -687,7 +688,37 @@ QPrinter::OutputFormat QPrinter::outputFormat() const
return d->outputFormat;
}
+/*!
+ \since 5.10
+
+ Sets the PDF version for this printer to \a version.
+
+ If \a version is the same value as currently set then no change will be made.
+*/
+void QPrinter::setPdfVersion(PdfVersion version)
+{
+ Q_D(QPrinter);
+
+ if (d->pdfVersion == version)
+ return;
+
+ d->pdfVersion = version;
+ if (d->outputFormat == QPrinter::PdfFormat) {
+ d->changeEngines(d->outputFormat, QPrinterInfo());
+ }
+}
+
+/*!
+ \since 5.10
+
+ Returns the PDF version for this printer. The default is \c PdfVersion_1_4.
+*/
+QPrinter::PdfVersion QPrinter::pdfVersion() const
+{
+ Q_D(const QPrinter);
+ return d->pdfVersion;
+}
/*! \internal
*/
diff --git a/src/printsupport/kernel/qprinter.h b/src/printsupport/kernel/qprinter.h
index 33a2d4dbc8..bfe2d346ae 100644
--- a/src/printsupport/kernel/qprinter.h
+++ b/src/printsupport/kernel/qprinter.h
@@ -134,6 +134,9 @@ public:
void setOutputFormat(OutputFormat format);
OutputFormat outputFormat() const;
+ void setPdfVersion(PdfVersion version);
+ PdfVersion pdfVersion() const;
+
void setPrinterName(const QString &);
QString printerName() const;
diff --git a/src/printsupport/kernel/qprinter_p.h b/src/printsupport/kernel/qprinter_p.h
index 603eaf7409..6ced466236 100644
--- a/src/printsupport/kernel/qprinter_p.h
+++ b/src/printsupport/kernel/qprinter_p.h
@@ -75,7 +75,8 @@ class Q_PRINTSUPPORT_EXPORT QPrinterPrivate
Q_DECLARE_PUBLIC(QPrinter)
public:
QPrinterPrivate(QPrinter *printer)
- : printEngine(0),
+ : pdfVersion(QPrinter::PdfVersion_1_4),
+ printEngine(0),
paintEngine(0),
realPrintEngine(0),
realPaintEngine(0),
@@ -107,6 +108,7 @@ public:
QPrinter::PrinterMode printerMode;
QPrinter::OutputFormat outputFormat;
+ QPrinter::PdfVersion pdfVersion;
QPrintEngine *printEngine;
QPaintEngine *paintEngine;
diff --git a/src/sql/doc/snippets/code/doc_src_sql-driver.cpp b/src/sql/doc/snippets/code/doc_src_sql-driver.cpp
index f25ad4f2b0..7983386642 100644
--- a/src/sql/doc/snippets/code/doc_src_sql-driver.cpp
+++ b/src/sql/doc/snippets/code/doc_src_sql-driver.cpp
@@ -90,3 +90,8 @@ qDebug() << q.value(0); // outputs the first RETURN/OUT value
QSqlDatabase: QMYSQL driver not loaded
QSqlDatabase: available drivers: QMYSQL
//! [31]
+
+
+//! [34]
+column.contains(QRegularExpression("pattern"));
+//! [34]
diff --git a/src/sql/doc/src/sql-driver.qdoc b/src/sql/doc/src/sql-driver.qdoc
index 4f3f2ce007..2811230106 100644
--- a/src/sql/doc/src/sql-driver.qdoc
+++ b/src/sql/doc/src/sql-driver.qdoc
@@ -568,6 +568,22 @@
\snippet code/doc_src_sql-driver.qdoc 23
+ \section3 Enable REGEXP operator
+
+ SQLite comes with a REGEXP operation. However the needed implementation must
+ be provided by the user. For convenience a default implementation can be
+ enabled by \l{QSqlDatabase::setConnectOptions()} {setting the connect
+ option} \c{QSQLITE_ENABLE_REGEXP} before \l{QSqlDatabase::open()} {the
+ database connection is opened}. Then a SQL statement like "column REGEXP
+ 'pattern'" basically expands to the Qt code
+
+ \snippet code/doc_src_sql-driver.cpp 34
+
+ For better performance the regular expressions are cached internally. By
+ default the cache size is 25, but it can be changed through the option's
+ value. For example passing "\c{QSQLITE_ENABLE_REGEXP=10}" reduces the
+ cache size to 10.
+
\section3 QSQLITE File Format Compatibility
SQLite minor releases sometimes break file format forward compatibility.
diff --git a/src/sql/kernel/qsqldatabase.cpp b/src/sql/kernel/qsqldatabase.cpp
index 412658e39c..bca981a865 100644
--- a/src/sql/kernel/qsqldatabase.cpp
+++ b/src/sql/kernel/qsqldatabase.cpp
@@ -1178,6 +1178,7 @@ QSqlRecord QSqlDatabase::record(const QString& tablename) const
\li QSQLITE_OPEN_READONLY
\li QSQLITE_OPEN_URI
\li QSQLITE_ENABLE_SHARED_CACHE
+ \li QSQLITE_ENABLE_REGEXP
\endlist
\li
diff --git a/src/sql/kernel/qsqlerror.cpp b/src/sql/kernel/qsqlerror.cpp
index d1fc5d4585..50b10aab40 100644
--- a/src/sql/kernel/qsqlerror.cpp
+++ b/src/sql/kernel/qsqlerror.cpp
@@ -98,6 +98,34 @@ public:
type \a type and the optional error number \a number.
*/
+/*! \fn QSqlError::QSqlError(QSqlError &&other)
+ Move-constructs a QSqlError instance, making it point at the same
+ object that \a other was pointing to.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new value.
+
+ \since 5.10
+*/
+
+/*! \fn QSqlError::operator=(QSqlError &&other)
+ Move-assigns \a other to this QSqlError instance.
+
+ \note The moved-from object \a other is placed in a
+ partially-formed state, in which the only valid operations are
+ destruction and assignment of a new value.
+
+ \since 5.10
+*/
+
+/*! \fn QSqlError::swap(QSqlError &other)
+ Swaps error \a other with this error. This operation is very fast
+ and never fails.
+
+ \since 5.10
+*/
+
#if QT_DEPRECATED_SINCE(5, 3)
QSqlError::QSqlError(const QString& driverText, const QString& databaseText, ErrorType type,
int number)
@@ -117,7 +145,6 @@ QSqlError::QSqlError(const QString& driverText, const QString& databaseText, Err
driverText, the database-specific error text \a databaseText, the
type \a type and the error code \a code.
*/
-
QSqlError::QSqlError(const QString &driverText, const QString &databaseText,
ErrorType type, const QString &code)
{
@@ -146,7 +173,10 @@ QSqlError::QSqlError(const QSqlError& other)
QSqlError& QSqlError::operator=(const QSqlError& other)
{
- *d = *other.d;
+ if (d)
+ *d = *other.d;
+ else
+ d = new QSqlErrorPrivate(*other.d);
return *this;
}
diff --git a/src/sql/kernel/qsqlerror.h b/src/sql/kernel/qsqlerror.h
index 0ccd32159d..6dac47a7fe 100644
--- a/src/sql/kernel/qsqlerror.h
+++ b/src/sql/kernel/qsqlerror.h
@@ -66,11 +66,16 @@ public:
ErrorType type = NoError,
const QString &errorCode = QString());
QSqlError(const QSqlError& other);
+ QSqlError(QSqlError &&other) Q_DECL_NOTHROW : d(other.d) { other.d = nullptr; }
QSqlError& operator=(const QSqlError& other);
+ QSqlError &operator=(QSqlError &&other) Q_DECL_NOTHROW { swap(other); return *this; }
+
bool operator==(const QSqlError& other) const;
bool operator!=(const QSqlError& other) const;
~QSqlError();
+ void swap(QSqlError &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
+
QString driverText() const;
QString databaseText() const;
ErrorType type() const;
@@ -102,6 +107,8 @@ private:
};
};
+Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QSqlError)
+
#ifndef QT_NO_DEBUG_STREAM
Q_SQL_EXPORT QDebug operator<<(QDebug, const QSqlError &);
#endif
diff --git a/src/sql/kernel/qsqlfield.cpp b/src/sql/kernel/qsqlfield.cpp
index bb810b11df..59b992e803 100644
--- a/src/sql/kernel/qsqlfield.cpp
+++ b/src/sql/kernel/qsqlfield.cpp
@@ -47,9 +47,9 @@ class QSqlFieldPrivate
{
public:
QSqlFieldPrivate(const QString &name,
- QVariant::Type type) :
+ QVariant::Type type, const QString &tableName) :
ref(1), nm(name), ro(false), type(type), req(QSqlField::Unknown),
- len(-1), prec(-1), tp(-1), gen(true), autoval(false)
+ len(-1), prec(-1), tp(-1), gen(true), autoval(false), table(tableName)
{
}
@@ -64,7 +64,8 @@ public:
def(other.def),
tp(other.tp),
gen(other.gen),
- autoval(other.autoval)
+ autoval(other.autoval),
+ table(other.table)
{}
bool operator==(const QSqlFieldPrivate& other) const
@@ -77,7 +78,8 @@ public:
&& prec == other.prec
&& def == other.def
&& gen == other.gen
- && autoval == other.autoval);
+ && autoval == other.autoval
+ && table == other.table);
}
QAtomicInt ref;
@@ -91,6 +93,7 @@ public:
int tp;
uint gen: 1;
uint autoval: 1;
+ QString table;
};
@@ -153,14 +156,15 @@ public:
/*!
Constructs an empty field called \a fieldName of variant type \a
- type.
+ type in \a table.
\sa setRequiredStatus(), setLength(), setPrecision(), setDefaultValue(),
setGenerated(), setReadOnly()
*/
-QSqlField::QSqlField(const QString& fieldName, QVariant::Type type)
+QSqlField::QSqlField(const QString &fieldName, QVariant::Type type,
+ const QString &table)
{
- d = new QSqlFieldPrivate(fieldName, type);
+ d = new QSqlFieldPrivate(fieldName, type, table);
val = QVariant(type);
}
@@ -518,6 +522,7 @@ QDebug operator<<(QDebug dbg, const QSqlField &f)
QDebugStateSaver saver(dbg);
dbg.nospace();
dbg << "QSqlField(" << f.name() << ", " << QMetaType::typeName(f.type());
+ dbg << ", tableName: " << (f.tableName().isEmpty() ? QStringLiteral("(not specified)") : f.tableName());
if (f.length() >= 0)
dbg << ", length: " << f.length();
if (f.precision() >= 0)
@@ -565,4 +570,27 @@ void QSqlField::setAutoValue(bool autoVal)
d->autoval = autoVal;
}
+/*!
+ Sets the tableName of the field to \a table.
+
+ \sa tableName()
+*/
+
+void QSqlField::setTableName(const QString &table)
+{
+ detach();
+ d->table = table;
+}
+
+/*!
+ Returns the tableName of the field.
+
+ \sa setTableName()
+*/
+
+QString QSqlField::tableName() const
+{
+ return d->table;
+}
+
QT_END_NAMESPACE
diff --git a/src/sql/kernel/qsqlfield.h b/src/sql/kernel/qsqlfield.h
index 0d8c51f801..30474735f4 100644
--- a/src/sql/kernel/qsqlfield.h
+++ b/src/sql/kernel/qsqlfield.h
@@ -55,7 +55,8 @@ public:
enum RequiredStatus { Unknown = -1, Optional = 0, Required = 1 };
explicit QSqlField(const QString& fieldName = QString(),
- QVariant::Type type = QVariant::Invalid);
+ QVariant::Type type = QVariant::Invalid,
+ const QString &tableName = QString());
QSqlField(const QSqlField& other);
QSqlField& operator=(const QSqlField& other);
@@ -68,6 +69,8 @@ public:
{ return val; }
void setName(const QString& name);
QString name() const;
+ void setTableName(const QString &tableName);
+ QString tableName() const;
bool isNull() const;
void setReadOnly(bool readOnly);
bool isReadOnly() const;
diff --git a/src/sql/kernel/qsqlrecord.cpp b/src/sql/kernel/qsqlrecord.cpp
index d5adff67a4..1c9ad5ec63 100644
--- a/src/sql/kernel/qsqlrecord.cpp
+++ b/src/sql/kernel/qsqlrecord.cpp
@@ -232,10 +232,23 @@ QString QSqlRecord::fieldName(int index) const
int QSqlRecord::indexOf(const QString& name) const
{
- QString nm = name.toUpper();
+ QString tableName;
+ QString fieldName = name;
+ const int idx = name.indexOf(QLatin1Char('.'));
+ if (idx != -1) {
+ tableName = name.left(idx);
+ fieldName = name.mid(idx + 1);
+ }
for (int i = 0; i < count(); ++i) {
- if (d->fields.at(i).name().toUpper() == nm) // TODO: case-insensitive comparison
+ // Check the passed in name first in case it is an alias using a dot.
+ // Then check if both the table and field match when there is a table name specified.
+ const auto currentField = d->fields.at(i);
+ const auto currentFieldName = currentField.name();
+ if (currentFieldName.compare(name, Qt::CaseInsensitive) == 0
+ || (idx != -1 && currentFieldName.compare(fieldName, Qt::CaseInsensitive) == 0
+ && currentField.tableName().compare(tableName, Qt::CaseInsensitive) == 0)) {
return i;
+ }
}
return -1;
}
diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp
index 864c5b9946..c0b1061c6b 100644
--- a/src/sql/models/qsqlquerymodel.cpp
+++ b/src/sql/models/qsqlquerymodel.cpp
@@ -212,6 +212,30 @@ bool QSqlQueryModel::canFetchMore(const QModelIndex &parent) const
return (!parent.isValid() && !d->atEnd);
}
+/*!
+ \since 5.10
+ \reimp
+
+ Returns the model's role names.
+
+ Qt defines only one role for the QSqlQueryModel:
+
+ \table
+ \header
+ \li Qt Role
+ \li QML Role Name
+ \row
+ \li Qt::DisplayRole
+ \li display
+ \endtable
+*/
+QHash<int, QByteArray> QSqlQueryModel::roleNames() const
+{
+ return QHash<int, QByteArray> {
+ { Qt::DisplayRole, QByteArrayLiteral("display") }
+ };
+}
+
/*! \internal
*/
void QSqlQueryModel::beginInsertRows(const QModelIndex &parent, int first, int last)
diff --git a/src/sql/models/qsqlquerymodel.h b/src/sql/models/qsqlquerymodel.h
index f786f71300..869a5f030c 100644
--- a/src/sql/models/qsqlquerymodel.h
+++ b/src/sql/models/qsqlquerymodel.h
@@ -58,22 +58,22 @@ class Q_SQL_EXPORT QSqlQueryModel: public QAbstractTableModel
Q_DECLARE_PRIVATE(QSqlQueryModel)
public:
- explicit QSqlQueryModel(QObject *parent = Q_NULLPTR);
+ explicit QSqlQueryModel(QObject *parent = nullptr);
virtual ~QSqlQueryModel();
- int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
- int columnCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+ int columnCount(const QModelIndex &parent = QModelIndex()) const override;
QSqlRecord record(int row) const;
QSqlRecord record() const;
- QVariant data(const QModelIndex &item, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+ QVariant data(const QModelIndex &item, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation,
- int role = Qt::DisplayRole) const Q_DECL_OVERRIDE;
+ int role = Qt::DisplayRole) const override;
bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value,
- int role = Qt::EditRole) Q_DECL_OVERRIDE;
+ int role = Qt::EditRole) override;
- bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
- bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
+ bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
+ bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex()) override;
void setQuery(const QSqlQuery &query);
void setQuery(const QString &query, const QSqlDatabase &db = QSqlDatabase());
@@ -83,8 +83,10 @@ public:
QSqlError lastError() const;
- void fetchMore(const QModelIndex &parent = QModelIndex()) Q_DECL_OVERRIDE;
- bool canFetchMore(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
+ void fetchMore(const QModelIndex &parent = QModelIndex()) override;
+ bool canFetchMore(const QModelIndex &parent = QModelIndex()) const override;
+
+ QHash<int, QByteArray> roleNames() const override;
protected:
void beginInsertRows(const QModelIndex &parent, int first, int last);
@@ -105,7 +107,7 @@ protected:
virtual QModelIndex indexInQuery(const QModelIndex &item) const;
void setLastError(const QSqlError &error);
- QSqlQueryModel(QSqlQueryModelPrivate &dd, QObject *parent = Q_NULLPTR);
+ QSqlQueryModel(QSqlQueryModelPrivate &dd, QObject *parent = nullptr);
};
QT_END_NAMESPACE
diff --git a/src/src.pro b/src/src.pro
index 43fc06f2e5..a2064b1362 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -49,6 +49,11 @@ src_tools_qdbuscpp2xml.target = sub-qdbuscpp2xml
force_bootstrap: src_tools_qdbuscpp2xml.depends = src_tools_bootstrap_dbus
else: src_tools_qdbuscpp2xml.depends = src_dbus
+src_tools_qvkgen.subdir = tools/qvkgen
+src_tools_qvkgen.target = sub-qvkgen
+force_bootstrap: src_tools_qvkgen.depends = src_tools_bootstrap
+else: src_tools_qvkgen.depends = src_corelib
+
src_winmain.subdir = $$PWD/winmain
src_winmain.target = sub-winmain
src_winmain.depends = sub-corelib # just for the module .pri file
@@ -188,6 +193,9 @@ qtConfig(gui) {
SUBDIRS += src_3rdparty_freetype
src_platformsupport.depends += src_3rdparty_freetype
}
+ SUBDIRS += src_tools_qvkgen
+ src_gui.depends += src_tools_qvkgen
+ TOOLS += src_tools_qvkgen
SUBDIRS += src_gui src_platformsupport src_platformheaders
qtConfig(opengl): SUBDIRS += src_openglextensions
src_plugins.depends += src_gui src_platformsupport src_platformheaders
diff --git a/src/testlib/qtest.h b/src/testlib/qtest.h
index ba63df5f36..ca045120d5 100644
--- a/src/testlib/qtest.h
+++ b/src/testlib/qtest.h
@@ -65,9 +65,14 @@ QT_BEGIN_NAMESPACE
namespace QTest
{
+template <> inline char *toString(const QStringView &str)
+{
+ return QTest::toPrettyUnicode(str);
+}
+
template<> inline char *toString(const QString &str)
{
- return QTest::toPrettyUnicode(reinterpret_cast<const ushort *>(str.constData()), str.length());
+ return toString(QStringView(str));
}
template<> inline char *toString(const QLatin1String &str)
@@ -84,21 +89,21 @@ template<> inline char *toString(const QByteArray &ba)
template<> inline char *toString(const QTime &time)
{
return time.isValid()
- ? qstrdup(qPrintable(time.toString(QLatin1String("hh:mm:ss.zzz"))))
+ ? qstrdup(qPrintable(time.toString(QStringViewLiteral("hh:mm:ss.zzz"))))
: qstrdup("Invalid QTime");
}
template<> inline char *toString(const QDate &date)
{
return date.isValid()
- ? qstrdup(qPrintable(date.toString(QLatin1String("yyyy/MM/dd"))))
+ ? qstrdup(qPrintable(date.toString(QStringViewLiteral("yyyy/MM/dd"))))
: qstrdup("Invalid QDate");
}
template<> inline char *toString(const QDateTime &dateTime)
{
return dateTime.isValid()
- ? qstrdup(qPrintable(dateTime.toString(QLatin1String("yyyy/MM/dd hh:mm:ss.zzz[t]"))))
+ ? qstrdup(qPrintable(dateTime.toString(QStringViewLiteral("yyyy/MM/dd hh:mm:ss.zzz[t]"))))
: qstrdup("Invalid QDateTime");
}
#endif // QT_NO_DATESTRING
@@ -194,6 +199,22 @@ template<> inline char *toString(const QVariant &v)
return qstrdup(vstring.constData());
}
+template <typename T1, typename T2>
+inline char *toString(const QPair<T1, T2> &pair)
+{
+ const QScopedArrayPointer<char> first(toString(pair.first));
+ const QScopedArrayPointer<char> second(toString(pair.second));
+ return toString(QString::asprintf("QPair(%s,%s)", first.data(), second.data()));
+}
+
+template <typename T1, typename T2>
+inline char *toString(const std::pair<T1, T2> &pair)
+{
+ const QScopedArrayPointer<char> first(toString(pair.first));
+ const QScopedArrayPointer<char> second(toString(pair.second));
+ return toString(QString::asprintf("std::pair(%s,%s)", first.data(), second.data()));
+}
+
inline char *toString(std::nullptr_t)
{
return toString(QLatin1String("nullptr"));
diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp
index 57661bb389..b24ce0578e 100644
--- a/src/testlib/qtestblacklist.cpp
+++ b/src/testlib/qtestblacklist.cpp
@@ -58,9 +58,10 @@ QT_BEGIN_NAMESPACE
referring to this documentation is kind to readers. Comments can also be used
to indicate the reasons for ignoring particular cases.
- A key names a platform, O/S, distribution, tool-chain or architecture; a !
- prefix reverses what it checks. A version, joined to a key (at present, only
- for distributions and for msvc) with a hyphen, limits the key to the specific
+ The key "ci" applies only when run by COIN. Other keys name platforms,
+ operating systems, distributions, tool-chains or architectures; a ! prefix
+ reverses what it checks. A version, joined to a key (at present, only for
+ distributions and for msvc) with a hyphen, limits the key to the specific
version. A keyword line matches if every key on it applies to the present
run. Successive lines are alternate conditions for ignoring a test.
@@ -70,13 +71,18 @@ QT_BEGIN_NAMESPACE
Subsequent lines give conditions for ignoring this test.
# See qtbase/src/testlib/qtestblacklist.cpp for format
- osx
+ # Test doesn't work on QNX at all
+ qnx
# QTBUG-12345
[testFunction]
linux
windows 64bit
+ # Flaky in COIN on macOS, not reproducible by developers
+ [testSlowly]
+ ci osx
+
# Needs basic C++11 support
[testfunction2:testData]
msvc-2010
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 8b0820b941..a4099c3cd8 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -275,6 +275,11 @@ namespace QTest
static QObject *currentTestObject = 0;
static QString mainSourcePath;
+#if defined(Q_OS_MACOS)
+ bool macNeedsActivate = false;
+ IOPMAssertionID powerID;
+#endif
+
class TestMethods {
Q_DISABLE_COPY(TestMethods)
public:
@@ -1271,6 +1276,16 @@ char *toPrettyCString(const char *p, int length)
return buffer.take();
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+// this used to be the signature up to and including Qt 5.9
+// keep it for BC reasons:
+Q_TESTLIB_EXPORT
+char *toPrettyUnicode(const ushort *p, int length)
+{
+ return toPrettyUnicode(QStringView(p, length));
+}
+#endif
+
/*!
\internal
Returns the same QString but with only the ASCII characters still shown;
@@ -1278,8 +1293,10 @@ char *toPrettyCString(const char *p, int length)
Similar to QDebug::putString().
*/
-char *toPrettyUnicode(const ushort *p, int length)
+char *toPrettyUnicode(QStringView string)
{
+ auto p = reinterpret_cast<const ushort *>(string.utf16());
+ auto length = string.size();
// keep it simple for the vast majority of cases
bool trimmed = false;
QScopedArrayPointer<char> buffer(new char[256]);
@@ -1345,9 +1362,7 @@ void TestMethods::invokeTests(QObject *testObject) const
{
const QMetaObject *metaObject = testObject->metaObject();
QTEST_ASSERT(metaObject);
- QTestLog::startLogging();
QTestResult::setCurrentTestFunction("initTestCase");
- QTestTable::globalTestTable();
if (m_initTestCaseDataMethod.isValid())
m_initTestCaseDataMethod.invoke(testObject, Qt::DirectConnection);
@@ -1392,9 +1407,6 @@ void TestMethods::invokeTests(QObject *testObject) const
}
QTestResult::finishedCurrentTestFunction();
QTestResult::setCurrentTestFunction(0);
- QTestTable::clearGlobalTestTable();
-
- QTestLog::stopLogging();
}
#if defined(Q_OS_UNIX)
@@ -1698,24 +1710,25 @@ static void initEnvironment()
int QTest::qExec(QObject *testObject, int argc, char **argv)
{
- initEnvironment();
- QBenchmarkGlobalData benchmarkData;
- QBenchmarkGlobalData::current = &benchmarkData;
+ qInit(testObject, argc, argv);
+ int ret = qRun();
+ qCleanup();
+ return ret;
+}
-#ifdef QTESTLIB_USE_VALGRIND
- int callgrindChildExitCode = 0;
-#endif
+/*! \internal
+ */
+void QTest::qInit(QObject *testObject, int argc, char **argv)
+{
+ initEnvironment();
+ QBenchmarkGlobalData::current = new QBenchmarkGlobalData;
#if defined(Q_OS_MACX)
- bool macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0);
- IOPMAssertionID powerID;
+ macNeedsActivate = qApp && (qstrcmp(qApp->metaObject()->className(), "QApplication") == 0);
// Don't restore saved window state for auto tests.
QTestPrivate::disableWindowRestore();
#endif
-#ifndef QT_NO_EXCEPTIONS
- try {
-#endif
#if defined(Q_OS_MACX)
if (macNeedsActivate) {
@@ -1745,6 +1758,24 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
qtest_qParseArgs(argc, argv, false);
+ QTestTable::globalTestTable();
+ QTestLog::startLogging();
+}
+
+/*! \internal
+ */
+int QTest::qRun()
+{
+ QTEST_ASSERT(currentTestObject);
+
+#ifdef QTESTLIB_USE_VALGRIND
+ int callgrindChildExitCode = 0;
+#endif
+
+#ifndef QT_NO_EXCEPTIONS
+ try {
+#endif
+
#if defined(Q_OS_WIN)
if (!noCrashHandler) {
# ifndef Q_CC_MINGW
@@ -1780,17 +1811,17 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
for (const QString &tf : qAsConst(QTest::testFunctions)) {
const QByteArray tfB = tf.toLatin1();
const QByteArray signature = tfB + QByteArrayLiteral("()");
- QMetaMethod m = TestMethods::findMethod(testObject, signature.constData());
+ QMetaMethod m = TestMethods::findMethod(currentTestObject, signature.constData());
if (!m.isValid() || !isValidSlot(m)) {
fprintf(stderr, "Unknown test function: '%s'. Possible matches:\n", tfB.constData());
qPrintTestSlots(stderr, tfB.constData());
- fprintf(stderr, "\n%s -functions\nlists all available test functions.\n", argv[0]);
+ fprintf(stderr, "\n%s -functions\nlists all available test functions.\n", QTestResult::currentAppName());
exit(1);
}
commandLineMethods.push_back(m);
}
- TestMethods test(testObject, commandLineMethods);
- test.invokeTests(testObject);
+ TestMethods test(currentTestObject, commandLineMethods);
+ test.invokeTests(currentTestObject);
}
#ifndef QT_NO_EXCEPTIONS
@@ -1815,16 +1846,6 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
}
#endif
- currentTestObject = 0;
-
- QSignalDumper::endDump();
-
-#if defined(Q_OS_MACX)
- if (macNeedsActivate) {
- IOPMAssertionRelease(powerID);
- }
-#endif
-
#ifdef QTESTLIB_USE_VALGRIND
if (QBenchmarkGlobalData::current->mode() == QBenchmarkGlobalData::CallgrindParentProcess)
return callgrindChildExitCode;
@@ -1834,6 +1855,26 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
return qMin(QTestLog::failCount(), 127);
}
+/*! \internal
+ */
+void QTest::qCleanup()
+{
+ currentTestObject = 0;
+
+ QTestTable::clearGlobalTestTable();
+ QTestLog::stopLogging();
+
+ delete QBenchmarkGlobalData::current;
+ QBenchmarkGlobalData::current = 0;
+
+ QSignalDumper::endDump();
+
+#if defined(Q_OS_MACOS)
+ if (macNeedsActivate)
+ IOPMAssertionRelease(powerID);
+#endif
+}
+
/*!
\overload
\since 4.4
diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h
index a59eb4ecb3..b738043cb7 100644
--- a/src/testlib/qtestcase.h
+++ b/src/testlib/qtestcase.h
@@ -259,12 +259,22 @@ namespace QTest
return Internal::toString(t);
}
+ template <typename T1, typename T2>
+ inline char *toString(const QPair<T1, T2> &pair);
+
+ template <typename T1, typename T2>
+ inline char *toString(const std::pair<T1, T2> &pair);
+
Q_TESTLIB_EXPORT char *toHexRepresentation(const char *ba, int length);
Q_TESTLIB_EXPORT char *toPrettyCString(const char *unicode, int length);
- Q_TESTLIB_EXPORT char *toPrettyUnicode(const ushort *unicode, int length);
+ Q_TESTLIB_EXPORT char *toPrettyUnicode(QStringView string);
Q_TESTLIB_EXPORT char *toString(const char *);
Q_TESTLIB_EXPORT char *toString(const void *);
+ Q_TESTLIB_EXPORT void qInit(QObject *testObject, int argc = 0, char **argv = Q_NULLPTR);
+ Q_TESTLIB_EXPORT int qRun();
+ Q_TESTLIB_EXPORT void qCleanup();
+
Q_TESTLIB_EXPORT int qExec(QObject *testObject, int argc = 0, char **argv = Q_NULLPTR);
Q_TESTLIB_EXPORT int qExec(QObject *testObject, const QStringList &arguments);
@@ -319,6 +329,8 @@ namespace QTest
Q_TESTLIB_EXPORT QTestData &newRow(const char *dataTag);
Q_TESTLIB_EXPORT QTestData &addRow(const char *format, ...) Q_ATTRIBUTE_FORMAT_PRINTF(1, 2);
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
+ // kept after adding implementation of <T1, T2> out of paranoia:
template <typename T>
inline bool qCompare(T const &t1, T const &t2, const char *actual, const char *expected,
const char *file, int line)
@@ -326,6 +338,7 @@ namespace QTest
return compare_helper(t1 == t2, "Compared values are not the same",
toString(t1), toString(t2), actual, expected, file, line);
}
+#endif
Q_TESTLIB_EXPORT bool qCompare(float const &t1, float const &t2,
const char *actual, const char *expected, const char *file, int line);
@@ -376,7 +389,12 @@ namespace QTest
#endif
template <typename T1, typename T2>
- bool qCompare(T1 const &, T2 const &, const char *, const char *, const char *, int);
+ inline bool qCompare(const T1 &t1, const T2 &t2, const char *actual, const char *expected,
+ const char *file, int line)
+ {
+ return compare_helper(t1 == t2, "Compared values are not the same",
+ toString(t1), toString(t2), actual, expected, file, line);
+ }
inline bool qCompare(double const &t1, float const &t2, const char *actual,
const char *expected, const char *file, int line)
diff --git a/src/testlib/qtestcase.qdoc b/src/testlib/qtestcase.qdoc
index 8f3d140add..2d1e27ec40 100644
--- a/src/testlib/qtestcase.qdoc
+++ b/src/testlib/qtestcase.qdoc
@@ -82,11 +82,6 @@
QCOMPARE tries to output the contents of the values if the comparison fails,
so it is visible from the test log why the comparison failed.
- QCOMPARE is very strict on the data types. Both \a actual and \a expected
- have to be of the same type, otherwise the test won't compile. This prohibits
- unspecified behavior from being introduced; that is behavior that usually
- occurs when the compiler implicitly casts the argument.
-
For your own classes, you can use \l QTest::toString() to format values for
outputting into the test log.
@@ -575,6 +570,15 @@
\sa QTest::keyClicks()
*/
+/*! \fn void QTest::keySequence(QWidget *widget, const QKeySequence &keySequence)
+ \overload
+ \since 5.10
+
+ Simulates typing of \a keySequence into a \a widget.
+
+ \sa QTest::keyClick(), QTest::keyClicks()
+*/
+
/*! \fn void QTest::keyClick(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
\overload
\since 5.0
@@ -611,6 +615,15 @@
\sa QTest::keyClicks()
*/
+/*! \fn void QTest::keySequence(QWindow *window, const QKeySequence &keySequence)
+ \overload
+ \since 5.10
+
+ Simulates typing of \a keySequence into a \a window.
+
+ \sa QTest::keyClick(), QTest::keyClicks()
+*/
+
/*! \fn void QTest::keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
Sends a Qt key event to \a widget with the given \a key and an associated \a action.
@@ -1071,6 +1084,10 @@
This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
time after being asked to show itself on the screen.
+ Note that a window that is mapped to screen may still not be considered exposed if the window client
+ area is completely covered by other windows, or if the window is otherwise not visible. This function
+ will then time out when waiting for such a window.
+
\sa QTest::qWaitForWindowActive(), QWindow::isExposed()
*/
@@ -1093,6 +1110,13 @@
This is mainly useful for asynchronous systems like X11, where a window will be mapped to screen some
time after being asked to show itself on the screen.
+ Note that a window that is mapped to screen may still not be considered exposed if the window client
+ area is completely covered by other windows, or if the window is otherwise not visible. This function
+ will then time out when waiting for such a window.
+
+ A specific configuration where this happens is when using QGLWidget as a viewport widget on macOS:
+ The viewport widget gets the expose event, not the parent widget.
+
\sa QTest::qWaitForWindowActive()
*/
diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h
index e750fdb5a9..a7cf78f25a 100644
--- a/src/testlib/qtestkeyboard.h
+++ b/src/testlib/qtestkeyboard.h
@@ -54,6 +54,7 @@
#include <QtGui/qguiapplication.h>
#include <QtGui/qwindow.h>
#include <QtGui/qevent.h>
+#include <QtGui/qkeysequence.h>
#ifdef QT_WIDGETS_LIB
#include <QtWidgets/qwidget.h>
@@ -165,6 +166,15 @@ namespace QTest
Q_DECL_UNUSED inline static void keyPress(QWindow *window, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
{ keyEvent(Press, window, key, modifier, delay); }
+ Q_DECL_UNUSED inline static void keySequence(QWindow *window, const QKeySequence &keySequence)
+ {
+ for (int i = 0; i < keySequence.count(); ++i) {
+ const Qt::Key key = Qt::Key(keySequence[i] & ~Qt::KeyboardModifierMask);
+ const Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(keySequence[i] & Qt::KeyboardModifierMask);
+ keyClick(window, key, modifiers);
+ }
+ }
+
#ifdef QT_WIDGETS_LIB
static void simulateEvent(QWidget *widget, bool press, int code,
Qt::KeyboardModifiers modifier, QString text, bool repeat, int delay=-1)
@@ -294,6 +304,16 @@ namespace QTest
{ keyEvent(Release, widget, key, modifier, delay); }
inline static void keyClick(QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier = Qt::NoModifier, int delay=-1)
{ keyEvent(Click, widget, key, modifier, delay); }
+
+ inline static void keySequence(QWidget *widget, const QKeySequence &keySequence)
+ {
+ for (int i = 0; i < keySequence.count(); ++i) {
+ const Qt::Key key = Qt::Key(keySequence[i] & ~Qt::KeyboardModifierMask);
+ const Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(keySequence[i] & Qt::KeyboardModifierMask);
+ keyClick(widget, key, modifiers);
+ }
+ }
+
#endif // QT_WIDGETS_LIB
}
diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro
index 521dd5f0f2..dedb4ff138 100644
--- a/src/tools/bootstrap/bootstrap.pro
+++ b/src/tools/bootstrap/bootstrap.pro
@@ -29,6 +29,7 @@ SOURCES += \
../../corelib/global/qmalloc.cpp \
../../corelib/global/qnumeric.cpp \
../../corelib/global/qoperatingsystemversion.cpp \
+ ../../corelib/global/qrandom.cpp \
../../corelib/io/qabstractfileengine.cpp \
../../corelib/io/qbuffer.cpp \
../../corelib/io/qdatastream.cpp \
@@ -93,7 +94,8 @@ SOURCES += \
../../xml/dom/qdom.cpp \
../../xml/sax/qxml.cpp
-unix:SOURCES += ../../corelib/io/qfilesystemengine_unix.cpp \
+unix:SOURCES += ../../corelib/kernel/qcore_unix.cpp \
+ ../../corelib/io/qfilesystemengine_unix.cpp \
../../corelib/io/qfilesystemiterator_unix.cpp \
../../corelib/io/qfsfileengine_unix.cpp
@@ -137,7 +139,7 @@ macx {
}
win32 {
- LIBS += -luser32 -lole32 -ladvapi32 -lshell32
+ LIBS += -luser32 -lole32 -ladvapi32 -lshell32 -lnetapi32
mingw: LIBS += -luuid
}
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index c4184929ef..0b45776b88 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -218,6 +218,7 @@ void Generator::generateCode()
registerFunctionStrings(cdef->slotList);
registerFunctionStrings(cdef->methodList);
registerFunctionStrings(cdef->constructorList);
+ registerByteArrayVector(cdef->nonClassSignalList);
registerPropertyStrings();
registerEnumStrings();
@@ -603,6 +604,19 @@ void Generator::generateCode()
// Generate plugin meta data
//
generatePluginMetaData();
+
+//
+// Generate function to make sure the non-class signals exist in the parent classes
+//
+ if (!cdef->nonClassSignalList.isEmpty()) {
+ fprintf(out, "// If you get a compile error in this function it can be because either\n");
+ fprintf(out, "// a) You are using a NOTIFY signal that does not exist. Fix it.\n");
+ fprintf(out, "// b) You are using a NOTIFY signal that does exist (in a parent class) but has a non-empty parameter list. This is a moc limitation.\n");
+ fprintf(out, "Q_DECL_UNUSED static void checkNotifySignalValidity_%s(%s *t) {\n", qualifiedClassNameIdentifier.constData(), cdef->qualified.constData());
+ for (const QByteArray &nonClassSignal : cdef->nonClassSignalList)
+ fprintf(out, " t->%s();\n", nonClassSignal.constData());
+ fprintf(out, "}\n");
+ }
}
@@ -648,6 +662,12 @@ void Generator::registerFunctionStrings(const QVector<FunctionDef>& list)
}
}
+void Generator::registerByteArrayVector(const QVector<QByteArray> &list)
+{
+ for (const QByteArray &ba : list)
+ strreg(ba);
+}
+
void Generator::generateFunctions(const QVector<FunctionDef>& list, const char *functype, int type, int &paramsIndex)
{
if (list.isEmpty())
@@ -841,12 +861,17 @@ void Generator::generateProperties()
fprintf(out, "\n // properties: notify_signal_id\n");
for (int i = 0; i < cdef->propertyList.count(); ++i) {
const PropertyDef &p = cdef->propertyList.at(i);
- if(p.notifyId == -1)
+ if (p.notifyId == -1) {
fprintf(out, " %4d,\n",
0);
- else
+ } else if (p.notifyId > -1) {
fprintf(out, " %4d,\n",
p.notifyId);
+ } else {
+ const int indexInStrings = strings.indexOf(p.notify);
+ fprintf(out, " %4d,\n",
+ indexInStrings | IsUnresolvedSignal);
+ }
}
}
if (cdef->revisionedProperties) {
@@ -1401,13 +1426,15 @@ void Generator::generateStaticMetacall()
prefix.constData(), p.member.constData(), p.type.constData());
fprintf(out, " %s%s = *reinterpret_cast< %s*>(_v);\n",
prefix.constData(), p.member.constData(), p.type.constData());
- if (!p.notify.isEmpty() && p.notifyId != -1) {
+ if (!p.notify.isEmpty() && p.notifyId > -1) {
const FunctionDef &f = cdef->signalList.at(p.notifyId);
if (f.arguments.size() == 0)
fprintf(out, " Q_EMIT _t->%s();\n", p.notify.constData());
else if (f.arguments.size() == 1 && f.arguments.at(0).normalizedType == p.type)
fprintf(out, " Q_EMIT _t->%s(%s%s);\n",
p.notify.constData(), prefix.constData(), p.member.constData());
+ } else if (!p.notify.isEmpty() && p.notifyId < -1) {
+ fprintf(out, " Q_EMIT _t->%s();\n", p.notify.constData());
}
fprintf(out, " }\n");
fprintf(out, " break;\n");
diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h
index 3833148fb3..8b80138302 100644
--- a/src/tools/moc/generator.h
+++ b/src/tools/moc/generator.h
@@ -46,6 +46,7 @@ private:
void registerClassInfoStrings();
void generateClassInfos();
void registerFunctionStrings(const QVector<FunctionDef> &list);
+ void registerByteArrayVector(const QVector<QByteArray> &list);
void generateFunctions(const QVector<FunctionDef> &list, const char *functype, int type, int &paramsIndex);
void generateFunctionRevisions(const QVector<FunctionDef> &list, const char *functype);
void generateFunctionParameters(const QVector<FunctionDef> &list, const char *functype);
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
index b30de66258..18945f1ce5 100644
--- a/src/tools/moc/main.cpp
+++ b/src/tools/moc/main.cpp
@@ -395,9 +395,9 @@ int runMoc(int argc, char **argv)
pp.macros.remove(macro);
}
const QStringList noNotesCompatValues = parser.values(noNotesWarningsCompatOption);
- if (parser.isSet(noNotesOption) || noNotesCompatValues.contains(QStringLiteral("n")))
+ if (parser.isSet(noNotesOption) || noNotesCompatValues.contains(QLatin1String("n")))
moc.displayNotes = false;
- if (parser.isSet(noWarningsOption) || noNotesCompatValues.contains(QStringLiteral("w")))
+ if (parser.isSet(noWarningsOption) || noNotesCompatValues.contains(QLatin1String("w")))
moc.displayWarnings = moc.displayNotes = false;
if (autoInclude) {
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index 4d3ccb8680..b9f71ddb15 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -1730,9 +1730,13 @@ void Moc::checkProperties(ClassDef *cdef)
}
p.notifyId = notifyId;
if (notifyId == -1) {
- QByteArray msg = "NOTIFY signal '" + p.notify + "' of property '" + p.name
- + "' does not exist in class " + cdef->classname + ".";
- error(msg.constData());
+ int index = cdef->nonClassSignalList.indexOf(p.notify);
+ if (index == -1) {
+ cdef->nonClassSignalList << p.notify;
+ p.notifyId = -1 - cdef->nonClassSignalList.count();
+ } else {
+ p.notifyId = -2 - index;
+ }
}
}
}
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index 6040f944f3..5f8cdfcf2c 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -121,7 +121,7 @@ struct PropertyDef
{
PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec), revision(0){}
QByteArray name, type, member, read, write, reset, designable, scriptable, editable, stored, user, notify, inPrivateClass;
- int notifyId;
+ int notifyId; // -1 means no notifyId, >= 0 means signal defined in this class, < -1 means signal not defined in this class
bool constant;
bool final;
enum Specification { ValueSpec, ReferenceSpec, PointerSpec };
@@ -179,6 +179,7 @@ struct ClassDef : BaseDef {
QVector<FunctionDef> constructorList;
QVector<FunctionDef> signalList, slotList, methodList, publicList;
+ QVector<QByteArray> nonClassSignalList;
int notifyableProperties = 0;
QVector<PropertyDef> propertyList;
int revisionedMethods = 0;
diff --git a/src/tools/moc/moc.pro b/src/tools/moc/moc.pro
index ccd29341d0..8f66a428c1 100644
--- a/src/tools/moc/moc.pro
+++ b/src/tools/moc/moc.pro
@@ -12,4 +12,5 @@ include(moc.pri)
HEADERS += qdatetime_p.h
SOURCES += main.cpp
+QMAKE_TARGET_DESCRIPTION = "Qt Meta Object Compiler"
load(qt_tool)
diff --git a/src/tools/qdbuscpp2xml/qdbuscpp2xml.pro b/src/tools/qdbuscpp2xml/qdbuscpp2xml.pro
index 5ac3159797..d0e8cfdf24 100644
--- a/src/tools/qdbuscpp2xml/qdbuscpp2xml.pro
+++ b/src/tools/qdbuscpp2xml/qdbuscpp2xml.pro
@@ -9,4 +9,5 @@ include(../moc/moc.pri)
SOURCES += qdbuscpp2xml.cpp
+QMAKE_TARGET_DESCRIPTION = "Qt D-Bus C++ to XML Compiler"
load(qt_tool)
diff --git a/src/tools/qdbusxml2cpp/qdbusxml2cpp.pro b/src/tools/qdbusxml2cpp/qdbusxml2cpp.pro
index 95fcbcbc50..8468d2ab44 100644
--- a/src/tools/qdbusxml2cpp/qdbusxml2cpp.pro
+++ b/src/tools/qdbusxml2cpp/qdbusxml2cpp.pro
@@ -12,4 +12,5 @@ QMAKE_CXXFLAGS += $$QT_HOST_CFLAGS_DBUS
SOURCES = qdbusxml2cpp.cpp
+QMAKE_TARGET_DESCRIPTION = "Qt D-Bus XML to C++ Compiler"
load(qt_tool)
diff --git a/src/tools/qlalr/qlalr.pro b/src/tools/qlalr/qlalr.pro
index bd5f337c64..ce0f4a4f59 100644
--- a/src/tools/qlalr/qlalr.pro
+++ b/src/tools/qlalr/qlalr.pro
@@ -25,4 +25,5 @@ OTHER_FILES += \
DEFINES += \
QT_NO_FOREACH
+QMAKE_TARGET_DESCRIPTION = "Qt Look Ahead LR Parser"
load(qt_tool)
diff --git a/src/tools/qvkgen/qvkgen.cpp b/src/tools/qvkgen/qvkgen.cpp
new file mode 100644
index 0000000000..059f9413cb
--- /dev/null
+++ b/src/tools/qvkgen/qvkgen.cpp
@@ -0,0 +1,530 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the tools applications of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qxmlstream.h>
+
+class VkSpecParser
+{
+public:
+ bool parse();
+
+ struct TypedName {
+ QString name;
+ QString type;
+ QString typeSuffix;
+ };
+
+ struct Command {
+ TypedName cmd;
+ QVector<TypedName> args;
+ bool deviceLevel;
+ };
+
+ QVector<Command> commands() const { return m_commands; }
+
+ void setFileName(const QString &fn) { m_fn = fn; }
+
+private:
+ void skip();
+ void parseCommands();
+ Command parseCommand();
+ TypedName parseParamOrProto(const QString &tag);
+ QString parseName();
+
+ QFile m_file;
+ QXmlStreamReader m_reader;
+ QVector<Command> m_commands;
+ QString m_fn;
+};
+
+bool VkSpecParser::parse()
+{
+ m_file.setFileName(m_fn);
+ if (!m_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning("Failed to open %s", qPrintable(m_file.fileName()));
+ return false;
+ }
+
+ m_reader.setDevice(&m_file);
+ while (!m_reader.atEnd()) {
+ m_reader.readNext();
+ if (m_reader.isStartElement()) {
+ if (m_reader.name() == QStringLiteral("commands"))
+ parseCommands();
+ }
+ }
+
+ return true;
+}
+
+void VkSpecParser::skip()
+{
+ QString tag = m_reader.name().toString();
+ while (!m_reader.atEnd()) {
+ m_reader.readNext();
+ if (m_reader.isEndElement() && m_reader.name() == tag)
+ break;
+ }
+}
+
+void VkSpecParser::parseCommands()
+{
+ m_commands.clear();
+
+ while (!m_reader.atEnd()) {
+ m_reader.readNext();
+ if (m_reader.isEndElement() && m_reader.name() == QStringLiteral("commands"))
+ return;
+ if (m_reader.isStartElement() && m_reader.name() == "command")
+ m_commands.append(parseCommand());
+ }
+}
+
+VkSpecParser::Command VkSpecParser::parseCommand()
+{
+ Command c;
+
+ while (!m_reader.atEnd()) {
+ m_reader.readNext();
+ if (m_reader.isEndElement() && m_reader.name() == QStringLiteral("command"))
+ break;
+ if (m_reader.isStartElement()) {
+ const QString protoStr = QStringLiteral("proto");
+ const QString paramStr = QStringLiteral("param");
+ if (m_reader.name() == protoStr) {
+ c.cmd = parseParamOrProto(protoStr);
+ } else if (m_reader.name() == paramStr) {
+ c.args.append(parseParamOrProto(paramStr));
+ } else {
+ skip();
+ }
+ }
+ }
+
+ c.deviceLevel = false;
+ if (!c.args.isEmpty()) {
+ QStringList dispatchableDeviceAndChildTypes {
+ QStringLiteral("VkDevice"),
+ QStringLiteral("VkQueue"),
+ QStringLiteral("VkCommandBuffer")
+ };
+ if (dispatchableDeviceAndChildTypes.contains(c.args[0].type)
+ && c.cmd.name != QStringLiteral("vkGetDeviceProcAddr"))
+ {
+ c.deviceLevel = true;
+ }
+ }
+
+ return c;
+}
+
+VkSpecParser::TypedName VkSpecParser::parseParamOrProto(const QString &tag)
+{
+ TypedName t;
+
+ while (!m_reader.atEnd()) {
+ m_reader.readNext();
+ if (m_reader.isEndElement() && m_reader.name() == tag)
+ break;
+ if (m_reader.isStartElement()) {
+ if (m_reader.name() == QStringLiteral("name")) {
+ t.name = parseName();
+ } else if (m_reader.name() != QStringLiteral("type")) {
+ skip();
+ }
+ } else {
+ QStringRef text = m_reader.text().trimmed();
+ if (!text.isEmpty()) {
+ if (text.startsWith(QLatin1Char('['))) {
+ t.typeSuffix += text;
+ } else {
+ if (!t.type.isEmpty())
+ t.type += QLatin1Char(' ');
+ t.type += text;
+ }
+ }
+ }
+ }
+
+ return t;
+}
+
+QString VkSpecParser::parseName()
+{
+ QString name;
+ while (!m_reader.atEnd()) {
+ m_reader.readNext();
+ if (m_reader.isEndElement() && m_reader.name() == QStringLiteral("name"))
+ break;
+ name += m_reader.text();
+ }
+ return name.trimmed();
+}
+
+QString funcSig(const VkSpecParser::Command &c, const char *className = nullptr)
+{
+ QString s;
+ s.sprintf("%s %s%s%s", qPrintable(c.cmd.type),
+ (className ? className : ""), (className ? "::" : ""),
+ qPrintable(c.cmd.name));
+ if (!c.args.isEmpty()) {
+ s += QLatin1Char('(');
+ bool first = true;
+ for (const VkSpecParser::TypedName &a : c.args) {
+ QString argStr;
+ argStr.sprintf("%s%s%s%s", qPrintable(a.type), (a.type.endsWith(QLatin1Char('*')) ? "" : " "),
+ qPrintable(a.name), qPrintable(a.typeSuffix));
+ if (!first)
+ s += QStringLiteral(", ");
+ else
+ first = false;
+ s += argStr;
+ }
+ s += QLatin1Char(')');
+ }
+ return s;
+}
+
+QString funcCall(const VkSpecParser::Command &c, int idx)
+{
+ QString s;
+ // template:
+ // [return] reinterpret_cast<PFN_vkEnumeratePhysicalDevices>(d_ptr->m_funcs[0])(instance, pPhysicalDeviceCount, pPhysicalDevices);
+ s.sprintf("%sreinterpret_cast<PFN_%s>(d_ptr->m_funcs[%d])",
+ (c.cmd.type == QStringLiteral("void") ? "" : "return "),
+ qPrintable(c.cmd.name),
+ idx);
+ if (!c.args.isEmpty()) {
+ s += QLatin1Char('(');
+ bool first = true;
+ for (const VkSpecParser::TypedName &a : c.args) {
+ if (!first)
+ s += QStringLiteral(", ");
+ else
+ first = false;
+ s += a.name;
+ }
+ s += QLatin1Char(')');
+ }
+ return s;
+}
+
+class Preamble
+{
+public:
+ QByteArray get(const QString &fn);
+
+private:
+ QByteArray m_str;
+} preamble;
+
+QByteArray Preamble::get(const QString &fn)
+{
+ if (!m_str.isEmpty())
+ return m_str;
+
+ QFile f(fn);
+ if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ qWarning("Failed to open %s", qPrintable(fn));
+ return m_str;
+ }
+
+ m_str = f.readAll();
+ m_str.replace("FOO", "QtGui");
+ m_str += "\n// This file is automatically generated by qvkgen. Do not edit.\n";
+
+ return m_str;
+}
+
+bool genVulkanFunctionsH(const QVector<VkSpecParser::Command> &commands, const QString &licHeaderFn, const QString &outputBase)
+{
+ QFile f(outputBase + QStringLiteral(".h"));
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("Failed to write %s", qPrintable(f.fileName()));
+ return false;
+ }
+
+ static const char *s =
+"%s\n"
+"#ifndef QVULKANFUNCTIONS_H\n"
+"#define QVULKANFUNCTIONS_H\n"
+"\n"
+"#include <QtGui/qtguiglobal.h>\n"
+"\n"
+"#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)\n"
+"\n"
+"#ifndef VK_NO_PROTOTYPES\n"
+"#define VK_NO_PROTOTYPES\n"
+"#endif\n"
+"#include <vulkan/vulkan.h>\n"
+"\n"
+"#include <QtCore/qscopedpointer.h>\n"
+"\n"
+"QT_BEGIN_NAMESPACE\n"
+"\n"
+"class QVulkanInstance;\n"
+"class QVulkanFunctionsPrivate;\n"
+"class QVulkanDeviceFunctionsPrivate;\n"
+"\n"
+"class Q_GUI_EXPORT QVulkanFunctions\n"
+"{\n"
+"public:\n"
+" ~QVulkanFunctions();\n"
+"\n"
+"%s\n"
+"private:\n"
+" Q_DISABLE_COPY(QVulkanFunctions)\n"
+" QVulkanFunctions(QVulkanInstance *inst);\n"
+"\n"
+" QScopedPointer<QVulkanFunctionsPrivate> d_ptr;\n"
+" friend class QVulkanInstance;\n"
+"};\n"
+"\n"
+"class Q_GUI_EXPORT QVulkanDeviceFunctions\n"
+"{\n"
+"public:\n"
+" ~QVulkanDeviceFunctions();\n"
+"\n"
+"%s\n"
+"private:\n"
+" Q_DISABLE_COPY(QVulkanDeviceFunctions)\n"
+" QVulkanDeviceFunctions(QVulkanInstance *inst, VkDevice device);\n"
+"\n"
+" QScopedPointer<QVulkanDeviceFunctionsPrivate> d_ptr;\n"
+" friend class QVulkanInstance;\n"
+"};\n"
+"\n"
+"QT_END_NAMESPACE\n"
+"\n"
+"#endif // QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)\n"
+"\n"
+"#endif // QVULKANFUNCTIONS_H\n";
+
+ QString instCmdStr;
+ QString devCmdStr;
+ for (const VkSpecParser::Command &c : commands) {
+ QString *dst = c.deviceLevel ? &devCmdStr : &instCmdStr;
+ *dst += QStringLiteral(" ");
+ *dst += funcSig(c);
+ *dst += QStringLiteral(";\n");
+ }
+
+ QString str;
+ str.sprintf(s, preamble.get(licHeaderFn).constData(), instCmdStr.toUtf8().constData(), devCmdStr.toUtf8().constData());
+
+ f.write(str.toUtf8());
+
+ return true;
+}
+
+bool genVulkanFunctionsPH(const QVector<VkSpecParser::Command> &commands, const QString &licHeaderFn, const QString &outputBase)
+{
+ QFile f(outputBase + QStringLiteral("_p.h"));
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("Failed to write %s", qPrintable(f.fileName()));
+ return false;
+ }
+
+ static const char *s =
+"%s\n"
+"#ifndef QVULKANFUNCTIONS_P_H\n"
+"#define QVULKANFUNCTIONS_P_H\n"
+"\n"
+"//\n"
+"// W A R N I N G\n"
+"// -------------\n"
+"//\n"
+"// This file is not part of the Qt API. It exists purely as an\n"
+"// implementation detail. This header file may change from version to\n"
+"// version without notice, or even be removed.\n"
+"//\n"
+"// We mean it.\n"
+"//\n"
+"\n"
+"#include \"qvulkanfunctions.h\"\n"
+"\n"
+"QT_BEGIN_NAMESPACE\n"
+"\n"
+"class QVulkanInstance;\n"
+"\n"
+"class QVulkanFunctionsPrivate\n"
+"{\n"
+"public:\n"
+" QVulkanFunctionsPrivate(QVulkanInstance *inst);\n"
+"\n"
+" PFN_vkVoidFunction m_funcs[%d];\n"
+"};\n"
+"\n"
+"class QVulkanDeviceFunctionsPrivate\n"
+"{\n"
+"public:\n"
+" QVulkanDeviceFunctionsPrivate(QVulkanInstance *inst, VkDevice device);\n"
+"\n"
+" PFN_vkVoidFunction m_funcs[%d];\n"
+"};\n"
+"\n"
+"QT_END_NAMESPACE\n"
+"\n"
+"#endif // QVULKANFUNCTIONS_P_H\n";
+
+ const int devLevelCount = std::count_if(commands.cbegin(), commands.cend(),
+ [](const VkSpecParser::Command &c) { return c.deviceLevel; });
+ const int instLevelCount = commands.count() - devLevelCount;
+
+ QString str;
+ str.sprintf(s, preamble.get(licHeaderFn).constData(), instLevelCount, devLevelCount);
+
+ f.write(str.toUtf8());
+
+ return true;
+}
+
+bool genVulkanFunctionsPC(const QVector<VkSpecParser::Command> &commands, const QString &licHeaderFn, const QString &outputBase)
+{
+ QFile f(outputBase + QStringLiteral("_p.cpp"));
+ if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ qWarning("Failed to write %s", qPrintable(f.fileName()));
+ return false;
+ }
+
+ static const char *s =
+"%s\n"
+"#include \"qvulkanfunctions_p.h\"\n"
+"#include \"qvulkaninstance.h\"\n"
+"\n"
+"QT_BEGIN_NAMESPACE\n"
+"\n%s"
+"QVulkanFunctionsPrivate::QVulkanFunctionsPrivate(QVulkanInstance *inst)\n"
+"{\n"
+" static const char *funcNames[] = {\n"
+"%s\n"
+" };\n"
+" for (int i = 0; i < %d; ++i) {\n"
+" m_funcs[i] = inst->getInstanceProcAddr(funcNames[i]);\n"
+" if (!m_funcs[i])\n"
+" qWarning(\"QVulkanFunctions: Failed to resolve %%s\", funcNames[i]);\n"
+" }\n"
+"}\n"
+"\n%s"
+"QVulkanDeviceFunctionsPrivate::QVulkanDeviceFunctionsPrivate(QVulkanInstance *inst, VkDevice device)\n"
+"{\n"
+" QVulkanFunctions *f = inst->functions();\n"
+" Q_ASSERT(f);\n\n"
+" static const char *funcNames[] = {\n"
+"%s\n"
+" };\n"
+" for (int i = 0; i < %d; ++i) {\n"
+" m_funcs[i] = f->vkGetDeviceProcAddr(device, funcNames[i]);\n"
+" if (!m_funcs[i])\n"
+" qWarning(\"QVulkanDeviceFunctions: Failed to resolve %%s\", funcNames[i]);\n"
+" }\n"
+"}\n"
+"\n"
+"QT_END_NAMESPACE\n";
+
+ QString devCmdWrapperStr;
+ QString instCmdWrapperStr;
+ int devIdx = 0;
+ int instIdx = 0;
+ QString devCmdNamesStr;
+ QString instCmdNamesStr;
+
+ for (int i = 0; i < commands.count(); ++i) {
+ QString *dst = commands[i].deviceLevel ? &devCmdWrapperStr : &instCmdWrapperStr;
+ int *idx = commands[i].deviceLevel ? &devIdx : &instIdx;
+ *dst += funcSig(commands[i], commands[i].deviceLevel ? "QVulkanDeviceFunctions" : "QVulkanFunctions");
+ *dst += QString(QStringLiteral("\n{\n Q_ASSERT(d_ptr->m_funcs[%1]);\n ")).arg(*idx);
+ *dst += funcCall(commands[i], *idx);
+ *dst += QStringLiteral(";\n}\n\n");
+ ++*idx;
+
+ dst = commands[i].deviceLevel ? &devCmdNamesStr : &instCmdNamesStr;
+ *dst += QStringLiteral(" \"");
+ *dst += commands[i].cmd.name;
+ *dst += QStringLiteral("\",\n");
+ }
+
+ if (devCmdNamesStr.count() > 2)
+ devCmdNamesStr = devCmdNamesStr.left(devCmdNamesStr.count() - 2);
+ if (instCmdNamesStr.count() > 2)
+ instCmdNamesStr = instCmdNamesStr.left(instCmdNamesStr.count() - 2);
+
+ QString str;
+ str.sprintf(s, preamble.get(licHeaderFn).constData(),
+ instCmdWrapperStr.toUtf8().constData(), instCmdNamesStr.toUtf8().constData(), instIdx,
+ devCmdWrapperStr.toUtf8().constData(), devCmdNamesStr.toUtf8().constData(), commands.count() - instIdx);
+
+ f.write(str.toUtf8());
+
+ return true;
+}
+
+int main(int argc, char **argv)
+{
+ QCoreApplication app(argc, argv);
+ VkSpecParser parser;
+
+ if (argc < 4) {
+ qWarning("Usage: qvkgen input_vk_xml input_license_header output_base\n"
+ " For example: qvkgen vulkan/vk.xml vulkan/qvulkanfunctions.header vulkan/qvulkanfunctions");
+ return 1;
+ }
+
+ parser.setFileName(QString::fromUtf8(argv[1]));
+
+ if (!parser.parse())
+ return 1;
+
+ QVector<VkSpecParser::Command> commands = parser.commands();
+ QStringList ignoredFuncs {
+ QStringLiteral("vkCreateInstance"),
+ QStringLiteral("vkDestroyInstance"),
+ QStringLiteral("vkGetInstanceProcAddr")
+ };
+
+ // Filter out extensions and unwanted functions.
+ // The check for the former is rather simplistic for now: skip if the last letter is uppercase...
+ for (int i = 0; i < commands.count(); ++i) {
+ QString name = commands[i].cmd.name;
+ QChar c = name[name.count() - 1];
+ if (c.isUpper() || ignoredFuncs.contains(name))
+ commands.remove(i--);
+ }
+
+ QString licenseHeaderFileName = QString::fromUtf8(argv[2]);
+ QString outputBase = QString::fromUtf8(argv[3]);
+ genVulkanFunctionsH(commands, licenseHeaderFileName, outputBase);
+ genVulkanFunctionsPH(commands, licenseHeaderFileName, outputBase);
+ genVulkanFunctionsPC(commands, licenseHeaderFileName, outputBase);
+
+ return 0;
+}
diff --git a/src/tools/qvkgen/qvkgen.pro b/src/tools/qvkgen/qvkgen.pro
new file mode 100644
index 0000000000..0428fdfe08
--- /dev/null
+++ b/src/tools/qvkgen/qvkgen.pro
@@ -0,0 +1,6 @@
+option(host_build)
+
+SOURCES += qvkgen.cpp
+
+QMAKE_TARGET_DESCRIPTION = "Qt Vulkan Header Generator"
+load(qt_tool)
diff --git a/src/tools/rcc/rcc.pro b/src/tools/rcc/rcc.pro
index 701f15ff22..208ec54a73 100644
--- a/src/tools/rcc/rcc.pro
+++ b/src/tools/rcc/rcc.pro
@@ -6,4 +6,5 @@ DEFINES += QT_RCC QT_NO_CAST_FROM_ASCII QT_NO_FOREACH
include(rcc.pri)
SOURCES += main.cpp
+QMAKE_TARGET_DESCRIPTION = "Qt Resource Compiler"
load(qt_tool)
diff --git a/src/tools/uic/cpp/cpp.pri b/src/tools/uic/cpp/cpp.pri
index 49c71a6dfa..a6b6188117 100644
--- a/src/tools/uic/cpp/cpp.pri
+++ b/src/tools/uic/cpp/cpp.pri
@@ -3,18 +3,10 @@ INCLUDEPATH += $$PWD $$QT_BUILD_TREE/src/tools/uic
DEFINES += QT_UIC_CPP_GENERATOR
# Input
-HEADERS += $$PWD/cppextractimages.h \
- $$PWD/cppwritedeclaration.h \
- $$PWD/cppwriteicondata.h \
- $$PWD/cppwriteicondeclaration.h \
- $$PWD/cppwriteiconinitialization.h \
+HEADERS += $$PWD/cppwritedeclaration.h \
$$PWD/cppwriteincludes.h \
$$PWD/cppwriteinitialization.h
-SOURCES += $$PWD/cppextractimages.cpp \
- $$PWD/cppwritedeclaration.cpp \
- $$PWD/cppwriteicondata.cpp \
- $$PWD/cppwriteicondeclaration.cpp \
- $$PWD/cppwriteiconinitialization.cpp \
+SOURCES += $$PWD/cppwritedeclaration.cpp \
$$PWD/cppwriteincludes.cpp \
$$PWD/cppwriteinitialization.cpp
diff --git a/src/tools/uic/cpp/cppextractimages.cpp b/src/tools/uic/cpp/cppextractimages.cpp
deleted file mode 100644
index 4d06d08dae..0000000000
--- a/src/tools/uic/cpp/cppextractimages.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "cppextractimages.h"
-#include "cppwriteicondata.h"
-#include "driver.h"
-#include "ui4.h"
-#include "utils.h"
-#include "uic.h"
-
-#include <qtextstream.h>
-#include <qtextcodec.h>
-#include <qdir.h>
-#include <qfile.h>
-#include <qfileinfo.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace CPP {
-
-ExtractImages::ExtractImages(const Option &opt)
- : m_output(0), m_option(opt)
-{
-}
-
-void ExtractImages::acceptUI(DomUI *node)
-{
- if (!m_option.extractImages)
- return;
-
- if (node->elementImages() == 0)
- return;
-
- QString className = node->elementClass() + m_option.postfix;
-
- QFile f;
- if (m_option.qrcOutputFile.size()) {
- f.setFileName(m_option.qrcOutputFile);
- if (!f.open(QIODevice::WriteOnly | QFile::Text)) {
- fprintf(stderr, "%s: Error: Could not create resource file\n", qPrintable(m_option.messagePrefix()));
- return;
- }
-
- QFileInfo fi(m_option.qrcOutputFile);
- QDir dir = fi.absoluteDir();
- if (!dir.exists(QLatin1String("images")) && !dir.mkdir(QLatin1String("images"))) {
- fprintf(stderr, "%s: Error: Could not create image dir\n", qPrintable(m_option.messagePrefix()));
- return;
- }
- dir.cd(QLatin1String("images"));
- m_imagesDir = dir;
-
- m_output = new QTextStream(&f);
-#ifndef QT_NO_TEXTCODEC
- m_output->setCodec(QTextCodec::codecForName("UTF-8"));
-#endif
-
- QTextStream &out = *m_output;
-
- out << "<RCC>\n";
- out << " <qresource prefix=\"/" << className << "\" >\n";
- TreeWalker::acceptUI(node);
- out << " </qresource>\n";
- out << "</RCC>\n";
-
- f.close();
- delete m_output;
- m_output = 0;
- }
-}
-
-void ExtractImages::acceptImages(DomImages *images)
-{
- TreeWalker::acceptImages(images);
-}
-
-void ExtractImages::acceptImage(DomImage *image)
-{
- QString format = image->elementData()->attributeFormat();
- QString extension = format.left(format.indexOf(QLatin1Char('.'))).toLower();
- QString fname = m_imagesDir.absoluteFilePath(image->attributeName() + QLatin1Char('.') + extension);
-
- *m_output << " <file>images/" << image->attributeName() << QLatin1Char('.') + extension << "</file>\n";
-
- QFile f;
- f.setFileName(fname);
- const bool isXPM_GZ = format == QLatin1String("XPM.GZ");
- QIODevice::OpenMode openMode = QIODevice::WriteOnly;
- if (isXPM_GZ)
- openMode |= QIODevice::Text;
- if (!f.open(openMode)) {
- fprintf(stderr, "%s: Error: Could not create image file %s: %s",
- qPrintable(m_option.messagePrefix()),
- qPrintable(fname), qPrintable(f.errorString()));
- return;
- }
-
- if (isXPM_GZ) {
- QTextStream *imageOut = new QTextStream(&f);
-#ifndef QT_NO_TEXTCODEC
- imageOut->setCodec(QTextCodec::codecForName("UTF-8"));
-#endif
-
- CPP::WriteIconData::writeImage(*imageOut, QString(), m_option.limitXPM_LineLength, image);
- delete imageOut;
- } else {
- CPP::WriteIconData::writeImage(f, image);
- }
-
- f.close();
-}
-
-} // namespace CPP
-
-QT_END_NAMESPACE
diff --git a/src/tools/uic/cpp/cppwritedeclaration.cpp b/src/tools/uic/cpp/cppwritedeclaration.cpp
index 3aadc878e3..e384a1e194 100644
--- a/src/tools/uic/cpp/cppwritedeclaration.cpp
+++ b/src/tools/uic/cpp/cppwritedeclaration.cpp
@@ -27,10 +27,7 @@
****************************************************************************/
#include "cppwritedeclaration.h"
-#include "cppwriteicondeclaration.h"
#include "cppwriteinitialization.h"
-#include "cppwriteiconinitialization.h"
-#include "cppextractimages.h"
#include "driver.h"
#include "ui4.h"
#include "uic.h"
@@ -56,47 +53,15 @@ namespace {
output << "} // namespace " << *it << "\n";
}
}
-
- void writeScriptContextClass(const QString &indent, QTextStream &str) {
- str << indent << "class ScriptContext\n"
- << indent << "{\n"
- << indent << "public:\n"
- << indent << " void run(const QString &script, QWidget *widget, const QWidgetList &childWidgets)\n"
- << indent << " {\n"
- << indent << " QScriptValue widgetObject = scriptEngine.newQObject(widget);\n"
- << indent << " QScriptValue childWidgetArray = scriptEngine.newArray (childWidgets.size());\n"
- << indent << " for (int i = 0; i < childWidgets.size(); i++)\n"
- << indent << " childWidgetArray.setProperty(i, scriptEngine.newQObject(childWidgets[i]));\n"
- << indent << " QScriptContext *ctx = scriptEngine.pushContext();\n"
- << indent << " ctx ->activationObject().setProperty(QLatin1String(\"widget\"), widgetObject);\n"
- << indent << " ctx ->activationObject().setProperty(QLatin1String(\"childWidgets\"), childWidgetArray);\n\n"
- << indent << " scriptEngine.evaluate(script);\n"
- << indent << " if (scriptEngine.hasUncaughtException ()) {\n"
- << indent << " qWarning() << \"An exception occurred at line \" << scriptEngine.uncaughtExceptionLineNumber()\n"
- << indent << " << \" of the script for \" << widget->objectName() << \": \" << engineError() << '\\n'\n"
- << indent << " << script;\n"
- << indent << " }\n\n"
- << indent << " scriptEngine.popContext();\n"
- << indent << " }\n\n"
- << indent << "private:\n"
- << indent << " QString engineError()\n"
- << indent << " {\n"
- << indent << " QScriptValue error = scriptEngine.evaluate(\"Error\");\n"
- << indent << " return error.toString();\n"
- << indent << " }\n\n"
- << indent << " QScriptEngine scriptEngine;\n"
- << indent << "};\n\n";
- }
}
namespace CPP {
-WriteDeclaration::WriteDeclaration(Uic *uic, bool activateScripts) :
+WriteDeclaration::WriteDeclaration(Uic *uic) :
m_uic(uic),
m_driver(uic->driver()),
m_output(uic->output()),
- m_option(uic->option()),
- m_activateScripts(activateScripts)
+ m_option(uic->option())
{
}
@@ -154,29 +119,7 @@ void WriteDeclaration::acceptUI(DomUI *node)
m_output << "\n";
- WriteInitialization(m_uic, m_activateScripts).acceptUI(node);
-
- if (node->elementImages()) {
- if (m_option.extractImages) {
- ExtractImages(m_uic->option()).acceptUI(node);
- } else {
- m_output << "\n"
- << "protected:\n"
- << m_option.indent << "enum IconID\n"
- << m_option.indent << "{\n";
- WriteIconDeclaration(m_uic).acceptUI(node);
-
- m_output << m_option.indent << m_option.indent << "unknown_ID\n"
- << m_option.indent << "};\n";
-
- WriteIconInitialization(m_uic).acceptUI(node);
- }
- }
-
- if (m_activateScripts) {
- m_output << "\nprivate:\n\n";
- writeScriptContextClass(m_option.indent, m_output);
- }
+ WriteInitialization(m_uic).acceptUI(node);
m_output << "};\n\n";
diff --git a/src/tools/uic/cpp/cppwritedeclaration.h b/src/tools/uic/cpp/cppwritedeclaration.h
index baa57c5978..ca2122293c 100644
--- a/src/tools/uic/cpp/cppwritedeclaration.h
+++ b/src/tools/uic/cpp/cppwritedeclaration.h
@@ -43,7 +43,7 @@ namespace CPP {
struct WriteDeclaration : public TreeWalker
{
- WriteDeclaration(Uic *uic, bool activateScripts);
+ WriteDeclaration(Uic *uic);
void acceptUI(DomUI *node) Q_DECL_OVERRIDE;
void acceptWidget(DomWidget *node) Q_DECL_OVERRIDE;
@@ -58,7 +58,6 @@ private:
Driver *m_driver;
QTextStream &m_output;
const Option &m_option;
- const bool m_activateScripts;
};
} // namespace CPP
diff --git a/src/tools/uic/cpp/cppwriteicondata.cpp b/src/tools/uic/cpp/cppwriteicondata.cpp
deleted file mode 100644
index 4601a4c5e9..0000000000
--- a/src/tools/uic/cpp/cppwriteicondata.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "cppwriteicondata.h"
-#include "driver.h"
-#include "ui4.h"
-#include "uic.h"
-
-#include <qtextstream.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace CPP {
-
-static QByteArray transformImageData(const QString &data)
-{
- int baSize = data.length() / 2;
- uchar *ba = new uchar[baSize];
- for (int i = 0; i < baSize; ++i) {
- char h = data[2 * (i)].toLatin1();
- char l = data[2 * (i) + 1].toLatin1();
- uchar r = 0;
- if (h <= '9')
- r += h - '0';
- else
- r += h - 'a' + 10;
- r = r << 4;
- if (l <= '9')
- r += l - '0';
- else
- r += l - 'a' + 10;
- ba[i] = r;
- }
- QByteArray ret(reinterpret_cast<const char *>(ba), baSize);
- delete [] ba;
- return ret;
-}
-
-static QByteArray unzipXPM(const QString &data, ulong &length)
-{
-#ifndef QT_NO_COMPRESS
- const int lengthOffset = 4;
- QByteArray ba(lengthOffset, ' ');
-
- // qUncompress() expects the first 4 bytes to be the expected length of the
- // uncompressed data
- ba[0] = (length & 0xff000000) >> 24;
- ba[1] = (length & 0x00ff0000) >> 16;
- ba[2] = (length & 0x0000ff00) >> 8;
- ba[3] = (length & 0x000000ff);
- ba.append(transformImageData(data));
- QByteArray baunzip = qUncompress(ba);
- return baunzip;
-#else
- Q_UNUSED(data);
- Q_UNUSED(length);
- return QByteArray();
-#endif
-}
-
-
-WriteIconData::WriteIconData(Uic *uic)
- : driver(uic->driver()), output(uic->output()), option(uic->option())
-{
-}
-
-void WriteIconData::acceptUI(DomUI *node)
-{
- TreeWalker::acceptUI(node);
-}
-
-void WriteIconData::acceptImages(DomImages *images)
-{
- TreeWalker::acceptImages(images);
-}
-
-void WriteIconData::acceptImage(DomImage *image)
-{
- // Limit line length when writing code.
- writeImage(output, option.indent, true, image);
-}
-
-void WriteIconData::writeImage(QTextStream &output, const QString &indent,
- bool limitXPM_LineLength, const DomImage *image)
-{
- QString img = image->attributeName() + QLatin1String("_data");
- QString data = image->elementData()->text();
- QString fmt = image->elementData()->attributeFormat();
- int size = image->elementData()->attributeLength();
-
- if (fmt == QLatin1String("XPM.GZ")) {
- ulong length = size;
- QByteArray baunzip = unzipXPM(data, length);
- length = baunzip.size();
- // shouldn't we test the initial 'length' against the
- // resulting 'length' to catch corrupt UIC files?
- int a = 0;
- int column = 0;
- bool inQuote = false;
- output << indent << "/* XPM */\n"
- << indent << "static const char* const " << img << "[] = { \n";
- while (baunzip[a] != '\"')
- a++;
- for (; a < (int) length; a++) {
- output << baunzip[a];
- if (baunzip[a] == '\n') {
- column = 0;
- } else if (baunzip[a] == '"') {
- inQuote = !inQuote;
- }
-
- column++;
- if (limitXPM_LineLength && column >= 512 && inQuote) {
- output << "\"\n\""; // be nice with MSVC & Co.
- column = 1;
- }
- }
-
- if (! baunzip.trimmed ().endsWith ("};"))
- output << "};";
-
- output << "\n\n";
- } else {
- output << indent << "static const unsigned char " << img << "[] = { \n";
- output << indent;
- int a ;
- for (a = 0; a < (int) (data.length()/2)-1; a++) {
- output << "0x" << QString(data[2*a]) << QString(data[2*a+1]) << ',';
- if (a % 12 == 11)
- output << '\n' << indent;
- else
- output << ' ';
- }
- output << "0x" << QString(data[2*a]) << QString(data[2*a+1]) << '\n';
- output << "};\n\n";
- }
-}
-
-void WriteIconData::writeImage(QIODevice &output, DomImage *image)
-{
- const QByteArray array = transformImageData(image->elementData()->text());
- output.write(array.constData(), array.size());
-}
-
-} // namespace CPP
-
-QT_END_NAMESPACE
diff --git a/src/tools/uic/cpp/cppwriteicondata.h b/src/tools/uic/cpp/cppwriteicondata.h
deleted file mode 100644
index c496d5a85b..0000000000
--- a/src/tools/uic/cpp/cppwriteicondata.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef CPPWRITEICONDATA_H
-#define CPPWRITEICONDATA_H
-
-#include "treewalker.h"
-
-QT_BEGIN_NAMESPACE
-
-class QTextStream;
-class QIODevice;
-class Driver;
-class Uic;
-
-struct Option;
-
-namespace CPP {
-
-class WriteIconData : public TreeWalker
-{
-public:
- WriteIconData(Uic *uic);
-
- void acceptUI(DomUI *node) Q_DECL_OVERRIDE;
- void acceptImages(DomImages *images) Q_DECL_OVERRIDE;
- void acceptImage(DomImage *image) Q_DECL_OVERRIDE;
-
- static void writeImage(QTextStream &output, const QString &indent,
- bool limitXPM_LineLength, const DomImage *image);
- static void writeImage(QIODevice &output, DomImage *image);
-
-private:
- Driver *driver;
- QTextStream &output;
- const Option &option;
-};
-
-} // namespace CPP
-
-QT_END_NAMESPACE
-
-#endif // CPPWRITEICONDATA_H
diff --git a/src/tools/uic/cpp/cppwriteiconinitialization.cpp b/src/tools/uic/cpp/cppwriteiconinitialization.cpp
deleted file mode 100644
index 33d1c8402e..0000000000
--- a/src/tools/uic/cpp/cppwriteiconinitialization.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the tools applications of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "cppwriteiconinitialization.h"
-#include "cppwriteicondata.h"
-#include "driver.h"
-#include "ui4.h"
-#include "utils.h"
-#include "uic.h"
-
-#include <qtextstream.h>
-#include <qstring.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace CPP {
-
-WriteIconInitialization::WriteIconInitialization(Uic *uic)
- : driver(uic->driver()), output(uic->output()), option(uic->option())
-{
- this->uic = uic;
-}
-
-void WriteIconInitialization::acceptUI(DomUI *node)
-{
- if (node->elementImages() == 0)
- return;
-
- QString className = node->elementClass() + option.postfix;
-
- output << option.indent << "static QPixmap " << iconFromDataFunction() << "(IconID id)\n"
- << option.indent << "{\n";
-
- WriteIconData(uic).acceptUI(node);
-
- output << option.indent << "switch (id) {\n";
-
- TreeWalker::acceptUI(node);
-
- output << option.indent << option.indent << "default: return QPixmap();\n";
-
- output << option.indent << "} // switch\n"
- << option.indent << "} // icon\n\n";
-}
-
-QString WriteIconInitialization::iconFromDataFunction()
-{
- return QLatin1String("qt_get_icon");
-}
-
-void WriteIconInitialization::acceptImages(DomImages *images)
-{
- TreeWalker::acceptImages(images);
-}
-
-void WriteIconInitialization::acceptImage(DomImage *image)
-{
- QString img = image->attributeName() + QLatin1String("_data");
- QString data = image->elementData()->text();
- QString fmt = image->elementData()->attributeFormat();
-
- QString imageId = image->attributeName() + QLatin1String("_ID");
- QString imageData = image->attributeName() + QLatin1String("_data");
- QString ind = option.indent + option.indent;
-
- output << ind << "case " << imageId << ": ";
-
- if (fmt == QLatin1String("XPM.GZ")) {
- output << "return " << "QPixmap((const char**)" << imageData << ");\n";
- } else {
- output << " { QImage img; img.loadFromData(" << imageData << ", sizeof(" << imageData << "), " << fixString(fmt, ind) << "); return QPixmap::fromImage(img); }\n";
- }
-}
-
-} // namespace CPP
-
-QT_END_NAMESPACE
diff --git a/src/tools/uic/cpp/cppwriteincludes.cpp b/src/tools/uic/cpp/cppwriteincludes.cpp
index dcbe400224..de64b85219 100644
--- a/src/tools/uic/cpp/cppwriteincludes.cpp
+++ b/src/tools/uic/cpp/cppwriteincludes.cpp
@@ -69,7 +69,7 @@ static inline QString moduleHeader(const QString &module, const QString &header)
namespace CPP {
WriteIncludes::WriteIncludes(Uic *uic)
- : m_uic(uic), m_output(uic->output()), m_scriptsActivated(false), m_laidOut(false)
+ : m_uic(uic), m_output(uic->output()), m_laidOut(false)
{
// When possible (no namespace) use the "QtModule/QClass" convention
// and create a re-mapping of the old header "qclass.h" to it. Do not do this
@@ -92,7 +92,6 @@ WriteIncludes::WriteIncludes(Uic *uic)
void WriteIncludes::acceptUI(DomUI *node)
{
- m_scriptsActivated = false;
m_laidOut = false;
m_localIncludes.clear();
m_globalIncludes.clear();
@@ -231,10 +230,6 @@ void WriteIncludes::acceptCustomWidget(DomCustomWidget *node)
if (className.isEmpty())
return;
- if (const DomScript *domScript = node->elementScript())
- if (!domScript->text().isEmpty())
- activateScripts();
-
if (!node->elementHeader() || node->elementHeader()->text().isEmpty()) {
add(className, false); // no header specified
} else {
@@ -296,21 +291,6 @@ void WriteIncludes::writeHeaders(const OrderedSet &headers, bool global)
}
}
-void WriteIncludes::acceptWidgetScripts(const DomScripts &scripts, DomWidget *, const DomWidgets &)
-{
- if (!scripts.empty()) {
- activateScripts();
- }
-}
-
-void WriteIncludes::activateScripts()
-{
- if (!m_scriptsActivated) {
- add(QLatin1String("QScriptEngine"));
- add(QLatin1String("QDebug"));
- m_scriptsActivated = true;
- }
-}
} // namespace CPP
QT_END_NAMESPACE
diff --git a/src/tools/uic/cpp/cppwriteincludes.h b/src/tools/uic/cpp/cppwriteincludes.h
index 7a6a499536..0d9c293efc 100644
--- a/src/tools/uic/cpp/cppwriteincludes.h
+++ b/src/tools/uic/cpp/cppwriteincludes.h
@@ -54,7 +54,6 @@ struct WriteIncludes : public TreeWalker
void acceptLayout(DomLayout *node) Q_DECL_OVERRIDE;
void acceptSpacer(DomSpacer *node) Q_DECL_OVERRIDE;
void acceptProperty(DomProperty *node) Q_DECL_OVERRIDE;
- void acceptWidgetScripts(const DomScripts &, DomWidget *, const DomWidgets &) Q_DECL_OVERRIDE;
//
// custom widgets
@@ -68,8 +67,6 @@ struct WriteIncludes : public TreeWalker
void acceptIncludes(DomIncludes *node) Q_DECL_OVERRIDE;
void acceptInclude(DomInclude *node) Q_DECL_OVERRIDE;
- bool scriptsActivated() const { return m_scriptsActivated; }
-
private:
void add(const QString &className, bool determineHeader = true, const QString &header = QString(), bool global = false);
@@ -79,7 +76,6 @@ private:
void insertInclude(const QString &header, bool global);
void writeHeaders(const OrderedSet &headers, bool global);
QString headerForClassName(const QString &className) const;
- void activateScripts();
const Uic *m_uic;
QTextStream &m_output;
@@ -94,7 +90,6 @@ private:
StringMap m_classToHeader;
StringMap m_oldHeaderToNewHeader;
- bool m_scriptsActivated;
bool m_laidOut;
};
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index d208ec6718..e599bc8f08 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -27,7 +27,6 @@
****************************************************************************/
#include "cppwriteinitialization.h"
-#include "cppwriteiconinitialization.h"
#include "driver.h"
#include "ui4.h"
#include "utils.h"
@@ -83,8 +82,8 @@ namespace {
int w = 0;
int h = 0;
- if (properties.contains(QLatin1String("sizeHint"))) {
- if (const DomSize *sizeHint = properties.value(QLatin1String("sizeHint"))->elementSize()) {
+ if (const DomProperty *sh = properties.value(QLatin1String("sizeHint"))) {
+ if (const DomSize *sizeHint = sh->elementSize()) {
w = sizeHint->elementWidth();
h = sizeHint->elementHeight();
}
@@ -92,17 +91,23 @@ namespace {
output << w << ", " << h << ", ";
// size type
- QString sizeType = properties.contains(QLatin1String("sizeType")) ?
- properties.value(QLatin1String("sizeType"))->elementEnum() :
- QString::fromLatin1("Expanding");
+ QString sizeType;
+ if (const DomProperty *st = properties.value(QLatin1String("sizeType"))) {
+ const QString value = st->elementEnum();
+ if (value.startsWith(QLatin1String("QSizePolicy::")))
+ sizeType = value;
+ else
+ sizeType = QLatin1String("QSizePolicy::") + value;
+ } else {
+ sizeType = QStringLiteral("QSizePolicy::Expanding");
+ }
- if (!sizeType.startsWith(QLatin1String("QSizePolicy::")))
- sizeType.prepend(QLatin1String("QSizePolicy::"));
// orientation
bool isVspacer = false;
- if (properties.contains(QLatin1String("orientation"))) {
- const QString orientation = properties.value(QLatin1String("orientation"))->elementEnum();
- if (orientation == QLatin1String("Qt::Vertical") || orientation == QLatin1String("Vertical")) isVspacer = true;
+ if (const DomProperty *o = properties.value(QLatin1String("orientation"))) {
+ const QString orientation = o->elementEnum();
+ if (orientation == QLatin1String("Qt::Vertical") || orientation == QLatin1String("Vertical"))
+ isVspacer = true;
}
if (isVspacer)
@@ -125,11 +130,6 @@ namespace {
str << indent << varName << "->" << setter << '(' << v << ");\n";
}
- void writeSetupUIScriptVariableDeclarations(const QString &indent, QTextStream &str) {
- str << indent << "ScriptContext scriptContext;\n"
- << indent << "QWidgetList childWidgets;\n";
- }
-
static inline bool iconHasStatePixmaps(const DomResourceIcon *i) {
return i->hasElementNormalOff() || i->hasElementNormalOn() ||
i->hasElementDisabledOff() || i->hasElementDisabledOn() ||
@@ -396,10 +396,8 @@ void WriteInitialization::LayoutDefaultHandler::writeProperty(int p, const QStri
int defaultStyleValue, bool suppressDefault, QTextStream &str) const
{
// User value
- const DomPropertyMap::const_iterator mit = properties.constFind(propertyName);
- const bool found = mit != properties.constEnd();
- if (found) {
- const int value = mit.value()->elementNumber();
+ if (const DomProperty *prop = properties.value(propertyName)) {
+ const int value = prop->elementNumber();
// Emulate the pre 4.3 behaviour: The value form default value was only used to determine
// the default value, layout properties were always written
const bool useLayoutFunctionPre43 = !suppressDefault && (m_state[p] == (HasDefaultFunction|HasDefaultValue)) && value == m_defaultValues[p];
@@ -461,7 +459,7 @@ static bool needsTranslation(const DomElement *element)
}
// --- WriteInitialization
-WriteInitialization::WriteInitialization(Uic *uic, bool activateScripts) :
+WriteInitialization::WriteInitialization(Uic *uic) :
m_uic(uic),
m_driver(uic->driver()), m_output(uic->output()), m_option(uic->option()),
m_indent(m_option.indent + m_option.indent),
@@ -472,14 +470,28 @@ WriteInitialization::WriteInitialization(Uic *uic, bool activateScripts) :
m_delayedOut(&m_delayedInitialization, QIODevice::WriteOnly),
m_refreshOut(&m_refreshInitialization, QIODevice::WriteOnly),
m_actionOut(&m_delayedActionInitialization, QIODevice::WriteOnly),
- m_activateScripts(activateScripts), m_layoutWidget(false),
+ m_layoutWidget(false),
m_firstThemeIcon(true)
{
}
+QString WriteInitialization::writeString(const QString &s, const QString &indent) const
+{
+ unsigned flags = 0;
+ const QString ret = fixString(s, indent, &flags);
+ if (flags & Utf8String)
+ return QLatin1String("QString::fromUtf8(") + ret + QLatin1Char(')');
+ // MSVC cannot concat L"foo" "bar" (C2308: concatenating mismatched strings),
+ // use QLatin1String instead (all platforms to avoid cross-compiling issues).
+ if (flags & MultiLineString)
+ return QLatin1String("QLatin1String(") + ret + QLatin1Char(')');
+ const QLatin1String stringWrapper = m_uic->option().stringLiteral ?
+ QLatin1String("QStringLiteral(") : QLatin1String("QLatin1String(");
+ return stringWrapper + ret + QLatin1Char(')');
+}
+
void WriteInitialization::acceptUI(DomUI *node)
{
- m_registeredImages.clear();
m_actionGroupChain.push(0);
m_widgetChain.push(0);
m_layoutChain.push(0);
@@ -490,9 +502,6 @@ void WriteInitialization::acceptUI(DomUI *node)
if (node->elementCustomWidgets())
TreeWalker::acceptCustomWidgets(node->elementCustomWidgets());
- if (node->elementImages())
- TreeWalker::acceptImages(node->elementImages());
-
if (m_option.generateImplemetation)
m_output << "#include <" << m_driver->headerFileName() << ">\n\n";
@@ -512,9 +521,6 @@ void WriteInitialization::acceptUI(DomUI *node)
m_output << m_option.indent << "void " << "setupUi(" << widgetClassName << " *" << varName << ")\n"
<< m_option.indent << "{\n";
- if (m_activateScripts)
- writeSetupUIScriptVariableDeclarations(m_indent, m_output);
-
const QStringList connections = m_uic->databaseInfo()->connections();
for (int i=0; i<connections.size(); ++i) {
QString connection = connections.at(i);
@@ -591,15 +597,15 @@ void WriteInitialization::addWizardPage(const QString &pageVarName, const DomWid
/* If the node has a (free-format) string "pageId" attribute (which could
* an integer or an enumeration value), use setPage(), else addPage(). */
QString id;
- const DomPropertyList attributes = page->elementAttribute();
+ const auto &attributes = page->elementAttribute();
if (!attributes.empty()) {
- const DomPropertyList::const_iterator acend = attributes.constEnd();
- for (DomPropertyList::const_iterator it = attributes.constBegin(); it != acend; ++it)
- if ((*it)->attributeName() == QLatin1String("pageId")) {
- if (const DomString *ds = (*it)->elementString())
+ for (const DomProperty *p : attributes) {
+ if (p->attributeName() == QLatin1String("pageId")) {
+ if (const DomString *ds = p->elementString())
id = ds->text();
break;
}
+ }
}
if (id.isEmpty()) {
m_output << m_indent << parentWidget << "->addPage(" << pageVarName << ");\n";
@@ -884,7 +890,7 @@ void WriteInitialization::acceptLayout(DomLayout *node)
const QString varName = m_driver->findOrInsertLayout(node);
const DomPropertyMap properties = propertyMap(node->elementProperty());
- const bool oldLayoutProperties = properties.constFind(QLatin1String("margin")) != properties.constEnd();
+ const bool oldLayoutProperties = properties.value(QLatin1String("margin")) != nullptr;
bool isGroupBox = false;
@@ -1149,9 +1155,7 @@ void WriteInitialization::writeProperties(const QString &varName,
if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QAxWidget"))) {
DomPropertyMap properties = propertyMap(lst);
- if (properties.contains(QLatin1String("control"))) {
- DomProperty *p = properties.value(QLatin1String("control"));
- Q_ASSERT( p );
+ if (DomProperty *p = properties.value(QLatin1String("control"))) {
m_output << m_indent << varName << "->setControl("
<< writeString(toString(p->elementString()), m_dindent) << ");\n";
}
@@ -1612,10 +1616,10 @@ QString WriteInitialization::writeFontProperties(const DomFont *f)
}
// Post 4.4 write resource icon
-static void writeResourceIcon(QTextStream &output,
- const QString &iconName,
- const QString &indent,
- const DomResourceIcon *i)
+void WriteInitialization::writeResourceIcon(QTextStream &output,
+ const QString &iconName,
+ const QString &indent,
+ const DomResourceIcon *i) const
{
if (i->hasElementNormalOff())
output << indent << iconName << ".addFile(" << writeString(i->elementNormalOff()->text(), indent) << ", QSize(), QIcon::Normal, QIcon::Off);\n";
@@ -1708,7 +1712,7 @@ void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QStri
return;
// old format
- const QList<DomColor*> colors = colorGroup->elementColor();
+ const auto &colors = colorGroup->elementColor();
for (int i=0; i<colors.size(); ++i) {
const DomColor *color = colors.at(i);
@@ -1719,7 +1723,7 @@ void WriteInitialization::writeColorGroup(DomColorGroup *colorGroup, const QStri
}
// new format
- const QList<DomColorRole *> colorRoles = colorGroup->elementColorRole();
+ const auto &colorRoles = colorGroup->elementColorRole();
for (const DomColorRole *colorRole : colorRoles) {
if (colorRole->hasAttributeRole()) {
const QString brushName = writeBrushInitialization(colorRole->elementBrush());
@@ -1796,7 +1800,7 @@ void WriteInitialization::writeBrush(const DomBrush *brush, const QString &brush
<< gradient->attributeCoordinateMode() << ");\n";
}
- const QList<DomGradientStop *> stops = gradient->elementGradientStop();
+ const auto &stops = gradient->elementGradientStop();
for (const DomGradientStop *stop : stops) {
const DomColor *color = stop->elementColor();
m_output << m_indent << gradientName << ".setColorAt("
@@ -1894,23 +1898,6 @@ QString WriteInitialization::pixCall(const QString &t, const QString &text) cons
type += QLatin1String("()");
return type;
}
- if (const DomImage *image = findImage(text)) {
- if (m_option.extractImages) {
- const QString format = image->elementData()->attributeFormat();
- const QString extension = format.left(format.indexOf(QLatin1Char('.'))).toLower();
- return QLatin1String("QPixmap(QString::fromUtf8(\":/")
- + m_generatedClass
- + QLatin1String("/images/")
- + text
- + QLatin1Char('.')
- + extension
- + QLatin1String("\"))");
- }
- return WriteIconInitialization::iconFromDataFunction()
- + QLatin1Char('(')
- + text
- + QLatin1String("_ID)");
- }
QString pixFunc = m_uic->pixmapFunction();
if (pixFunc.isEmpty())
@@ -1927,63 +1914,34 @@ QString WriteInitialization::pixCall(const QString &t, const QString &text) cons
void WriteInitialization::initializeComboBox(DomWidget *w)
{
const QString varName = m_driver->findOrInsertWidget(w);
- const QString className = w->attributeClass();
- const QList<DomItem*> items = w->elementItem();
+ const auto &items = w->elementItem();
if (items.isEmpty())
return;
- // If possible use qcombobox's addItems() which is much faster then a bunch of addItem() calls
- bool makeStringListCall = true;
- bool translatable = false;
- QStringList list;
- for (int i=0; i<items.size(); ++i) {
+ for (int i = 0; i < items.size(); ++i) {
const DomItem *item = items.at(i);
const DomPropertyMap properties = propertyMap(item->elementProperty());
const DomProperty *text = properties.value(QLatin1String("text"));
- const DomProperty *pixmap = properties.value(QLatin1String("icon"));
- bool needsTr = needsTranslation(text->elementString());
- if (pixmap != 0 || (i > 0 && translatable != needsTr)) {
- makeStringListCall = false;
- break;
- }
- translatable = needsTr;
- list.append(autoTrCall(text->elementString())); // fix me here
- }
+ const DomProperty *icon = properties.value(QLatin1String("icon"));
- if (makeStringListCall) {
- QTextStream &o = translatable ? m_refreshOut : m_output;
- if (translatable)
- o << m_indent << varName << "->clear();\n";
- o << m_indent << varName << "->insertItems(0, QStringList()" << '\n';
- for (int i = 0; i < list.size(); ++i)
- o << m_indent << " << " << list.at(i) << "\n";
- o << m_indent << ");\n";
- } else {
- for (int i = 0; i < items.size(); ++i) {
- const DomItem *item = items.at(i);
- const DomPropertyMap properties = propertyMap(item->elementProperty());
- const DomProperty *text = properties.value(QLatin1String("text"));
- const DomProperty *icon = properties.value(QLatin1String("icon"));
-
- QString iconValue;
- if (icon)
- iconValue = iconCall(icon);
-
- m_output << m_indent << varName << "->addItem(";
- if (icon)
- m_output << iconValue << ", ";
-
- if (needsTranslation(text->elementString())) {
- m_output << "QString());\n";
- m_refreshOut << m_indent << varName << "->setItemText(" << i << ", " << trCall(text->elementString()) << ");\n";
- } else {
- m_output << noTrCall(text->elementString()) << ");\n";
- }
+ QString iconValue;
+ if (icon)
+ iconValue = iconCall(icon);
+
+ m_output << m_indent << varName << "->addItem(";
+ if (icon)
+ m_output << iconValue << ", ";
+
+ if (needsTranslation(text->elementString())) {
+ m_output << "QString());\n";
+ m_refreshOut << m_indent << varName << "->setItemText(" << i << ", " << trCall(text->elementString()) << ");\n";
+ } else {
+ m_output << noTrCall(text->elementString()) << ");\n";
}
- m_refreshOut << "\n";
}
+ m_refreshOut << "\n";
}
QString WriteInitialization::disableSorting(DomWidget *w, const QString &varName)
@@ -2118,9 +2076,8 @@ void WriteInitialization::addCommonInitializers(Item *item,
void WriteInitialization::initializeListWidget(DomWidget *w)
{
const QString varName = m_driver->findOrInsertWidget(w);
- const QString className = w->attributeClass();
- const QList<DomItem*> items = w->elementItem();
+ const auto &items = w->elementItem();
if (items.isEmpty())
return;
@@ -2150,7 +2107,7 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w)
// columns
Item item(QLatin1String("QTreeWidgetItem"), m_indent, m_output, m_refreshOut, m_driver);
- const QList<DomColumn*> columns = w->elementColumn();
+ const auto &columns = w->elementColumn();
for (int i = 0; i < columns.size(); ++i) {
const DomColumn *column = columns.at(i);
@@ -2193,7 +2150,7 @@ void WriteInitialization::initializeTreeWidget(DomWidget *w)
conditions an item is needed needs to be done bottom-up, the whole process makes
two passes, storing the intermediate result in a recursive StringInitializerListMap.
*/
-QList<WriteInitialization::Item *> WriteInitialization::initializeTreeWidgetItems(const QList<DomItem *> &domItems)
+QList<WriteInitialization::Item *> WriteInitialization::initializeTreeWidgetItems(const QVector<DomItem *> &domItems)
{
// items
QList<Item *> items;
@@ -2237,7 +2194,7 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
const QString varName = m_driver->findOrInsertWidget(w);
// columns
- const QList<DomColumn *> columns = w->elementColumn();
+ const auto &columns = w->elementColumn();
if (columns.size() != 0) {
m_output << m_indent << "if (" << varName << "->columnCount() < " << columns.size() << ")\n"
@@ -2259,7 +2216,7 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
}
// rows
- const QList<DomRow *> rows = w->elementRow();
+ const auto &rows = w->elementRow();
if (rows.size() != 0) {
m_output << m_indent << "if (" << varName << "->rowCount() < " << rows.size() << ")\n"
@@ -2283,7 +2240,7 @@ void WriteInitialization::initializeTableWidget(DomWidget *w)
// items
QString tempName = disableSorting(w, varName);
- const QList<DomItem *> items = w->elementItem();
+ const auto &items = w->elementItem();
for (int i = 0; i < items.size(); ++i) {
const DomItem *cell = items.at(i);
@@ -2428,11 +2385,6 @@ void WriteInitialization::acceptConnection(DomConnection *connection)
<< ");\n";
}
-DomImage *WriteInitialization::findImage(const QString &name) const
-{
- return m_registeredImages.value(name);
-}
-
DomWidget *WriteInitialization::findWidget(QLatin1String widgetClass)
{
for (int i = m_widgetChain.count() - 1; i >= 0; --i) {
@@ -2445,49 +2397,6 @@ DomWidget *WriteInitialization::findWidget(QLatin1String widgetClass)
return 0;
}
-void WriteInitialization::acceptImage(DomImage *image)
-{
- if (!image->hasAttributeName())
- return;
-
- m_registeredImages.insert(image->attributeName(), image);
-}
-
-void WriteInitialization::acceptWidgetScripts(const DomScripts &widgetScripts, DomWidget *node, const DomWidgets &childWidgets)
-{
- // Add the per-class custom scripts to the per-widget ones.
- DomScripts scripts(widgetScripts);
-
- if (DomScript *customWidgetScript = m_uic->customWidgetsInfo()->customWidgetScript(node->attributeClass()))
- scripts.push_front(customWidgetScript);
-
- if (scripts.empty())
- return;
-
- // concatenate script snippets
- QString script;
- for (const DomScript *domScript : qAsConst(scripts)) {
- const QString snippet = domScript->text();
- if (!snippet.isEmpty())
- script += QStringRef(&snippet).trimmed() + QLatin1Char('\n');
- }
- if (script.isEmpty())
- return;
-
- // Build the list of children and insert call
- m_output << m_indent << "childWidgets.clear();\n";
- if (!childWidgets.empty()) {
- m_output << m_indent << "childWidgets";
- for (DomWidget *child : childWidgets)
- m_output << " << " << m_driver->findOrInsertWidget(child);
- m_output << ";\n";
- }
- m_output << m_indent << "scriptContext.run("
- << writeString(script, m_dindent) << ", "
- << m_driver->findOrInsertWidget(node) << ", childWidgets);\n";
-}
-
-
static void generateMultiDirectiveBegin(QTextStream &outputStream, const QSet<QString> &directives)
{
if (directives.isEmpty())
diff --git a/src/tools/uic/cpp/cppwriteinitialization.h b/src/tools/uic/cpp/cppwriteinitialization.h
index a9691e1de4..b26f51875d 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.h
+++ b/src/tools/uic/cpp/cppwriteinitialization.h
@@ -88,14 +88,13 @@ struct WriteInitialization : public TreeWalker
typedef QList<DomProperty*> DomPropertyList;
typedef QHash<QString, DomProperty*> DomPropertyMap;
- WriteInitialization(Uic *uic, bool activateScripts);
+ WriteInitialization(Uic *uic);
//
// widgets
//
void acceptUI(DomUI *node) Q_DECL_OVERRIDE;
void acceptWidget(DomWidget *node) Q_DECL_OVERRIDE;
- void acceptWidgetScripts(const DomScripts &, DomWidget *node, const DomWidgets &childWidgets) Q_DECL_OVERRIDE;
void acceptLayout(DomLayout *node) Q_DECL_OVERRIDE;
void acceptSpacer(DomSpacer *node) Q_DECL_OVERRIDE;
@@ -130,11 +129,6 @@ struct WriteInitialization : public TreeWalker
//
void acceptConnection(DomConnection *connection) Q_DECL_OVERRIDE;
-//
-// images
-//
- void acceptImage(DomImage *image) Q_DECL_OVERRIDE;
-
enum {
Use43UiFile = 0,
TopLevelMargin,
@@ -145,6 +139,8 @@ struct WriteInitialization : public TreeWalker
private:
static QString domColor2QString(const DomColor *c);
+ QString writeString(const QString &s, const QString &indent) const;
+
QString iconCall(const DomProperty *prop);
QString pixCall(const DomProperty *prop) const;
QString pixCall(const QString &type, const QString &text) const;
@@ -221,7 +217,7 @@ private:
void initializeComboBox(DomWidget *w);
void initializeListWidget(DomWidget *w);
void initializeTreeWidget(DomWidget *w);
- QList<Item *> initializeTreeWidgetItems(const QList<DomItem *> &domItems);
+ QList<Item *> initializeTreeWidgetItems(const QVector<DomItem *> &domItems);
void initializeTableWidget(DomWidget *w);
QString disableSorting(DomWidget *w, const QString &varName);
@@ -229,12 +225,12 @@ private:
QString findDeclaration(const QString &name);
DomWidget *findWidget(QLatin1String widgetClass);
- DomImage *findImage(const QString &name) const;
bool isValidObject(const QString &name) const;
private:
QString writeFontProperties(const DomFont *f);
+ void writeResourceIcon(QTextStream &output, const QString &iconName, const QString &indent, const DomResourceIcon *i) const;
QString writeIconProperties(const DomResourceIcon *i);
QString writeSizePolicy(const DomSizePolicy *sp);
QString writeBrushInitialization(const DomBrush *brush);
@@ -263,7 +259,6 @@ private:
QSet<QString> m_buttonGroups;
QHash<QString, DomWidget*> m_registeredWidgets;
- QHash<QString, DomImage*> m_registeredImages;
QHash<QString, DomAction*> m_registeredActions;
typedef QHash<uint, QString> ColorBrushHash;
ColorBrushHash m_colorBrushHash;
@@ -314,7 +309,6 @@ private:
QString m_delayedActionInitialization;
QTextStream m_actionOut;
- const bool m_activateScripts;
bool m_layoutWidget;
bool m_firstThemeIcon;
diff --git a/src/tools/uic/customwidgetsinfo.cpp b/src/tools/uic/customwidgetsinfo.cpp
index 662a249d71..6883b715ae 100644
--- a/src/tools/uic/customwidgetsinfo.cpp
+++ b/src/tools/uic/customwidgetsinfo.cpp
@@ -91,18 +91,6 @@ QString CustomWidgetsInfo::realClassName(const QString &className) const
return className;
}
-DomScript *CustomWidgetsInfo::customWidgetScript(const QString &name) const
-{
- if (m_customWidgets.empty())
- return 0;
-
- const NameCustomWidgetMap::const_iterator it = m_customWidgets.constFind(name);
- if (it == m_customWidgets.constEnd())
- return 0;
-
- return it.value()->elementScript();
-}
-
QString CustomWidgetsInfo::customWidgetAddPageMethod(const QString &name) const
{
if (DomCustomWidget *dcw = m_customWidgets.value(name, 0))
diff --git a/src/tools/uic/customwidgetsinfo.h b/src/tools/uic/customwidgetsinfo.h
index 7bc2b62619..3ce27d546c 100644
--- a/src/tools/uic/customwidgetsinfo.h
+++ b/src/tools/uic/customwidgetsinfo.h
@@ -57,8 +57,6 @@ public:
inline DomCustomWidget *customWidget(const QString &name) const
{ return m_customWidgets.value(name); }
- DomScript *customWidgetScript(const QString &name) const;
-
QString customWidgetAddPageMethod(const QString &name) const;
QString realClassName(const QString &className) const;
diff --git a/src/tools/uic/databaseinfo.cpp b/src/tools/uic/databaseinfo.cpp
index 73fcf06c54..fa5d5f5df0 100644
--- a/src/tools/uic/databaseinfo.cpp
+++ b/src/tools/uic/databaseinfo.cpp
@@ -52,11 +52,11 @@ void DatabaseInfo::acceptWidget(DomWidget *node)
{
QHash<QString, DomProperty*> properties = propertyMap(node->elementProperty());
- DomProperty *frameworkCode = properties.value(QLatin1String("frameworkCode"), 0);
+ DomProperty *frameworkCode = properties.value(QLatin1String("frameworkCode"));
if (frameworkCode && toBool(frameworkCode->elementBool()) == false)
return;
- DomProperty *db = properties.value(QLatin1String("database"), 0);
+ DomProperty *db = properties.value(QLatin1String("database"));
if (db && db->elementStringList()) {
QStringList info = db->elementStringList()->elementString();
diff --git a/src/tools/uic/main.cpp b/src/tools/uic/main.cpp
index 3599470403..46a1e66bcc 100644
--- a/src/tools/uic/main.cpp
+++ b/src/tools/uic/main.cpp
@@ -75,6 +75,10 @@ int runUic(int argc, char *argv[])
noImplicitIncludesOption.setDescription(QStringLiteral("Disable generation of #include-directives."));
parser.addOption(noImplicitIncludesOption);
+ QCommandLineOption noStringLiteralOption(QStringList() << QStringLiteral("s") << QStringLiteral("no-stringliteral"));
+ noStringLiteralOption.setDescription(QStringLiteral("Use QLatin1String instead of QStringLiteral in generated code."));
+ parser.addOption(noStringLiteralOption);
+
QCommandLineOption postfixOption(QStringLiteral("postfix"));
postfixOption.setDescription(QStringLiteral("Postfix to add to all generated classnames."));
postfixOption.setValueName(QStringLiteral("postfix"));
@@ -107,6 +111,7 @@ int runUic(int argc, char *argv[])
driver.option().outputFile = parser.value(outputOption);
driver.option().headerProtection = !parser.isSet(noProtOption);
driver.option().implicitIncludes = !parser.isSet(noImplicitIncludesOption);
+ driver.option().stringLiteral = !parser.isSet(noStringLiteralOption);
driver.option().idBased = parser.isSet(idBasedOption);
driver.option().postfix = parser.value(postfixOption);
driver.option().translateFunction = parser.value(translateOption);
diff --git a/src/tools/uic/option.h b/src/tools/uic/option.h
index 1483d94c07..c7278393fb 100644
--- a/src/tools/uic/option.h
+++ b/src/tools/uic/option.h
@@ -48,10 +48,10 @@ struct Option
unsigned int generateNamespace : 1;
unsigned int autoConnection : 1;
unsigned int dependencies : 1;
- unsigned int extractImages : 1;
unsigned int limitXPM_LineLength : 1;
unsigned int implicitIncludes: 1;
unsigned int idBased: 1;
+ unsigned int stringLiteral: 1;
Generator generator;
QString inputFile;
@@ -74,10 +74,10 @@ struct Option
generateNamespace(1),
autoConnection(1),
dependencies(0),
- extractImages(0),
limitXPM_LineLength(0),
implicitIncludes(1),
idBased(0),
+ stringLiteral(1),
generator(CppGenerator),
prefix(QLatin1String("Ui_"))
{ indent.fill(QLatin1Char(' '), 4); }
diff --git a/src/tools/uic/treewalker.cpp b/src/tools/uic/treewalker.cpp
index eb9f1c02f8..4c9981580b 100644
--- a/src/tools/uic/treewalker.cpp
+++ b/src/tools/uic/treewalker.cpp
@@ -38,9 +38,6 @@ void TreeWalker::acceptUI(DomUI *ui)
acceptButtonGroups(domButtonGroups);
acceptTabStops(ui->elementTabStops());
-
- if (ui->elementImages())
- acceptImages(ui->elementImages());
}
void TreeWalker::acceptLayoutDefault(DomLayoutDefault *layoutDefault)
@@ -112,9 +109,6 @@ void TreeWalker::acceptWidget(DomWidget *widget)
if (!widget->elementLayout().isEmpty())
acceptLayout(widget->elementLayout().at(0));
-
- const DomScripts scripts(widget->elementScript());
- acceptWidgetScripts(scripts, widget, childWidgets);
}
void TreeWalker::acceptSpacer(DomSpacer *spacer)
@@ -251,17 +245,6 @@ void TreeWalker::acceptActionRef(DomActionRef *actionRef)
Q_UNUSED(actionRef);
}
-void TreeWalker::acceptImages(DomImages *images)
-{
- for (int i=0; i<images->elementImage().size(); ++i)
- acceptImage(images->elementImage().at(i));
-}
-
-void TreeWalker::acceptImage(DomImage *image)
-{
- Q_UNUSED(image);
-}
-
void TreeWalker::acceptIncludes(DomIncludes *includes)
{
for (int i=0; i<includes->elementInclude().size(); ++i)
@@ -295,17 +278,11 @@ void TreeWalker::acceptConnectionHint(DomConnectionHint *connectionHint)
Q_UNUSED(connectionHint);
}
-void TreeWalker::acceptWidgetScripts(const DomScripts &, DomWidget *, const DomWidgets &)
-{
-}
-
void TreeWalker::acceptButtonGroups(const DomButtonGroups *domButtonGroups)
{
- typedef QList<DomButtonGroup*> DomButtonGroupList;
- const DomButtonGroupList domGroups = domButtonGroups->elementButtonGroup();
- const DomButtonGroupList::const_iterator cend = domGroups.constEnd();
- for (DomButtonGroupList::const_iterator it = domGroups.constBegin(); it != cend; ++it)
- acceptButtonGroup(*it);
+ const auto &domGroups = domButtonGroups->elementButtonGroup();
+ for (const DomButtonGroup *g : domGroups)
+ acceptButtonGroup(g);
}
void TreeWalker::acceptButtonGroup(const DomButtonGroup *)
diff --git a/src/tools/uic/treewalker.h b/src/tools/uic/treewalker.h
index 0739f5138c..78da17d628 100644
--- a/src/tools/uic/treewalker.h
+++ b/src/tools/uic/treewalker.h
@@ -101,11 +101,8 @@ struct TreeWalker
virtual void acceptTime(DomTime *time);
virtual void acceptDateTime(DomDateTime *dateTime);
virtual void acceptProperty(DomProperty *property);
- typedef QList<DomScript *> DomScripts;
- typedef QList<DomWidget *> DomWidgets;
- virtual void acceptWidgetScripts(const DomScripts &, DomWidget *node, const DomWidgets &childWidgets);
- virtual void acceptImages(DomImages *images);
- virtual void acceptImage(DomImage *image);
+ typedef QVector<DomScript *> DomScripts;
+ typedef QVector<DomWidget *> DomWidgets;
virtual void acceptIncludes(DomIncludes *includes);
virtual void acceptInclude(DomInclude *incl);
virtual void acceptAction(DomAction *action);
diff --git a/src/tools/uic/ui4.cpp b/src/tools/uic/ui4.cpp
index 5a609ef42b..bc1039871e 100644
--- a/src/tools/uic/ui4.cpp
+++ b/src/tools/uic/ui4.cpp
@@ -40,71 +40,6 @@ using namespace QFormInternal;
** Implementations
*/
-void DomUI::clear(bool clear_all)
-{
- delete m_widget;
- delete m_layoutDefault;
- delete m_layoutFunction;
- delete m_customWidgets;
- delete m_tabStops;
- delete m_images;
- delete m_includes;
- delete m_resources;
- delete m_connections;
- delete m_designerdata;
- delete m_slots;
- delete m_buttonGroups;
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_version = false;
- m_has_attr_language = false;
- m_has_attr_displayname = false;
- m_has_attr_stdsetdef = false;
- m_attr_stdsetdef = 0;
- m_has_attr_stdSetDef = false;
- m_attr_stdSetDef = 0;
- }
-
- m_children = 0;
- m_widget = 0;
- m_layoutDefault = 0;
- m_layoutFunction = 0;
- m_customWidgets = 0;
- m_tabStops = 0;
- m_images = 0;
- m_includes = 0;
- m_resources = 0;
- m_connections = 0;
- m_designerdata = 0;
- m_slots = 0;
- m_buttonGroups = 0;
-}
-
-DomUI::DomUI()
-{
- m_children = 0;
- m_has_attr_version = false;
- m_has_attr_language = false;
- m_has_attr_displayname = false;
- m_has_attr_stdsetdef = false;
- m_attr_stdsetdef = 0;
- m_has_attr_stdSetDef = false;
- m_attr_stdSetDef = 0;
- m_widget = 0;
- m_layoutDefault = 0;
- m_layoutFunction = 0;
- m_customWidgets = 0;
- m_tabStops = 0;
- m_images = 0;
- m_includes = 0;
- m_resources = 0;
- m_connections = 0;
- m_designerdata = 0;
- m_slots = 0;
- m_buttonGroups = 0;
-}
-
DomUI::~DomUI()
{
delete m_widget;
@@ -112,7 +47,6 @@ DomUI::~DomUI()
delete m_layoutFunction;
delete m_customWidgets;
delete m_tabStops;
- delete m_images;
delete m_includes;
delete m_resources;
delete m_connections;
@@ -123,10 +57,9 @@ DomUI::~DomUI()
void DomUI::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("version")) {
setAttributeVersion(attribute.value().toString());
continue;
@@ -150,97 +83,96 @@ void DomUI::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("author")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("author"), Qt::CaseInsensitive)) {
setElementAuthor(reader.readElementText());
continue;
}
- if (tag == QLatin1String("comment")) {
+ if (!tag.compare(QLatin1String("comment"), Qt::CaseInsensitive)) {
setElementComment(reader.readElementText());
continue;
}
- if (tag == QLatin1String("exportmacro")) {
+ if (!tag.compare(QLatin1String("exportmacro"), Qt::CaseInsensitive)) {
setElementExportMacro(reader.readElementText());
continue;
}
- if (tag == QLatin1String("class")) {
+ if (!tag.compare(QLatin1String("class"), Qt::CaseInsensitive)) {
setElementClass(reader.readElementText());
continue;
}
- if (tag == QLatin1String("widget")) {
+ if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
DomWidget *v = new DomWidget();
v->read(reader);
setElementWidget(v);
continue;
}
- if (tag == QLatin1String("layoutdefault")) {
+ if (!tag.compare(QLatin1String("layoutdefault"), Qt::CaseInsensitive)) {
DomLayoutDefault *v = new DomLayoutDefault();
v->read(reader);
setElementLayoutDefault(v);
continue;
}
- if (tag == QLatin1String("layoutfunction")) {
+ if (!tag.compare(QLatin1String("layoutfunction"), Qt::CaseInsensitive)) {
DomLayoutFunction *v = new DomLayoutFunction();
v->read(reader);
setElementLayoutFunction(v);
continue;
}
- if (tag == QLatin1String("pixmapfunction")) {
+ if (!tag.compare(QLatin1String("pixmapfunction"), Qt::CaseInsensitive)) {
setElementPixmapFunction(reader.readElementText());
continue;
}
- if (tag == QLatin1String("customwidgets")) {
+ if (!tag.compare(QLatin1String("customwidgets"), Qt::CaseInsensitive)) {
DomCustomWidgets *v = new DomCustomWidgets();
v->read(reader);
setElementCustomWidgets(v);
continue;
}
- if (tag == QLatin1String("tabstops")) {
+ if (!tag.compare(QLatin1String("tabstops"), Qt::CaseInsensitive)) {
DomTabStops *v = new DomTabStops();
v->read(reader);
setElementTabStops(v);
continue;
}
- if (tag == QLatin1String("images")) {
- DomImages *v = new DomImages();
- v->read(reader);
- setElementImages(v);
+ if (!tag.compare(QLatin1String("images"), Qt::CaseInsensitive)) {
+ qWarning("Omitting deprecated element <images>.");
+ reader.skipCurrentElement();
continue;
}
- if (tag == QLatin1String("includes")) {
+ if (!tag.compare(QLatin1String("includes"), Qt::CaseInsensitive)) {
DomIncludes *v = new DomIncludes();
v->read(reader);
setElementIncludes(v);
continue;
}
- if (tag == QLatin1String("resources")) {
+ if (!tag.compare(QLatin1String("resources"), Qt::CaseInsensitive)) {
DomResources *v = new DomResources();
v->read(reader);
setElementResources(v);
continue;
}
- if (tag == QLatin1String("connections")) {
+ if (!tag.compare(QLatin1String("connections"), Qt::CaseInsensitive)) {
DomConnections *v = new DomConnections();
v->read(reader);
setElementConnections(v);
continue;
}
- if (tag == QLatin1String("designerdata")) {
+ if (!tag.compare(QLatin1String("designerdata"), Qt::CaseInsensitive)) {
DomDesignerData *v = new DomDesignerData();
v->read(reader);
setElementDesignerdata(v);
continue;
}
- if (tag == QLatin1String("slots")) {
+ if (!tag.compare(QLatin1String("slots"), Qt::CaseInsensitive)) {
DomSlots *v = new DomSlots();
v->read(reader);
setElementSlots(v);
continue;
}
- if (tag == QLatin1String("buttongroups")) {
+ if (!tag.compare(QLatin1String("buttongroups"), Qt::CaseInsensitive)) {
DomButtonGroups *v = new DomButtonGroups();
v->read(reader);
setElementButtonGroups(v);
@@ -250,12 +182,7 @@ void DomUI::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -264,7 +191,7 @@ void DomUI::read(QXmlStreamReader &reader)
void DomUI::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("ui") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("ui") : tagName.toLower());
if (hasAttributeVersion())
writer.writeAttribute(QStringLiteral("version"), attributeVersion());
@@ -281,284 +208,246 @@ void DomUI::write(QXmlStreamWriter &writer, const QString &tagName) const
if (hasAttributeStdSetDef())
writer.writeAttribute(QStringLiteral("stdsetdef"), QString::number(attributeStdSetDef()));
- if (m_children & Author) {
+ if (m_children & Author)
writer.writeTextElement(QStringLiteral("author"), m_author);
- }
- if (m_children & Comment) {
+ if (m_children & Comment)
writer.writeTextElement(QStringLiteral("comment"), m_comment);
- }
- if (m_children & ExportMacro) {
+ if (m_children & ExportMacro)
writer.writeTextElement(QStringLiteral("exportmacro"), m_exportMacro);
- }
- if (m_children & Class) {
+ if (m_children & Class)
writer.writeTextElement(QStringLiteral("class"), m_class);
- }
- if (m_children & Widget) {
+ if (m_children & Widget)
m_widget->write(writer, QStringLiteral("widget"));
- }
- if (m_children & LayoutDefault) {
+ if (m_children & LayoutDefault)
m_layoutDefault->write(writer, QStringLiteral("layoutdefault"));
- }
- if (m_children & LayoutFunction) {
+ if (m_children & LayoutFunction)
m_layoutFunction->write(writer, QStringLiteral("layoutfunction"));
- }
- if (m_children & PixmapFunction) {
+ if (m_children & PixmapFunction)
writer.writeTextElement(QStringLiteral("pixmapfunction"), m_pixmapFunction);
- }
- if (m_children & CustomWidgets) {
+ if (m_children & CustomWidgets)
m_customWidgets->write(writer, QStringLiteral("customwidgets"));
- }
- if (m_children & TabStops) {
+ if (m_children & TabStops)
m_tabStops->write(writer, QStringLiteral("tabstops"));
- }
- if (m_children & Images) {
- m_images->write(writer, QStringLiteral("images"));
- }
-
- if (m_children & Includes) {
+ if (m_children & Includes)
m_includes->write(writer, QStringLiteral("includes"));
- }
- if (m_children & Resources) {
+ if (m_children & Resources)
m_resources->write(writer, QStringLiteral("resources"));
- }
- if (m_children & Connections) {
+ if (m_children & Connections)
m_connections->write(writer, QStringLiteral("connections"));
- }
- if (m_children & Designerdata) {
+ if (m_children & Designerdata)
m_designerdata->write(writer, QStringLiteral("designerdata"));
- }
- if (m_children & Slots) {
+ if (m_children & Slots)
m_slots->write(writer, QStringLiteral("slots"));
- }
- if (m_children & ButtonGroups) {
+ if (m_children & ButtonGroups)
m_buttonGroups->write(writer, QStringLiteral("buttongroups"));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomUI::setElementAuthor(const QString& a)
+void DomUI::setElementAuthor(const QString &a)
{
m_children |= Author;
m_author = a;
}
-void DomUI::setElementComment(const QString& a)
+void DomUI::setElementComment(const QString &a)
{
m_children |= Comment;
m_comment = a;
}
-void DomUI::setElementExportMacro(const QString& a)
+void DomUI::setElementExportMacro(const QString &a)
{
m_children |= ExportMacro;
m_exportMacro = a;
}
-void DomUI::setElementClass(const QString& a)
+void DomUI::setElementClass(const QString &a)
{
m_children |= Class;
m_class = a;
}
-DomWidget* DomUI::takeElementWidget()
+DomWidget *DomUI::takeElementWidget()
{
- DomWidget* a = m_widget;
+ DomWidget *a = m_widget;
m_widget = 0;
m_children ^= Widget;
return a;
}
-void DomUI::setElementWidget(DomWidget* a)
+void DomUI::setElementWidget(DomWidget *a)
{
delete m_widget;
m_children |= Widget;
m_widget = a;
}
-DomLayoutDefault* DomUI::takeElementLayoutDefault()
+DomLayoutDefault *DomUI::takeElementLayoutDefault()
{
- DomLayoutDefault* a = m_layoutDefault;
+ DomLayoutDefault *a = m_layoutDefault;
m_layoutDefault = 0;
m_children ^= LayoutDefault;
return a;
}
-void DomUI::setElementLayoutDefault(DomLayoutDefault* a)
+void DomUI::setElementLayoutDefault(DomLayoutDefault *a)
{
delete m_layoutDefault;
m_children |= LayoutDefault;
m_layoutDefault = a;
}
-DomLayoutFunction* DomUI::takeElementLayoutFunction()
+DomLayoutFunction *DomUI::takeElementLayoutFunction()
{
- DomLayoutFunction* a = m_layoutFunction;
+ DomLayoutFunction *a = m_layoutFunction;
m_layoutFunction = 0;
m_children ^= LayoutFunction;
return a;
}
-void DomUI::setElementLayoutFunction(DomLayoutFunction* a)
+void DomUI::setElementLayoutFunction(DomLayoutFunction *a)
{
delete m_layoutFunction;
m_children |= LayoutFunction;
m_layoutFunction = a;
}
-void DomUI::setElementPixmapFunction(const QString& a)
+void DomUI::setElementPixmapFunction(const QString &a)
{
m_children |= PixmapFunction;
m_pixmapFunction = a;
}
-DomCustomWidgets* DomUI::takeElementCustomWidgets()
+DomCustomWidgets *DomUI::takeElementCustomWidgets()
{
- DomCustomWidgets* a = m_customWidgets;
+ DomCustomWidgets *a = m_customWidgets;
m_customWidgets = 0;
m_children ^= CustomWidgets;
return a;
}
-void DomUI::setElementCustomWidgets(DomCustomWidgets* a)
+void DomUI::setElementCustomWidgets(DomCustomWidgets *a)
{
delete m_customWidgets;
m_children |= CustomWidgets;
m_customWidgets = a;
}
-DomTabStops* DomUI::takeElementTabStops()
+DomTabStops *DomUI::takeElementTabStops()
{
- DomTabStops* a = m_tabStops;
+ DomTabStops *a = m_tabStops;
m_tabStops = 0;
m_children ^= TabStops;
return a;
}
-void DomUI::setElementTabStops(DomTabStops* a)
+void DomUI::setElementTabStops(DomTabStops *a)
{
delete m_tabStops;
m_children |= TabStops;
m_tabStops = a;
}
-DomImages* DomUI::takeElementImages()
-{
- DomImages* a = m_images;
- m_images = 0;
- m_children ^= Images;
- return a;
-}
-
-void DomUI::setElementImages(DomImages* a)
-{
- delete m_images;
- m_children |= Images;
- m_images = a;
-}
-
-DomIncludes* DomUI::takeElementIncludes()
+DomIncludes *DomUI::takeElementIncludes()
{
- DomIncludes* a = m_includes;
+ DomIncludes *a = m_includes;
m_includes = 0;
m_children ^= Includes;
return a;
}
-void DomUI::setElementIncludes(DomIncludes* a)
+void DomUI::setElementIncludes(DomIncludes *a)
{
delete m_includes;
m_children |= Includes;
m_includes = a;
}
-DomResources* DomUI::takeElementResources()
+DomResources *DomUI::takeElementResources()
{
- DomResources* a = m_resources;
+ DomResources *a = m_resources;
m_resources = 0;
m_children ^= Resources;
return a;
}
-void DomUI::setElementResources(DomResources* a)
+void DomUI::setElementResources(DomResources *a)
{
delete m_resources;
m_children |= Resources;
m_resources = a;
}
-DomConnections* DomUI::takeElementConnections()
+DomConnections *DomUI::takeElementConnections()
{
- DomConnections* a = m_connections;
+ DomConnections *a = m_connections;
m_connections = 0;
m_children ^= Connections;
return a;
}
-void DomUI::setElementConnections(DomConnections* a)
+void DomUI::setElementConnections(DomConnections *a)
{
delete m_connections;
m_children |= Connections;
m_connections = a;
}
-DomDesignerData* DomUI::takeElementDesignerdata()
+DomDesignerData *DomUI::takeElementDesignerdata()
{
- DomDesignerData* a = m_designerdata;
+ DomDesignerData *a = m_designerdata;
m_designerdata = 0;
m_children ^= Designerdata;
return a;
}
-void DomUI::setElementDesignerdata(DomDesignerData* a)
+void DomUI::setElementDesignerdata(DomDesignerData *a)
{
delete m_designerdata;
m_children |= Designerdata;
m_designerdata = a;
}
-DomSlots* DomUI::takeElementSlots()
+DomSlots *DomUI::takeElementSlots()
{
- DomSlots* a = m_slots;
+ DomSlots *a = m_slots;
m_slots = 0;
m_children ^= Slots;
return a;
}
-void DomUI::setElementSlots(DomSlots* a)
+void DomUI::setElementSlots(DomSlots *a)
{
delete m_slots;
m_children |= Slots;
m_slots = a;
}
-DomButtonGroups* DomUI::takeElementButtonGroups()
+DomButtonGroups *DomUI::takeElementButtonGroups()
{
- DomButtonGroups* a = m_buttonGroups;
+ DomButtonGroups *a = m_buttonGroups;
m_buttonGroups = 0;
m_children ^= ButtonGroups;
return a;
}
-void DomUI::setElementButtonGroups(DomButtonGroups* a)
+void DomUI::setElementButtonGroups(DomButtonGroups *a)
{
delete m_buttonGroups;
m_children |= ButtonGroups;
@@ -625,13 +514,6 @@ void DomUI::clearElementTabStops()
m_children &= ~TabStops;
}
-void DomUI::clearElementImages()
-{
- delete m_images;
- m_images = 0;
- m_children &= ~Images;
-}
-
void DomUI::clearElementIncludes()
{
delete m_includes;
@@ -674,23 +556,6 @@ void DomUI::clearElementButtonGroups()
m_children &= ~ButtonGroups;
}
-void DomIncludes::clear(bool clear_all)
-{
- qDeleteAll(m_include);
- m_include.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomIncludes::DomIncludes()
-{
- m_children = 0;
-}
-
DomIncludes::~DomIncludes()
{
qDeleteAll(m_include);
@@ -699,12 +564,11 @@ DomIncludes::~DomIncludes()
void DomIncludes::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("include")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("include"), Qt::CaseInsensitive)) {
DomInclude *v = new DomInclude();
v->read(reader);
m_include.append(v);
@@ -714,12 +578,7 @@ void DomIncludes::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -728,54 +587,29 @@ void DomIncludes::read(QXmlStreamReader &reader)
void DomIncludes::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("includes") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("includes") : tagName.toLower());
- for (int i = 0; i < m_include.size(); ++i) {
- DomInclude* v = m_include[i];
+ for (DomInclude *v : m_include)
v->write(writer, QStringLiteral("include"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomIncludes::setElementInclude(const QList<DomInclude*>& a)
+void DomIncludes::setElementInclude(const QVector<DomInclude *> &a)
{
m_children |= Include;
m_include = a;
}
-void DomInclude::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_location = false;
- m_has_attr_impldecl = false;
- }
-
- m_children = 0;
-}
-
-DomInclude::DomInclude()
-{
- m_children = 0;
- m_has_attr_location = false;
- m_has_attr_impldecl = false;
- m_text.clear();
-}
-
DomInclude::~DomInclude()
{
}
void DomInclude::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("location")) {
setAttributeLocation(attribute.value().toString());
continue;
@@ -787,16 +621,15 @@ void DomInclude::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
+ return;
case QXmlStreamReader::Characters :
if (!reader.isWhitespace())
m_text.append(reader.text().toString());
@@ -809,7 +642,7 @@ void DomInclude::read(QXmlStreamReader &reader)
void DomInclude::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("include") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("include") : tagName.toLower());
if (hasAttributeLocation())
writer.writeAttribute(QStringLiteral("location"), attributeLocation());
@@ -823,25 +656,6 @@ void DomInclude::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeEndElement();
}
-void DomResources::clear(bool clear_all)
-{
- qDeleteAll(m_include);
- m_include.clear();
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_name = false;
- }
-
- m_children = 0;
-}
-
-DomResources::DomResources()
-{
- m_children = 0;
- m_has_attr_name = false;
-}
-
DomResources::~DomResources()
{
qDeleteAll(m_include);
@@ -850,10 +664,9 @@ DomResources::~DomResources()
void DomResources::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("name")) {
setAttributeName(attribute.value().toString());
continue;
@@ -861,11 +674,11 @@ void DomResources::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("include")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("include"), Qt::CaseInsensitive)) {
DomResource *v = new DomResource();
v->read(reader);
m_include.append(v);
@@ -875,12 +688,7 @@ void DomResources::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -889,54 +697,32 @@ void DomResources::read(QXmlStreamReader &reader)
void DomResources::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resources") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("resources") : tagName.toLower());
if (hasAttributeName())
writer.writeAttribute(QStringLiteral("name"), attributeName());
- for (int i = 0; i < m_include.size(); ++i) {
- DomResource* v = m_include[i];
+ for (DomResource *v : m_include)
v->write(writer, QStringLiteral("include"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomResources::setElementInclude(const QList<DomResource*>& a)
+void DomResources::setElementInclude(const QVector<DomResource *> &a)
{
m_children |= Include;
m_include = a;
}
-void DomResource::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_location = false;
- }
-
- m_children = 0;
-}
-
-DomResource::DomResource()
-{
- m_children = 0;
- m_has_attr_location = false;
-}
-
DomResource::~DomResource()
{
}
void DomResource::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("location")) {
setAttributeLocation(attribute.value().toString());
continue;
@@ -944,20 +730,15 @@ void DomResource::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -966,42 +747,14 @@ void DomResource::read(QXmlStreamReader &reader)
void DomResource::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resource") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("resource") : tagName.toLower());
if (hasAttributeLocation())
writer.writeAttribute(QStringLiteral("location"), attributeLocation());
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
writer.writeEndElement();
}
-void DomActionGroup::clear(bool clear_all)
-{
- qDeleteAll(m_action);
- m_action.clear();
- qDeleteAll(m_actionGroup);
- m_actionGroup.clear();
- qDeleteAll(m_property);
- m_property.clear();
- qDeleteAll(m_attribute);
- m_attribute.clear();
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_name = false;
- }
-
- m_children = 0;
-}
-
-DomActionGroup::DomActionGroup()
-{
- m_children = 0;
- m_has_attr_name = false;
-}
-
DomActionGroup::~DomActionGroup()
{
qDeleteAll(m_action);
@@ -1016,10 +769,9 @@ DomActionGroup::~DomActionGroup()
void DomActionGroup::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("name")) {
setAttributeName(attribute.value().toString());
continue;
@@ -1027,29 +779,29 @@ void DomActionGroup::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("action")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("action"), Qt::CaseInsensitive)) {
DomAction *v = new DomAction();
v->read(reader);
m_action.append(v);
continue;
}
- if (tag == QLatin1String("actiongroup")) {
+ if (!tag.compare(QLatin1String("actiongroup"), Qt::CaseInsensitive)) {
DomActionGroup *v = new DomActionGroup();
v->read(reader);
m_actionGroup.append(v);
continue;
}
- if (tag == QLatin1String("property")) {
+ if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (tag == QLatin1String("attribute")) {
+ if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
@@ -1059,12 +811,7 @@ void DomActionGroup::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -1073,80 +820,50 @@ void DomActionGroup::read(QXmlStreamReader &reader)
void DomActionGroup::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("actiongroup") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("actiongroup") : tagName.toLower());
if (hasAttributeName())
writer.writeAttribute(QStringLiteral("name"), attributeName());
- for (int i = 0; i < m_action.size(); ++i) {
- DomAction* v = m_action[i];
+ for (DomAction *v : m_action)
v->write(writer, QStringLiteral("action"));
- }
- for (int i = 0; i < m_actionGroup.size(); ++i) {
- DomActionGroup* v = m_actionGroup[i];
+
+ for (DomActionGroup *v : m_actionGroup)
v->write(writer, QStringLiteral("actiongroup"));
- }
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
+
+ for (DomProperty *v : m_property)
v->write(writer, QStringLiteral("property"));
- }
- for (int i = 0; i < m_attribute.size(); ++i) {
- DomProperty* v = m_attribute[i];
+
+ for (DomProperty *v : m_attribute)
v->write(writer, QStringLiteral("attribute"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomActionGroup::setElementAction(const QList<DomAction*>& a)
+void DomActionGroup::setElementAction(const QVector<DomAction *> &a)
{
m_children |= Action;
m_action = a;
}
-void DomActionGroup::setElementActionGroup(const QList<DomActionGroup*>& a)
+void DomActionGroup::setElementActionGroup(const QVector<DomActionGroup *> &a)
{
m_children |= ActionGroup;
m_actionGroup = a;
}
-void DomActionGroup::setElementProperty(const QList<DomProperty*>& a)
+void DomActionGroup::setElementProperty(const QList<DomProperty *> &a)
{
m_children |= Property;
m_property = a;
}
-void DomActionGroup::setElementAttribute(const QList<DomProperty*>& a)
+void DomActionGroup::setElementAttribute(const QList<DomProperty *> &a)
{
m_children |= Attribute;
m_attribute = a;
}
-void DomAction::clear(bool clear_all)
-{
- qDeleteAll(m_property);
- m_property.clear();
- qDeleteAll(m_attribute);
- m_attribute.clear();
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_name = false;
- m_has_attr_menu = false;
- }
-
- m_children = 0;
-}
-
-DomAction::DomAction()
-{
- m_children = 0;
- m_has_attr_name = false;
- m_has_attr_menu = false;
-}
-
DomAction::~DomAction()
{
qDeleteAll(m_property);
@@ -1157,10 +874,9 @@ DomAction::~DomAction()
void DomAction::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("name")) {
setAttributeName(attribute.value().toString());
continue;
@@ -1172,17 +888,17 @@ void DomAction::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("property")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (tag == QLatin1String("attribute")) {
+ if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
@@ -1192,12 +908,7 @@ void DomAction::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -1206,7 +917,7 @@ void DomAction::read(QXmlStreamReader &reader)
void DomAction::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("action") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("action") : tagName.toLower());
if (hasAttributeName())
writer.writeAttribute(QStringLiteral("name"), attributeName());
@@ -1214,59 +925,36 @@ void DomAction::write(QXmlStreamWriter &writer, const QString &tagName) const
if (hasAttributeMenu())
writer.writeAttribute(QStringLiteral("menu"), attributeMenu());
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
+ for (DomProperty *v : m_property)
v->write(writer, QStringLiteral("property"));
- }
- for (int i = 0; i < m_attribute.size(); ++i) {
- DomProperty* v = m_attribute[i];
+
+ for (DomProperty *v : m_attribute)
v->write(writer, QStringLiteral("attribute"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomAction::setElementProperty(const QList<DomProperty*>& a)
+void DomAction::setElementProperty(const QList<DomProperty *> &a)
{
m_children |= Property;
m_property = a;
}
-void DomAction::setElementAttribute(const QList<DomProperty*>& a)
+void DomAction::setElementAttribute(const QList<DomProperty *> &a)
{
m_children |= Attribute;
m_attribute = a;
}
-void DomActionRef::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_name = false;
- }
-
- m_children = 0;
-}
-
-DomActionRef::DomActionRef()
-{
- m_children = 0;
- m_has_attr_name = false;
-}
-
DomActionRef::~DomActionRef()
{
}
void DomActionRef::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("name")) {
setAttributeName(attribute.value().toString());
continue;
@@ -1274,20 +962,15 @@ void DomActionRef::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -1296,38 +979,14 @@ void DomActionRef::read(QXmlStreamReader &reader)
void DomActionRef::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("actionref") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("actionref") : tagName.toLower());
if (hasAttributeName())
writer.writeAttribute(QStringLiteral("name"), attributeName());
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
writer.writeEndElement();
}
-void DomButtonGroup::clear(bool clear_all)
-{
- qDeleteAll(m_property);
- m_property.clear();
- qDeleteAll(m_attribute);
- m_attribute.clear();
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_name = false;
- }
-
- m_children = 0;
-}
-
-DomButtonGroup::DomButtonGroup()
-{
- m_children = 0;
- m_has_attr_name = false;
-}
-
DomButtonGroup::~DomButtonGroup()
{
qDeleteAll(m_property);
@@ -1338,10 +997,9 @@ DomButtonGroup::~DomButtonGroup()
void DomButtonGroup::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("name")) {
setAttributeName(attribute.value().toString());
continue;
@@ -1349,17 +1007,17 @@ void DomButtonGroup::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("property")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (tag == QLatin1String("attribute")) {
+ if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
@@ -1369,12 +1027,7 @@ void DomButtonGroup::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -1383,54 +1036,32 @@ void DomButtonGroup::read(QXmlStreamReader &reader)
void DomButtonGroup::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("buttongroup") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("buttongroup") : tagName.toLower());
if (hasAttributeName())
writer.writeAttribute(QStringLiteral("name"), attributeName());
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
+ for (DomProperty *v : m_property)
v->write(writer, QStringLiteral("property"));
- }
- for (int i = 0; i < m_attribute.size(); ++i) {
- DomProperty* v = m_attribute[i];
+
+ for (DomProperty *v : m_attribute)
v->write(writer, QStringLiteral("attribute"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomButtonGroup::setElementProperty(const QList<DomProperty*>& a)
+void DomButtonGroup::setElementProperty(const QList<DomProperty *> &a)
{
m_children |= Property;
m_property = a;
}
-void DomButtonGroup::setElementAttribute(const QList<DomProperty*>& a)
+void DomButtonGroup::setElementAttribute(const QList<DomProperty *> &a)
{
m_children |= Attribute;
m_attribute = a;
}
-void DomButtonGroups::clear(bool clear_all)
-{
- qDeleteAll(m_buttonGroup);
- m_buttonGroup.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomButtonGroups::DomButtonGroups()
-{
- m_children = 0;
-}
-
DomButtonGroups::~DomButtonGroups()
{
qDeleteAll(m_buttonGroup);
@@ -1439,12 +1070,11 @@ DomButtonGroups::~DomButtonGroups()
void DomButtonGroups::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("buttongroup")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("buttongroup"), Qt::CaseInsensitive)) {
DomButtonGroup *v = new DomButtonGroup();
v->read(reader);
m_buttonGroup.append(v);
@@ -1454,12 +1084,7 @@ void DomButtonGroups::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -1468,295 +1093,20 @@ void DomButtonGroups::read(QXmlStreamReader &reader)
void DomButtonGroups::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("buttongroups") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("buttongroups") : tagName.toLower());
- for (int i = 0; i < m_buttonGroup.size(); ++i) {
- DomButtonGroup* v = m_buttonGroup[i];
+ for (DomButtonGroup *v : m_buttonGroup)
v->write(writer, QStringLiteral("buttongroup"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomButtonGroups::setElementButtonGroup(const QList<DomButtonGroup*>& a)
+void DomButtonGroups::setElementButtonGroup(const QVector<DomButtonGroup *> &a)
{
m_children |= ButtonGroup;
m_buttonGroup = a;
}
-void DomImages::clear(bool clear_all)
-{
- qDeleteAll(m_image);
- m_image.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomImages::DomImages()
-{
- m_children = 0;
-}
-
-DomImages::~DomImages()
-{
- qDeleteAll(m_image);
- m_image.clear();
-}
-
-void DomImages::read(QXmlStreamReader &reader)
-{
-
- for (bool finished = false; !finished && !reader.hasError();) {
- switch (reader.readNext()) {
- case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("image")) {
- DomImage *v = new DomImage();
- v->read(reader);
- m_image.append(v);
- continue;
- }
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
- }
- break;
- case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
- default :
- break;
- }
- }
-}
-
-void DomImages::write(QXmlStreamWriter &writer, const QString &tagName) const
-{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("images") : tagName.toLower());
-
- for (int i = 0; i < m_image.size(); ++i) {
- DomImage* v = m_image[i];
- v->write(writer, QStringLiteral("image"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
- writer.writeEndElement();
-}
-
-void DomImages::setElementImage(const QList<DomImage*>& a)
-{
- m_children |= Image;
- m_image = a;
-}
-
-void DomImage::clear(bool clear_all)
-{
- delete m_data;
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_name = false;
- }
-
- m_children = 0;
- m_data = 0;
-}
-
-DomImage::DomImage()
-{
- m_children = 0;
- m_has_attr_name = false;
- m_data = 0;
-}
-
-DomImage::~DomImage()
-{
- delete m_data;
-}
-
-void DomImage::read(QXmlStreamReader &reader)
-{
-
- const QXmlStreamAttributes attributes = reader.attributes();
- for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
- if (name == QLatin1String("name")) {
- setAttributeName(attribute.value().toString());
- continue;
- }
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
- }
-
- for (bool finished = false; !finished && !reader.hasError();) {
- switch (reader.readNext()) {
- case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("data")) {
- DomImageData *v = new DomImageData();
- v->read(reader);
- setElementData(v);
- continue;
- }
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
- }
- break;
- case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
- default :
- break;
- }
- }
-}
-
-void DomImage::write(QXmlStreamWriter &writer, const QString &tagName) const
-{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("image") : tagName.toLower());
-
- if (hasAttributeName())
- writer.writeAttribute(QStringLiteral("name"), attributeName());
-
- if (m_children & Data) {
- m_data->write(writer, QStringLiteral("data"));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
- writer.writeEndElement();
-}
-
-DomImageData* DomImage::takeElementData()
-{
- DomImageData* a = m_data;
- m_data = 0;
- m_children ^= Data;
- return a;
-}
-
-void DomImage::setElementData(DomImageData* a)
-{
- delete m_data;
- m_children |= Data;
- m_data = a;
-}
-
-void DomImage::clearElementData()
-{
- delete m_data;
- m_data = 0;
- m_children &= ~Data;
-}
-
-void DomImageData::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_format = false;
- m_has_attr_length = false;
- m_attr_length = 0;
- }
-
- m_children = 0;
-}
-
-DomImageData::DomImageData()
-{
- m_children = 0;
- m_has_attr_format = false;
- m_has_attr_length = false;
- m_attr_length = 0;
- m_text.clear();
-}
-
-DomImageData::~DomImageData()
-{
-}
-
-void DomImageData::read(QXmlStreamReader &reader)
-{
-
- const QXmlStreamAttributes attributes = reader.attributes();
- for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
- if (name == QLatin1String("format")) {
- setAttributeFormat(attribute.value().toString());
- continue;
- }
- if (name == QLatin1String("length")) {
- setAttributeLength(attribute.value().toInt());
- continue;
- }
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
- }
-
- for (bool finished = false; !finished && !reader.hasError();) {
- switch (reader.readNext()) {
- case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
- }
- break;
- case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
- default :
- break;
- }
- }
-}
-
-void DomImageData::write(QXmlStreamWriter &writer, const QString &tagName) const
-{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("imagedata") : tagName.toLower());
-
- if (hasAttributeFormat())
- writer.writeAttribute(QStringLiteral("format"), attributeFormat());
-
- if (hasAttributeLength())
- writer.writeAttribute(QStringLiteral("length"), QString::number(attributeLength()));
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
- writer.writeEndElement();
-}
-
-void DomCustomWidgets::clear(bool clear_all)
-{
- qDeleteAll(m_customWidget);
- m_customWidget.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomCustomWidgets::DomCustomWidgets()
-{
- m_children = 0;
-}
-
DomCustomWidgets::~DomCustomWidgets()
{
qDeleteAll(m_customWidget);
@@ -1765,12 +1115,11 @@ DomCustomWidgets::~DomCustomWidgets()
void DomCustomWidgets::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("customwidget")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("customwidget"), Qt::CaseInsensitive)) {
DomCustomWidget *v = new DomCustomWidget();
v->read(reader);
m_customWidget.append(v);
@@ -1780,12 +1129,7 @@ void DomCustomWidgets::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -1794,52 +1138,29 @@ void DomCustomWidgets::read(QXmlStreamReader &reader)
void DomCustomWidgets::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("customwidgets") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("customwidgets") : tagName.toLower());
- for (int i = 0; i < m_customWidget.size(); ++i) {
- DomCustomWidget* v = m_customWidget[i];
+ for (DomCustomWidget *v : m_customWidget)
v->write(writer, QStringLiteral("customwidget"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomCustomWidgets::setElementCustomWidget(const QList<DomCustomWidget*>& a)
+void DomCustomWidgets::setElementCustomWidget(const QVector<DomCustomWidget *> &a)
{
m_children |= CustomWidget;
m_customWidget = a;
}
-void DomHeader::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_location = false;
- }
-
- m_children = 0;
-}
-
-DomHeader::DomHeader()
-{
- m_children = 0;
- m_has_attr_location = false;
- m_text.clear();
-}
-
DomHeader::~DomHeader()
{
}
void DomHeader::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("location")) {
setAttributeLocation(attribute.value().toString());
continue;
@@ -1847,16 +1168,15 @@ void DomHeader::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
+ return;
case QXmlStreamReader::Characters :
if (!reader.isWhitespace())
m_text.append(reader.text().toString());
@@ -1869,7 +1189,7 @@ void DomHeader::read(QXmlStreamReader &reader)
void DomHeader::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("header") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("header") : tagName.toLower());
if (hasAttributeLocation())
writer.writeAttribute(QStringLiteral("location"), attributeLocation());
@@ -1880,119 +1200,74 @@ void DomHeader::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeEndElement();
}
-void DomCustomWidget::clear(bool clear_all)
-{
- delete m_header;
- delete m_sizeHint;
- delete m_sizePolicy;
- delete m_script;
- delete m_properties;
- delete m_slots;
- delete m_propertyspecifications;
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_header = 0;
- m_sizeHint = 0;
- m_container = 0;
- m_sizePolicy = 0;
- m_script = 0;
- m_properties = 0;
- m_slots = 0;
- m_propertyspecifications = 0;
-}
-
-DomCustomWidget::DomCustomWidget()
-{
- m_children = 0;
- m_header = 0;
- m_sizeHint = 0;
- m_container = 0;
- m_sizePolicy = 0;
- m_script = 0;
- m_properties = 0;
- m_slots = 0;
- m_propertyspecifications = 0;
-}
-
DomCustomWidget::~DomCustomWidget()
{
delete m_header;
delete m_sizeHint;
- delete m_sizePolicy;
- delete m_script;
- delete m_properties;
delete m_slots;
delete m_propertyspecifications;
}
void DomCustomWidget::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("class")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("class"), Qt::CaseInsensitive)) {
setElementClass(reader.readElementText());
continue;
}
- if (tag == QLatin1String("extends")) {
+ if (!tag.compare(QLatin1String("extends"), Qt::CaseInsensitive)) {
setElementExtends(reader.readElementText());
continue;
}
- if (tag == QLatin1String("header")) {
+ if (!tag.compare(QLatin1String("header"), Qt::CaseInsensitive)) {
DomHeader *v = new DomHeader();
v->read(reader);
setElementHeader(v);
continue;
}
- if (tag == QLatin1String("sizehint")) {
+ if (!tag.compare(QLatin1String("sizehint"), Qt::CaseInsensitive)) {
DomSize *v = new DomSize();
v->read(reader);
setElementSizeHint(v);
continue;
}
- if (tag == QLatin1String("addpagemethod")) {
+ if (!tag.compare(QLatin1String("addpagemethod"), Qt::CaseInsensitive)) {
setElementAddPageMethod(reader.readElementText());
continue;
}
- if (tag == QLatin1String("container")) {
+ if (!tag.compare(QLatin1String("container"), Qt::CaseInsensitive)) {
setElementContainer(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("sizepolicy")) {
- DomSizePolicyData *v = new DomSizePolicyData();
- v->read(reader);
- setElementSizePolicy(v);
+ if (!tag.compare(QLatin1String("sizepolicy"), Qt::CaseInsensitive)) {
+ qWarning("Omitting deprecated element <sizepolicy>.");
+ reader.skipCurrentElement();
continue;
}
- if (tag == QLatin1String("pixmap")) {
+ if (!tag.compare(QLatin1String("pixmap"), Qt::CaseInsensitive)) {
setElementPixmap(reader.readElementText());
continue;
}
- if (tag == QLatin1String("script")) {
- DomScript *v = new DomScript();
- v->read(reader);
- setElementScript(v);
+ if (!tag.compare(QLatin1String("script"), Qt::CaseInsensitive)) {
+ qWarning("Omitting deprecated element <script>.");
+ reader.skipCurrentElement();
continue;
}
- if (tag == QLatin1String("properties")) {
- DomProperties *v = new DomProperties();
- v->read(reader);
- setElementProperties(v);
+ if (!tag.compare(QLatin1String("properties"), Qt::CaseInsensitive)) {
+ qWarning("Omitting deprecated element <properties>.");
+ reader.skipCurrentElement();
continue;
}
- if (tag == QLatin1String("slots")) {
+ if (!tag.compare(QLatin1String("slots"), Qt::CaseInsensitive)) {
DomSlots *v = new DomSlots();
v->read(reader);
setElementSlots(v);
continue;
}
- if (tag == QLatin1String("propertyspecifications")) {
+ if (!tag.compare(QLatin1String("propertyspecifications"), Qt::CaseInsensitive)) {
DomPropertySpecifications *v = new DomPropertySpecifications();
v->read(reader);
setElementPropertyspecifications(v);
@@ -2002,12 +1277,7 @@ void DomCustomWidget::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -2016,105 +1286,81 @@ void DomCustomWidget::read(QXmlStreamReader &reader)
void DomCustomWidget::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("customwidget") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("customwidget") : tagName.toLower());
- if (m_children & Class) {
+ if (m_children & Class)
writer.writeTextElement(QStringLiteral("class"), m_class);
- }
- if (m_children & Extends) {
+ if (m_children & Extends)
writer.writeTextElement(QStringLiteral("extends"), m_extends);
- }
- if (m_children & Header) {
+ if (m_children & Header)
m_header->write(writer, QStringLiteral("header"));
- }
- if (m_children & SizeHint) {
+ if (m_children & SizeHint)
m_sizeHint->write(writer, QStringLiteral("sizehint"));
- }
- if (m_children & AddPageMethod) {
+ if (m_children & AddPageMethod)
writer.writeTextElement(QStringLiteral("addpagemethod"), m_addPageMethod);
- }
- if (m_children & Container) {
+ if (m_children & Container)
writer.writeTextElement(QStringLiteral("container"), QString::number(m_container));
- }
-
- if (m_children & SizePolicy) {
- m_sizePolicy->write(writer, QStringLiteral("sizepolicy"));
- }
- if (m_children & Pixmap) {
+ if (m_children & Pixmap)
writer.writeTextElement(QStringLiteral("pixmap"), m_pixmap);
- }
-
- if (m_children & Script) {
- m_script->write(writer, QStringLiteral("script"));
- }
- if (m_children & Properties) {
- m_properties->write(writer, QStringLiteral("properties"));
- }
-
- if (m_children & Slots) {
+ if (m_children & Slots)
m_slots->write(writer, QStringLiteral("slots"));
- }
- if (m_children & Propertyspecifications) {
+ if (m_children & Propertyspecifications)
m_propertyspecifications->write(writer, QStringLiteral("propertyspecifications"));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomCustomWidget::setElementClass(const QString& a)
+void DomCustomWidget::setElementClass(const QString &a)
{
m_children |= Class;
m_class = a;
}
-void DomCustomWidget::setElementExtends(const QString& a)
+void DomCustomWidget::setElementExtends(const QString &a)
{
m_children |= Extends;
m_extends = a;
}
-DomHeader* DomCustomWidget::takeElementHeader()
+DomHeader *DomCustomWidget::takeElementHeader()
{
- DomHeader* a = m_header;
+ DomHeader *a = m_header;
m_header = 0;
m_children ^= Header;
return a;
}
-void DomCustomWidget::setElementHeader(DomHeader* a)
+void DomCustomWidget::setElementHeader(DomHeader *a)
{
delete m_header;
m_children |= Header;
m_header = a;
}
-DomSize* DomCustomWidget::takeElementSizeHint()
+DomSize *DomCustomWidget::takeElementSizeHint()
{
- DomSize* a = m_sizeHint;
+ DomSize *a = m_sizeHint;
m_sizeHint = 0;
m_children ^= SizeHint;
return a;
}
-void DomCustomWidget::setElementSizeHint(DomSize* a)
+void DomCustomWidget::setElementSizeHint(DomSize *a)
{
delete m_sizeHint;
m_children |= SizeHint;
m_sizeHint = a;
}
-void DomCustomWidget::setElementAddPageMethod(const QString& a)
+void DomCustomWidget::setElementAddPageMethod(const QString &a)
{
m_children |= AddPageMethod;
m_addPageMethod = a;
@@ -2126,81 +1372,36 @@ void DomCustomWidget::setElementContainer(int a)
m_container = a;
}
-DomSizePolicyData* DomCustomWidget::takeElementSizePolicy()
-{
- DomSizePolicyData* a = m_sizePolicy;
- m_sizePolicy = 0;
- m_children ^= SizePolicy;
- return a;
-}
-
-void DomCustomWidget::setElementSizePolicy(DomSizePolicyData* a)
-{
- delete m_sizePolicy;
- m_children |= SizePolicy;
- m_sizePolicy = a;
-}
-
-void DomCustomWidget::setElementPixmap(const QString& a)
+void DomCustomWidget::setElementPixmap(const QString &a)
{
m_children |= Pixmap;
m_pixmap = a;
}
-DomScript* DomCustomWidget::takeElementScript()
-{
- DomScript* a = m_script;
- m_script = 0;
- m_children ^= Script;
- return a;
-}
-
-void DomCustomWidget::setElementScript(DomScript* a)
-{
- delete m_script;
- m_children |= Script;
- m_script = a;
-}
-
-DomProperties* DomCustomWidget::takeElementProperties()
+DomSlots *DomCustomWidget::takeElementSlots()
{
- DomProperties* a = m_properties;
- m_properties = 0;
- m_children ^= Properties;
- return a;
-}
-
-void DomCustomWidget::setElementProperties(DomProperties* a)
-{
- delete m_properties;
- m_children |= Properties;
- m_properties = a;
-}
-
-DomSlots* DomCustomWidget::takeElementSlots()
-{
- DomSlots* a = m_slots;
+ DomSlots *a = m_slots;
m_slots = 0;
m_children ^= Slots;
return a;
}
-void DomCustomWidget::setElementSlots(DomSlots* a)
+void DomCustomWidget::setElementSlots(DomSlots *a)
{
delete m_slots;
m_children |= Slots;
m_slots = a;
}
-DomPropertySpecifications* DomCustomWidget::takeElementPropertyspecifications()
+DomPropertySpecifications *DomCustomWidget::takeElementPropertyspecifications()
{
- DomPropertySpecifications* a = m_propertyspecifications;
+ DomPropertySpecifications *a = m_propertyspecifications;
m_propertyspecifications = 0;
m_children ^= Propertyspecifications;
return a;
}
-void DomCustomWidget::setElementPropertyspecifications(DomPropertySpecifications* a)
+void DomCustomWidget::setElementPropertyspecifications(DomPropertySpecifications *a)
{
delete m_propertyspecifications;
m_children |= Propertyspecifications;
@@ -2241,32 +1442,11 @@ void DomCustomWidget::clearElementContainer()
m_children &= ~Container;
}
-void DomCustomWidget::clearElementSizePolicy()
-{
- delete m_sizePolicy;
- m_sizePolicy = 0;
- m_children &= ~SizePolicy;
-}
-
void DomCustomWidget::clearElementPixmap()
{
m_children &= ~Pixmap;
}
-void DomCustomWidget::clearElementScript()
-{
- delete m_script;
- m_script = 0;
- m_children &= ~Script;
-}
-
-void DomCustomWidget::clearElementProperties()
-{
- delete m_properties;
- m_properties = 0;
- m_children &= ~Properties;
-}
-
void DomCustomWidget::clearElementSlots()
{
delete m_slots;
@@ -2281,272 +1461,15 @@ void DomCustomWidget::clearElementPropertyspecifications()
m_children &= ~Propertyspecifications;
}
-void DomProperties::clear(bool clear_all)
-{
- qDeleteAll(m_property);
- m_property.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomProperties::DomProperties()
-{
- m_children = 0;
-}
-
-DomProperties::~DomProperties()
-{
- qDeleteAll(m_property);
- m_property.clear();
-}
-
-void DomProperties::read(QXmlStreamReader &reader)
-{
-
- for (bool finished = false; !finished && !reader.hasError();) {
- switch (reader.readNext()) {
- case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("property")) {
- DomPropertyData *v = new DomPropertyData();
- v->read(reader);
- m_property.append(v);
- continue;
- }
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
- }
- break;
- case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
- default :
- break;
- }
- }
-}
-
-void DomProperties::write(QXmlStreamWriter &writer, const QString &tagName) const
-{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("properties") : tagName.toLower());
-
- for (int i = 0; i < m_property.size(); ++i) {
- DomPropertyData* v = m_property[i];
- v->write(writer, QStringLiteral("property"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
- writer.writeEndElement();
-}
-
-void DomProperties::setElementProperty(const QList<DomPropertyData*>& a)
-{
- m_children |= Property;
- m_property = a;
-}
-
-void DomPropertyData::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_type = false;
- }
-
- m_children = 0;
-}
-
-DomPropertyData::DomPropertyData()
-{
- m_children = 0;
- m_has_attr_type = false;
-}
-
-DomPropertyData::~DomPropertyData()
-{
-}
-
-void DomPropertyData::read(QXmlStreamReader &reader)
-{
-
- const QXmlStreamAttributes attributes = reader.attributes();
- for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
- if (name == QLatin1String("type")) {
- setAttributeType(attribute.value().toString());
- continue;
- }
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
- }
-
- for (bool finished = false; !finished && !reader.hasError();) {
- switch (reader.readNext()) {
- case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
- }
- break;
- case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
- default :
- break;
- }
- }
-}
-
-void DomPropertyData::write(QXmlStreamWriter &writer, const QString &tagName) const
-{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("propertydata") : tagName.toLower());
-
- if (hasAttributeType())
- writer.writeAttribute(QStringLiteral("type"), attributeType());
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
- writer.writeEndElement();
-}
-
-void DomSizePolicyData::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_horData = 0;
- m_verData = 0;
-}
-
-DomSizePolicyData::DomSizePolicyData()
-{
- m_children = 0;
- m_horData = 0;
- m_verData = 0;
-}
-
-DomSizePolicyData::~DomSizePolicyData()
-{
-}
-
-void DomSizePolicyData::read(QXmlStreamReader &reader)
-{
-
- for (bool finished = false; !finished && !reader.hasError();) {
- switch (reader.readNext()) {
- case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("hordata")) {
- setElementHorData(reader.readElementText().toInt());
- continue;
- }
- if (tag == QLatin1String("verdata")) {
- setElementVerData(reader.readElementText().toInt());
- continue;
- }
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
- }
- break;
- case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
- default :
- break;
- }
- }
-}
-
-void DomSizePolicyData::write(QXmlStreamWriter &writer, const QString &tagName) const
-{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("sizepolicydata") : tagName.toLower());
-
- if (m_children & HorData) {
- writer.writeTextElement(QStringLiteral("hordata"), QString::number(m_horData));
- }
-
- if (m_children & VerData) {
- writer.writeTextElement(QStringLiteral("verdata"), QString::number(m_verData));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
- writer.writeEndElement();
-}
-
-void DomSizePolicyData::setElementHorData(int a)
-{
- m_children |= HorData;
- m_horData = a;
-}
-
-void DomSizePolicyData::setElementVerData(int a)
-{
- m_children |= VerData;
- m_verData = a;
-}
-
-void DomSizePolicyData::clearElementHorData()
-{
- m_children &= ~HorData;
-}
-
-void DomSizePolicyData::clearElementVerData()
-{
- m_children &= ~VerData;
-}
-
-void DomLayoutDefault::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_spacing = false;
- m_attr_spacing = 0;
- m_has_attr_margin = false;
- m_attr_margin = 0;
- }
-
- m_children = 0;
-}
-
-DomLayoutDefault::DomLayoutDefault()
-{
- m_children = 0;
- m_has_attr_spacing = false;
- m_attr_spacing = 0;
- m_has_attr_margin = false;
- m_attr_margin = 0;
-}
-
DomLayoutDefault::~DomLayoutDefault()
{
}
void DomLayoutDefault::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("spacing")) {
setAttributeSpacing(attribute.value().toInt());
continue;
@@ -2558,20 +1481,15 @@ void DomLayoutDefault::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -2580,7 +1498,7 @@ void DomLayoutDefault::read(QXmlStreamReader &reader)
void DomLayoutDefault::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("layoutdefault") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("layoutdefault") : tagName.toLower());
if (hasAttributeSpacing())
writer.writeAttribute(QStringLiteral("spacing"), QString::number(attributeSpacing()));
@@ -2588,41 +1506,18 @@ void DomLayoutDefault::write(QXmlStreamWriter &writer, const QString &tagName) c
if (hasAttributeMargin())
writer.writeAttribute(QStringLiteral("margin"), QString::number(attributeMargin()));
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
writer.writeEndElement();
}
-void DomLayoutFunction::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_spacing = false;
- m_has_attr_margin = false;
- }
-
- m_children = 0;
-}
-
-DomLayoutFunction::DomLayoutFunction()
-{
- m_children = 0;
- m_has_attr_spacing = false;
- m_has_attr_margin = false;
-}
-
DomLayoutFunction::~DomLayoutFunction()
{
}
void DomLayoutFunction::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("spacing")) {
setAttributeSpacing(attribute.value().toString());
continue;
@@ -2634,20 +1529,15 @@ void DomLayoutFunction::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -2656,7 +1546,7 @@ void DomLayoutFunction::read(QXmlStreamReader &reader)
void DomLayoutFunction::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("layoutfunction") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("layoutfunction") : tagName.toLower());
if (hasAttributeSpacing())
writer.writeAttribute(QStringLiteral("spacing"), attributeSpacing());
@@ -2664,28 +1554,9 @@ void DomLayoutFunction::write(QXmlStreamWriter &writer, const QString &tagName)
if (hasAttributeMargin())
writer.writeAttribute(QStringLiteral("margin"), attributeMargin());
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
writer.writeEndElement();
}
-void DomTabStops::clear(bool clear_all)
-{
- m_tabStop.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomTabStops::DomTabStops()
-{
- m_children = 0;
-}
-
DomTabStops::~DomTabStops()
{
m_tabStop.clear();
@@ -2693,12 +1564,11 @@ DomTabStops::~DomTabStops()
void DomTabStops::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("tabstop")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("tabstop"), Qt::CaseInsensitive)) {
m_tabStop.append(reader.readElementText());
continue;
}
@@ -2706,12 +1576,7 @@ void DomTabStops::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -2720,59 +1585,20 @@ void DomTabStops::read(QXmlStreamReader &reader)
void DomTabStops::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("tabstops") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("tabstops") : tagName.toLower());
- for (int i = 0; i < m_tabStop.size(); ++i) {
- QString v = m_tabStop[i];
+ for (const QString &v : m_tabStop)
writer.writeTextElement(QStringLiteral("tabstop"), v);
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomTabStops::setElementTabStop(const QStringList& a)
+void DomTabStops::setElementTabStop(const QStringList &a)
{
m_children |= TabStop;
m_tabStop = a;
}
-void DomLayout::clear(bool clear_all)
-{
- qDeleteAll(m_property);
- m_property.clear();
- qDeleteAll(m_attribute);
- m_attribute.clear();
- qDeleteAll(m_item);
- m_item.clear();
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_class = false;
- m_has_attr_name = false;
- m_has_attr_stretch = false;
- m_has_attr_rowStretch = false;
- m_has_attr_columnStretch = false;
- m_has_attr_rowMinimumHeight = false;
- m_has_attr_columnMinimumWidth = false;
- }
-
- m_children = 0;
-}
-
-DomLayout::DomLayout()
-{
- m_children = 0;
- m_has_attr_class = false;
- m_has_attr_name = false;
- m_has_attr_stretch = false;
- m_has_attr_rowStretch = false;
- m_has_attr_columnStretch = false;
- m_has_attr_rowMinimumHeight = false;
- m_has_attr_columnMinimumWidth = false;
-}
-
DomLayout::~DomLayout()
{
qDeleteAll(m_property);
@@ -2785,10 +1611,9 @@ DomLayout::~DomLayout()
void DomLayout::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("class")) {
setAttributeClass(attribute.value().toString());
continue;
@@ -2820,23 +1645,23 @@ void DomLayout::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("property")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (tag == QLatin1String("attribute")) {
+ if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
- if (tag == QLatin1String("item")) {
+ if (!tag.compare(QLatin1String("item"), Qt::CaseInsensitive)) {
DomLayoutItem *v = new DomLayoutItem();
v->read(reader);
m_item.append(v);
@@ -2846,12 +1671,7 @@ void DomLayout::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -2860,7 +1680,7 @@ void DomLayout::read(QXmlStreamReader &reader)
void DomLayout::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("layout") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("layout") : tagName.toLower());
if (hasAttributeClass())
writer.writeAttribute(QStringLiteral("class"), attributeClass());
@@ -2883,99 +1703,61 @@ void DomLayout::write(QXmlStreamWriter &writer, const QString &tagName) const
if (hasAttributeColumnMinimumWidth())
writer.writeAttribute(QStringLiteral("columnminimumwidth"), attributeColumnMinimumWidth());
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
+ for (DomProperty *v : m_property)
v->write(writer, QStringLiteral("property"));
- }
- for (int i = 0; i < m_attribute.size(); ++i) {
- DomProperty* v = m_attribute[i];
+
+ for (DomProperty *v : m_attribute)
v->write(writer, QStringLiteral("attribute"));
- }
- for (int i = 0; i < m_item.size(); ++i) {
- DomLayoutItem* v = m_item[i];
+
+ for (DomLayoutItem *v : m_item)
v->write(writer, QStringLiteral("item"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomLayout::setElementProperty(const QList<DomProperty*>& a)
+void DomLayout::setElementProperty(const QList<DomProperty *> &a)
{
m_children |= Property;
m_property = a;
}
-void DomLayout::setElementAttribute(const QList<DomProperty*>& a)
+void DomLayout::setElementAttribute(const QList<DomProperty *> &a)
{
m_children |= Attribute;
m_attribute = a;
}
-void DomLayout::setElementItem(const QList<DomLayoutItem*>& a)
+void DomLayout::setElementItem(const QVector<DomLayoutItem *> &a)
{
m_children |= Item;
m_item = a;
}
-void DomLayoutItem::clear(bool clear_all)
+DomLayoutItem::~DomLayoutItem()
{
delete m_widget;
delete m_layout;
delete m_spacer;
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_row = false;
- m_attr_row = 0;
- m_has_attr_column = false;
- m_attr_column = 0;
- m_has_attr_rowSpan = false;
- m_attr_rowSpan = 0;
- m_has_attr_colSpan = false;
- m_attr_colSpan = 0;
- m_has_attr_alignment = false;
- }
-
- m_kind = Unknown;
-
- m_widget = 0;
- m_layout = 0;
- m_spacer = 0;
}
-DomLayoutItem::DomLayoutItem()
-{
- m_kind = Unknown;
-
- m_has_attr_row = false;
- m_attr_row = 0;
- m_has_attr_column = false;
- m_attr_column = 0;
- m_has_attr_rowSpan = false;
- m_attr_rowSpan = 0;
- m_has_attr_colSpan = false;
- m_attr_colSpan = 0;
- m_has_attr_alignment = false;
- m_widget = 0;
- m_layout = 0;
- m_spacer = 0;
-}
-
-DomLayoutItem::~DomLayoutItem()
+void DomLayoutItem::clear()
{
delete m_widget;
delete m_layout;
delete m_spacer;
+
+ m_kind = Unknown;
+
+ m_widget = nullptr;
+ m_layout = nullptr;
+ m_spacer = nullptr;
}
void DomLayoutItem::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("row")) {
setAttributeRow(attribute.value().toInt());
continue;
@@ -2999,23 +1781,23 @@ void DomLayoutItem::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("widget")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
DomWidget *v = new DomWidget();
v->read(reader);
setElementWidget(v);
continue;
}
- if (tag == QLatin1String("layout")) {
+ if (!tag.compare(QLatin1String("layout"), Qt::CaseInsensitive)) {
DomLayout *v = new DomLayout();
v->read(reader);
setElementLayout(v);
continue;
}
- if (tag == QLatin1String("spacer")) {
+ if (!tag.compare(QLatin1String("spacer"), Qt::CaseInsensitive)) {
DomSpacer *v = new DomSpacer();
v->read(reader);
setElementSpacer(v);
@@ -3025,12 +1807,7 @@ void DomLayoutItem::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -3039,7 +1816,7 @@ void DomLayoutItem::read(QXmlStreamReader &reader)
void DomLayoutItem::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("layoutitem") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("layoutitem") : tagName.toLower());
if (hasAttributeRow())
writer.writeAttribute(QStringLiteral("row"), QString::number(attributeRow()));
@@ -3057,95 +1834,72 @@ void DomLayoutItem::write(QXmlStreamWriter &writer, const QString &tagName) cons
writer.writeAttribute(QStringLiteral("alignment"), attributeAlignment());
switch (kind()) {
- case Widget: {
- DomWidget* v = elementWidget();
- if (v != 0) {
- v->write(writer, QStringLiteral("widget"));
- }
- break;
- }
- case Layout: {
- DomLayout* v = elementLayout();
- if (v != 0) {
- v->write(writer, QStringLiteral("layout"));
- }
- break;
- }
- case Spacer: {
- DomSpacer* v = elementSpacer();
- if (v != 0) {
- v->write(writer, QStringLiteral("spacer"));
- }
- break;
- }
- default:
- break;
+ case Widget: {
+ DomWidget *v = elementWidget();
+ if (v != 0)
+ v->write(writer, QStringLiteral("widget"));
+ break;
+ }
+ case Layout: {
+ DomLayout *v = elementLayout();
+ if (v != 0)
+ v->write(writer, QStringLiteral("layout"));
+ break;
+ }
+ case Spacer: {
+ DomSpacer *v = elementSpacer();
+ if (v != 0)
+ v->write(writer, QStringLiteral("spacer"));
+ break;
+ }
+ default:
+ break;
}
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
writer.writeEndElement();
}
-DomWidget* DomLayoutItem::takeElementWidget()
+DomWidget *DomLayoutItem::takeElementWidget()
{
- DomWidget* a = m_widget;
+ DomWidget *a = m_widget;
m_widget = 0;
return a;
}
-void DomLayoutItem::setElementWidget(DomWidget* a)
+void DomLayoutItem::setElementWidget(DomWidget *a)
{
- clear(false);
+ clear();
m_kind = Widget;
m_widget = a;
}
-DomLayout* DomLayoutItem::takeElementLayout()
+DomLayout *DomLayoutItem::takeElementLayout()
{
- DomLayout* a = m_layout;
+ DomLayout *a = m_layout;
m_layout = 0;
return a;
}
-void DomLayoutItem::setElementLayout(DomLayout* a)
+void DomLayoutItem::setElementLayout(DomLayout *a)
{
- clear(false);
+ clear();
m_kind = Layout;
m_layout = a;
}
-DomSpacer* DomLayoutItem::takeElementSpacer()
+DomSpacer *DomLayoutItem::takeElementSpacer()
{
- DomSpacer* a = m_spacer;
+ DomSpacer *a = m_spacer;
m_spacer = 0;
return a;
}
-void DomLayoutItem::setElementSpacer(DomSpacer* a)
+void DomLayoutItem::setElementSpacer(DomSpacer *a)
{
- clear(false);
+ clear();
m_kind = Spacer;
m_spacer = a;
}
-void DomRow::clear(bool clear_all)
-{
- qDeleteAll(m_property);
- m_property.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomRow::DomRow()
-{
- m_children = 0;
-}
-
DomRow::~DomRow()
{
qDeleteAll(m_property);
@@ -3154,12 +1908,11 @@ DomRow::~DomRow()
void DomRow::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("property")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_property.append(v);
@@ -3169,12 +1922,7 @@ void DomRow::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -3183,41 +1931,20 @@ void DomRow::read(QXmlStreamReader &reader)
void DomRow::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("row") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("row") : tagName.toLower());
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
+ for (DomProperty *v : m_property)
v->write(writer, QStringLiteral("property"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomRow::setElementProperty(const QList<DomProperty*>& a)
+void DomRow::setElementProperty(const QList<DomProperty *> &a)
{
m_children |= Property;
m_property = a;
}
-void DomColumn::clear(bool clear_all)
-{
- qDeleteAll(m_property);
- m_property.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomColumn::DomColumn()
-{
- m_children = 0;
-}
-
DomColumn::~DomColumn()
{
qDeleteAll(m_property);
@@ -3226,12 +1953,11 @@ DomColumn::~DomColumn()
void DomColumn::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("property")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_property.append(v);
@@ -3241,12 +1967,7 @@ void DomColumn::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -3255,51 +1976,20 @@ void DomColumn::read(QXmlStreamReader &reader)
void DomColumn::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("column") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("column") : tagName.toLower());
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
+ for (DomProperty *v : m_property)
v->write(writer, QStringLiteral("property"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomColumn::setElementProperty(const QList<DomProperty*>& a)
+void DomColumn::setElementProperty(const QList<DomProperty *> &a)
{
m_children |= Property;
m_property = a;
}
-void DomItem::clear(bool clear_all)
-{
- qDeleteAll(m_property);
- m_property.clear();
- qDeleteAll(m_item);
- m_item.clear();
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_row = false;
- m_attr_row = 0;
- m_has_attr_column = false;
- m_attr_column = 0;
- }
-
- m_children = 0;
-}
-
-DomItem::DomItem()
-{
- m_children = 0;
- m_has_attr_row = false;
- m_attr_row = 0;
- m_has_attr_column = false;
- m_attr_column = 0;
-}
-
DomItem::~DomItem()
{
qDeleteAll(m_property);
@@ -3310,10 +2000,9 @@ DomItem::~DomItem()
void DomItem::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("row")) {
setAttributeRow(attribute.value().toInt());
continue;
@@ -3325,17 +2014,17 @@ void DomItem::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("property")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (tag == QLatin1String("item")) {
+ if (!tag.compare(QLatin1String("item"), Qt::CaseInsensitive)) {
DomItem *v = new DomItem();
v->read(reader);
m_item.append(v);
@@ -3345,12 +2034,7 @@ void DomItem::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -3359,7 +2043,7 @@ void DomItem::read(QXmlStreamReader &reader)
void DomItem::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("item") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("item") : tagName.toLower());
if (hasAttributeRow())
writer.writeAttribute(QStringLiteral("row"), QString::number(attributeRow()));
@@ -3367,90 +2051,32 @@ void DomItem::write(QXmlStreamWriter &writer, const QString &tagName) const
if (hasAttributeColumn())
writer.writeAttribute(QStringLiteral("column"), QString::number(attributeColumn()));
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
+ for (DomProperty *v : m_property)
v->write(writer, QStringLiteral("property"));
- }
- for (int i = 0; i < m_item.size(); ++i) {
- DomItem* v = m_item[i];
+
+ for (DomItem *v : m_item)
v->write(writer, QStringLiteral("item"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomItem::setElementProperty(const QList<DomProperty*>& a)
+void DomItem::setElementProperty(const QList<DomProperty *> &a)
{
m_children |= Property;
m_property = a;
}
-void DomItem::setElementItem(const QList<DomItem*>& a)
+void DomItem::setElementItem(const QVector<DomItem *> &a)
{
m_children |= Item;
m_item = a;
}
-void DomWidget::clear(bool clear_all)
-{
- m_class.clear();
- qDeleteAll(m_property);
- m_property.clear();
- qDeleteAll(m_script);
- m_script.clear();
- qDeleteAll(m_widgetData);
- m_widgetData.clear();
- qDeleteAll(m_attribute);
- m_attribute.clear();
- qDeleteAll(m_row);
- m_row.clear();
- qDeleteAll(m_column);
- m_column.clear();
- qDeleteAll(m_item);
- m_item.clear();
- qDeleteAll(m_layout);
- m_layout.clear();
- qDeleteAll(m_widget);
- m_widget.clear();
- qDeleteAll(m_action);
- m_action.clear();
- qDeleteAll(m_actionGroup);
- m_actionGroup.clear();
- qDeleteAll(m_addAction);
- m_addAction.clear();
- m_zOrder.clear();
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_class = false;
- m_has_attr_name = false;
- m_has_attr_native = false;
- m_attr_native = false;
- }
-
- m_children = 0;
-}
-
-DomWidget::DomWidget()
-{
- m_children = 0;
- m_has_attr_class = false;
- m_has_attr_name = false;
- m_has_attr_native = false;
- m_attr_native = false;
-}
-
DomWidget::~DomWidget()
{
m_class.clear();
qDeleteAll(m_property);
m_property.clear();
- qDeleteAll(m_script);
- m_script.clear();
- qDeleteAll(m_widgetData);
- m_widgetData.clear();
qDeleteAll(m_attribute);
m_attribute.clear();
qDeleteAll(m_row);
@@ -3474,10 +2100,9 @@ DomWidget::~DomWidget()
void DomWidget::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("class")) {
setAttributeClass(attribute.value().toString());
continue;
@@ -3493,87 +2118,85 @@ void DomWidget::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("class")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("class"), Qt::CaseInsensitive)) {
m_class.append(reader.readElementText());
continue;
}
- if (tag == QLatin1String("property")) {
+ if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_property.append(v);
continue;
}
- if (tag == QLatin1String("script")) {
- DomScript *v = new DomScript();
- v->read(reader);
- m_script.append(v);
+ if (!tag.compare(QLatin1String("script"), Qt::CaseInsensitive)) {
+ qWarning("Omitting deprecated element <script>.");
+ reader.skipCurrentElement();
continue;
}
- if (tag == QLatin1String("widgetdata")) {
- DomWidgetData *v = new DomWidgetData();
- v->read(reader);
- m_widgetData.append(v);
+ if (!tag.compare(QLatin1String("widgetdata"), Qt::CaseInsensitive)) {
+ qWarning("Omitting deprecated element <widgetdata>.");
+ reader.skipCurrentElement();
continue;
}
- if (tag == QLatin1String("attribute")) {
+ if (!tag.compare(QLatin1String("attribute"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_attribute.append(v);
continue;
}
- if (tag == QLatin1String("row")) {
+ if (!tag.compare(QLatin1String("row"), Qt::CaseInsensitive)) {
DomRow *v = new DomRow();
v->read(reader);
m_row.append(v);
continue;
}
- if (tag == QLatin1String("column")) {
+ if (!tag.compare(QLatin1String("column"), Qt::CaseInsensitive)) {
DomColumn *v = new DomColumn();
v->read(reader);
m_column.append(v);
continue;
}
- if (tag == QLatin1String("item")) {
+ if (!tag.compare(QLatin1String("item"), Qt::CaseInsensitive)) {
DomItem *v = new DomItem();
v->read(reader);
m_item.append(v);
continue;
}
- if (tag == QLatin1String("layout")) {
+ if (!tag.compare(QLatin1String("layout"), Qt::CaseInsensitive)) {
DomLayout *v = new DomLayout();
v->read(reader);
m_layout.append(v);
continue;
}
- if (tag == QLatin1String("widget")) {
+ if (!tag.compare(QLatin1String("widget"), Qt::CaseInsensitive)) {
DomWidget *v = new DomWidget();
v->read(reader);
m_widget.append(v);
continue;
}
- if (tag == QLatin1String("action")) {
+ if (!tag.compare(QLatin1String("action"), Qt::CaseInsensitive)) {
DomAction *v = new DomAction();
v->read(reader);
m_action.append(v);
continue;
}
- if (tag == QLatin1String("actiongroup")) {
+ if (!tag.compare(QLatin1String("actiongroup"), Qt::CaseInsensitive)) {
DomActionGroup *v = new DomActionGroup();
v->read(reader);
m_actionGroup.append(v);
continue;
}
- if (tag == QLatin1String("addaction")) {
+ if (!tag.compare(QLatin1String("addaction"), Qt::CaseInsensitive)) {
DomActionRef *v = new DomActionRef();
v->read(reader);
m_addAction.append(v);
continue;
}
- if (tag == QLatin1String("zorder")) {
+ if (!tag.compare(QLatin1String("zorder"), Qt::CaseInsensitive)) {
m_zOrder.append(reader.readElementText());
continue;
}
@@ -3581,12 +2204,7 @@ void DomWidget::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -3595,7 +2213,7 @@ void DomWidget::read(QXmlStreamReader &reader)
void DomWidget::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("widget") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("widget") : tagName.toLower());
if (hasAttributeClass())
writer.writeAttribute(QStringLiteral("class"), attributeClass());
@@ -3606,171 +2224,117 @@ void DomWidget::write(QXmlStreamWriter &writer, const QString &tagName) const
if (hasAttributeNative())
writer.writeAttribute(QStringLiteral("native"), (attributeNative() ? QLatin1String("true") : QLatin1String("false")));
- for (int i = 0; i < m_class.size(); ++i) {
- QString v = m_class[i];
+ for (const QString &v : m_class)
writer.writeTextElement(QStringLiteral("class"), v);
- }
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
+
+ for (DomProperty *v : m_property)
v->write(writer, QStringLiteral("property"));
- }
- for (int i = 0; i < m_script.size(); ++i) {
- DomScript* v = m_script[i];
- v->write(writer, QStringLiteral("script"));
- }
- for (int i = 0; i < m_widgetData.size(); ++i) {
- DomWidgetData* v = m_widgetData[i];
- v->write(writer, QStringLiteral("widgetdata"));
- }
- for (int i = 0; i < m_attribute.size(); ++i) {
- DomProperty* v = m_attribute[i];
+
+ for (DomProperty *v : m_attribute)
v->write(writer, QStringLiteral("attribute"));
- }
- for (int i = 0; i < m_row.size(); ++i) {
- DomRow* v = m_row[i];
+
+ for (DomRow *v : m_row)
v->write(writer, QStringLiteral("row"));
- }
- for (int i = 0; i < m_column.size(); ++i) {
- DomColumn* v = m_column[i];
+
+ for (DomColumn *v : m_column)
v->write(writer, QStringLiteral("column"));
- }
- for (int i = 0; i < m_item.size(); ++i) {
- DomItem* v = m_item[i];
+
+ for (DomItem *v : m_item)
v->write(writer, QStringLiteral("item"));
- }
- for (int i = 0; i < m_layout.size(); ++i) {
- DomLayout* v = m_layout[i];
+
+ for (DomLayout *v : m_layout)
v->write(writer, QStringLiteral("layout"));
- }
- for (int i = 0; i < m_widget.size(); ++i) {
- DomWidget* v = m_widget[i];
+
+ for (DomWidget *v : m_widget)
v->write(writer, QStringLiteral("widget"));
- }
- for (int i = 0; i < m_action.size(); ++i) {
- DomAction* v = m_action[i];
+
+ for (DomAction *v : m_action)
v->write(writer, QStringLiteral("action"));
- }
- for (int i = 0; i < m_actionGroup.size(); ++i) {
- DomActionGroup* v = m_actionGroup[i];
+
+ for (DomActionGroup *v : m_actionGroup)
v->write(writer, QStringLiteral("actiongroup"));
- }
- for (int i = 0; i < m_addAction.size(); ++i) {
- DomActionRef* v = m_addAction[i];
+
+ for (DomActionRef *v : m_addAction)
v->write(writer, QStringLiteral("addaction"));
- }
- for (int i = 0; i < m_zOrder.size(); ++i) {
- QString v = m_zOrder[i];
+
+ for (const QString &v : m_zOrder)
writer.writeTextElement(QStringLiteral("zorder"), v);
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomWidget::setElementClass(const QStringList& a)
+void DomWidget::setElementClass(const QStringList &a)
{
m_children |= Class;
m_class = a;
}
-void DomWidget::setElementProperty(const QList<DomProperty*>& a)
+void DomWidget::setElementProperty(const QList<DomProperty *> &a)
{
m_children |= Property;
m_property = a;
}
-void DomWidget::setElementScript(const QList<DomScript*>& a)
-{
- m_children |= Script;
- m_script = a;
-}
-
-void DomWidget::setElementWidgetData(const QList<DomWidgetData*>& a)
-{
- m_children |= WidgetData;
- m_widgetData = a;
-}
-
-void DomWidget::setElementAttribute(const QList<DomProperty*>& a)
+void DomWidget::setElementAttribute(const QList<DomProperty *> &a)
{
m_children |= Attribute;
m_attribute = a;
}
-void DomWidget::setElementRow(const QList<DomRow*>& a)
+void DomWidget::setElementRow(const QVector<DomRow *> &a)
{
m_children |= Row;
m_row = a;
}
-void DomWidget::setElementColumn(const QList<DomColumn*>& a)
+void DomWidget::setElementColumn(const QVector<DomColumn *> &a)
{
m_children |= Column;
m_column = a;
}
-void DomWidget::setElementItem(const QList<DomItem*>& a)
+void DomWidget::setElementItem(const QVector<DomItem *> &a)
{
m_children |= Item;
m_item = a;
}
-void DomWidget::setElementLayout(const QList<DomLayout*>& a)
+void DomWidget::setElementLayout(const QVector<DomLayout *> &a)
{
m_children |= Layout;
m_layout = a;
}
-void DomWidget::setElementWidget(const QList<DomWidget*>& a)
+void DomWidget::setElementWidget(const QVector<DomWidget *> &a)
{
m_children |= Widget;
m_widget = a;
}
-void DomWidget::setElementAction(const QList<DomAction*>& a)
+void DomWidget::setElementAction(const QVector<DomAction *> &a)
{
m_children |= Action;
m_action = a;
}
-void DomWidget::setElementActionGroup(const QList<DomActionGroup*>& a)
+void DomWidget::setElementActionGroup(const QVector<DomActionGroup *> &a)
{
m_children |= ActionGroup;
m_actionGroup = a;
}
-void DomWidget::setElementAddAction(const QList<DomActionRef*>& a)
+void DomWidget::setElementAddAction(const QVector<DomActionRef *> &a)
{
m_children |= AddAction;
m_addAction = a;
}
-void DomWidget::setElementZOrder(const QStringList& a)
+void DomWidget::setElementZOrder(const QStringList &a)
{
m_children |= ZOrder;
m_zOrder = a;
}
-void DomSpacer::clear(bool clear_all)
-{
- qDeleteAll(m_property);
- m_property.clear();
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_name = false;
- }
-
- m_children = 0;
-}
-
-DomSpacer::DomSpacer()
-{
- m_children = 0;
- m_has_attr_name = false;
-}
-
DomSpacer::~DomSpacer()
{
qDeleteAll(m_property);
@@ -3779,10 +2343,9 @@ DomSpacer::~DomSpacer()
void DomSpacer::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("name")) {
setAttributeName(attribute.value().toString());
continue;
@@ -3790,11 +2353,11 @@ void DomSpacer::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("property")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_property.append(v);
@@ -3804,12 +2367,7 @@ void DomSpacer::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -3818,62 +2376,32 @@ void DomSpacer::read(QXmlStreamReader &reader)
void DomSpacer::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("spacer") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("spacer") : tagName.toLower());
if (hasAttributeName())
writer.writeAttribute(QStringLiteral("name"), attributeName());
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
+ for (DomProperty *v : m_property)
v->write(writer, QStringLiteral("property"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomSpacer::setElementProperty(const QList<DomProperty*>& a)
+void DomSpacer::setElementProperty(const QList<DomProperty *> &a)
{
m_children |= Property;
m_property = a;
}
-void DomColor::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_alpha = false;
- m_attr_alpha = 0;
- }
-
- m_children = 0;
- m_red = 0;
- m_green = 0;
- m_blue = 0;
-}
-
-DomColor::DomColor()
-{
- m_children = 0;
- m_has_attr_alpha = false;
- m_attr_alpha = 0;
- m_red = 0;
- m_green = 0;
- m_blue = 0;
-}
-
DomColor::~DomColor()
{
}
void DomColor::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("alpha")) {
setAttributeAlpha(attribute.value().toInt());
continue;
@@ -3881,19 +2409,19 @@ void DomColor::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("red")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("red"), Qt::CaseInsensitive)) {
setElementRed(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("green")) {
+ if (!tag.compare(QLatin1String("green"), Qt::CaseInsensitive)) {
setElementGreen(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("blue")) {
+ if (!tag.compare(QLatin1String("blue"), Qt::CaseInsensitive)) {
setElementBlue(reader.readElementText().toInt());
continue;
}
@@ -3901,12 +2429,7 @@ void DomColor::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -3915,25 +2438,19 @@ void DomColor::read(QXmlStreamReader &reader)
void DomColor::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("color") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("color") : tagName.toLower());
if (hasAttributeAlpha())
writer.writeAttribute(QStringLiteral("alpha"), QString::number(attributeAlpha()));
- if (m_children & Red) {
+ if (m_children & Red)
writer.writeTextElement(QStringLiteral("red"), QString::number(m_red));
- }
- if (m_children & Green) {
+ if (m_children & Green)
writer.writeTextElement(QStringLiteral("green"), QString::number(m_green));
- }
- if (m_children & Blue) {
+ if (m_children & Blue)
writer.writeTextElement(QStringLiteral("blue"), QString::number(m_blue));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -3971,28 +2488,6 @@ void DomColor::clearElementBlue()
m_children &= ~Blue;
}
-void DomGradientStop::clear(bool clear_all)
-{
- delete m_color;
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_position = false;
- m_attr_position = 0.0;
- }
-
- m_children = 0;
- m_color = 0;
-}
-
-DomGradientStop::DomGradientStop()
-{
- m_children = 0;
- m_has_attr_position = false;
- m_attr_position = 0.0;
- m_color = 0;
-}
-
DomGradientStop::~DomGradientStop()
{
delete m_color;
@@ -4000,10 +2495,9 @@ DomGradientStop::~DomGradientStop()
void DomGradientStop::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("position")) {
setAttributePosition(attribute.value().toDouble());
continue;
@@ -4011,11 +2505,11 @@ void DomGradientStop::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("color")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
DomColor *v = new DomColor();
v->read(reader);
setElementColor(v);
@@ -4025,12 +2519,7 @@ void DomGradientStop::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -4039,30 +2528,26 @@ void DomGradientStop::read(QXmlStreamReader &reader)
void DomGradientStop::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("gradientstop") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("gradientstop") : tagName.toLower());
if (hasAttributePosition())
writer.writeAttribute(QStringLiteral("position"), QString::number(attributePosition(), 'f', 15));
- if (m_children & Color) {
+ if (m_children & Color)
m_color->write(writer, QStringLiteral("color"));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-DomColor* DomGradientStop::takeElementColor()
+DomColor *DomGradientStop::takeElementColor()
{
- DomColor* a = m_color;
+ DomColor *a = m_color;
m_color = 0;
m_children ^= Color;
return a;
}
-void DomGradientStop::setElementColor(DomColor* a)
+void DomGradientStop::setElementColor(DomColor *a)
{
delete m_color;
m_children |= Color;
@@ -4076,69 +2561,6 @@ void DomGradientStop::clearElementColor()
m_children &= ~Color;
}
-void DomGradient::clear(bool clear_all)
-{
- qDeleteAll(m_gradientStop);
- m_gradientStop.clear();
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_startX = false;
- m_attr_startX = 0.0;
- m_has_attr_startY = false;
- m_attr_startY = 0.0;
- m_has_attr_endX = false;
- m_attr_endX = 0.0;
- m_has_attr_endY = false;
- m_attr_endY = 0.0;
- m_has_attr_centralX = false;
- m_attr_centralX = 0.0;
- m_has_attr_centralY = false;
- m_attr_centralY = 0.0;
- m_has_attr_focalX = false;
- m_attr_focalX = 0.0;
- m_has_attr_focalY = false;
- m_attr_focalY = 0.0;
- m_has_attr_radius = false;
- m_attr_radius = 0.0;
- m_has_attr_angle = false;
- m_attr_angle = 0.0;
- m_has_attr_type = false;
- m_has_attr_spread = false;
- m_has_attr_coordinateMode = false;
- }
-
- m_children = 0;
-}
-
-DomGradient::DomGradient()
-{
- m_children = 0;
- m_has_attr_startX = false;
- m_attr_startX = 0.0;
- m_has_attr_startY = false;
- m_attr_startY = 0.0;
- m_has_attr_endX = false;
- m_attr_endX = 0.0;
- m_has_attr_endY = false;
- m_attr_endY = 0.0;
- m_has_attr_centralX = false;
- m_attr_centralX = 0.0;
- m_has_attr_centralY = false;
- m_attr_centralY = 0.0;
- m_has_attr_focalX = false;
- m_attr_focalX = 0.0;
- m_has_attr_focalY = false;
- m_attr_focalY = 0.0;
- m_has_attr_radius = false;
- m_attr_radius = 0.0;
- m_has_attr_angle = false;
- m_attr_angle = 0.0;
- m_has_attr_type = false;
- m_has_attr_spread = false;
- m_has_attr_coordinateMode = false;
-}
-
DomGradient::~DomGradient()
{
qDeleteAll(m_gradientStop);
@@ -4147,10 +2569,9 @@ DomGradient::~DomGradient()
void DomGradient::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("startx")) {
setAttributeStartX(attribute.value().toDouble());
continue;
@@ -4206,11 +2627,11 @@ void DomGradient::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("gradientstop")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("gradientstop"), Qt::CaseInsensitive)) {
DomGradientStop *v = new DomGradientStop();
v->read(reader);
m_gradientStop.append(v);
@@ -4220,12 +2641,7 @@ void DomGradient::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -4234,7 +2650,7 @@ void DomGradient::read(QXmlStreamReader &reader)
void DomGradient::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("gradient") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("gradient") : tagName.toLower());
if (hasAttributeStartX())
writer.writeAttribute(QStringLiteral("startx"), QString::number(attributeStartX(), 'f', 15));
@@ -4275,63 +2691,43 @@ void DomGradient::write(QXmlStreamWriter &writer, const QString &tagName) const
if (hasAttributeCoordinateMode())
writer.writeAttribute(QStringLiteral("coordinatemode"), attributeCoordinateMode());
- for (int i = 0; i < m_gradientStop.size(); ++i) {
- DomGradientStop* v = m_gradientStop[i];
+ for (DomGradientStop *v : m_gradientStop)
v->write(writer, QStringLiteral("gradientstop"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomGradient::setElementGradientStop(const QList<DomGradientStop*>& a)
+void DomGradient::setElementGradientStop(const QVector<DomGradientStop *> &a)
{
m_children |= GradientStop;
m_gradientStop = a;
}
-void DomBrush::clear(bool clear_all)
+DomBrush::~DomBrush()
{
delete m_color;
delete m_texture;
delete m_gradient;
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_brushStyle = false;
- }
-
- m_kind = Unknown;
-
- m_color = 0;
- m_texture = 0;
- m_gradient = 0;
}
-DomBrush::DomBrush()
-{
- m_kind = Unknown;
-
- m_has_attr_brushStyle = false;
- m_color = 0;
- m_texture = 0;
- m_gradient = 0;
-}
-
-DomBrush::~DomBrush()
+void DomBrush::clear()
{
delete m_color;
delete m_texture;
delete m_gradient;
+
+ m_kind = Unknown;
+
+ m_color = nullptr;
+ m_texture = nullptr;
+ m_gradient = nullptr;
}
void DomBrush::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("brushstyle")) {
setAttributeBrushStyle(attribute.value().toString());
continue;
@@ -4339,23 +2735,23 @@ void DomBrush::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("color")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
DomColor *v = new DomColor();
v->read(reader);
setElementColor(v);
continue;
}
- if (tag == QLatin1String("texture")) {
+ if (!tag.compare(QLatin1String("texture"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
setElementTexture(v);
continue;
}
- if (tag == QLatin1String("gradient")) {
+ if (!tag.compare(QLatin1String("gradient"), Qt::CaseInsensitive)) {
DomGradient *v = new DomGradient();
v->read(reader);
setElementGradient(v);
@@ -4365,12 +2761,7 @@ void DomBrush::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -4379,104 +2770,78 @@ void DomBrush::read(QXmlStreamReader &reader)
void DomBrush::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("brush") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("brush") : tagName.toLower());
if (hasAttributeBrushStyle())
writer.writeAttribute(QStringLiteral("brushstyle"), attributeBrushStyle());
switch (kind()) {
- case Color: {
- DomColor* v = elementColor();
- if (v != 0) {
- v->write(writer, QStringLiteral("color"));
- }
- break;
- }
- case Texture: {
- DomProperty* v = elementTexture();
- if (v != 0) {
- v->write(writer, QStringLiteral("texture"));
- }
- break;
- }
- case Gradient: {
- DomGradient* v = elementGradient();
- if (v != 0) {
- v->write(writer, QStringLiteral("gradient"));
- }
- break;
- }
- default:
- break;
+ case Color: {
+ DomColor *v = elementColor();
+ if (v != 0)
+ v->write(writer, QStringLiteral("color"));
+ break;
+ }
+ case Texture: {
+ DomProperty *v = elementTexture();
+ if (v != 0)
+ v->write(writer, QStringLiteral("texture"));
+ break;
+ }
+ case Gradient: {
+ DomGradient *v = elementGradient();
+ if (v != 0)
+ v->write(writer, QStringLiteral("gradient"));
+ break;
+ }
+ default:
+ break;
}
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
writer.writeEndElement();
}
-DomColor* DomBrush::takeElementColor()
+DomColor *DomBrush::takeElementColor()
{
- DomColor* a = m_color;
+ DomColor *a = m_color;
m_color = 0;
return a;
}
-void DomBrush::setElementColor(DomColor* a)
+void DomBrush::setElementColor(DomColor *a)
{
- clear(false);
+ clear();
m_kind = Color;
m_color = a;
}
-DomProperty* DomBrush::takeElementTexture()
+DomProperty *DomBrush::takeElementTexture()
{
- DomProperty* a = m_texture;
+ DomProperty *a = m_texture;
m_texture = 0;
return a;
}
-void DomBrush::setElementTexture(DomProperty* a)
+void DomBrush::setElementTexture(DomProperty *a)
{
- clear(false);
+ clear();
m_kind = Texture;
m_texture = a;
}
-DomGradient* DomBrush::takeElementGradient()
+DomGradient *DomBrush::takeElementGradient()
{
- DomGradient* a = m_gradient;
+ DomGradient *a = m_gradient;
m_gradient = 0;
return a;
}
-void DomBrush::setElementGradient(DomGradient* a)
+void DomBrush::setElementGradient(DomGradient *a)
{
- clear(false);
+ clear();
m_kind = Gradient;
m_gradient = a;
}
-void DomColorRole::clear(bool clear_all)
-{
- delete m_brush;
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_role = false;
- }
-
- m_children = 0;
- m_brush = 0;
-}
-
-DomColorRole::DomColorRole()
-{
- m_children = 0;
- m_has_attr_role = false;
- m_brush = 0;
-}
-
DomColorRole::~DomColorRole()
{
delete m_brush;
@@ -4484,10 +2849,9 @@ DomColorRole::~DomColorRole()
void DomColorRole::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("role")) {
setAttributeRole(attribute.value().toString());
continue;
@@ -4495,11 +2859,11 @@ void DomColorRole::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("brush")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("brush"), Qt::CaseInsensitive)) {
DomBrush *v = new DomBrush();
v->read(reader);
setElementBrush(v);
@@ -4509,12 +2873,7 @@ void DomColorRole::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -4523,30 +2882,26 @@ void DomColorRole::read(QXmlStreamReader &reader)
void DomColorRole::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("colorrole") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("colorrole") : tagName.toLower());
if (hasAttributeRole())
writer.writeAttribute(QStringLiteral("role"), attributeRole());
- if (m_children & Brush) {
+ if (m_children & Brush)
m_brush->write(writer, QStringLiteral("brush"));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-DomBrush* DomColorRole::takeElementBrush()
+DomBrush *DomColorRole::takeElementBrush()
{
- DomBrush* a = m_brush;
+ DomBrush *a = m_brush;
m_brush = 0;
m_children ^= Brush;
return a;
}
-void DomColorRole::setElementBrush(DomBrush* a)
+void DomColorRole::setElementBrush(DomBrush *a)
{
delete m_brush;
m_children |= Brush;
@@ -4560,25 +2915,6 @@ void DomColorRole::clearElementBrush()
m_children &= ~Brush;
}
-void DomColorGroup::clear(bool clear_all)
-{
- qDeleteAll(m_colorRole);
- m_colorRole.clear();
- qDeleteAll(m_color);
- m_color.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomColorGroup::DomColorGroup()
-{
- m_children = 0;
-}
-
DomColorGroup::~DomColorGroup()
{
qDeleteAll(m_colorRole);
@@ -4589,18 +2925,17 @@ DomColorGroup::~DomColorGroup()
void DomColorGroup::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("colorrole")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("colorrole"), Qt::CaseInsensitive)) {
DomColorRole *v = new DomColorRole();
v->read(reader);
m_colorRole.append(v);
continue;
}
- if (tag == QLatin1String("color")) {
+ if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
DomColor *v = new DomColor();
v->read(reader);
m_color.append(v);
@@ -4610,12 +2945,7 @@ void DomColorGroup::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -4624,58 +2954,29 @@ void DomColorGroup::read(QXmlStreamReader &reader)
void DomColorGroup::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("colorgroup") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("colorgroup") : tagName.toLower());
- for (int i = 0; i < m_colorRole.size(); ++i) {
- DomColorRole* v = m_colorRole[i];
+ for (DomColorRole *v : m_colorRole)
v->write(writer, QStringLiteral("colorrole"));
- }
- for (int i = 0; i < m_color.size(); ++i) {
- DomColor* v = m_color[i];
+
+ for (DomColor *v : m_color)
v->write(writer, QStringLiteral("color"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomColorGroup::setElementColorRole(const QList<DomColorRole*>& a)
+void DomColorGroup::setElementColorRole(const QVector<DomColorRole *> &a)
{
m_children |= ColorRole;
m_colorRole = a;
}
-void DomColorGroup::setElementColor(const QList<DomColor*>& a)
+void DomColorGroup::setElementColor(const QVector<DomColor *> &a)
{
m_children |= Color;
m_color = a;
}
-void DomPalette::clear(bool clear_all)
-{
- delete m_active;
- delete m_inactive;
- delete m_disabled;
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_active = 0;
- m_inactive = 0;
- m_disabled = 0;
-}
-
-DomPalette::DomPalette()
-{
- m_children = 0;
- m_active = 0;
- m_inactive = 0;
- m_disabled = 0;
-}
-
DomPalette::~DomPalette()
{
delete m_active;
@@ -4685,24 +2986,23 @@ DomPalette::~DomPalette()
void DomPalette::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("active")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("active"), Qt::CaseInsensitive)) {
DomColorGroup *v = new DomColorGroup();
v->read(reader);
setElementActive(v);
continue;
}
- if (tag == QLatin1String("inactive")) {
+ if (!tag.compare(QLatin1String("inactive"), Qt::CaseInsensitive)) {
DomColorGroup *v = new DomColorGroup();
v->read(reader);
setElementInactive(v);
continue;
}
- if (tag == QLatin1String("disabled")) {
+ if (!tag.compare(QLatin1String("disabled"), Qt::CaseInsensitive)) {
DomColorGroup *v = new DomColorGroup();
v->read(reader);
setElementDisabled(v);
@@ -4712,12 +3012,7 @@ void DomPalette::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -4726,65 +3021,59 @@ void DomPalette::read(QXmlStreamReader &reader)
void DomPalette::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("palette") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("palette") : tagName.toLower());
- if (m_children & Active) {
+ if (m_children & Active)
m_active->write(writer, QStringLiteral("active"));
- }
- if (m_children & Inactive) {
+ if (m_children & Inactive)
m_inactive->write(writer, QStringLiteral("inactive"));
- }
- if (m_children & Disabled) {
+ if (m_children & Disabled)
m_disabled->write(writer, QStringLiteral("disabled"));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-DomColorGroup* DomPalette::takeElementActive()
+DomColorGroup *DomPalette::takeElementActive()
{
- DomColorGroup* a = m_active;
+ DomColorGroup *a = m_active;
m_active = 0;
m_children ^= Active;
return a;
}
-void DomPalette::setElementActive(DomColorGroup* a)
+void DomPalette::setElementActive(DomColorGroup *a)
{
delete m_active;
m_children |= Active;
m_active = a;
}
-DomColorGroup* DomPalette::takeElementInactive()
+DomColorGroup *DomPalette::takeElementInactive()
{
- DomColorGroup* a = m_inactive;
+ DomColorGroup *a = m_inactive;
m_inactive = 0;
m_children ^= Inactive;
return a;
}
-void DomPalette::setElementInactive(DomColorGroup* a)
+void DomPalette::setElementInactive(DomColorGroup *a)
{
delete m_inactive;
m_children |= Inactive;
m_inactive = a;
}
-DomColorGroup* DomPalette::takeElementDisabled()
+DomColorGroup *DomPalette::takeElementDisabled()
{
- DomColorGroup* a = m_disabled;
+ DomColorGroup *a = m_disabled;
m_disabled = 0;
m_children ^= Disabled;
return a;
}
-void DomPalette::setElementDisabled(DomColorGroup* a)
+void DomPalette::setElementDisabled(DomColorGroup *a)
{
delete m_disabled;
m_children |= Disabled;
@@ -4812,85 +3101,53 @@ void DomPalette::clearElementDisabled()
m_children &= ~Disabled;
}
-void DomFont::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_pointSize = 0;
- m_weight = 0;
- m_italic = false;
- m_bold = false;
- m_underline = false;
- m_strikeOut = false;
- m_antialiasing = false;
- m_kerning = false;
-}
-
-DomFont::DomFont()
-{
- m_children = 0;
- m_pointSize = 0;
- m_weight = 0;
- m_italic = false;
- m_bold = false;
- m_underline = false;
- m_strikeOut = false;
- m_antialiasing = false;
- m_kerning = false;
-}
-
DomFont::~DomFont()
{
}
void DomFont::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("family")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("family"), Qt::CaseInsensitive)) {
setElementFamily(reader.readElementText());
continue;
}
- if (tag == QLatin1String("pointsize")) {
+ if (!tag.compare(QLatin1String("pointsize"), Qt::CaseInsensitive)) {
setElementPointSize(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("weight")) {
+ if (!tag.compare(QLatin1String("weight"), Qt::CaseInsensitive)) {
setElementWeight(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("italic")) {
+ if (!tag.compare(QLatin1String("italic"), Qt::CaseInsensitive)) {
setElementItalic(reader.readElementText() == QLatin1String("true"));
continue;
}
- if (tag == QLatin1String("bold")) {
+ if (!tag.compare(QLatin1String("bold"), Qt::CaseInsensitive)) {
setElementBold(reader.readElementText() == QLatin1String("true"));
continue;
}
- if (tag == QLatin1String("underline")) {
+ if (!tag.compare(QLatin1String("underline"), Qt::CaseInsensitive)) {
setElementUnderline(reader.readElementText() == QLatin1String("true"));
continue;
}
- if (tag == QLatin1String("strikeout")) {
+ if (!tag.compare(QLatin1String("strikeout"), Qt::CaseInsensitive)) {
setElementStrikeOut(reader.readElementText() == QLatin1String("true"));
continue;
}
- if (tag == QLatin1String("antialiasing")) {
+ if (!tag.compare(QLatin1String("antialiasing"), Qt::CaseInsensitive)) {
setElementAntialiasing(reader.readElementText() == QLatin1String("true"));
continue;
}
- if (tag == QLatin1String("stylestrategy")) {
+ if (!tag.compare(QLatin1String("stylestrategy"), Qt::CaseInsensitive)) {
setElementStyleStrategy(reader.readElementText());
continue;
}
- if (tag == QLatin1String("kerning")) {
+ if (!tag.compare(QLatin1String("kerning"), Qt::CaseInsensitive)) {
setElementKerning(reader.readElementText() == QLatin1String("true"));
continue;
}
@@ -4898,12 +3155,7 @@ void DomFont::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -4912,55 +3164,42 @@ void DomFont::read(QXmlStreamReader &reader)
void DomFont::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("font") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("font") : tagName.toLower());
- if (m_children & Family) {
+ if (m_children & Family)
writer.writeTextElement(QStringLiteral("family"), m_family);
- }
- if (m_children & PointSize) {
+ if (m_children & PointSize)
writer.writeTextElement(QStringLiteral("pointsize"), QString::number(m_pointSize));
- }
- if (m_children & Weight) {
+ if (m_children & Weight)
writer.writeTextElement(QStringLiteral("weight"), QString::number(m_weight));
- }
- if (m_children & Italic) {
+ if (m_children & Italic)
writer.writeTextElement(QStringLiteral("italic"), (m_italic ? QLatin1String("true") : QLatin1String("false")));
- }
- if (m_children & Bold) {
+ if (m_children & Bold)
writer.writeTextElement(QStringLiteral("bold"), (m_bold ? QLatin1String("true") : QLatin1String("false")));
- }
- if (m_children & Underline) {
+ if (m_children & Underline)
writer.writeTextElement(QStringLiteral("underline"), (m_underline ? QLatin1String("true") : QLatin1String("false")));
- }
- if (m_children & StrikeOut) {
+ if (m_children & StrikeOut)
writer.writeTextElement(QStringLiteral("strikeout"), (m_strikeOut ? QLatin1String("true") : QLatin1String("false")));
- }
- if (m_children & Antialiasing) {
+ if (m_children & Antialiasing)
writer.writeTextElement(QStringLiteral("antialiasing"), (m_antialiasing ? QLatin1String("true") : QLatin1String("false")));
- }
- if (m_children & StyleStrategy) {
+ if (m_children & StyleStrategy)
writer.writeTextElement(QStringLiteral("stylestrategy"), m_styleStrategy);
- }
- if (m_children & Kerning) {
+ if (m_children & Kerning)
writer.writeTextElement(QStringLiteral("kerning"), (m_kerning ? QLatin1String("true") : QLatin1String("false")));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomFont::setElementFamily(const QString& a)
+void DomFont::setElementFamily(const QString &a)
{
m_children |= Family;
m_family = a;
@@ -5008,7 +3247,7 @@ void DomFont::setElementAntialiasing(bool a)
m_antialiasing = a;
}
-void DomFont::setElementStyleStrategy(const QString& a)
+void DomFont::setElementStyleStrategy(const QString &a)
{
m_children |= StyleStrategy;
m_styleStrategy = a;
@@ -5070,41 +3309,21 @@ void DomFont::clearElementKerning()
m_children &= ~Kerning;
}
-void DomPoint::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_x = 0;
- m_y = 0;
-}
-
-DomPoint::DomPoint()
-{
- m_children = 0;
- m_x = 0;
- m_y = 0;
-}
-
DomPoint::~DomPoint()
{
}
void DomPoint::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("x")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("x"), Qt::CaseInsensitive)) {
setElementX(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("y")) {
+ if (!tag.compare(QLatin1String("y"), Qt::CaseInsensitive)) {
setElementY(reader.readElementText().toInt());
continue;
}
@@ -5112,12 +3331,7 @@ void DomPoint::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -5126,18 +3340,13 @@ void DomPoint::read(QXmlStreamReader &reader)
void DomPoint::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("point") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("point") : tagName.toLower());
- if (m_children & X) {
+ if (m_children & X)
writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x));
- }
- if (m_children & Y) {
+ if (m_children & Y)
writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -5164,53 +3373,29 @@ void DomPoint::clearElementY()
m_children &= ~Y;
}
-void DomRect::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_x = 0;
- m_y = 0;
- m_width = 0;
- m_height = 0;
-}
-
-DomRect::DomRect()
-{
- m_children = 0;
- m_x = 0;
- m_y = 0;
- m_width = 0;
- m_height = 0;
-}
-
DomRect::~DomRect()
{
}
void DomRect::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("x")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("x"), Qt::CaseInsensitive)) {
setElementX(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("y")) {
+ if (!tag.compare(QLatin1String("y"), Qt::CaseInsensitive)) {
setElementY(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("width")) {
+ if (!tag.compare(QLatin1String("width"), Qt::CaseInsensitive)) {
setElementWidth(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("height")) {
+ if (!tag.compare(QLatin1String("height"), Qt::CaseInsensitive)) {
setElementHeight(reader.readElementText().toInt());
continue;
}
@@ -5218,12 +3403,7 @@ void DomRect::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -5232,26 +3412,19 @@ void DomRect::read(QXmlStreamReader &reader)
void DomRect::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("rect") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("rect") : tagName.toLower());
- if (m_children & X) {
+ if (m_children & X)
writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x));
- }
- if (m_children & Y) {
+ if (m_children & Y)
writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y));
- }
- if (m_children & Width) {
+ if (m_children & Width)
writer.writeTextElement(QStringLiteral("width"), QString::number(m_width));
- }
- if (m_children & Height) {
+ if (m_children & Height)
writer.writeTextElement(QStringLiteral("height"), QString::number(m_height));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -5300,35 +3473,15 @@ void DomRect::clearElementHeight()
m_children &= ~Height;
}
-void DomLocale::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_language = false;
- m_has_attr_country = false;
- }
-
- m_children = 0;
-}
-
-DomLocale::DomLocale()
-{
- m_children = 0;
- m_has_attr_language = false;
- m_has_attr_country = false;
-}
-
DomLocale::~DomLocale()
{
}
void DomLocale::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("language")) {
setAttributeLanguage(attribute.value().toString());
continue;
@@ -5340,20 +3493,15 @@ void DomLocale::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -5362,7 +3510,7 @@ void DomLocale::read(QXmlStreamReader &reader)
void DomLocale::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("locale") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("locale") : tagName.toLower());
if (hasAttributeLanguage())
writer.writeAttribute(QStringLiteral("language"), attributeLanguage());
@@ -5370,49 +3518,18 @@ void DomLocale::write(QXmlStreamWriter &writer, const QString &tagName) const
if (hasAttributeCountry())
writer.writeAttribute(QStringLiteral("country"), attributeCountry());
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
writer.writeEndElement();
}
-void DomSizePolicy::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_hSizeType = false;
- m_has_attr_vSizeType = false;
- }
-
- m_children = 0;
- m_hSizeType = 0;
- m_vSizeType = 0;
- m_horStretch = 0;
- m_verStretch = 0;
-}
-
-DomSizePolicy::DomSizePolicy()
-{
- m_children = 0;
- m_has_attr_hSizeType = false;
- m_has_attr_vSizeType = false;
- m_hSizeType = 0;
- m_vSizeType = 0;
- m_horStretch = 0;
- m_verStretch = 0;
-}
-
DomSizePolicy::~DomSizePolicy()
{
}
void DomSizePolicy::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("hsizetype")) {
setAttributeHSizeType(attribute.value().toString());
continue;
@@ -5424,23 +3541,23 @@ void DomSizePolicy::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("hsizetype")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("hsizetype"), Qt::CaseInsensitive)) {
setElementHSizeType(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("vsizetype")) {
+ if (!tag.compare(QLatin1String("vsizetype"), Qt::CaseInsensitive)) {
setElementVSizeType(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("horstretch")) {
+ if (!tag.compare(QLatin1String("horstretch"), Qt::CaseInsensitive)) {
setElementHorStretch(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("verstretch")) {
+ if (!tag.compare(QLatin1String("verstretch"), Qt::CaseInsensitive)) {
setElementVerStretch(reader.readElementText().toInt());
continue;
}
@@ -5448,12 +3565,7 @@ void DomSizePolicy::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -5462,7 +3574,7 @@ void DomSizePolicy::read(QXmlStreamReader &reader)
void DomSizePolicy::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("sizepolicy") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("sizepolicy") : tagName.toLower());
if (hasAttributeHSizeType())
writer.writeAttribute(QStringLiteral("hsizetype"), attributeHSizeType());
@@ -5470,24 +3582,17 @@ void DomSizePolicy::write(QXmlStreamWriter &writer, const QString &tagName) cons
if (hasAttributeVSizeType())
writer.writeAttribute(QStringLiteral("vsizetype"), attributeVSizeType());
- if (m_children & HSizeType) {
+ if (m_children & HSizeType)
writer.writeTextElement(QStringLiteral("hsizetype"), QString::number(m_hSizeType));
- }
- if (m_children & VSizeType) {
+ if (m_children & VSizeType)
writer.writeTextElement(QStringLiteral("vsizetype"), QString::number(m_vSizeType));
- }
- if (m_children & HorStretch) {
+ if (m_children & HorStretch)
writer.writeTextElement(QStringLiteral("horstretch"), QString::number(m_horStretch));
- }
- if (m_children & VerStretch) {
+ if (m_children & VerStretch)
writer.writeTextElement(QStringLiteral("verstretch"), QString::number(m_verStretch));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -5536,41 +3641,21 @@ void DomSizePolicy::clearElementVerStretch()
m_children &= ~VerStretch;
}
-void DomSize::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_width = 0;
- m_height = 0;
-}
-
-DomSize::DomSize()
-{
- m_children = 0;
- m_width = 0;
- m_height = 0;
-}
-
DomSize::~DomSize()
{
}
void DomSize::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("width")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("width"), Qt::CaseInsensitive)) {
setElementWidth(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("height")) {
+ if (!tag.compare(QLatin1String("height"), Qt::CaseInsensitive)) {
setElementHeight(reader.readElementText().toInt());
continue;
}
@@ -5578,12 +3663,7 @@ void DomSize::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -5592,18 +3672,13 @@ void DomSize::read(QXmlStreamReader &reader)
void DomSize::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("size") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("size") : tagName.toLower());
- if (m_children & Width) {
+ if (m_children & Width)
writer.writeTextElement(QStringLiteral("width"), QString::number(m_width));
- }
- if (m_children & Height) {
+ if (m_children & Height)
writer.writeTextElement(QStringLiteral("height"), QString::number(m_height));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -5630,47 +3705,25 @@ void DomSize::clearElementHeight()
m_children &= ~Height;
}
-void DomDate::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_year = 0;
- m_month = 0;
- m_day = 0;
-}
-
-DomDate::DomDate()
-{
- m_children = 0;
- m_year = 0;
- m_month = 0;
- m_day = 0;
-}
-
DomDate::~DomDate()
{
}
void DomDate::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("year")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("year"), Qt::CaseInsensitive)) {
setElementYear(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("month")) {
+ if (!tag.compare(QLatin1String("month"), Qt::CaseInsensitive)) {
setElementMonth(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("day")) {
+ if (!tag.compare(QLatin1String("day"), Qt::CaseInsensitive)) {
setElementDay(reader.readElementText().toInt());
continue;
}
@@ -5678,12 +3731,7 @@ void DomDate::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -5692,22 +3740,16 @@ void DomDate::read(QXmlStreamReader &reader)
void DomDate::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("date") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("date") : tagName.toLower());
- if (m_children & Year) {
+ if (m_children & Year)
writer.writeTextElement(QStringLiteral("year"), QString::number(m_year));
- }
- if (m_children & Month) {
+ if (m_children & Month)
writer.writeTextElement(QStringLiteral("month"), QString::number(m_month));
- }
- if (m_children & Day) {
+ if (m_children & Day)
writer.writeTextElement(QStringLiteral("day"), QString::number(m_day));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -5745,47 +3787,25 @@ void DomDate::clearElementDay()
m_children &= ~Day;
}
-void DomTime::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_hour = 0;
- m_minute = 0;
- m_second = 0;
-}
-
-DomTime::DomTime()
-{
- m_children = 0;
- m_hour = 0;
- m_minute = 0;
- m_second = 0;
-}
-
DomTime::~DomTime()
{
}
void DomTime::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("hour")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("hour"), Qt::CaseInsensitive)) {
setElementHour(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("minute")) {
+ if (!tag.compare(QLatin1String("minute"), Qt::CaseInsensitive)) {
setElementMinute(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("second")) {
+ if (!tag.compare(QLatin1String("second"), Qt::CaseInsensitive)) {
setElementSecond(reader.readElementText().toInt());
continue;
}
@@ -5793,12 +3813,7 @@ void DomTime::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -5807,22 +3822,16 @@ void DomTime::read(QXmlStreamReader &reader)
void DomTime::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("time") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("time") : tagName.toLower());
- if (m_children & Hour) {
+ if (m_children & Hour)
writer.writeTextElement(QStringLiteral("hour"), QString::number(m_hour));
- }
- if (m_children & Minute) {
+ if (m_children & Minute)
writer.writeTextElement(QStringLiteral("minute"), QString::number(m_minute));
- }
- if (m_children & Second) {
+ if (m_children & Second)
writer.writeTextElement(QStringLiteral("second"), QString::number(m_second));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -5860,65 +3869,37 @@ void DomTime::clearElementSecond()
m_children &= ~Second;
}
-void DomDateTime::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_hour = 0;
- m_minute = 0;
- m_second = 0;
- m_year = 0;
- m_month = 0;
- m_day = 0;
-}
-
-DomDateTime::DomDateTime()
-{
- m_children = 0;
- m_hour = 0;
- m_minute = 0;
- m_second = 0;
- m_year = 0;
- m_month = 0;
- m_day = 0;
-}
-
DomDateTime::~DomDateTime()
{
}
void DomDateTime::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("hour")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("hour"), Qt::CaseInsensitive)) {
setElementHour(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("minute")) {
+ if (!tag.compare(QLatin1String("minute"), Qt::CaseInsensitive)) {
setElementMinute(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("second")) {
+ if (!tag.compare(QLatin1String("second"), Qt::CaseInsensitive)) {
setElementSecond(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("year")) {
+ if (!tag.compare(QLatin1String("year"), Qt::CaseInsensitive)) {
setElementYear(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("month")) {
+ if (!tag.compare(QLatin1String("month"), Qt::CaseInsensitive)) {
setElementMonth(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("day")) {
+ if (!tag.compare(QLatin1String("day"), Qt::CaseInsensitive)) {
setElementDay(reader.readElementText().toInt());
continue;
}
@@ -5926,12 +3907,7 @@ void DomDateTime::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -5940,34 +3916,25 @@ void DomDateTime::read(QXmlStreamReader &reader)
void DomDateTime::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("datetime") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("datetime") : tagName.toLower());
- if (m_children & Hour) {
+ if (m_children & Hour)
writer.writeTextElement(QStringLiteral("hour"), QString::number(m_hour));
- }
- if (m_children & Minute) {
+ if (m_children & Minute)
writer.writeTextElement(QStringLiteral("minute"), QString::number(m_minute));
- }
- if (m_children & Second) {
+ if (m_children & Second)
writer.writeTextElement(QStringLiteral("second"), QString::number(m_second));
- }
- if (m_children & Year) {
+ if (m_children & Year)
writer.writeTextElement(QStringLiteral("year"), QString::number(m_year));
- }
- if (m_children & Month) {
+ if (m_children & Month)
writer.writeTextElement(QStringLiteral("month"), QString::number(m_month));
- }
- if (m_children & Day) {
+ if (m_children & Day)
writer.writeTextElement(QStringLiteral("day"), QString::number(m_day));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -6038,28 +4005,6 @@ void DomDateTime::clearElementDay()
m_children &= ~Day;
}
-void DomStringList::clear(bool clear_all)
-{
- m_string.clear();
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_notr = false;
- m_has_attr_comment = false;
- m_has_attr_extraComment = false;
- }
-
- m_children = 0;
-}
-
-DomStringList::DomStringList()
-{
- m_children = 0;
- m_has_attr_notr = false;
- m_has_attr_comment = false;
- m_has_attr_extraComment = false;
-}
-
DomStringList::~DomStringList()
{
m_string.clear();
@@ -6067,10 +4012,9 @@ DomStringList::~DomStringList()
void DomStringList::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("notr")) {
setAttributeNotr(attribute.value().toString());
continue;
@@ -6086,11 +4030,11 @@ void DomStringList::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("string")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("string"), Qt::CaseInsensitive)) {
m_string.append(reader.readElementText());
continue;
}
@@ -6098,12 +4042,7 @@ void DomStringList::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -6112,7 +4051,7 @@ void DomStringList::read(QXmlStreamReader &reader)
void DomStringList::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("stringlist") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("stringlist") : tagName.toLower());
if (hasAttributeNotr())
writer.writeAttribute(QStringLiteral("notr"), attributeNotr());
@@ -6123,52 +4062,27 @@ void DomStringList::write(QXmlStreamWriter &writer, const QString &tagName) cons
if (hasAttributeExtraComment())
writer.writeAttribute(QStringLiteral("extracomment"), attributeExtraComment());
- for (int i = 0; i < m_string.size(); ++i) {
- QString v = m_string[i];
+ for (const QString &v : m_string)
writer.writeTextElement(QStringLiteral("string"), v);
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomStringList::setElementString(const QStringList& a)
+void DomStringList::setElementString(const QStringList &a)
{
m_children |= String;
m_string = a;
}
-void DomResourcePixmap::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_resource = false;
- m_has_attr_alias = false;
- }
-
- m_children = 0;
-}
-
-DomResourcePixmap::DomResourcePixmap()
-{
- m_children = 0;
- m_has_attr_resource = false;
- m_has_attr_alias = false;
- m_text.clear();
-}
-
DomResourcePixmap::~DomResourcePixmap()
{
}
void DomResourcePixmap::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("resource")) {
setAttributeResource(attribute.value().toString());
continue;
@@ -6180,16 +4094,15 @@ void DomResourcePixmap::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
+ return;
case QXmlStreamReader::Characters :
if (!reader.isWhitespace())
m_text.append(reader.text().toString());
@@ -6202,7 +4115,7 @@ void DomResourcePixmap::read(QXmlStreamReader &reader)
void DomResourcePixmap::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resourcepixmap") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("resourcepixmap") : tagName.toLower());
if (hasAttributeResource())
writer.writeAttribute(QStringLiteral("resource"), attributeResource());
@@ -6216,50 +4129,6 @@ void DomResourcePixmap::write(QXmlStreamWriter &writer, const QString &tagName)
writer.writeEndElement();
}
-void DomResourceIcon::clear(bool clear_all)
-{
- delete m_normalOff;
- delete m_normalOn;
- delete m_disabledOff;
- delete m_disabledOn;
- delete m_activeOff;
- delete m_activeOn;
- delete m_selectedOff;
- delete m_selectedOn;
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_theme = false;
- m_has_attr_resource = false;
- }
-
- m_children = 0;
- m_normalOff = 0;
- m_normalOn = 0;
- m_disabledOff = 0;
- m_disabledOn = 0;
- m_activeOff = 0;
- m_activeOn = 0;
- m_selectedOff = 0;
- m_selectedOn = 0;
-}
-
-DomResourceIcon::DomResourceIcon()
-{
- m_children = 0;
- m_has_attr_theme = false;
- m_has_attr_resource = false;
- m_text.clear();
- m_normalOff = 0;
- m_normalOn = 0;
- m_disabledOff = 0;
- m_disabledOn = 0;
- m_activeOff = 0;
- m_activeOn = 0;
- m_selectedOff = 0;
- m_selectedOn = 0;
-}
-
DomResourceIcon::~DomResourceIcon()
{
delete m_normalOff;
@@ -6274,10 +4143,9 @@ DomResourceIcon::~DomResourceIcon()
void DomResourceIcon::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("theme")) {
setAttributeTheme(attribute.value().toString());
continue;
@@ -6289,53 +4157,53 @@ void DomResourceIcon::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("normaloff")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("normaloff"), Qt::CaseInsensitive)) {
DomResourcePixmap *v = new DomResourcePixmap();
v->read(reader);
setElementNormalOff(v);
continue;
}
- if (tag == QLatin1String("normalon")) {
+ if (!tag.compare(QLatin1String("normalon"), Qt::CaseInsensitive)) {
DomResourcePixmap *v = new DomResourcePixmap();
v->read(reader);
setElementNormalOn(v);
continue;
}
- if (tag == QLatin1String("disabledoff")) {
+ if (!tag.compare(QLatin1String("disabledoff"), Qt::CaseInsensitive)) {
DomResourcePixmap *v = new DomResourcePixmap();
v->read(reader);
setElementDisabledOff(v);
continue;
}
- if (tag == QLatin1String("disabledon")) {
+ if (!tag.compare(QLatin1String("disabledon"), Qt::CaseInsensitive)) {
DomResourcePixmap *v = new DomResourcePixmap();
v->read(reader);
setElementDisabledOn(v);
continue;
}
- if (tag == QLatin1String("activeoff")) {
+ if (!tag.compare(QLatin1String("activeoff"), Qt::CaseInsensitive)) {
DomResourcePixmap *v = new DomResourcePixmap();
v->read(reader);
setElementActiveOff(v);
continue;
}
- if (tag == QLatin1String("activeon")) {
+ if (!tag.compare(QLatin1String("activeon"), Qt::CaseInsensitive)) {
DomResourcePixmap *v = new DomResourcePixmap();
v->read(reader);
setElementActiveOn(v);
continue;
}
- if (tag == QLatin1String("selectedoff")) {
+ if (!tag.compare(QLatin1String("selectedoff"), Qt::CaseInsensitive)) {
DomResourcePixmap *v = new DomResourcePixmap();
v->read(reader);
setElementSelectedOff(v);
continue;
}
- if (tag == QLatin1String("selectedon")) {
+ if (!tag.compare(QLatin1String("selectedon"), Qt::CaseInsensitive)) {
DomResourcePixmap *v = new DomResourcePixmap();
v->read(reader);
setElementSelectedOn(v);
@@ -6345,8 +4213,7 @@ void DomResourceIcon::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
+ return;
case QXmlStreamReader::Characters :
if (!reader.isWhitespace())
m_text.append(reader.text().toString());
@@ -6359,7 +4226,7 @@ void DomResourceIcon::read(QXmlStreamReader &reader)
void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("resourceicon") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("resourceicon") : tagName.toLower());
if (hasAttributeTheme())
writer.writeAttribute(QStringLiteral("theme"), attributeTheme());
@@ -6367,37 +4234,29 @@ void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) co
if (hasAttributeResource())
writer.writeAttribute(QStringLiteral("resource"), attributeResource());
- if (m_children & NormalOff) {
+ if (m_children & NormalOff)
m_normalOff->write(writer, QStringLiteral("normaloff"));
- }
- if (m_children & NormalOn) {
+ if (m_children & NormalOn)
m_normalOn->write(writer, QStringLiteral("normalon"));
- }
- if (m_children & DisabledOff) {
+ if (m_children & DisabledOff)
m_disabledOff->write(writer, QStringLiteral("disabledoff"));
- }
- if (m_children & DisabledOn) {
+ if (m_children & DisabledOn)
m_disabledOn->write(writer, QStringLiteral("disabledon"));
- }
- if (m_children & ActiveOff) {
+ if (m_children & ActiveOff)
m_activeOff->write(writer, QStringLiteral("activeoff"));
- }
- if (m_children & ActiveOn) {
+ if (m_children & ActiveOn)
m_activeOn->write(writer, QStringLiteral("activeon"));
- }
- if (m_children & SelectedOff) {
+ if (m_children & SelectedOff)
m_selectedOff->write(writer, QStringLiteral("selectedoff"));
- }
- if (m_children & SelectedOn) {
+ if (m_children & SelectedOn)
m_selectedOn->write(writer, QStringLiteral("selectedon"));
- }
if (!m_text.isEmpty())
writer.writeCharacters(m_text);
@@ -6405,120 +4264,120 @@ void DomResourceIcon::write(QXmlStreamWriter &writer, const QString &tagName) co
writer.writeEndElement();
}
-DomResourcePixmap* DomResourceIcon::takeElementNormalOff()
+DomResourcePixmap *DomResourceIcon::takeElementNormalOff()
{
- DomResourcePixmap* a = m_normalOff;
+ DomResourcePixmap *a = m_normalOff;
m_normalOff = 0;
m_children ^= NormalOff;
return a;
}
-void DomResourceIcon::setElementNormalOff(DomResourcePixmap* a)
+void DomResourceIcon::setElementNormalOff(DomResourcePixmap *a)
{
delete m_normalOff;
m_children |= NormalOff;
m_normalOff = a;
}
-DomResourcePixmap* DomResourceIcon::takeElementNormalOn()
+DomResourcePixmap *DomResourceIcon::takeElementNormalOn()
{
- DomResourcePixmap* a = m_normalOn;
+ DomResourcePixmap *a = m_normalOn;
m_normalOn = 0;
m_children ^= NormalOn;
return a;
}
-void DomResourceIcon::setElementNormalOn(DomResourcePixmap* a)
+void DomResourceIcon::setElementNormalOn(DomResourcePixmap *a)
{
delete m_normalOn;
m_children |= NormalOn;
m_normalOn = a;
}
-DomResourcePixmap* DomResourceIcon::takeElementDisabledOff()
+DomResourcePixmap *DomResourceIcon::takeElementDisabledOff()
{
- DomResourcePixmap* a = m_disabledOff;
+ DomResourcePixmap *a = m_disabledOff;
m_disabledOff = 0;
m_children ^= DisabledOff;
return a;
}
-void DomResourceIcon::setElementDisabledOff(DomResourcePixmap* a)
+void DomResourceIcon::setElementDisabledOff(DomResourcePixmap *a)
{
delete m_disabledOff;
m_children |= DisabledOff;
m_disabledOff = a;
}
-DomResourcePixmap* DomResourceIcon::takeElementDisabledOn()
+DomResourcePixmap *DomResourceIcon::takeElementDisabledOn()
{
- DomResourcePixmap* a = m_disabledOn;
+ DomResourcePixmap *a = m_disabledOn;
m_disabledOn = 0;
m_children ^= DisabledOn;
return a;
}
-void DomResourceIcon::setElementDisabledOn(DomResourcePixmap* a)
+void DomResourceIcon::setElementDisabledOn(DomResourcePixmap *a)
{
delete m_disabledOn;
m_children |= DisabledOn;
m_disabledOn = a;
}
-DomResourcePixmap* DomResourceIcon::takeElementActiveOff()
+DomResourcePixmap *DomResourceIcon::takeElementActiveOff()
{
- DomResourcePixmap* a = m_activeOff;
+ DomResourcePixmap *a = m_activeOff;
m_activeOff = 0;
m_children ^= ActiveOff;
return a;
}
-void DomResourceIcon::setElementActiveOff(DomResourcePixmap* a)
+void DomResourceIcon::setElementActiveOff(DomResourcePixmap *a)
{
delete m_activeOff;
m_children |= ActiveOff;
m_activeOff = a;
}
-DomResourcePixmap* DomResourceIcon::takeElementActiveOn()
+DomResourcePixmap *DomResourceIcon::takeElementActiveOn()
{
- DomResourcePixmap* a = m_activeOn;
+ DomResourcePixmap *a = m_activeOn;
m_activeOn = 0;
m_children ^= ActiveOn;
return a;
}
-void DomResourceIcon::setElementActiveOn(DomResourcePixmap* a)
+void DomResourceIcon::setElementActiveOn(DomResourcePixmap *a)
{
delete m_activeOn;
m_children |= ActiveOn;
m_activeOn = a;
}
-DomResourcePixmap* DomResourceIcon::takeElementSelectedOff()
+DomResourcePixmap *DomResourceIcon::takeElementSelectedOff()
{
- DomResourcePixmap* a = m_selectedOff;
+ DomResourcePixmap *a = m_selectedOff;
m_selectedOff = 0;
m_children ^= SelectedOff;
return a;
}
-void DomResourceIcon::setElementSelectedOff(DomResourcePixmap* a)
+void DomResourceIcon::setElementSelectedOff(DomResourcePixmap *a)
{
delete m_selectedOff;
m_children |= SelectedOff;
m_selectedOff = a;
}
-DomResourcePixmap* DomResourceIcon::takeElementSelectedOn()
+DomResourcePixmap *DomResourceIcon::takeElementSelectedOn()
{
- DomResourcePixmap* a = m_selectedOn;
+ DomResourcePixmap *a = m_selectedOn;
m_selectedOn = 0;
m_children ^= SelectedOn;
return a;
}
-void DomResourceIcon::setElementSelectedOn(DomResourcePixmap* a)
+void DomResourceIcon::setElementSelectedOn(DomResourcePixmap *a)
{
delete m_selectedOn;
m_children |= SelectedOn;
@@ -6581,38 +4440,15 @@ void DomResourceIcon::clearElementSelectedOn()
m_children &= ~SelectedOn;
}
-void DomString::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_notr = false;
- m_has_attr_comment = false;
- m_has_attr_extraComment = false;
- }
-
- m_children = 0;
-}
-
-DomString::DomString()
-{
- m_children = 0;
- m_has_attr_notr = false;
- m_has_attr_comment = false;
- m_has_attr_extraComment = false;
- m_text.clear();
-}
-
DomString::~DomString()
{
}
void DomString::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("notr")) {
setAttributeNotr(attribute.value().toString());
continue;
@@ -6628,16 +4464,15 @@ void DomString::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
+ return;
case QXmlStreamReader::Characters :
if (!reader.isWhitespace())
m_text.append(reader.text().toString());
@@ -6650,7 +4485,7 @@ void DomString::read(QXmlStreamReader &reader)
void DomString::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("string") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("string") : tagName.toLower());
if (hasAttributeNotr())
writer.writeAttribute(QStringLiteral("notr"), attributeNotr());
@@ -6667,41 +4502,21 @@ void DomString::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeEndElement();
}
-void DomPointF::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_x = 0;
- m_y = 0;
-}
-
-DomPointF::DomPointF()
-{
- m_children = 0;
- m_x = 0;
- m_y = 0;
-}
-
DomPointF::~DomPointF()
{
}
void DomPointF::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("x")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("x"), Qt::CaseInsensitive)) {
setElementX(reader.readElementText().toDouble());
continue;
}
- if (tag == QLatin1String("y")) {
+ if (!tag.compare(QLatin1String("y"), Qt::CaseInsensitive)) {
setElementY(reader.readElementText().toDouble());
continue;
}
@@ -6709,12 +4524,7 @@ void DomPointF::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -6723,18 +4533,13 @@ void DomPointF::read(QXmlStreamReader &reader)
void DomPointF::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("pointf") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("pointf") : tagName.toLower());
- if (m_children & X) {
+ if (m_children & X)
writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x, 'f', 15));
- }
- if (m_children & Y) {
+ if (m_children & Y)
writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y, 'f', 15));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -6761,53 +4566,29 @@ void DomPointF::clearElementY()
m_children &= ~Y;
}
-void DomRectF::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_x = 0;
- m_y = 0;
- m_width = 0;
- m_height = 0;
-}
-
-DomRectF::DomRectF()
-{
- m_children = 0;
- m_x = 0;
- m_y = 0;
- m_width = 0;
- m_height = 0;
-}
-
DomRectF::~DomRectF()
{
}
void DomRectF::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("x")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("x"), Qt::CaseInsensitive)) {
setElementX(reader.readElementText().toDouble());
continue;
}
- if (tag == QLatin1String("y")) {
+ if (!tag.compare(QLatin1String("y"), Qt::CaseInsensitive)) {
setElementY(reader.readElementText().toDouble());
continue;
}
- if (tag == QLatin1String("width")) {
+ if (!tag.compare(QLatin1String("width"), Qt::CaseInsensitive)) {
setElementWidth(reader.readElementText().toDouble());
continue;
}
- if (tag == QLatin1String("height")) {
+ if (!tag.compare(QLatin1String("height"), Qt::CaseInsensitive)) {
setElementHeight(reader.readElementText().toDouble());
continue;
}
@@ -6815,12 +4596,7 @@ void DomRectF::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -6829,26 +4605,19 @@ void DomRectF::read(QXmlStreamReader &reader)
void DomRectF::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("rectf") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("rectf") : tagName.toLower());
- if (m_children & X) {
+ if (m_children & X)
writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x, 'f', 15));
- }
- if (m_children & Y) {
+ if (m_children & Y)
writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y, 'f', 15));
- }
- if (m_children & Width) {
+ if (m_children & Width)
writer.writeTextElement(QStringLiteral("width"), QString::number(m_width, 'f', 15));
- }
- if (m_children & Height) {
+ if (m_children & Height)
writer.writeTextElement(QStringLiteral("height"), QString::number(m_height, 'f', 15));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -6897,41 +4666,21 @@ void DomRectF::clearElementHeight()
m_children &= ~Height;
}
-void DomSizeF::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_width = 0;
- m_height = 0;
-}
-
-DomSizeF::DomSizeF()
-{
- m_children = 0;
- m_width = 0;
- m_height = 0;
-}
-
DomSizeF::~DomSizeF()
{
}
void DomSizeF::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("width")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("width"), Qt::CaseInsensitive)) {
setElementWidth(reader.readElementText().toDouble());
continue;
}
- if (tag == QLatin1String("height")) {
+ if (!tag.compare(QLatin1String("height"), Qt::CaseInsensitive)) {
setElementHeight(reader.readElementText().toDouble());
continue;
}
@@ -6939,12 +4688,7 @@ void DomSizeF::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -6953,18 +4697,13 @@ void DomSizeF::read(QXmlStreamReader &reader)
void DomSizeF::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("sizef") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("sizef") : tagName.toLower());
- if (m_children & Width) {
+ if (m_children & Width)
writer.writeTextElement(QStringLiteral("width"), QString::number(m_width, 'f', 15));
- }
- if (m_children & Height) {
+ if (m_children & Height)
writer.writeTextElement(QStringLiteral("height"), QString::number(m_height, 'f', 15));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -6991,35 +4730,17 @@ void DomSizeF::clearElementHeight()
m_children &= ~Height;
}
-void DomChar::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_unicode = 0;
-}
-
-DomChar::DomChar()
-{
- m_children = 0;
- m_unicode = 0;
-}
-
DomChar::~DomChar()
{
}
void DomChar::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("unicode")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("unicode"), Qt::CaseInsensitive)) {
setElementUnicode(reader.readElementText().toInt());
continue;
}
@@ -7027,12 +4748,7 @@ void DomChar::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -7041,14 +4757,10 @@ void DomChar::read(QXmlStreamReader &reader)
void DomChar::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("char") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("char") : tagName.toLower());
- if (m_children & Unicode) {
+ if (m_children & Unicode)
writer.writeTextElement(QStringLiteral("unicode"), QString::number(m_unicode));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -7064,24 +4776,6 @@ void DomChar::clearElementUnicode()
m_children &= ~Unicode;
}
-void DomUrl::clear(bool clear_all)
-{
- delete m_string;
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_string = 0;
-}
-
-DomUrl::DomUrl()
-{
- m_children = 0;
- m_string = 0;
-}
-
DomUrl::~DomUrl()
{
delete m_string;
@@ -7089,12 +4783,11 @@ DomUrl::~DomUrl()
void DomUrl::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("string")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("string"), Qt::CaseInsensitive)) {
DomString *v = new DomString();
v->read(reader);
setElementString(v);
@@ -7104,12 +4797,7 @@ void DomUrl::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -7118,27 +4806,23 @@ void DomUrl::read(QXmlStreamReader &reader)
void DomUrl::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("url") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("url") : tagName.toLower());
- if (m_children & String) {
+ if (m_children & String)
m_string->write(writer, QStringLiteral("string"));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-DomString* DomUrl::takeElementString()
+DomString *DomUrl::takeElementString()
{
- DomString* a = m_string;
+ DomString *a = m_string;
m_string = 0;
m_children ^= String;
return a;
}
-void DomUrl::setElementString(DomString* a)
+void DomUrl::setElementString(DomString *a)
{
delete m_string;
m_children |= String;
@@ -7152,7 +4836,7 @@ void DomUrl::clearElementString()
m_children &= ~String;
}
-void DomProperty::clear(bool clear_all)
+DomProperty::~DomProperty()
{
delete m_color;
delete m_font;
@@ -7175,84 +4859,9 @@ void DomProperty::clear(bool clear_all)
delete m_char;
delete m_url;
delete m_brush;
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_name = false;
- m_has_attr_stdset = false;
- m_attr_stdset = 0;
- }
-
- m_kind = Unknown;
-
- m_color = 0;
- m_cursor = 0;
- m_font = 0;
- m_iconSet = 0;
- m_pixmap = 0;
- m_palette = 0;
- m_point = 0;
- m_rect = 0;
- m_locale = 0;
- m_sizePolicy = 0;
- m_size = 0;
- m_string = 0;
- m_stringList = 0;
- m_number = 0;
- m_float = 0.0;
- m_double = 0;
- m_date = 0;
- m_time = 0;
- m_dateTime = 0;
- m_pointF = 0;
- m_rectF = 0;
- m_sizeF = 0;
- m_longLong = 0;
- m_char = 0;
- m_url = 0;
- m_UInt = 0;
- m_uLongLong = 0;
- m_brush = 0;
}
-DomProperty::DomProperty()
-{
- m_kind = Unknown;
-
- m_has_attr_name = false;
- m_has_attr_stdset = false;
- m_attr_stdset = 0;
- m_color = 0;
- m_cursor = 0;
- m_font = 0;
- m_iconSet = 0;
- m_pixmap = 0;
- m_palette = 0;
- m_point = 0;
- m_rect = 0;
- m_locale = 0;
- m_sizePolicy = 0;
- m_size = 0;
- m_string = 0;
- m_stringList = 0;
- m_number = 0;
- m_float = 0.0;
- m_double = 0;
- m_date = 0;
- m_time = 0;
- m_dateTime = 0;
- m_pointF = 0;
- m_rectF = 0;
- m_sizeF = 0;
- m_longLong = 0;
- m_char = 0;
- m_url = 0;
- m_UInt = 0;
- m_uLongLong = 0;
- m_brush = 0;
-}
-
-DomProperty::~DomProperty()
+void DomProperty::clear()
{
delete m_color;
delete m_font;
@@ -7275,14 +4884,44 @@ DomProperty::~DomProperty()
delete m_char;
delete m_url;
delete m_brush;
+
+ m_kind = Unknown;
+
+ m_color = nullptr;
+ m_cursor = 0;
+ m_font = nullptr;
+ m_iconSet = nullptr;
+ m_pixmap = nullptr;
+ m_palette = nullptr;
+ m_point = nullptr;
+ m_rect = nullptr;
+ m_locale = nullptr;
+ m_sizePolicy = nullptr;
+ m_size = nullptr;
+ m_string = nullptr;
+ m_stringList = nullptr;
+ m_number = 0;
+ m_float = 0.0;
+ m_double = 0.0;
+ m_date = nullptr;
+ m_time = nullptr;
+ m_dateTime = nullptr;
+ m_pointF = nullptr;
+ m_rectF = nullptr;
+ m_sizeF = nullptr;
+ m_longLong = 0;
+ m_char = nullptr;
+ m_url = nullptr;
+ m_UInt = 0;
+ m_uLongLong = 0;
+ m_brush = nullptr;
}
void DomProperty::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("name")) {
setAttributeName(attribute.value().toString());
continue;
@@ -7294,179 +4933,179 @@ void DomProperty::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("bool")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("bool"), Qt::CaseInsensitive)) {
setElementBool(reader.readElementText());
continue;
}
- if (tag == QLatin1String("color")) {
+ if (!tag.compare(QLatin1String("color"), Qt::CaseInsensitive)) {
DomColor *v = new DomColor();
v->read(reader);
setElementColor(v);
continue;
}
- if (tag == QLatin1String("cstring")) {
+ if (!tag.compare(QLatin1String("cstring"), Qt::CaseInsensitive)) {
setElementCstring(reader.readElementText());
continue;
}
- if (tag == QLatin1String("cursor")) {
+ if (!tag.compare(QLatin1String("cursor"), Qt::CaseInsensitive)) {
setElementCursor(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("cursorshape")) {
+ if (!tag.compare(QLatin1String("cursorshape"), Qt::CaseInsensitive)) {
setElementCursorShape(reader.readElementText());
continue;
}
- if (tag == QLatin1String("enum")) {
+ if (!tag.compare(QLatin1String("enum"), Qt::CaseInsensitive)) {
setElementEnum(reader.readElementText());
continue;
}
- if (tag == QLatin1String("font")) {
+ if (!tag.compare(QLatin1String("font"), Qt::CaseInsensitive)) {
DomFont *v = new DomFont();
v->read(reader);
setElementFont(v);
continue;
}
- if (tag == QLatin1String("iconset")) {
+ if (!tag.compare(QLatin1String("iconset"), Qt::CaseInsensitive)) {
DomResourceIcon *v = new DomResourceIcon();
v->read(reader);
setElementIconSet(v);
continue;
}
- if (tag == QLatin1String("pixmap")) {
+ if (!tag.compare(QLatin1String("pixmap"), Qt::CaseInsensitive)) {
DomResourcePixmap *v = new DomResourcePixmap();
v->read(reader);
setElementPixmap(v);
continue;
}
- if (tag == QLatin1String("palette")) {
+ if (!tag.compare(QLatin1String("palette"), Qt::CaseInsensitive)) {
DomPalette *v = new DomPalette();
v->read(reader);
setElementPalette(v);
continue;
}
- if (tag == QLatin1String("point")) {
+ if (!tag.compare(QLatin1String("point"), Qt::CaseInsensitive)) {
DomPoint *v = new DomPoint();
v->read(reader);
setElementPoint(v);
continue;
}
- if (tag == QLatin1String("rect")) {
+ if (!tag.compare(QLatin1String("rect"), Qt::CaseInsensitive)) {
DomRect *v = new DomRect();
v->read(reader);
setElementRect(v);
continue;
}
- if (tag == QLatin1String("set")) {
+ if (!tag.compare(QLatin1String("set"), Qt::CaseInsensitive)) {
setElementSet(reader.readElementText());
continue;
}
- if (tag == QLatin1String("locale")) {
+ if (!tag.compare(QLatin1String("locale"), Qt::CaseInsensitive)) {
DomLocale *v = new DomLocale();
v->read(reader);
setElementLocale(v);
continue;
}
- if (tag == QLatin1String("sizepolicy")) {
+ if (!tag.compare(QLatin1String("sizepolicy"), Qt::CaseInsensitive)) {
DomSizePolicy *v = new DomSizePolicy();
v->read(reader);
setElementSizePolicy(v);
continue;
}
- if (tag == QLatin1String("size")) {
+ if (!tag.compare(QLatin1String("size"), Qt::CaseInsensitive)) {
DomSize *v = new DomSize();
v->read(reader);
setElementSize(v);
continue;
}
- if (tag == QLatin1String("string")) {
+ if (!tag.compare(QLatin1String("string"), Qt::CaseInsensitive)) {
DomString *v = new DomString();
v->read(reader);
setElementString(v);
continue;
}
- if (tag == QLatin1String("stringlist")) {
+ if (!tag.compare(QLatin1String("stringlist"), Qt::CaseInsensitive)) {
DomStringList *v = new DomStringList();
v->read(reader);
setElementStringList(v);
continue;
}
- if (tag == QLatin1String("number")) {
+ if (!tag.compare(QLatin1String("number"), Qt::CaseInsensitive)) {
setElementNumber(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("float")) {
+ if (!tag.compare(QLatin1String("float"), Qt::CaseInsensitive)) {
setElementFloat(reader.readElementText().toFloat());
continue;
}
- if (tag == QLatin1String("double")) {
+ if (!tag.compare(QLatin1String("double"), Qt::CaseInsensitive)) {
setElementDouble(reader.readElementText().toDouble());
continue;
}
- if (tag == QLatin1String("date")) {
+ if (!tag.compare(QLatin1String("date"), Qt::CaseInsensitive)) {
DomDate *v = new DomDate();
v->read(reader);
setElementDate(v);
continue;
}
- if (tag == QLatin1String("time")) {
+ if (!tag.compare(QLatin1String("time"), Qt::CaseInsensitive)) {
DomTime *v = new DomTime();
v->read(reader);
setElementTime(v);
continue;
}
- if (tag == QLatin1String("datetime")) {
+ if (!tag.compare(QLatin1String("datetime"), Qt::CaseInsensitive)) {
DomDateTime *v = new DomDateTime();
v->read(reader);
setElementDateTime(v);
continue;
}
- if (tag == QLatin1String("pointf")) {
+ if (!tag.compare(QLatin1String("pointf"), Qt::CaseInsensitive)) {
DomPointF *v = new DomPointF();
v->read(reader);
setElementPointF(v);
continue;
}
- if (tag == QLatin1String("rectf")) {
+ if (!tag.compare(QLatin1String("rectf"), Qt::CaseInsensitive)) {
DomRectF *v = new DomRectF();
v->read(reader);
setElementRectF(v);
continue;
}
- if (tag == QLatin1String("sizef")) {
+ if (!tag.compare(QLatin1String("sizef"), Qt::CaseInsensitive)) {
DomSizeF *v = new DomSizeF();
v->read(reader);
setElementSizeF(v);
continue;
}
- if (tag == QLatin1String("longlong")) {
+ if (!tag.compare(QLatin1String("longlong"), Qt::CaseInsensitive)) {
setElementLongLong(reader.readElementText().toLongLong());
continue;
}
- if (tag == QLatin1String("char")) {
+ if (!tag.compare(QLatin1String("char"), Qt::CaseInsensitive)) {
DomChar *v = new DomChar();
v->read(reader);
setElementChar(v);
continue;
}
- if (tag == QLatin1String("url")) {
+ if (!tag.compare(QLatin1String("url"), Qt::CaseInsensitive)) {
DomUrl *v = new DomUrl();
v->read(reader);
setElementUrl(v);
continue;
}
- if (tag == QLatin1String("uint")) {
+ if (!tag.compare(QLatin1String("uint"), Qt::CaseInsensitive)) {
setElementUInt(reader.readElementText().toUInt());
continue;
}
- if (tag == QLatin1String("ulonglong")) {
+ if (!tag.compare(QLatin1String("ulonglong"), Qt::CaseInsensitive)) {
setElementULongLong(reader.readElementText().toULongLong());
continue;
}
- if (tag == QLatin1String("brush")) {
+ if (!tag.compare(QLatin1String("brush"), Qt::CaseInsensitive)) {
DomBrush *v = new DomBrush();
v->read(reader);
setElementBrush(v);
@@ -7476,12 +5115,7 @@ void DomProperty::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -7490,7 +5124,7 @@ void DomProperty::read(QXmlStreamReader &reader)
void DomProperty::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("property") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("property") : tagName.toLower());
if (hasAttributeName())
writer.writeAttribute(QStringLiteral("name"), attributeName());
@@ -7499,605 +5133,564 @@ void DomProperty::write(QXmlStreamWriter &writer, const QString &tagName) const
writer.writeAttribute(QStringLiteral("stdset"), QString::number(attributeStdset()));
switch (kind()) {
- case Bool: {
- writer.writeTextElement(QStringLiteral("bool"), elementBool());
- break;
- }
- case Color: {
- DomColor* v = elementColor();
- if (v != 0) {
- v->write(writer, QStringLiteral("color"));
- }
- break;
- }
- case Cstring: {
- writer.writeTextElement(QStringLiteral("cstring"), elementCstring());
- break;
- }
- case Cursor: {
- writer.writeTextElement(QStringLiteral("cursor"), QString::number(elementCursor()));
- break;
- }
- case CursorShape: {
- writer.writeTextElement(QStringLiteral("cursorShape"), elementCursorShape());
- break;
- }
- case Enum: {
- writer.writeTextElement(QStringLiteral("enum"), elementEnum());
- break;
- }
- case Font: {
- DomFont* v = elementFont();
- if (v != 0) {
- v->write(writer, QStringLiteral("font"));
- }
- break;
- }
- case IconSet: {
- DomResourceIcon* v = elementIconSet();
- if (v != 0) {
- v->write(writer, QStringLiteral("iconset"));
- }
- break;
- }
- case Pixmap: {
- DomResourcePixmap* v = elementPixmap();
- if (v != 0) {
- v->write(writer, QStringLiteral("pixmap"));
- }
- break;
- }
- case Palette: {
- DomPalette* v = elementPalette();
- if (v != 0) {
- v->write(writer, QStringLiteral("palette"));
- }
- break;
- }
- case Point: {
- DomPoint* v = elementPoint();
- if (v != 0) {
- v->write(writer, QStringLiteral("point"));
- }
- break;
- }
- case Rect: {
- DomRect* v = elementRect();
- if (v != 0) {
- v->write(writer, QStringLiteral("rect"));
- }
- break;
- }
- case Set: {
- writer.writeTextElement(QStringLiteral("set"), elementSet());
- break;
- }
- case Locale: {
- DomLocale* v = elementLocale();
- if (v != 0) {
- v->write(writer, QStringLiteral("locale"));
- }
- break;
- }
- case SizePolicy: {
- DomSizePolicy* v = elementSizePolicy();
- if (v != 0) {
- v->write(writer, QStringLiteral("sizepolicy"));
- }
- break;
- }
- case Size: {
- DomSize* v = elementSize();
- if (v != 0) {
- v->write(writer, QStringLiteral("size"));
- }
- break;
- }
- case String: {
- DomString* v = elementString();
- if (v != 0) {
- v->write(writer, QStringLiteral("string"));
- }
- break;
- }
- case StringList: {
- DomStringList* v = elementStringList();
- if (v != 0) {
- v->write(writer, QStringLiteral("stringlist"));
- }
- break;
- }
- case Number: {
- writer.writeTextElement(QStringLiteral("number"), QString::number(elementNumber()));
- break;
- }
- case Float: {
- writer.writeTextElement(QStringLiteral("float"), QString::number(elementFloat(), 'f', 8));
- break;
- }
- case Double: {
- writer.writeTextElement(QStringLiteral("double"), QString::number(elementDouble(), 'f', 15));
- break;
- }
- case Date: {
- DomDate* v = elementDate();
- if (v != 0) {
- v->write(writer, QStringLiteral("date"));
- }
- break;
- }
- case Time: {
- DomTime* v = elementTime();
- if (v != 0) {
- v->write(writer, QStringLiteral("time"));
- }
- break;
- }
- case DateTime: {
- DomDateTime* v = elementDateTime();
- if (v != 0) {
- v->write(writer, QStringLiteral("datetime"));
- }
- break;
- }
- case PointF: {
- DomPointF* v = elementPointF();
- if (v != 0) {
- v->write(writer, QStringLiteral("pointf"));
- }
- break;
- }
- case RectF: {
- DomRectF* v = elementRectF();
- if (v != 0) {
- v->write(writer, QStringLiteral("rectf"));
- }
- break;
- }
- case SizeF: {
- DomSizeF* v = elementSizeF();
- if (v != 0) {
- v->write(writer, QStringLiteral("sizef"));
- }
- break;
- }
- case LongLong: {
- writer.writeTextElement(QStringLiteral("longLong"), QString::number(elementLongLong()));
- break;
- }
- case Char: {
- DomChar* v = elementChar();
- if (v != 0) {
- v->write(writer, QStringLiteral("char"));
- }
- break;
- }
- case Url: {
- DomUrl* v = elementUrl();
- if (v != 0) {
- v->write(writer, QStringLiteral("url"));
- }
- break;
- }
- case UInt: {
- writer.writeTextElement(QStringLiteral("UInt"), QString::number(elementUInt()));
- break;
- }
- case ULongLong: {
- writer.writeTextElement(QStringLiteral("uLongLong"), QString::number(elementULongLong()));
- break;
- }
- case Brush: {
- DomBrush* v = elementBrush();
- if (v != 0) {
- v->write(writer, QStringLiteral("brush"));
- }
- break;
- }
- default:
- break;
+ case Bool: {
+ writer.writeTextElement(QStringLiteral("bool"), elementBool());
+ break;
+ }
+ case Color: {
+ DomColor *v = elementColor();
+ if (v != 0)
+ v->write(writer, QStringLiteral("color"));
+ break;
+ }
+ case Cstring: {
+ writer.writeTextElement(QStringLiteral("cstring"), elementCstring());
+ break;
+ }
+ case Cursor: {
+ writer.writeTextElement(QStringLiteral("cursor"), QString::number(elementCursor()));
+ break;
+ }
+ case CursorShape: {
+ writer.writeTextElement(QStringLiteral("cursorShape"), elementCursorShape());
+ break;
+ }
+ case Enum: {
+ writer.writeTextElement(QStringLiteral("enum"), elementEnum());
+ break;
+ }
+ case Font: {
+ DomFont *v = elementFont();
+ if (v != 0)
+ v->write(writer, QStringLiteral("font"));
+ break;
+ }
+ case IconSet: {
+ DomResourceIcon *v = elementIconSet();
+ if (v != 0)
+ v->write(writer, QStringLiteral("iconset"));
+ break;
+ }
+ case Pixmap: {
+ DomResourcePixmap *v = elementPixmap();
+ if (v != 0)
+ v->write(writer, QStringLiteral("pixmap"));
+ break;
+ }
+ case Palette: {
+ DomPalette *v = elementPalette();
+ if (v != 0)
+ v->write(writer, QStringLiteral("palette"));
+ break;
+ }
+ case Point: {
+ DomPoint *v = elementPoint();
+ if (v != 0)
+ v->write(writer, QStringLiteral("point"));
+ break;
+ }
+ case Rect: {
+ DomRect *v = elementRect();
+ if (v != 0)
+ v->write(writer, QStringLiteral("rect"));
+ break;
+ }
+ case Set: {
+ writer.writeTextElement(QStringLiteral("set"), elementSet());
+ break;
+ }
+ case Locale: {
+ DomLocale *v = elementLocale();
+ if (v != 0)
+ v->write(writer, QStringLiteral("locale"));
+ break;
+ }
+ case SizePolicy: {
+ DomSizePolicy *v = elementSizePolicy();
+ if (v != 0)
+ v->write(writer, QStringLiteral("sizepolicy"));
+ break;
+ }
+ case Size: {
+ DomSize *v = elementSize();
+ if (v != 0)
+ v->write(writer, QStringLiteral("size"));
+ break;
+ }
+ case String: {
+ DomString *v = elementString();
+ if (v != 0)
+ v->write(writer, QStringLiteral("string"));
+ break;
+ }
+ case StringList: {
+ DomStringList *v = elementStringList();
+ if (v != 0)
+ v->write(writer, QStringLiteral("stringlist"));
+ break;
+ }
+ case Number: {
+ writer.writeTextElement(QStringLiteral("number"), QString::number(elementNumber()));
+ break;
+ }
+ case Float: {
+ writer.writeTextElement(QStringLiteral("float"), QString::number(elementFloat(), 'f', 8));
+ break;
+ }
+ case Double: {
+ writer.writeTextElement(QStringLiteral("double"), QString::number(elementDouble(), 'f', 15));
+ break;
+ }
+ case Date: {
+ DomDate *v = elementDate();
+ if (v != 0)
+ v->write(writer, QStringLiteral("date"));
+ break;
+ }
+ case Time: {
+ DomTime *v = elementTime();
+ if (v != 0)
+ v->write(writer, QStringLiteral("time"));
+ break;
+ }
+ case DateTime: {
+ DomDateTime *v = elementDateTime();
+ if (v != 0)
+ v->write(writer, QStringLiteral("datetime"));
+ break;
+ }
+ case PointF: {
+ DomPointF *v = elementPointF();
+ if (v != 0)
+ v->write(writer, QStringLiteral("pointf"));
+ break;
+ }
+ case RectF: {
+ DomRectF *v = elementRectF();
+ if (v != 0)
+ v->write(writer, QStringLiteral("rectf"));
+ break;
+ }
+ case SizeF: {
+ DomSizeF *v = elementSizeF();
+ if (v != 0)
+ v->write(writer, QStringLiteral("sizef"));
+ break;
+ }
+ case LongLong: {
+ writer.writeTextElement(QStringLiteral("longLong"), QString::number(elementLongLong()));
+ break;
+ }
+ case Char: {
+ DomChar *v = elementChar();
+ if (v != 0)
+ v->write(writer, QStringLiteral("char"));
+ break;
+ }
+ case Url: {
+ DomUrl *v = elementUrl();
+ if (v != 0)
+ v->write(writer, QStringLiteral("url"));
+ break;
+ }
+ case UInt: {
+ writer.writeTextElement(QStringLiteral("UInt"), QString::number(elementUInt()));
+ break;
+ }
+ case ULongLong: {
+ writer.writeTextElement(QStringLiteral("uLongLong"), QString::number(elementULongLong()));
+ break;
+ }
+ case Brush: {
+ DomBrush *v = elementBrush();
+ if (v != 0)
+ v->write(writer, QStringLiteral("brush"));
+ break;
+ }
+ default:
+ break;
}
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
writer.writeEndElement();
}
-void DomProperty::setElementBool(const QString& a)
+void DomProperty::setElementBool(const QString &a)
{
- clear(false);
+ clear();
m_kind = Bool;
m_bool = a;
}
-DomColor* DomProperty::takeElementColor()
+DomColor *DomProperty::takeElementColor()
{
- DomColor* a = m_color;
+ DomColor *a = m_color;
m_color = 0;
return a;
}
-void DomProperty::setElementColor(DomColor* a)
+void DomProperty::setElementColor(DomColor *a)
{
- clear(false);
+ clear();
m_kind = Color;
m_color = a;
}
-void DomProperty::setElementCstring(const QString& a)
+void DomProperty::setElementCstring(const QString &a)
{
- clear(false);
+ clear();
m_kind = Cstring;
m_cstring = a;
}
void DomProperty::setElementCursor(int a)
{
- clear(false);
+ clear();
m_kind = Cursor;
m_cursor = a;
}
-void DomProperty::setElementCursorShape(const QString& a)
+void DomProperty::setElementCursorShape(const QString &a)
{
- clear(false);
+ clear();
m_kind = CursorShape;
m_cursorShape = a;
}
-void DomProperty::setElementEnum(const QString& a)
+void DomProperty::setElementEnum(const QString &a)
{
- clear(false);
+ clear();
m_kind = Enum;
m_enum = a;
}
-DomFont* DomProperty::takeElementFont()
+DomFont *DomProperty::takeElementFont()
{
- DomFont* a = m_font;
+ DomFont *a = m_font;
m_font = 0;
return a;
}
-void DomProperty::setElementFont(DomFont* a)
+void DomProperty::setElementFont(DomFont *a)
{
- clear(false);
+ clear();
m_kind = Font;
m_font = a;
}
-DomResourceIcon* DomProperty::takeElementIconSet()
+DomResourceIcon *DomProperty::takeElementIconSet()
{
- DomResourceIcon* a = m_iconSet;
+ DomResourceIcon *a = m_iconSet;
m_iconSet = 0;
return a;
}
-void DomProperty::setElementIconSet(DomResourceIcon* a)
+void DomProperty::setElementIconSet(DomResourceIcon *a)
{
- clear(false);
+ clear();
m_kind = IconSet;
m_iconSet = a;
}
-DomResourcePixmap* DomProperty::takeElementPixmap()
+DomResourcePixmap *DomProperty::takeElementPixmap()
{
- DomResourcePixmap* a = m_pixmap;
+ DomResourcePixmap *a = m_pixmap;
m_pixmap = 0;
return a;
}
-void DomProperty::setElementPixmap(DomResourcePixmap* a)
+void DomProperty::setElementPixmap(DomResourcePixmap *a)
{
- clear(false);
+ clear();
m_kind = Pixmap;
m_pixmap = a;
}
-DomPalette* DomProperty::takeElementPalette()
+DomPalette *DomProperty::takeElementPalette()
{
- DomPalette* a = m_palette;
+ DomPalette *a = m_palette;
m_palette = 0;
return a;
}
-void DomProperty::setElementPalette(DomPalette* a)
+void DomProperty::setElementPalette(DomPalette *a)
{
- clear(false);
+ clear();
m_kind = Palette;
m_palette = a;
}
-DomPoint* DomProperty::takeElementPoint()
+DomPoint *DomProperty::takeElementPoint()
{
- DomPoint* a = m_point;
+ DomPoint *a = m_point;
m_point = 0;
return a;
}
-void DomProperty::setElementPoint(DomPoint* a)
+void DomProperty::setElementPoint(DomPoint *a)
{
- clear(false);
+ clear();
m_kind = Point;
m_point = a;
}
-DomRect* DomProperty::takeElementRect()
+DomRect *DomProperty::takeElementRect()
{
- DomRect* a = m_rect;
+ DomRect *a = m_rect;
m_rect = 0;
return a;
}
-void DomProperty::setElementRect(DomRect* a)
+void DomProperty::setElementRect(DomRect *a)
{
- clear(false);
+ clear();
m_kind = Rect;
m_rect = a;
}
-void DomProperty::setElementSet(const QString& a)
+void DomProperty::setElementSet(const QString &a)
{
- clear(false);
+ clear();
m_kind = Set;
m_set = a;
}
-DomLocale* DomProperty::takeElementLocale()
+DomLocale *DomProperty::takeElementLocale()
{
- DomLocale* a = m_locale;
+ DomLocale *a = m_locale;
m_locale = 0;
return a;
}
-void DomProperty::setElementLocale(DomLocale* a)
+void DomProperty::setElementLocale(DomLocale *a)
{
- clear(false);
+ clear();
m_kind = Locale;
m_locale = a;
}
-DomSizePolicy* DomProperty::takeElementSizePolicy()
+DomSizePolicy *DomProperty::takeElementSizePolicy()
{
- DomSizePolicy* a = m_sizePolicy;
+ DomSizePolicy *a = m_sizePolicy;
m_sizePolicy = 0;
return a;
}
-void DomProperty::setElementSizePolicy(DomSizePolicy* a)
+void DomProperty::setElementSizePolicy(DomSizePolicy *a)
{
- clear(false);
+ clear();
m_kind = SizePolicy;
m_sizePolicy = a;
}
-DomSize* DomProperty::takeElementSize()
+DomSize *DomProperty::takeElementSize()
{
- DomSize* a = m_size;
+ DomSize *a = m_size;
m_size = 0;
return a;
}
-void DomProperty::setElementSize(DomSize* a)
+void DomProperty::setElementSize(DomSize *a)
{
- clear(false);
+ clear();
m_kind = Size;
m_size = a;
}
-DomString* DomProperty::takeElementString()
+DomString *DomProperty::takeElementString()
{
- DomString* a = m_string;
+ DomString *a = m_string;
m_string = 0;
return a;
}
-void DomProperty::setElementString(DomString* a)
+void DomProperty::setElementString(DomString *a)
{
- clear(false);
+ clear();
m_kind = String;
m_string = a;
}
-DomStringList* DomProperty::takeElementStringList()
+DomStringList *DomProperty::takeElementStringList()
{
- DomStringList* a = m_stringList;
+ DomStringList *a = m_stringList;
m_stringList = 0;
return a;
}
-void DomProperty::setElementStringList(DomStringList* a)
+void DomProperty::setElementStringList(DomStringList *a)
{
- clear(false);
+ clear();
m_kind = StringList;
m_stringList = a;
}
void DomProperty::setElementNumber(int a)
{
- clear(false);
+ clear();
m_kind = Number;
m_number = a;
}
void DomProperty::setElementFloat(float a)
{
- clear(false);
+ clear();
m_kind = Float;
m_float = a;
}
void DomProperty::setElementDouble(double a)
{
- clear(false);
+ clear();
m_kind = Double;
m_double = a;
}
-DomDate* DomProperty::takeElementDate()
+DomDate *DomProperty::takeElementDate()
{
- DomDate* a = m_date;
+ DomDate *a = m_date;
m_date = 0;
return a;
}
-void DomProperty::setElementDate(DomDate* a)
+void DomProperty::setElementDate(DomDate *a)
{
- clear(false);
+ clear();
m_kind = Date;
m_date = a;
}
-DomTime* DomProperty::takeElementTime()
+DomTime *DomProperty::takeElementTime()
{
- DomTime* a = m_time;
+ DomTime *a = m_time;
m_time = 0;
return a;
}
-void DomProperty::setElementTime(DomTime* a)
+void DomProperty::setElementTime(DomTime *a)
{
- clear(false);
+ clear();
m_kind = Time;
m_time = a;
}
-DomDateTime* DomProperty::takeElementDateTime()
+DomDateTime *DomProperty::takeElementDateTime()
{
- DomDateTime* a = m_dateTime;
+ DomDateTime *a = m_dateTime;
m_dateTime = 0;
return a;
}
-void DomProperty::setElementDateTime(DomDateTime* a)
+void DomProperty::setElementDateTime(DomDateTime *a)
{
- clear(false);
+ clear();
m_kind = DateTime;
m_dateTime = a;
}
-DomPointF* DomProperty::takeElementPointF()
+DomPointF *DomProperty::takeElementPointF()
{
- DomPointF* a = m_pointF;
+ DomPointF *a = m_pointF;
m_pointF = 0;
return a;
}
-void DomProperty::setElementPointF(DomPointF* a)
+void DomProperty::setElementPointF(DomPointF *a)
{
- clear(false);
+ clear();
m_kind = PointF;
m_pointF = a;
}
-DomRectF* DomProperty::takeElementRectF()
+DomRectF *DomProperty::takeElementRectF()
{
- DomRectF* a = m_rectF;
+ DomRectF *a = m_rectF;
m_rectF = 0;
return a;
}
-void DomProperty::setElementRectF(DomRectF* a)
+void DomProperty::setElementRectF(DomRectF *a)
{
- clear(false);
+ clear();
m_kind = RectF;
m_rectF = a;
}
-DomSizeF* DomProperty::takeElementSizeF()
+DomSizeF *DomProperty::takeElementSizeF()
{
- DomSizeF* a = m_sizeF;
+ DomSizeF *a = m_sizeF;
m_sizeF = 0;
return a;
}
-void DomProperty::setElementSizeF(DomSizeF* a)
+void DomProperty::setElementSizeF(DomSizeF *a)
{
- clear(false);
+ clear();
m_kind = SizeF;
m_sizeF = a;
}
void DomProperty::setElementLongLong(qlonglong a)
{
- clear(false);
+ clear();
m_kind = LongLong;
m_longLong = a;
}
-DomChar* DomProperty::takeElementChar()
+DomChar *DomProperty::takeElementChar()
{
- DomChar* a = m_char;
+ DomChar *a = m_char;
m_char = 0;
return a;
}
-void DomProperty::setElementChar(DomChar* a)
+void DomProperty::setElementChar(DomChar *a)
{
- clear(false);
+ clear();
m_kind = Char;
m_char = a;
}
-DomUrl* DomProperty::takeElementUrl()
+DomUrl *DomProperty::takeElementUrl()
{
- DomUrl* a = m_url;
+ DomUrl *a = m_url;
m_url = 0;
return a;
}
-void DomProperty::setElementUrl(DomUrl* a)
+void DomProperty::setElementUrl(DomUrl *a)
{
- clear(false);
+ clear();
m_kind = Url;
m_url = a;
}
void DomProperty::setElementUInt(uint a)
{
- clear(false);
+ clear();
m_kind = UInt;
m_UInt = a;
}
void DomProperty::setElementULongLong(qulonglong a)
{
- clear(false);
+ clear();
m_kind = ULongLong;
m_uLongLong = a;
}
-DomBrush* DomProperty::takeElementBrush()
+DomBrush *DomProperty::takeElementBrush()
{
- DomBrush* a = m_brush;
+ DomBrush *a = m_brush;
m_brush = 0;
return a;
}
-void DomProperty::setElementBrush(DomBrush* a)
+void DomProperty::setElementBrush(DomBrush *a)
{
- clear(false);
+ clear();
m_kind = Brush;
m_brush = a;
}
-void DomConnections::clear(bool clear_all)
-{
- qDeleteAll(m_connection);
- m_connection.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomConnections::DomConnections()
-{
- m_children = 0;
-}
-
DomConnections::~DomConnections()
{
qDeleteAll(m_connection);
@@ -8106,12 +5699,11 @@ DomConnections::~DomConnections()
void DomConnections::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("connection")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("connection"), Qt::CaseInsensitive)) {
DomConnection *v = new DomConnection();
v->read(reader);
m_connection.append(v);
@@ -8121,12 +5713,7 @@ void DomConnections::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -8135,42 +5722,20 @@ void DomConnections::read(QXmlStreamReader &reader)
void DomConnections::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("connections") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("connections") : tagName.toLower());
- for (int i = 0; i < m_connection.size(); ++i) {
- DomConnection* v = m_connection[i];
+ for (DomConnection *v : m_connection)
v->write(writer, QStringLiteral("connection"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomConnections::setElementConnection(const QList<DomConnection*>& a)
+void DomConnections::setElementConnection(const QVector<DomConnection *> &a)
{
m_children |= Connection;
m_connection = a;
}
-void DomConnection::clear(bool clear_all)
-{
- delete m_hints;
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
- m_hints = 0;
-}
-
-DomConnection::DomConnection()
-{
- m_children = 0;
- m_hints = 0;
-}
-
DomConnection::~DomConnection()
{
delete m_hints;
@@ -8178,28 +5743,27 @@ DomConnection::~DomConnection()
void DomConnection::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("sender")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("sender"), Qt::CaseInsensitive)) {
setElementSender(reader.readElementText());
continue;
}
- if (tag == QLatin1String("signal")) {
+ if (!tag.compare(QLatin1String("signal"), Qt::CaseInsensitive)) {
setElementSignal(reader.readElementText());
continue;
}
- if (tag == QLatin1String("receiver")) {
+ if (!tag.compare(QLatin1String("receiver"), Qt::CaseInsensitive)) {
setElementReceiver(reader.readElementText());
continue;
}
- if (tag == QLatin1String("slot")) {
+ if (!tag.compare(QLatin1String("slot"), Qt::CaseInsensitive)) {
setElementSlot(reader.readElementText());
continue;
}
- if (tag == QLatin1String("hints")) {
+ if (!tag.compare(QLatin1String("hints"), Qt::CaseInsensitive)) {
DomConnectionHints *v = new DomConnectionHints();
v->read(reader);
setElementHints(v);
@@ -8209,12 +5773,7 @@ void DomConnection::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -8223,67 +5782,59 @@ void DomConnection::read(QXmlStreamReader &reader)
void DomConnection::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("connection") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("connection") : tagName.toLower());
- if (m_children & Sender) {
+ if (m_children & Sender)
writer.writeTextElement(QStringLiteral("sender"), m_sender);
- }
- if (m_children & Signal) {
+ if (m_children & Signal)
writer.writeTextElement(QStringLiteral("signal"), m_signal);
- }
- if (m_children & Receiver) {
+ if (m_children & Receiver)
writer.writeTextElement(QStringLiteral("receiver"), m_receiver);
- }
- if (m_children & Slot) {
+ if (m_children & Slot)
writer.writeTextElement(QStringLiteral("slot"), m_slot);
- }
- if (m_children & Hints) {
+ if (m_children & Hints)
m_hints->write(writer, QStringLiteral("hints"));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomConnection::setElementSender(const QString& a)
+void DomConnection::setElementSender(const QString &a)
{
m_children |= Sender;
m_sender = a;
}
-void DomConnection::setElementSignal(const QString& a)
+void DomConnection::setElementSignal(const QString &a)
{
m_children |= Signal;
m_signal = a;
}
-void DomConnection::setElementReceiver(const QString& a)
+void DomConnection::setElementReceiver(const QString &a)
{
m_children |= Receiver;
m_receiver = a;
}
-void DomConnection::setElementSlot(const QString& a)
+void DomConnection::setElementSlot(const QString &a)
{
m_children |= Slot;
m_slot = a;
}
-DomConnectionHints* DomConnection::takeElementHints()
+DomConnectionHints *DomConnection::takeElementHints()
{
- DomConnectionHints* a = m_hints;
+ DomConnectionHints *a = m_hints;
m_hints = 0;
m_children ^= Hints;
return a;
}
-void DomConnection::setElementHints(DomConnectionHints* a)
+void DomConnection::setElementHints(DomConnectionHints *a)
{
delete m_hints;
m_children |= Hints;
@@ -8317,23 +5868,6 @@ void DomConnection::clearElementHints()
m_children &= ~Hints;
}
-void DomConnectionHints::clear(bool clear_all)
-{
- qDeleteAll(m_hint);
- m_hint.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomConnectionHints::DomConnectionHints()
-{
- m_children = 0;
-}
-
DomConnectionHints::~DomConnectionHints()
{
qDeleteAll(m_hint);
@@ -8342,12 +5876,11 @@ DomConnectionHints::~DomConnectionHints()
void DomConnectionHints::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("hint")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("hint"), Qt::CaseInsensitive)) {
DomConnectionHint *v = new DomConnectionHint();
v->read(reader);
m_hint.append(v);
@@ -8357,12 +5890,7 @@ void DomConnectionHints::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -8371,55 +5899,29 @@ void DomConnectionHints::read(QXmlStreamReader &reader)
void DomConnectionHints::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("connectionhints") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("connectionhints") : tagName.toLower());
- for (int i = 0; i < m_hint.size(); ++i) {
- DomConnectionHint* v = m_hint[i];
+ for (DomConnectionHint *v : m_hint)
v->write(writer, QStringLiteral("hint"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomConnectionHints::setElementHint(const QList<DomConnectionHint*>& a)
+void DomConnectionHints::setElementHint(const QVector<DomConnectionHint *> &a)
{
m_children |= Hint;
m_hint = a;
}
-void DomConnectionHint::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_type = false;
- }
-
- m_children = 0;
- m_x = 0;
- m_y = 0;
-}
-
-DomConnectionHint::DomConnectionHint()
-{
- m_children = 0;
- m_has_attr_type = false;
- m_x = 0;
- m_y = 0;
-}
-
DomConnectionHint::~DomConnectionHint()
{
}
void DomConnectionHint::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("type")) {
setAttributeType(attribute.value().toString());
continue;
@@ -8427,15 +5929,15 @@ void DomConnectionHint::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("x")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("x"), Qt::CaseInsensitive)) {
setElementX(reader.readElementText().toInt());
continue;
}
- if (tag == QLatin1String("y")) {
+ if (!tag.compare(QLatin1String("y"), Qt::CaseInsensitive)) {
setElementY(reader.readElementText().toInt());
continue;
}
@@ -8443,12 +5945,7 @@ void DomConnectionHint::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -8457,21 +5954,16 @@ void DomConnectionHint::read(QXmlStreamReader &reader)
void DomConnectionHint::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("connectionhint") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("connectionhint") : tagName.toLower());
if (hasAttributeType())
writer.writeAttribute(QStringLiteral("type"), attributeType());
- if (m_children & X) {
+ if (m_children & X)
writer.writeTextElement(QString(QLatin1Char('x')), QString::number(m_x));
- }
- if (m_children & Y) {
+ if (m_children & Y)
writer.writeTextElement(QString(QLatin1Char('y')), QString::number(m_y));
- }
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
@@ -8498,171 +5990,6 @@ void DomConnectionHint::clearElementY()
m_children &= ~Y;
}
-void DomScript::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_source = false;
- m_has_attr_language = false;
- }
-
- m_children = 0;
-}
-
-DomScript::DomScript()
-{
- m_children = 0;
- m_has_attr_source = false;
- m_has_attr_language = false;
-}
-
-DomScript::~DomScript()
-{
-}
-
-void DomScript::read(QXmlStreamReader &reader)
-{
-
- const QXmlStreamAttributes attributes = reader.attributes();
- for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
- if (name == QLatin1String("source")) {
- setAttributeSource(attribute.value().toString());
- continue;
- }
- if (name == QLatin1String("language")) {
- setAttributeLanguage(attribute.value().toString());
- continue;
- }
- reader.raiseError(QLatin1String("Unexpected attribute ") + name);
- }
-
- for (bool finished = false; !finished && !reader.hasError();) {
- switch (reader.readNext()) {
- case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
- }
- break;
- case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
- default :
- break;
- }
- }
-}
-
-void DomScript::write(QXmlStreamWriter &writer, const QString &tagName) const
-{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("script") : tagName.toLower());
-
- if (hasAttributeSource())
- writer.writeAttribute(QStringLiteral("source"), attributeSource());
-
- if (hasAttributeLanguage())
- writer.writeAttribute(QStringLiteral("language"), attributeLanguage());
-
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
- writer.writeEndElement();
-}
-
-void DomWidgetData::clear(bool clear_all)
-{
- qDeleteAll(m_property);
- m_property.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomWidgetData::DomWidgetData()
-{
- m_children = 0;
-}
-
-DomWidgetData::~DomWidgetData()
-{
- qDeleteAll(m_property);
- m_property.clear();
-}
-
-void DomWidgetData::read(QXmlStreamReader &reader)
-{
-
- for (bool finished = false; !finished && !reader.hasError();) {
- switch (reader.readNext()) {
- case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("property")) {
- DomProperty *v = new DomProperty();
- v->read(reader);
- m_property.append(v);
- continue;
- }
- reader.raiseError(QLatin1String("Unexpected element ") + tag);
- }
- break;
- case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
- default :
- break;
- }
- }
-}
-
-void DomWidgetData::write(QXmlStreamWriter &writer, const QString &tagName) const
-{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("widgetdata") : tagName.toLower());
-
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
- v->write(writer, QStringLiteral("property"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
- writer.writeEndElement();
-}
-
-void DomWidgetData::setElementProperty(const QList<DomProperty*>& a)
-{
- m_children |= Property;
- m_property = a;
-}
-
-void DomDesignerData::clear(bool clear_all)
-{
- qDeleteAll(m_property);
- m_property.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomDesignerData::DomDesignerData()
-{
- m_children = 0;
-}
-
DomDesignerData::~DomDesignerData()
{
qDeleteAll(m_property);
@@ -8671,12 +5998,11 @@ DomDesignerData::~DomDesignerData()
void DomDesignerData::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("property")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("property"), Qt::CaseInsensitive)) {
DomProperty *v = new DomProperty();
v->read(reader);
m_property.append(v);
@@ -8686,12 +6012,7 @@ void DomDesignerData::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -8700,41 +6021,20 @@ void DomDesignerData::read(QXmlStreamReader &reader)
void DomDesignerData::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("designerdata") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("designerdata") : tagName.toLower());
- for (int i = 0; i < m_property.size(); ++i) {
- DomProperty* v = m_property[i];
+ for (DomProperty *v : m_property)
v->write(writer, QStringLiteral("property"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomDesignerData::setElementProperty(const QList<DomProperty*>& a)
+void DomDesignerData::setElementProperty(const QList<DomProperty *> &a)
{
m_children |= Property;
m_property = a;
}
-void DomSlots::clear(bool clear_all)
-{
- m_signal.clear();
- m_slot.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomSlots::DomSlots()
-{
- m_children = 0;
-}
-
DomSlots::~DomSlots()
{
m_signal.clear();
@@ -8743,16 +6043,15 @@ DomSlots::~DomSlots()
void DomSlots::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("signal")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("signal"), Qt::CaseInsensitive)) {
m_signal.append(reader.readElementText());
continue;
}
- if (tag == QLatin1String("slot")) {
+ if (!tag.compare(QLatin1String("slot"), Qt::CaseInsensitive)) {
m_slot.append(reader.readElementText());
continue;
}
@@ -8760,12 +6059,7 @@ void DomSlots::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -8774,53 +6068,29 @@ void DomSlots::read(QXmlStreamReader &reader)
void DomSlots::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("slots") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("slots") : tagName.toLower());
- for (int i = 0; i < m_signal.size(); ++i) {
- QString v = m_signal[i];
+ for (const QString &v : m_signal)
writer.writeTextElement(QStringLiteral("signal"), v);
- }
- for (int i = 0; i < m_slot.size(); ++i) {
- QString v = m_slot[i];
+
+ for (const QString &v : m_slot)
writer.writeTextElement(QStringLiteral("slot"), v);
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomSlots::setElementSignal(const QStringList& a)
+void DomSlots::setElementSignal(const QStringList &a)
{
m_children |= Signal;
m_signal = a;
}
-void DomSlots::setElementSlot(const QStringList& a)
+void DomSlots::setElementSlot(const QStringList &a)
{
m_children |= Slot;
m_slot = a;
}
-void DomPropertySpecifications::clear(bool clear_all)
-{
- qDeleteAll(m_tooltip);
- m_tooltip.clear();
- qDeleteAll(m_stringpropertyspecification);
- m_stringpropertyspecification.clear();
-
- if (clear_all) {
- m_text.clear();
- }
-
- m_children = 0;
-}
-
-DomPropertySpecifications::DomPropertySpecifications()
-{
- m_children = 0;
-}
-
DomPropertySpecifications::~DomPropertySpecifications()
{
qDeleteAll(m_tooltip);
@@ -8831,18 +6101,17 @@ DomPropertySpecifications::~DomPropertySpecifications()
void DomPropertySpecifications::read(QXmlStreamReader &reader)
{
-
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
- if (tag == QLatin1String("tooltip")) {
+ const QStringRef tag = reader.name();
+ if (!tag.compare(QLatin1String("tooltip"), Qt::CaseInsensitive)) {
DomPropertyToolTip *v = new DomPropertyToolTip();
v->read(reader);
m_tooltip.append(v);
continue;
}
- if (tag == QLatin1String("stringpropertyspecification")) {
+ if (!tag.compare(QLatin1String("stringpropertyspecification"), Qt::CaseInsensitive)) {
DomStringPropertySpecification *v = new DomStringPropertySpecification();
v->read(reader);
m_stringpropertyspecification.append(v);
@@ -8852,12 +6121,7 @@ void DomPropertySpecifications::read(QXmlStreamReader &reader)
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -8866,61 +6130,38 @@ void DomPropertySpecifications::read(QXmlStreamReader &reader)
void DomPropertySpecifications::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("propertyspecifications") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("propertyspecifications") : tagName.toLower());
- for (int i = 0; i < m_tooltip.size(); ++i) {
- DomPropertyToolTip* v = m_tooltip[i];
+ for (DomPropertyToolTip *v : m_tooltip)
v->write(writer, QStringLiteral("tooltip"));
- }
- for (int i = 0; i < m_stringpropertyspecification.size(); ++i) {
- DomStringPropertySpecification* v = m_stringpropertyspecification[i];
+
+ for (DomStringPropertySpecification *v : m_stringpropertyspecification)
v->write(writer, QStringLiteral("stringpropertyspecification"));
- }
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
writer.writeEndElement();
}
-void DomPropertySpecifications::setElementTooltip(const QList<DomPropertyToolTip*>& a)
+void DomPropertySpecifications::setElementTooltip(const QVector<DomPropertyToolTip *> &a)
{
m_children |= Tooltip;
m_tooltip = a;
}
-void DomPropertySpecifications::setElementStringpropertyspecification(const QList<DomStringPropertySpecification*>& a)
+void DomPropertySpecifications::setElementStringpropertyspecification(const QVector<DomStringPropertySpecification *> &a)
{
m_children |= Stringpropertyspecification;
m_stringpropertyspecification = a;
}
-void DomPropertyToolTip::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_name = false;
- }
-
- m_children = 0;
-}
-
-DomPropertyToolTip::DomPropertyToolTip()
-{
- m_children = 0;
- m_has_attr_name = false;
-}
-
DomPropertyToolTip::~DomPropertyToolTip()
{
}
void DomPropertyToolTip::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("name")) {
setAttributeName(attribute.value().toString());
continue;
@@ -8928,20 +6169,15 @@ void DomPropertyToolTip::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -8950,48 +6186,23 @@ void DomPropertyToolTip::read(QXmlStreamReader &reader)
void DomPropertyToolTip::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("propertytooltip") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("propertytooltip") : tagName.toLower());
if (hasAttributeName())
writer.writeAttribute(QStringLiteral("name"), attributeName());
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
writer.writeEndElement();
}
-void DomStringPropertySpecification::clear(bool clear_all)
-{
-
- if (clear_all) {
- m_text.clear();
- m_has_attr_name = false;
- m_has_attr_type = false;
- m_has_attr_notr = false;
- }
-
- m_children = 0;
-}
-
-DomStringPropertySpecification::DomStringPropertySpecification()
-{
- m_children = 0;
- m_has_attr_name = false;
- m_has_attr_type = false;
- m_has_attr_notr = false;
-}
-
DomStringPropertySpecification::~DomStringPropertySpecification()
{
}
void DomStringPropertySpecification::read(QXmlStreamReader &reader)
{
-
- const QXmlStreamAttributes attributes = reader.attributes();
+ const QXmlStreamAttributes &attributes = reader.attributes();
for (const QXmlStreamAttribute &attribute : attributes) {
- QStringRef name = attribute.name();
+ const QStringRef name = attribute.name();
if (name == QLatin1String("name")) {
setAttributeName(attribute.value().toString());
continue;
@@ -9007,20 +6218,15 @@ void DomStringPropertySpecification::read(QXmlStreamReader &reader)
reader.raiseError(QLatin1String("Unexpected attribute ") + name);
}
- for (bool finished = false; !finished && !reader.hasError();) {
+ while (!reader.hasError()) {
switch (reader.readNext()) {
case QXmlStreamReader::StartElement : {
- const QString tag = reader.name().toString().toLower();
+ const QStringRef tag = reader.name();
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
case QXmlStreamReader::EndElement :
- finished = true;
- break;
- case QXmlStreamReader::Characters :
- if (!reader.isWhitespace())
- m_text.append(reader.text().toString());
- break;
+ return;
default :
break;
}
@@ -9029,7 +6235,7 @@ void DomStringPropertySpecification::read(QXmlStreamReader &reader)
void DomStringPropertySpecification::write(QXmlStreamWriter &writer, const QString &tagName) const
{
- writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("stringpropertyspecification") : tagName.toLower());
+ writer.writeStartElement(tagName.isEmpty() ? QStringLiteral("stringpropertyspecification") : tagName.toLower());
if (hasAttributeName())
writer.writeAttribute(QStringLiteral("name"), attributeName());
@@ -9040,9 +6246,6 @@ void DomStringPropertySpecification::write(QXmlStreamWriter &writer, const QStri
if (hasAttributeNotr())
writer.writeAttribute(QStringLiteral("notr"), attributeNotr());
- if (!m_text.isEmpty())
- writer.writeCharacters(m_text);
-
writer.writeEndElement();
}
diff --git a/src/tools/uic/ui4.h b/src/tools/uic/ui4.h
index 820d2c5f8c..08a5ed01d5 100644
--- a/src/tools/uic/ui4.h
+++ b/src/tools/uic/ui4.h
@@ -45,6 +45,7 @@
#include <qlist.h>
#include <qstring.h>
#include <qstringlist.h>
+#include <qvector.h>
#include <qxmlstream.h>
#include <qglobal.h>
@@ -85,15 +86,9 @@ class DomAction;
class DomActionRef;
class DomButtonGroup;
class DomButtonGroups;
-class DomImages;
-class DomImage;
-class DomImageData;
class DomCustomWidgets;
class DomHeader;
class DomCustomWidget;
-class DomProperties;
-class DomPropertyData;
-class DomSizePolicyData;
class DomLayoutDefault;
class DomLayoutFunction;
class DomTabStops;
@@ -134,8 +129,6 @@ class DomConnections;
class DomConnection;
class DomConnectionHints;
class DomConnectionHint;
-class DomScript;
-class DomWidgetData;
class DomDesignerData;
class DomSlots;
class DomPropertySpecifications;
@@ -147,29 +140,28 @@ class DomStringPropertySpecification;
*/
class QDESIGNER_UILIB_EXPORT DomUI {
+ Q_DISABLE_COPY(DomUI)
public:
- DomUI();
+ DomUI() = default;
~DomUI();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeVersion() const { return m_has_attr_version; }
inline QString attributeVersion() const { return m_attr_version; }
- inline void setAttributeVersion(const QString& a) { m_attr_version = a; m_has_attr_version = true; }
+ inline void setAttributeVersion(const QString &a) { m_attr_version = a; m_has_attr_version = true; }
inline void clearAttributeVersion() { m_has_attr_version = false; }
inline bool hasAttributeLanguage() const { return m_has_attr_language; }
inline QString attributeLanguage() const { return m_attr_language; }
- inline void setAttributeLanguage(const QString& a) { m_attr_language = a; m_has_attr_language = true; }
+ inline void setAttributeLanguage(const QString &a) { m_attr_language = a; m_has_attr_language = true; }
inline void clearAttributeLanguage() { m_has_attr_language = false; }
inline bool hasAttributeDisplayname() const { return m_has_attr_displayname; }
inline QString attributeDisplayname() const { return m_attr_displayname; }
- inline void setAttributeDisplayname(const QString& a) { m_attr_displayname = a; m_has_attr_displayname = true; }
+ inline void setAttributeDisplayname(const QString &a) { m_attr_displayname = a; m_has_attr_displayname = true; }
inline void clearAttributeDisplayname() { m_has_attr_displayname = false; }
inline bool hasAttributeStdsetdef() const { return m_has_attr_stdsetdef; }
@@ -184,141 +176,132 @@ public:
// child element accessors
inline QString elementAuthor() const { return m_author; }
- void setElementAuthor(const QString& a);
+ void setElementAuthor(const QString &a);
inline bool hasElementAuthor() const { return m_children & Author; }
void clearElementAuthor();
inline QString elementComment() const { return m_comment; }
- void setElementComment(const QString& a);
+ void setElementComment(const QString &a);
inline bool hasElementComment() const { return m_children & Comment; }
void clearElementComment();
inline QString elementExportMacro() const { return m_exportMacro; }
- void setElementExportMacro(const QString& a);
+ void setElementExportMacro(const QString &a);
inline bool hasElementExportMacro() const { return m_children & ExportMacro; }
void clearElementExportMacro();
inline QString elementClass() const { return m_class; }
- void setElementClass(const QString& a);
+ void setElementClass(const QString &a);
inline bool hasElementClass() const { return m_children & Class; }
void clearElementClass();
- inline DomWidget* elementWidget() const { return m_widget; }
- DomWidget* takeElementWidget();
- void setElementWidget(DomWidget* a);
+ inline DomWidget *elementWidget() const { return m_widget; }
+ DomWidget *takeElementWidget();
+ void setElementWidget(DomWidget *a);
inline bool hasElementWidget() const { return m_children & Widget; }
void clearElementWidget();
- inline DomLayoutDefault* elementLayoutDefault() const { return m_layoutDefault; }
- DomLayoutDefault* takeElementLayoutDefault();
- void setElementLayoutDefault(DomLayoutDefault* a);
+ inline DomLayoutDefault *elementLayoutDefault() const { return m_layoutDefault; }
+ DomLayoutDefault *takeElementLayoutDefault();
+ void setElementLayoutDefault(DomLayoutDefault *a);
inline bool hasElementLayoutDefault() const { return m_children & LayoutDefault; }
void clearElementLayoutDefault();
- inline DomLayoutFunction* elementLayoutFunction() const { return m_layoutFunction; }
- DomLayoutFunction* takeElementLayoutFunction();
- void setElementLayoutFunction(DomLayoutFunction* a);
+ inline DomLayoutFunction *elementLayoutFunction() const { return m_layoutFunction; }
+ DomLayoutFunction *takeElementLayoutFunction();
+ void setElementLayoutFunction(DomLayoutFunction *a);
inline bool hasElementLayoutFunction() const { return m_children & LayoutFunction; }
void clearElementLayoutFunction();
inline QString elementPixmapFunction() const { return m_pixmapFunction; }
- void setElementPixmapFunction(const QString& a);
+ void setElementPixmapFunction(const QString &a);
inline bool hasElementPixmapFunction() const { return m_children & PixmapFunction; }
void clearElementPixmapFunction();
- inline DomCustomWidgets* elementCustomWidgets() const { return m_customWidgets; }
- DomCustomWidgets* takeElementCustomWidgets();
- void setElementCustomWidgets(DomCustomWidgets* a);
+ inline DomCustomWidgets *elementCustomWidgets() const { return m_customWidgets; }
+ DomCustomWidgets *takeElementCustomWidgets();
+ void setElementCustomWidgets(DomCustomWidgets *a);
inline bool hasElementCustomWidgets() const { return m_children & CustomWidgets; }
void clearElementCustomWidgets();
- inline DomTabStops* elementTabStops() const { return m_tabStops; }
- DomTabStops* takeElementTabStops();
- void setElementTabStops(DomTabStops* a);
+ inline DomTabStops *elementTabStops() const { return m_tabStops; }
+ DomTabStops *takeElementTabStops();
+ void setElementTabStops(DomTabStops *a);
inline bool hasElementTabStops() const { return m_children & TabStops; }
void clearElementTabStops();
- inline DomImages* elementImages() const { return m_images; }
- DomImages* takeElementImages();
- void setElementImages(DomImages* a);
- inline bool hasElementImages() const { return m_children & Images; }
- void clearElementImages();
-
- inline DomIncludes* elementIncludes() const { return m_includes; }
- DomIncludes* takeElementIncludes();
- void setElementIncludes(DomIncludes* a);
+ inline DomIncludes *elementIncludes() const { return m_includes; }
+ DomIncludes *takeElementIncludes();
+ void setElementIncludes(DomIncludes *a);
inline bool hasElementIncludes() const { return m_children & Includes; }
void clearElementIncludes();
- inline DomResources* elementResources() const { return m_resources; }
- DomResources* takeElementResources();
- void setElementResources(DomResources* a);
+ inline DomResources *elementResources() const { return m_resources; }
+ DomResources *takeElementResources();
+ void setElementResources(DomResources *a);
inline bool hasElementResources() const { return m_children & Resources; }
void clearElementResources();
- inline DomConnections* elementConnections() const { return m_connections; }
- DomConnections* takeElementConnections();
- void setElementConnections(DomConnections* a);
+ inline DomConnections *elementConnections() const { return m_connections; }
+ DomConnections *takeElementConnections();
+ void setElementConnections(DomConnections *a);
inline bool hasElementConnections() const { return m_children & Connections; }
void clearElementConnections();
- inline DomDesignerData* elementDesignerdata() const { return m_designerdata; }
- DomDesignerData* takeElementDesignerdata();
- void setElementDesignerdata(DomDesignerData* a);
+ inline DomDesignerData *elementDesignerdata() const { return m_designerdata; }
+ DomDesignerData *takeElementDesignerdata();
+ void setElementDesignerdata(DomDesignerData *a);
inline bool hasElementDesignerdata() const { return m_children & Designerdata; }
void clearElementDesignerdata();
- inline DomSlots* elementSlots() const { return m_slots; }
- DomSlots* takeElementSlots();
- void setElementSlots(DomSlots* a);
+ inline DomSlots *elementSlots() const { return m_slots; }
+ DomSlots *takeElementSlots();
+ void setElementSlots(DomSlots *a);
inline bool hasElementSlots() const { return m_children & Slots; }
void clearElementSlots();
- inline DomButtonGroups* elementButtonGroups() const { return m_buttonGroups; }
- DomButtonGroups* takeElementButtonGroups();
- void setElementButtonGroups(DomButtonGroups* a);
+ inline DomButtonGroups *elementButtonGroups() const { return m_buttonGroups; }
+ DomButtonGroups *takeElementButtonGroups();
+ void setElementButtonGroups(DomButtonGroups *a);
inline bool hasElementButtonGroups() const { return m_children & ButtonGroups; }
void clearElementButtonGroups();
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_version;
- bool m_has_attr_version;
+ bool m_has_attr_version = false;
QString m_attr_language;
- bool m_has_attr_language;
+ bool m_has_attr_language = false;
QString m_attr_displayname;
- bool m_has_attr_displayname;
+ bool m_has_attr_displayname = false;
- int m_attr_stdsetdef;
- bool m_has_attr_stdsetdef;
+ int m_attr_stdsetdef = 0;
+ bool m_has_attr_stdsetdef = false;
- int m_attr_stdSetDef;
- bool m_has_attr_stdSetDef;
+ int m_attr_stdSetDef = 0;
+ bool m_has_attr_stdSetDef = false;
// child element data
- uint m_children;
+ uint m_children = 0;
QString m_author;
QString m_comment;
QString m_exportMacro;
QString m_class;
- DomWidget* m_widget;
- DomLayoutDefault* m_layoutDefault;
- DomLayoutFunction* m_layoutFunction;
+ DomWidget *m_widget = nullptr;
+ DomLayoutDefault *m_layoutDefault = nullptr;
+ DomLayoutFunction *m_layoutFunction = nullptr;
QString m_pixmapFunction;
- DomCustomWidgets* m_customWidgets;
- DomTabStops* m_tabStops;
- DomImages* m_images;
- DomIncludes* m_includes;
- DomResources* m_resources;
- DomConnections* m_connections;
- DomDesignerData* m_designerdata;
- DomSlots* m_slots;
- DomButtonGroups* m_buttonGroups;
+ DomCustomWidgets *m_customWidgets = nullptr;
+ DomTabStops *m_tabStops = nullptr;
+ DomIncludes *m_includes = nullptr;
+ DomResources *m_resources = nullptr;
+ DomConnections *m_connections = nullptr;
+ DomDesignerData *m_designerdata = nullptr;
+ DomSlots *m_slots = nullptr;
+ DomButtonGroups *m_buttonGroups = nullptr;
+
enum Child {
Author = 1,
Comment = 2,
@@ -330,586 +313,388 @@ private:
PixmapFunction = 128,
CustomWidgets = 256,
TabStops = 512,
- Images = 1024,
- Includes = 2048,
- Resources = 4096,
- Connections = 8192,
- Designerdata = 16384,
- Slots = 32768,
- ButtonGroups = 65536
+ Includes = 1024,
+ Resources = 2048,
+ Connections = 4096,
+ Designerdata = 8192,
+ Slots = 16384,
+ ButtonGroups = 32768
};
-
- DomUI(const DomUI &other);
- void operator = (const DomUI&other);
};
class QDESIGNER_UILIB_EXPORT DomIncludes {
+ Q_DISABLE_COPY(DomIncludes)
public:
- DomIncludes();
+ DomIncludes() = default;
~DomIncludes();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
- inline QList<DomInclude*> elementInclude() const { return m_include; }
- void setElementInclude(const QList<DomInclude*>& a);
+ inline QVector<DomInclude *> elementInclude() const { return m_include; }
+ void setElementInclude(const QVector<DomInclude *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- QList<DomInclude*> m_include;
+ uint m_children = 0;
+ QVector<DomInclude *> m_include;
+
enum Child {
Include = 1
};
-
- DomIncludes(const DomIncludes &other);
- void operator = (const DomIncludes&other);
};
class QDESIGNER_UILIB_EXPORT DomInclude {
+ Q_DISABLE_COPY(DomInclude)
public:
- DomInclude();
+ DomInclude() = default;
~DomInclude();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+
inline QString text() const { return m_text; }
inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeLocation() const { return m_has_attr_location; }
inline QString attributeLocation() const { return m_attr_location; }
- inline void setAttributeLocation(const QString& a) { m_attr_location = a; m_has_attr_location = true; }
+ inline void setAttributeLocation(const QString &a) { m_attr_location = a; m_has_attr_location = true; }
inline void clearAttributeLocation() { m_has_attr_location = false; }
inline bool hasAttributeImpldecl() const { return m_has_attr_impldecl; }
inline QString attributeImpldecl() const { return m_attr_impldecl; }
- inline void setAttributeImpldecl(const QString& a) { m_attr_impldecl = a; m_has_attr_impldecl = true; }
+ inline void setAttributeImpldecl(const QString &a) { m_attr_impldecl = a; m_has_attr_impldecl = true; }
inline void clearAttributeImpldecl() { m_has_attr_impldecl = false; }
- // child element accessors
private:
QString m_text;
- void clear(bool clear_all = true);
// attribute data
QString m_attr_location;
- bool m_has_attr_location;
+ bool m_has_attr_location = false;
QString m_attr_impldecl;
- bool m_has_attr_impldecl;
-
- // child element data
- uint m_children;
-
- DomInclude(const DomInclude &other);
- void operator = (const DomInclude&other);
+ bool m_has_attr_impldecl = false;
};
class QDESIGNER_UILIB_EXPORT DomResources {
+ Q_DISABLE_COPY(DomResources)
public:
- DomResources();
+ DomResources() = default;
~DomResources();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
// child element accessors
- inline QList<DomResource*> elementInclude() const { return m_include; }
- void setElementInclude(const QList<DomResource*>& a);
+ inline QVector<DomResource *> elementInclude() const { return m_include; }
+ void setElementInclude(const QVector<DomResource *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_name;
- bool m_has_attr_name;
+ bool m_has_attr_name = false;
// child element data
- uint m_children;
- QList<DomResource*> m_include;
+ uint m_children = 0;
+ QVector<DomResource *> m_include;
+
enum Child {
Include = 1
};
-
- DomResources(const DomResources &other);
- void operator = (const DomResources&other);
};
class QDESIGNER_UILIB_EXPORT DomResource {
+ Q_DISABLE_COPY(DomResource)
public:
- DomResource();
+ DomResource() = default;
~DomResource();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeLocation() const { return m_has_attr_location; }
inline QString attributeLocation() const { return m_attr_location; }
- inline void setAttributeLocation(const QString& a) { m_attr_location = a; m_has_attr_location = true; }
+ inline void setAttributeLocation(const QString &a) { m_attr_location = a; m_has_attr_location = true; }
inline void clearAttributeLocation() { m_has_attr_location = false; }
- // child element accessors
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_location;
- bool m_has_attr_location;
-
- // child element data
- uint m_children;
-
- DomResource(const DomResource &other);
- void operator = (const DomResource&other);
+ bool m_has_attr_location = false;
};
class QDESIGNER_UILIB_EXPORT DomActionGroup {
+ Q_DISABLE_COPY(DomActionGroup)
public:
- DomActionGroup();
+ DomActionGroup() = default;
~DomActionGroup();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
// child element accessors
- inline QList<DomAction*> elementAction() const { return m_action; }
- void setElementAction(const QList<DomAction*>& a);
+ inline QVector<DomAction *> elementAction() const { return m_action; }
+ void setElementAction(const QVector<DomAction *> &a);
- inline QList<DomActionGroup*> elementActionGroup() const { return m_actionGroup; }
- void setElementActionGroup(const QList<DomActionGroup*>& a);
+ inline QVector<DomActionGroup *> elementActionGroup() const { return m_actionGroup; }
+ void setElementActionGroup(const QVector<DomActionGroup *> &a);
inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
+ void setElementProperty(const QList<DomProperty *> &a);
inline QList<DomProperty*> elementAttribute() const { return m_attribute; }
- void setElementAttribute(const QList<DomProperty*>& a);
+ void setElementAttribute(const QList<DomProperty *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_name;
- bool m_has_attr_name;
+ bool m_has_attr_name = false;
// child element data
- uint m_children;
- QList<DomAction*> m_action;
- QList<DomActionGroup*> m_actionGroup;
+ uint m_children = 0;
+ QVector<DomAction *> m_action;
+ QVector<DomActionGroup *> m_actionGroup;
QList<DomProperty*> m_property;
QList<DomProperty*> m_attribute;
+
enum Child {
Action = 1,
ActionGroup = 2,
Property = 4,
Attribute = 8
};
-
- DomActionGroup(const DomActionGroup &other);
- void operator = (const DomActionGroup&other);
};
class QDESIGNER_UILIB_EXPORT DomAction {
+ Q_DISABLE_COPY(DomAction)
public:
- DomAction();
+ DomAction() = default;
~DomAction();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
inline bool hasAttributeMenu() const { return m_has_attr_menu; }
inline QString attributeMenu() const { return m_attr_menu; }
- inline void setAttributeMenu(const QString& a) { m_attr_menu = a; m_has_attr_menu = true; }
+ inline void setAttributeMenu(const QString &a) { m_attr_menu = a; m_has_attr_menu = true; }
inline void clearAttributeMenu() { m_has_attr_menu = false; }
// child element accessors
inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
+ void setElementProperty(const QList<DomProperty *> &a);
inline QList<DomProperty*> elementAttribute() const { return m_attribute; }
- void setElementAttribute(const QList<DomProperty*>& a);
+ void setElementAttribute(const QList<DomProperty *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_name;
- bool m_has_attr_name;
+ bool m_has_attr_name = false;
QString m_attr_menu;
- bool m_has_attr_menu;
+ bool m_has_attr_menu = false;
// child element data
- uint m_children;
+ uint m_children = 0;
QList<DomProperty*> m_property;
QList<DomProperty*> m_attribute;
+
enum Child {
Property = 1,
Attribute = 2
};
-
- DomAction(const DomAction &other);
- void operator = (const DomAction&other);
};
class QDESIGNER_UILIB_EXPORT DomActionRef {
+ Q_DISABLE_COPY(DomActionRef)
public:
- DomActionRef();
+ DomActionRef() = default;
~DomActionRef();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
- // child element accessors
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_name;
- bool m_has_attr_name;
-
- // child element data
- uint m_children;
-
- DomActionRef(const DomActionRef &other);
- void operator = (const DomActionRef&other);
+ bool m_has_attr_name = false;
};
class QDESIGNER_UILIB_EXPORT DomButtonGroup {
+ Q_DISABLE_COPY(DomButtonGroup)
public:
- DomButtonGroup();
+ DomButtonGroup() = default;
~DomButtonGroup();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
// child element accessors
inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
+ void setElementProperty(const QList<DomProperty *> &a);
inline QList<DomProperty*> elementAttribute() const { return m_attribute; }
- void setElementAttribute(const QList<DomProperty*>& a);
+ void setElementAttribute(const QList<DomProperty *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_name;
- bool m_has_attr_name;
+ bool m_has_attr_name = false;
// child element data
- uint m_children;
+ uint m_children = 0;
QList<DomProperty*> m_property;
QList<DomProperty*> m_attribute;
+
enum Child {
Property = 1,
Attribute = 2
};
-
- DomButtonGroup(const DomButtonGroup &other);
- void operator = (const DomButtonGroup&other);
};
class QDESIGNER_UILIB_EXPORT DomButtonGroups {
+ Q_DISABLE_COPY(DomButtonGroups)
public:
- DomButtonGroups();
+ DomButtonGroups() = default;
~DomButtonGroups();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
-
- // attribute accessors
- // child element accessors
- inline QList<DomButtonGroup*> elementButtonGroup() const { return m_buttonGroup; }
- void setElementButtonGroup(const QList<DomButtonGroup*>& a);
-
-private:
- QString m_text;
- void clear(bool clear_all = true);
-
- // attribute data
- // child element data
- uint m_children;
- QList<DomButtonGroup*> m_buttonGroup;
- enum Child {
- ButtonGroup = 1
- };
-
- DomButtonGroups(const DomButtonGroups &other);
- void operator = (const DomButtonGroups&other);
-};
-
-class QDESIGNER_UILIB_EXPORT DomImages {
-public:
- DomImages();
- ~DomImages();
-
- void read(QXmlStreamReader &reader);
- void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
- inline QList<DomImage*> elementImage() const { return m_image; }
- void setElementImage(const QList<DomImage*>& a);
+ inline QVector<DomButtonGroup *> elementButtonGroup() const { return m_buttonGroup; }
+ void setElementButtonGroup(const QVector<DomButtonGroup *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- QList<DomImage*> m_image;
- enum Child {
- Image = 1
- };
-
- DomImages(const DomImages &other);
- void operator = (const DomImages&other);
-};
-
-class QDESIGNER_UILIB_EXPORT DomImage {
-public:
- DomImage();
- ~DomImage();
-
- void read(QXmlStreamReader &reader);
- void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
-
- // attribute accessors
- inline bool hasAttributeName() const { return m_has_attr_name; }
- inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
- inline void clearAttributeName() { m_has_attr_name = false; }
-
- // child element accessors
- inline DomImageData* elementData() const { return m_data; }
- DomImageData* takeElementData();
- void setElementData(DomImageData* a);
- inline bool hasElementData() const { return m_children & Data; }
- void clearElementData();
-
-private:
- QString m_text;
- void clear(bool clear_all = true);
+ uint m_children = 0;
+ QVector<DomButtonGroup *> m_buttonGroup;
- // attribute data
- QString m_attr_name;
- bool m_has_attr_name;
-
- // child element data
- uint m_children;
- DomImageData* m_data;
enum Child {
- Data = 1
+ ButtonGroup = 1
};
-
- DomImage(const DomImage &other);
- void operator = (const DomImage&other);
-};
-
-class QDESIGNER_UILIB_EXPORT DomImageData {
-public:
- DomImageData();
- ~DomImageData();
-
- void read(QXmlStreamReader &reader);
- void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
-
- // attribute accessors
- inline bool hasAttributeFormat() const { return m_has_attr_format; }
- inline QString attributeFormat() const { return m_attr_format; }
- inline void setAttributeFormat(const QString& a) { m_attr_format = a; m_has_attr_format = true; }
- inline void clearAttributeFormat() { m_has_attr_format = false; }
-
- inline bool hasAttributeLength() const { return m_has_attr_length; }
- inline int attributeLength() const { return m_attr_length; }
- inline void setAttributeLength(int a) { m_attr_length = a; m_has_attr_length = true; }
- inline void clearAttributeLength() { m_has_attr_length = false; }
-
- // child element accessors
-private:
- QString m_text;
- void clear(bool clear_all = true);
-
- // attribute data
- QString m_attr_format;
- bool m_has_attr_format;
-
- int m_attr_length;
- bool m_has_attr_length;
-
- // child element data
- uint m_children;
-
- DomImageData(const DomImageData &other);
- void operator = (const DomImageData&other);
};
class QDESIGNER_UILIB_EXPORT DomCustomWidgets {
+ Q_DISABLE_COPY(DomCustomWidgets)
public:
- DomCustomWidgets();
+ DomCustomWidgets() = default;
~DomCustomWidgets();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
- inline QList<DomCustomWidget*> elementCustomWidget() const { return m_customWidget; }
- void setElementCustomWidget(const QList<DomCustomWidget*>& a);
+ inline QVector<DomCustomWidget *> elementCustomWidget() const { return m_customWidget; }
+ void setElementCustomWidget(const QVector<DomCustomWidget *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- QList<DomCustomWidget*> m_customWidget;
+ uint m_children = 0;
+ QVector<DomCustomWidget *> m_customWidget;
+
enum Child {
CustomWidget = 1
};
-
- DomCustomWidgets(const DomCustomWidgets &other);
- void operator = (const DomCustomWidgets&other);
};
class QDESIGNER_UILIB_EXPORT DomHeader {
+ Q_DISABLE_COPY(DomHeader)
public:
- DomHeader();
+ DomHeader() = default;
~DomHeader();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+
inline QString text() const { return m_text; }
inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeLocation() const { return m_has_attr_location; }
inline QString attributeLocation() const { return m_attr_location; }
- inline void setAttributeLocation(const QString& a) { m_attr_location = a; m_has_attr_location = true; }
+ inline void setAttributeLocation(const QString &a) { m_attr_location = a; m_has_attr_location = true; }
inline void clearAttributeLocation() { m_has_attr_location = false; }
- // child element accessors
private:
QString m_text;
- void clear(bool clear_all = true);
// attribute data
QString m_attr_location;
- bool m_has_attr_location;
-
- // child element data
- uint m_children;
-
- DomHeader(const DomHeader &other);
- void operator = (const DomHeader&other);
+ bool m_has_attr_location = false;
};
class QDESIGNER_UILIB_EXPORT DomCustomWidget {
+ Q_DISABLE_COPY(DomCustomWidget)
public:
- DomCustomWidget();
+ DomCustomWidget() = default;
~DomCustomWidget();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline QString elementClass() const { return m_class; }
- void setElementClass(const QString& a);
+ void setElementClass(const QString &a);
inline bool hasElementClass() const { return m_children & Class; }
void clearElementClass();
inline QString elementExtends() const { return m_extends; }
- void setElementExtends(const QString& a);
+ void setElementExtends(const QString &a);
inline bool hasElementExtends() const { return m_children & Extends; }
void clearElementExtends();
- inline DomHeader* elementHeader() const { return m_header; }
- DomHeader* takeElementHeader();
- void setElementHeader(DomHeader* a);
+ inline DomHeader *elementHeader() const { return m_header; }
+ DomHeader *takeElementHeader();
+ void setElementHeader(DomHeader *a);
inline bool hasElementHeader() const { return m_children & Header; }
void clearElementHeader();
- inline DomSize* elementSizeHint() const { return m_sizeHint; }
- DomSize* takeElementSizeHint();
- void setElementSizeHint(DomSize* a);
+ inline DomSize *elementSizeHint() const { return m_sizeHint; }
+ DomSize *takeElementSizeHint();
+ void setElementSizeHint(DomSize *a);
inline bool hasElementSizeHint() const { return m_children & SizeHint; }
void clearElementSizeHint();
inline QString elementAddPageMethod() const { return m_addPageMethod; }
- void setElementAddPageMethod(const QString& a);
+ void setElementAddPageMethod(const QString &a);
inline bool hasElementAddPageMethod() const { return m_children & AddPageMethod; }
void clearElementAddPageMethod();
@@ -918,60 +703,37 @@ public:
inline bool hasElementContainer() const { return m_children & Container; }
void clearElementContainer();
- inline DomSizePolicyData* elementSizePolicy() const { return m_sizePolicy; }
- DomSizePolicyData* takeElementSizePolicy();
- void setElementSizePolicy(DomSizePolicyData* a);
- inline bool hasElementSizePolicy() const { return m_children & SizePolicy; }
- void clearElementSizePolicy();
-
inline QString elementPixmap() const { return m_pixmap; }
- void setElementPixmap(const QString& a);
+ void setElementPixmap(const QString &a);
inline bool hasElementPixmap() const { return m_children & Pixmap; }
void clearElementPixmap();
- inline DomScript* elementScript() const { return m_script; }
- DomScript* takeElementScript();
- void setElementScript(DomScript* a);
- inline bool hasElementScript() const { return m_children & Script; }
- void clearElementScript();
-
- inline DomProperties* elementProperties() const { return m_properties; }
- DomProperties* takeElementProperties();
- void setElementProperties(DomProperties* a);
- inline bool hasElementProperties() const { return m_children & Properties; }
- void clearElementProperties();
-
- inline DomSlots* elementSlots() const { return m_slots; }
- DomSlots* takeElementSlots();
- void setElementSlots(DomSlots* a);
+ inline DomSlots *elementSlots() const { return m_slots; }
+ DomSlots *takeElementSlots();
+ void setElementSlots(DomSlots *a);
inline bool hasElementSlots() const { return m_children & Slots; }
void clearElementSlots();
- inline DomPropertySpecifications* elementPropertyspecifications() const { return m_propertyspecifications; }
- DomPropertySpecifications* takeElementPropertyspecifications();
- void setElementPropertyspecifications(DomPropertySpecifications* a);
+ inline DomPropertySpecifications *elementPropertyspecifications() const { return m_propertyspecifications; }
+ DomPropertySpecifications *takeElementPropertyspecifications();
+ void setElementPropertyspecifications(DomPropertySpecifications *a);
inline bool hasElementPropertyspecifications() const { return m_children & Propertyspecifications; }
void clearElementPropertyspecifications();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
+ uint m_children = 0;
QString m_class;
QString m_extends;
- DomHeader* m_header;
- DomSize* m_sizeHint;
+ DomHeader *m_header = nullptr;
+ DomSize *m_sizeHint = nullptr;
QString m_addPageMethod;
- int m_container;
- DomSizePolicyData* m_sizePolicy;
+ int m_container = 0;
QString m_pixmap;
- DomScript* m_script;
- DomProperties* m_properties;
- DomSlots* m_slots;
- DomPropertySpecifications* m_propertyspecifications;
+ DomSlots *m_slots = nullptr;
+ DomPropertySpecifications *m_propertyspecifications = nullptr;
+
enum Child {
Class = 1,
Extends = 2,
@@ -979,130 +741,20 @@ private:
SizeHint = 8,
AddPageMethod = 16,
Container = 32,
- SizePolicy = 64,
- Pixmap = 128,
- Script = 256,
- Properties = 512,
- Slots = 1024,
- Propertyspecifications = 2048
- };
-
- DomCustomWidget(const DomCustomWidget &other);
- void operator = (const DomCustomWidget&other);
-};
-
-class QDESIGNER_UILIB_EXPORT DomProperties {
-public:
- DomProperties();
- ~DomProperties();
-
- void read(QXmlStreamReader &reader);
- void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
-
- // attribute accessors
- // child element accessors
- inline QList<DomPropertyData*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomPropertyData*>& a);
-
-private:
- QString m_text;
- void clear(bool clear_all = true);
-
- // attribute data
- // child element data
- uint m_children;
- QList<DomPropertyData*> m_property;
- enum Child {
- Property = 1
- };
-
- DomProperties(const DomProperties &other);
- void operator = (const DomProperties&other);
-};
-
-class QDESIGNER_UILIB_EXPORT DomPropertyData {
-public:
- DomPropertyData();
- ~DomPropertyData();
-
- void read(QXmlStreamReader &reader);
- void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
-
- // attribute accessors
- inline bool hasAttributeType() const { return m_has_attr_type; }
- inline QString attributeType() const { return m_attr_type; }
- inline void setAttributeType(const QString& a) { m_attr_type = a; m_has_attr_type = true; }
- inline void clearAttributeType() { m_has_attr_type = false; }
-
- // child element accessors
-private:
- QString m_text;
- void clear(bool clear_all = true);
-
- // attribute data
- QString m_attr_type;
- bool m_has_attr_type;
-
- // child element data
- uint m_children;
-
- DomPropertyData(const DomPropertyData &other);
- void operator = (const DomPropertyData&other);
-};
-
-class QDESIGNER_UILIB_EXPORT DomSizePolicyData {
-public:
- DomSizePolicyData();
- ~DomSizePolicyData();
-
- void read(QXmlStreamReader &reader);
- void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
-
- // attribute accessors
- // child element accessors
- inline int elementHorData() const { return m_horData; }
- void setElementHorData(int a);
- inline bool hasElementHorData() const { return m_children & HorData; }
- void clearElementHorData();
-
- inline int elementVerData() const { return m_verData; }
- void setElementVerData(int a);
- inline bool hasElementVerData() const { return m_children & VerData; }
- void clearElementVerData();
-
-private:
- QString m_text;
- void clear(bool clear_all = true);
-
- // attribute data
- // child element data
- uint m_children;
- int m_horData;
- int m_verData;
- enum Child {
- HorData = 1,
- VerData = 2
+ Pixmap = 64,
+ Slots = 128,
+ Propertyspecifications = 256
};
-
- DomSizePolicyData(const DomSizePolicyData &other);
- void operator = (const DomSizePolicyData&other);
};
class QDESIGNER_UILIB_EXPORT DomLayoutDefault {
+ Q_DISABLE_COPY(DomLayoutDefault)
public:
- DomLayoutDefault();
+ DomLayoutDefault() = default;
~DomLayoutDefault();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeSpacing() const { return m_has_attr_spacing; }
@@ -1115,202 +767,167 @@ public:
inline void setAttributeMargin(int a) { m_attr_margin = a; m_has_attr_margin = true; }
inline void clearAttributeMargin() { m_has_attr_margin = false; }
- // child element accessors
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
- int m_attr_spacing;
- bool m_has_attr_spacing;
-
- int m_attr_margin;
- bool m_has_attr_margin;
+ int m_attr_spacing = 0;
+ bool m_has_attr_spacing = false;
- // child element data
- uint m_children;
-
- DomLayoutDefault(const DomLayoutDefault &other);
- void operator = (const DomLayoutDefault&other);
+ int m_attr_margin = 0;
+ bool m_has_attr_margin = false;
};
class QDESIGNER_UILIB_EXPORT DomLayoutFunction {
+ Q_DISABLE_COPY(DomLayoutFunction)
public:
- DomLayoutFunction();
+ DomLayoutFunction() = default;
~DomLayoutFunction();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeSpacing() const { return m_has_attr_spacing; }
inline QString attributeSpacing() const { return m_attr_spacing; }
- inline void setAttributeSpacing(const QString& a) { m_attr_spacing = a; m_has_attr_spacing = true; }
+ inline void setAttributeSpacing(const QString &a) { m_attr_spacing = a; m_has_attr_spacing = true; }
inline void clearAttributeSpacing() { m_has_attr_spacing = false; }
inline bool hasAttributeMargin() const { return m_has_attr_margin; }
inline QString attributeMargin() const { return m_attr_margin; }
- inline void setAttributeMargin(const QString& a) { m_attr_margin = a; m_has_attr_margin = true; }
+ inline void setAttributeMargin(const QString &a) { m_attr_margin = a; m_has_attr_margin = true; }
inline void clearAttributeMargin() { m_has_attr_margin = false; }
- // child element accessors
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_spacing;
- bool m_has_attr_spacing;
+ bool m_has_attr_spacing = false;
QString m_attr_margin;
- bool m_has_attr_margin;
-
- // child element data
- uint m_children;
-
- DomLayoutFunction(const DomLayoutFunction &other);
- void operator = (const DomLayoutFunction&other);
+ bool m_has_attr_margin = false;
};
class QDESIGNER_UILIB_EXPORT DomTabStops {
+ Q_DISABLE_COPY(DomTabStops)
public:
- DomTabStops();
+ DomTabStops() = default;
~DomTabStops();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline QStringList elementTabStop() const { return m_tabStop; }
- void setElementTabStop(const QStringList& a);
+ void setElementTabStop(const QStringList &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
+ uint m_children = 0;
QStringList m_tabStop;
+
enum Child {
TabStop = 1
};
-
- DomTabStops(const DomTabStops &other);
- void operator = (const DomTabStops&other);
};
class QDESIGNER_UILIB_EXPORT DomLayout {
+ Q_DISABLE_COPY(DomLayout)
public:
- DomLayout();
+ DomLayout() = default;
~DomLayout();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeClass() const { return m_has_attr_class; }
inline QString attributeClass() const { return m_attr_class; }
- inline void setAttributeClass(const QString& a) { m_attr_class = a; m_has_attr_class = true; }
+ inline void setAttributeClass(const QString &a) { m_attr_class = a; m_has_attr_class = true; }
inline void clearAttributeClass() { m_has_attr_class = false; }
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
inline bool hasAttributeStretch() const { return m_has_attr_stretch; }
inline QString attributeStretch() const { return m_attr_stretch; }
- inline void setAttributeStretch(const QString& a) { m_attr_stretch = a; m_has_attr_stretch = true; }
+ inline void setAttributeStretch(const QString &a) { m_attr_stretch = a; m_has_attr_stretch = true; }
inline void clearAttributeStretch() { m_has_attr_stretch = false; }
inline bool hasAttributeRowStretch() const { return m_has_attr_rowStretch; }
inline QString attributeRowStretch() const { return m_attr_rowStretch; }
- inline void setAttributeRowStretch(const QString& a) { m_attr_rowStretch = a; m_has_attr_rowStretch = true; }
+ inline void setAttributeRowStretch(const QString &a) { m_attr_rowStretch = a; m_has_attr_rowStretch = true; }
inline void clearAttributeRowStretch() { m_has_attr_rowStretch = false; }
inline bool hasAttributeColumnStretch() const { return m_has_attr_columnStretch; }
inline QString attributeColumnStretch() const { return m_attr_columnStretch; }
- inline void setAttributeColumnStretch(const QString& a) { m_attr_columnStretch = a; m_has_attr_columnStretch = true; }
+ inline void setAttributeColumnStretch(const QString &a) { m_attr_columnStretch = a; m_has_attr_columnStretch = true; }
inline void clearAttributeColumnStretch() { m_has_attr_columnStretch = false; }
inline bool hasAttributeRowMinimumHeight() const { return m_has_attr_rowMinimumHeight; }
inline QString attributeRowMinimumHeight() const { return m_attr_rowMinimumHeight; }
- inline void setAttributeRowMinimumHeight(const QString& a) { m_attr_rowMinimumHeight = a; m_has_attr_rowMinimumHeight = true; }
+ inline void setAttributeRowMinimumHeight(const QString &a) { m_attr_rowMinimumHeight = a; m_has_attr_rowMinimumHeight = true; }
inline void clearAttributeRowMinimumHeight() { m_has_attr_rowMinimumHeight = false; }
inline bool hasAttributeColumnMinimumWidth() const { return m_has_attr_columnMinimumWidth; }
inline QString attributeColumnMinimumWidth() const { return m_attr_columnMinimumWidth; }
- inline void setAttributeColumnMinimumWidth(const QString& a) { m_attr_columnMinimumWidth = a; m_has_attr_columnMinimumWidth = true; }
+ inline void setAttributeColumnMinimumWidth(const QString &a) { m_attr_columnMinimumWidth = a; m_has_attr_columnMinimumWidth = true; }
inline void clearAttributeColumnMinimumWidth() { m_has_attr_columnMinimumWidth = false; }
// child element accessors
inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
+ void setElementProperty(const QList<DomProperty *> &a);
inline QList<DomProperty*> elementAttribute() const { return m_attribute; }
- void setElementAttribute(const QList<DomProperty*>& a);
+ void setElementAttribute(const QList<DomProperty *> &a);
- inline QList<DomLayoutItem*> elementItem() const { return m_item; }
- void setElementItem(const QList<DomLayoutItem*>& a);
+ inline QVector<DomLayoutItem *> elementItem() const { return m_item; }
+ void setElementItem(const QVector<DomLayoutItem *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_class;
- bool m_has_attr_class;
+ bool m_has_attr_class = false;
QString m_attr_name;
- bool m_has_attr_name;
+ bool m_has_attr_name = false;
QString m_attr_stretch;
- bool m_has_attr_stretch;
+ bool m_has_attr_stretch = false;
QString m_attr_rowStretch;
- bool m_has_attr_rowStretch;
+ bool m_has_attr_rowStretch = false;
QString m_attr_columnStretch;
- bool m_has_attr_columnStretch;
+ bool m_has_attr_columnStretch = false;
QString m_attr_rowMinimumHeight;
- bool m_has_attr_rowMinimumHeight;
+ bool m_has_attr_rowMinimumHeight = false;
QString m_attr_columnMinimumWidth;
- bool m_has_attr_columnMinimumWidth;
+ bool m_has_attr_columnMinimumWidth = false;
// child element data
- uint m_children;
+ uint m_children = 0;
QList<DomProperty*> m_property;
QList<DomProperty*> m_attribute;
- QList<DomLayoutItem*> m_item;
+ QVector<DomLayoutItem *> m_item;
+
enum Child {
Property = 1,
Attribute = 2,
Item = 4
};
-
- DomLayout(const DomLayout &other);
- void operator = (const DomLayout&other);
};
class QDESIGNER_UILIB_EXPORT DomLayoutItem {
+ Q_DISABLE_COPY(DomLayoutItem)
public:
- DomLayoutItem();
+ DomLayoutItem() = default;
~DomLayoutItem();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeRow() const { return m_has_attr_row; }
@@ -1335,126 +952,107 @@ public:
inline bool hasAttributeAlignment() const { return m_has_attr_alignment; }
inline QString attributeAlignment() const { return m_attr_alignment; }
- inline void setAttributeAlignment(const QString& a) { m_attr_alignment = a; m_has_attr_alignment = true; }
+ inline void setAttributeAlignment(const QString &a) { m_attr_alignment = a; m_has_attr_alignment = true; }
inline void clearAttributeAlignment() { m_has_attr_alignment = false; }
// child element accessors
enum Kind { Unknown = 0, Widget, Layout, Spacer };
inline Kind kind() const { return m_kind; }
- inline DomWidget* elementWidget() const { return m_widget; }
- DomWidget* takeElementWidget();
- void setElementWidget(DomWidget* a);
+ inline DomWidget *elementWidget() const { return m_widget; }
+ DomWidget *takeElementWidget();
+ void setElementWidget(DomWidget *a);
- inline DomLayout* elementLayout() const { return m_layout; }
- DomLayout* takeElementLayout();
- void setElementLayout(DomLayout* a);
+ inline DomLayout *elementLayout() const { return m_layout; }
+ DomLayout *takeElementLayout();
+ void setElementLayout(DomLayout *a);
- inline DomSpacer* elementSpacer() const { return m_spacer; }
- DomSpacer* takeElementSpacer();
- void setElementSpacer(DomSpacer* a);
+ inline DomSpacer *elementSpacer() const { return m_spacer; }
+ DomSpacer *takeElementSpacer();
+ void setElementSpacer(DomSpacer *a);
private:
- QString m_text;
- void clear(bool clear_all = true);
+ void clear();
// attribute data
- int m_attr_row;
- bool m_has_attr_row;
+ int m_attr_row = 0;
+ bool m_has_attr_row = false;
- int m_attr_column;
- bool m_has_attr_column;
+ int m_attr_column = 0;
+ bool m_has_attr_column = false;
- int m_attr_rowSpan;
- bool m_has_attr_rowSpan;
+ int m_attr_rowSpan = 0;
+ bool m_has_attr_rowSpan = false;
- int m_attr_colSpan;
- bool m_has_attr_colSpan;
+ int m_attr_colSpan = 0;
+ bool m_has_attr_colSpan = false;
QString m_attr_alignment;
- bool m_has_attr_alignment;
+ bool m_has_attr_alignment = false;
// child element data
- Kind m_kind;
- DomWidget* m_widget;
- DomLayout* m_layout;
- DomSpacer* m_spacer;
-
- DomLayoutItem(const DomLayoutItem &other);
- void operator = (const DomLayoutItem&other);
+ Kind m_kind = Unknown;
+ DomWidget *m_widget = nullptr;
+ DomLayout *m_layout = nullptr;
+ DomSpacer *m_spacer = nullptr;
};
class QDESIGNER_UILIB_EXPORT DomRow {
+ Q_DISABLE_COPY(DomRow)
public:
- DomRow();
+ DomRow() = default;
~DomRow();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
+ void setElementProperty(const QList<DomProperty *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
+ uint m_children = 0;
QList<DomProperty*> m_property;
+
enum Child {
Property = 1
};
-
- DomRow(const DomRow &other);
- void operator = (const DomRow&other);
};
class QDESIGNER_UILIB_EXPORT DomColumn {
+ Q_DISABLE_COPY(DomColumn)
public:
- DomColumn();
+ DomColumn() = default;
~DomColumn();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
+ void setElementProperty(const QList<DomProperty *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
+ uint m_children = 0;
QList<DomProperty*> m_property;
+
enum Child {
Property = 1
};
-
- DomColumn(const DomColumn &other);
- void operator = (const DomColumn&other);
};
class QDESIGNER_UILIB_EXPORT DomItem {
+ Q_DISABLE_COPY(DomItem)
public:
- DomItem();
+ DomItem() = default;
~DomItem();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeRow() const { return m_has_attr_row; }
@@ -1469,54 +1067,48 @@ public:
// child element accessors
inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
+ void setElementProperty(const QList<DomProperty *> &a);
- inline QList<DomItem*> elementItem() const { return m_item; }
- void setElementItem(const QList<DomItem*>& a);
+ inline QVector<DomItem *> elementItem() const { return m_item; }
+ void setElementItem(const QVector<DomItem *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
- int m_attr_row;
- bool m_has_attr_row;
+ int m_attr_row = 0;
+ bool m_has_attr_row = false;
- int m_attr_column;
- bool m_has_attr_column;
+ int m_attr_column = 0;
+ bool m_has_attr_column = false;
// child element data
- uint m_children;
+ uint m_children = 0;
QList<DomProperty*> m_property;
- QList<DomItem*> m_item;
+ QVector<DomItem *> m_item;
+
enum Child {
Property = 1,
Item = 2
};
-
- DomItem(const DomItem &other);
- void operator = (const DomItem&other);
};
class QDESIGNER_UILIB_EXPORT DomWidget {
+ Q_DISABLE_COPY(DomWidget)
public:
- DomWidget();
+ DomWidget() = default;
~DomWidget();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeClass() const { return m_has_attr_class; }
inline QString attributeClass() const { return m_attr_class; }
- inline void setAttributeClass(const QString& a) { m_attr_class = a; m_has_attr_class = true; }
+ inline void setAttributeClass(const QString &a) { m_attr_class = a; m_has_attr_class = true; }
inline void clearAttributeClass() { m_has_attr_class = false; }
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
inline bool hasAttributeNative() const { return m_has_attr_native; }
@@ -1526,146 +1118,124 @@ public:
// child element accessors
inline QStringList elementClass() const { return m_class; }
- void setElementClass(const QStringList& a);
+ void setElementClass(const QStringList &a);
inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
-
- inline QList<DomScript*> elementScript() const { return m_script; }
- void setElementScript(const QList<DomScript*>& a);
-
- inline QList<DomWidgetData*> elementWidgetData() const { return m_widgetData; }
- void setElementWidgetData(const QList<DomWidgetData*>& a);
+ void setElementProperty(const QList<DomProperty *> &a);
inline QList<DomProperty*> elementAttribute() const { return m_attribute; }
- void setElementAttribute(const QList<DomProperty*>& a);
+ void setElementAttribute(const QList<DomProperty *> &a);
- inline QList<DomRow*> elementRow() const { return m_row; }
- void setElementRow(const QList<DomRow*>& a);
+ inline QVector<DomRow *> elementRow() const { return m_row; }
+ void setElementRow(const QVector<DomRow *> &a);
- inline QList<DomColumn*> elementColumn() const { return m_column; }
- void setElementColumn(const QList<DomColumn*>& a);
+ inline QVector<DomColumn *> elementColumn() const { return m_column; }
+ void setElementColumn(const QVector<DomColumn *> &a);
- inline QList<DomItem*> elementItem() const { return m_item; }
- void setElementItem(const QList<DomItem*>& a);
+ inline QVector<DomItem *> elementItem() const { return m_item; }
+ void setElementItem(const QVector<DomItem *> &a);
- inline QList<DomLayout*> elementLayout() const { return m_layout; }
- void setElementLayout(const QList<DomLayout*>& a);
+ inline QVector<DomLayout *> elementLayout() const { return m_layout; }
+ void setElementLayout(const QVector<DomLayout *> &a);
- inline QList<DomWidget*> elementWidget() const { return m_widget; }
- void setElementWidget(const QList<DomWidget*>& a);
+ inline QVector<DomWidget *> elementWidget() const { return m_widget; }
+ void setElementWidget(const QVector<DomWidget *> &a);
- inline QList<DomAction*> elementAction() const { return m_action; }
- void setElementAction(const QList<DomAction*>& a);
+ inline QVector<DomAction *> elementAction() const { return m_action; }
+ void setElementAction(const QVector<DomAction *> &a);
- inline QList<DomActionGroup*> elementActionGroup() const { return m_actionGroup; }
- void setElementActionGroup(const QList<DomActionGroup*>& a);
+ inline QVector<DomActionGroup *> elementActionGroup() const { return m_actionGroup; }
+ void setElementActionGroup(const QVector<DomActionGroup *> &a);
- inline QList<DomActionRef*> elementAddAction() const { return m_addAction; }
- void setElementAddAction(const QList<DomActionRef*>& a);
+ inline QVector<DomActionRef *> elementAddAction() const { return m_addAction; }
+ void setElementAddAction(const QVector<DomActionRef *> &a);
inline QStringList elementZOrder() const { return m_zOrder; }
- void setElementZOrder(const QStringList& a);
+ void setElementZOrder(const QStringList &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_class;
- bool m_has_attr_class;
+ bool m_has_attr_class = false;
QString m_attr_name;
- bool m_has_attr_name;
+ bool m_has_attr_name = false;
- bool m_attr_native;
- bool m_has_attr_native;
+ bool m_attr_native = false;
+ bool m_has_attr_native = false;
// child element data
- uint m_children;
+ uint m_children = 0;
QStringList m_class;
QList<DomProperty*> m_property;
- QList<DomScript*> m_script;
- QList<DomWidgetData*> m_widgetData;
QList<DomProperty*> m_attribute;
- QList<DomRow*> m_row;
- QList<DomColumn*> m_column;
- QList<DomItem*> m_item;
- QList<DomLayout*> m_layout;
- QList<DomWidget*> m_widget;
- QList<DomAction*> m_action;
- QList<DomActionGroup*> m_actionGroup;
- QList<DomActionRef*> m_addAction;
+ QVector<DomRow *> m_row;
+ QVector<DomColumn *> m_column;
+ QVector<DomItem *> m_item;
+ QVector<DomLayout *> m_layout;
+ QVector<DomWidget *> m_widget;
+ QVector<DomAction *> m_action;
+ QVector<DomActionGroup *> m_actionGroup;
+ QVector<DomActionRef *> m_addAction;
QStringList m_zOrder;
+
enum Child {
Class = 1,
Property = 2,
- Script = 4,
- WidgetData = 8,
- Attribute = 16,
- Row = 32,
- Column = 64,
- Item = 128,
- Layout = 256,
- Widget = 512,
- Action = 1024,
- ActionGroup = 2048,
- AddAction = 4096,
- ZOrder = 8192
+ Attribute = 4,
+ Row = 8,
+ Column = 16,
+ Item = 32,
+ Layout = 64,
+ Widget = 128,
+ Action = 256,
+ ActionGroup = 512,
+ AddAction = 1024,
+ ZOrder = 2048
};
-
- DomWidget(const DomWidget &other);
- void operator = (const DomWidget&other);
};
class QDESIGNER_UILIB_EXPORT DomSpacer {
+ Q_DISABLE_COPY(DomSpacer)
public:
- DomSpacer();
+ DomSpacer() = default;
~DomSpacer();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
// child element accessors
inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
+ void setElementProperty(const QList<DomProperty *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_name;
- bool m_has_attr_name;
+ bool m_has_attr_name = false;
// child element data
- uint m_children;
+ uint m_children = 0;
QList<DomProperty*> m_property;
+
enum Child {
Property = 1
};
-
- DomSpacer(const DomSpacer &other);
- void operator = (const DomSpacer&other);
};
class QDESIGNER_UILIB_EXPORT DomColor {
+ Q_DISABLE_COPY(DomColor)
public:
- DomColor();
+ DomColor() = default;
~DomColor();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeAlpha() const { return m_has_attr_alpha; }
@@ -1690,37 +1260,31 @@ public:
void clearElementBlue();
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
- int m_attr_alpha;
- bool m_has_attr_alpha;
+ int m_attr_alpha = 0;
+ bool m_has_attr_alpha = false;
// child element data
- uint m_children;
- int m_red;
- int m_green;
- int m_blue;
+ uint m_children = 0;
+ int m_red = 0;
+ int m_green = 0;
+ int m_blue = 0;
+
enum Child {
Red = 1,
Green = 2,
Blue = 4
};
-
- DomColor(const DomColor &other);
- void operator = (const DomColor&other);
};
class QDESIGNER_UILIB_EXPORT DomGradientStop {
+ Q_DISABLE_COPY(DomGradientStop)
public:
- DomGradientStop();
+ DomGradientStop() = default;
~DomGradientStop();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributePosition() const { return m_has_attr_position; }
@@ -1729,40 +1293,34 @@ public:
inline void clearAttributePosition() { m_has_attr_position = false; }
// child element accessors
- inline DomColor* elementColor() const { return m_color; }
- DomColor* takeElementColor();
- void setElementColor(DomColor* a);
+ inline DomColor *elementColor() const { return m_color; }
+ DomColor *takeElementColor();
+ void setElementColor(DomColor *a);
inline bool hasElementColor() const { return m_children & Color; }
void clearElementColor();
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
- double m_attr_position;
- bool m_has_attr_position;
+ double m_attr_position = 0.0;
+ bool m_has_attr_position = false;
// child element data
- uint m_children;
- DomColor* m_color;
+ uint m_children = 0;
+ DomColor *m_color = nullptr;
+
enum Child {
Color = 1
};
-
- DomGradientStop(const DomGradientStop &other);
- void operator = (const DomGradientStop&other);
};
class QDESIGNER_UILIB_EXPORT DomGradient {
+ Q_DISABLE_COPY(DomGradient)
public:
- DomGradient();
+ DomGradient() = default;
~DomGradient();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeStartX() const { return m_has_attr_startX; }
@@ -1817,270 +1375,238 @@ public:
inline bool hasAttributeType() const { return m_has_attr_type; }
inline QString attributeType() const { return m_attr_type; }
- inline void setAttributeType(const QString& a) { m_attr_type = a; m_has_attr_type = true; }
+ inline void setAttributeType(const QString &a) { m_attr_type = a; m_has_attr_type = true; }
inline void clearAttributeType() { m_has_attr_type = false; }
inline bool hasAttributeSpread() const { return m_has_attr_spread; }
inline QString attributeSpread() const { return m_attr_spread; }
- inline void setAttributeSpread(const QString& a) { m_attr_spread = a; m_has_attr_spread = true; }
+ inline void setAttributeSpread(const QString &a) { m_attr_spread = a; m_has_attr_spread = true; }
inline void clearAttributeSpread() { m_has_attr_spread = false; }
inline bool hasAttributeCoordinateMode() const { return m_has_attr_coordinateMode; }
inline QString attributeCoordinateMode() const { return m_attr_coordinateMode; }
- inline void setAttributeCoordinateMode(const QString& a) { m_attr_coordinateMode = a; m_has_attr_coordinateMode = true; }
+ inline void setAttributeCoordinateMode(const QString &a) { m_attr_coordinateMode = a; m_has_attr_coordinateMode = true; }
inline void clearAttributeCoordinateMode() { m_has_attr_coordinateMode = false; }
// child element accessors
- inline QList<DomGradientStop*> elementGradientStop() const { return m_gradientStop; }
- void setElementGradientStop(const QList<DomGradientStop*>& a);
+ inline QVector<DomGradientStop *> elementGradientStop() const { return m_gradientStop; }
+ void setElementGradientStop(const QVector<DomGradientStop *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
- double m_attr_startX;
- bool m_has_attr_startX;
+ double m_attr_startX = 0.0;
+ bool m_has_attr_startX = false;
- double m_attr_startY;
- bool m_has_attr_startY;
+ double m_attr_startY = 0.0;
+ bool m_has_attr_startY = false;
- double m_attr_endX;
- bool m_has_attr_endX;
+ double m_attr_endX = 0.0;
+ bool m_has_attr_endX = false;
- double m_attr_endY;
- bool m_has_attr_endY;
+ double m_attr_endY = 0.0;
+ bool m_has_attr_endY = false;
- double m_attr_centralX;
- bool m_has_attr_centralX;
+ double m_attr_centralX = 0.0;
+ bool m_has_attr_centralX = false;
- double m_attr_centralY;
- bool m_has_attr_centralY;
+ double m_attr_centralY = 0.0;
+ bool m_has_attr_centralY = false;
- double m_attr_focalX;
- bool m_has_attr_focalX;
+ double m_attr_focalX = 0.0;
+ bool m_has_attr_focalX = false;
- double m_attr_focalY;
- bool m_has_attr_focalY;
+ double m_attr_focalY = 0.0;
+ bool m_has_attr_focalY = false;
- double m_attr_radius;
- bool m_has_attr_radius;
+ double m_attr_radius = 0.0;
+ bool m_has_attr_radius = false;
- double m_attr_angle;
- bool m_has_attr_angle;
+ double m_attr_angle = 0.0;
+ bool m_has_attr_angle = false;
QString m_attr_type;
- bool m_has_attr_type;
+ bool m_has_attr_type = false;
QString m_attr_spread;
- bool m_has_attr_spread;
+ bool m_has_attr_spread = false;
QString m_attr_coordinateMode;
- bool m_has_attr_coordinateMode;
+ bool m_has_attr_coordinateMode = false;
// child element data
- uint m_children;
- QList<DomGradientStop*> m_gradientStop;
+ uint m_children = 0;
+ QVector<DomGradientStop *> m_gradientStop;
+
enum Child {
GradientStop = 1
};
-
- DomGradient(const DomGradient &other);
- void operator = (const DomGradient&other);
};
class QDESIGNER_UILIB_EXPORT DomBrush {
+ Q_DISABLE_COPY(DomBrush)
public:
- DomBrush();
+ DomBrush() = default;
~DomBrush();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeBrushStyle() const { return m_has_attr_brushStyle; }
inline QString attributeBrushStyle() const { return m_attr_brushStyle; }
- inline void setAttributeBrushStyle(const QString& a) { m_attr_brushStyle = a; m_has_attr_brushStyle = true; }
+ inline void setAttributeBrushStyle(const QString &a) { m_attr_brushStyle = a; m_has_attr_brushStyle = true; }
inline void clearAttributeBrushStyle() { m_has_attr_brushStyle = false; }
// child element accessors
enum Kind { Unknown = 0, Color, Texture, Gradient };
inline Kind kind() const { return m_kind; }
- inline DomColor* elementColor() const { return m_color; }
- DomColor* takeElementColor();
- void setElementColor(DomColor* a);
+ inline DomColor *elementColor() const { return m_color; }
+ DomColor *takeElementColor();
+ void setElementColor(DomColor *a);
- inline DomProperty* elementTexture() const { return m_texture; }
- DomProperty* takeElementTexture();
- void setElementTexture(DomProperty* a);
+ inline DomProperty *elementTexture() const { return m_texture; }
+ DomProperty *takeElementTexture();
+ void setElementTexture(DomProperty *a);
- inline DomGradient* elementGradient() const { return m_gradient; }
- DomGradient* takeElementGradient();
- void setElementGradient(DomGradient* a);
+ inline DomGradient *elementGradient() const { return m_gradient; }
+ DomGradient *takeElementGradient();
+ void setElementGradient(DomGradient *a);
private:
- QString m_text;
- void clear(bool clear_all = true);
+ void clear();
// attribute data
QString m_attr_brushStyle;
- bool m_has_attr_brushStyle;
+ bool m_has_attr_brushStyle = false;
// child element data
- Kind m_kind;
- DomColor* m_color;
- DomProperty* m_texture;
- DomGradient* m_gradient;
-
- DomBrush(const DomBrush &other);
- void operator = (const DomBrush&other);
+ Kind m_kind = Unknown;
+ DomColor *m_color = nullptr;
+ DomProperty *m_texture = nullptr;
+ DomGradient *m_gradient = nullptr;
};
class QDESIGNER_UILIB_EXPORT DomColorRole {
+ Q_DISABLE_COPY(DomColorRole)
public:
- DomColorRole();
+ DomColorRole() = default;
~DomColorRole();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeRole() const { return m_has_attr_role; }
inline QString attributeRole() const { return m_attr_role; }
- inline void setAttributeRole(const QString& a) { m_attr_role = a; m_has_attr_role = true; }
+ inline void setAttributeRole(const QString &a) { m_attr_role = a; m_has_attr_role = true; }
inline void clearAttributeRole() { m_has_attr_role = false; }
// child element accessors
- inline DomBrush* elementBrush() const { return m_brush; }
- DomBrush* takeElementBrush();
- void setElementBrush(DomBrush* a);
+ inline DomBrush *elementBrush() const { return m_brush; }
+ DomBrush *takeElementBrush();
+ void setElementBrush(DomBrush *a);
inline bool hasElementBrush() const { return m_children & Brush; }
void clearElementBrush();
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_role;
- bool m_has_attr_role;
+ bool m_has_attr_role = false;
// child element data
- uint m_children;
- DomBrush* m_brush;
+ uint m_children = 0;
+ DomBrush *m_brush = nullptr;
+
enum Child {
Brush = 1
};
-
- DomColorRole(const DomColorRole &other);
- void operator = (const DomColorRole&other);
};
class QDESIGNER_UILIB_EXPORT DomColorGroup {
+ Q_DISABLE_COPY(DomColorGroup)
public:
- DomColorGroup();
+ DomColorGroup() = default;
~DomColorGroup();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
- inline QList<DomColorRole*> elementColorRole() const { return m_colorRole; }
- void setElementColorRole(const QList<DomColorRole*>& a);
+ inline QVector<DomColorRole *> elementColorRole() const { return m_colorRole; }
+ void setElementColorRole(const QVector<DomColorRole *> &a);
- inline QList<DomColor*> elementColor() const { return m_color; }
- void setElementColor(const QList<DomColor*>& a);
+ inline QVector<DomColor *> elementColor() const { return m_color; }
+ void setElementColor(const QVector<DomColor *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- QList<DomColorRole*> m_colorRole;
- QList<DomColor*> m_color;
+ uint m_children = 0;
+ QVector<DomColorRole *> m_colorRole;
+ QVector<DomColor *> m_color;
+
enum Child {
ColorRole = 1,
Color = 2
};
-
- DomColorGroup(const DomColorGroup &other);
- void operator = (const DomColorGroup&other);
};
class QDESIGNER_UILIB_EXPORT DomPalette {
+ Q_DISABLE_COPY(DomPalette)
public:
- DomPalette();
+ DomPalette() = default;
~DomPalette();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
- inline DomColorGroup* elementActive() const { return m_active; }
- DomColorGroup* takeElementActive();
- void setElementActive(DomColorGroup* a);
+ inline DomColorGroup *elementActive() const { return m_active; }
+ DomColorGroup *takeElementActive();
+ void setElementActive(DomColorGroup *a);
inline bool hasElementActive() const { return m_children & Active; }
void clearElementActive();
- inline DomColorGroup* elementInactive() const { return m_inactive; }
- DomColorGroup* takeElementInactive();
- void setElementInactive(DomColorGroup* a);
+ inline DomColorGroup *elementInactive() const { return m_inactive; }
+ DomColorGroup *takeElementInactive();
+ void setElementInactive(DomColorGroup *a);
inline bool hasElementInactive() const { return m_children & Inactive; }
void clearElementInactive();
- inline DomColorGroup* elementDisabled() const { return m_disabled; }
- DomColorGroup* takeElementDisabled();
- void setElementDisabled(DomColorGroup* a);
+ inline DomColorGroup *elementDisabled() const { return m_disabled; }
+ DomColorGroup *takeElementDisabled();
+ void setElementDisabled(DomColorGroup *a);
inline bool hasElementDisabled() const { return m_children & Disabled; }
void clearElementDisabled();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- DomColorGroup* m_active;
- DomColorGroup* m_inactive;
- DomColorGroup* m_disabled;
+ uint m_children = 0;
+ DomColorGroup *m_active = nullptr;
+ DomColorGroup *m_inactive = nullptr;
+ DomColorGroup *m_disabled = nullptr;
+
enum Child {
Active = 1,
Inactive = 2,
Disabled = 4
};
-
- DomPalette(const DomPalette &other);
- void operator = (const DomPalette&other);
};
class QDESIGNER_UILIB_EXPORT DomFont {
+ Q_DISABLE_COPY(DomFont)
public:
- DomFont();
+ DomFont() = default;
~DomFont();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline QString elementFamily() const { return m_family; }
- void setElementFamily(const QString& a);
+ void setElementFamily(const QString &a);
inline bool hasElementFamily() const { return m_children & Family; }
void clearElementFamily();
@@ -2120,7 +1646,7 @@ public:
void clearElementAntialiasing();
inline QString elementStyleStrategy() const { return m_styleStrategy; }
- void setElementStyleStrategy(const QString& a);
+ void setElementStyleStrategy(const QString &a);
inline bool hasElementStyleStrategy() const { return m_children & StyleStrategy; }
void clearElementStyleStrategy();
@@ -2130,22 +1656,20 @@ public:
void clearElementKerning();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
+ uint m_children = 0;
QString m_family;
- int m_pointSize;
- int m_weight;
- bool m_italic;
- bool m_bold;
- bool m_underline;
- bool m_strikeOut;
- bool m_antialiasing;
+ int m_pointSize = 0;
+ int m_weight = 0;
+ bool m_italic = false;
+ bool m_bold = false;
+ bool m_underline = false;
+ bool m_strikeOut = false;
+ bool m_antialiasing = false;
QString m_styleStrategy;
- bool m_kerning;
+ bool m_kerning = false;
+
enum Child {
Family = 1,
PointSize = 2,
@@ -2158,22 +1682,17 @@ private:
StyleStrategy = 256,
Kerning = 512
};
-
- DomFont(const DomFont &other);
- void operator = (const DomFont&other);
};
class QDESIGNER_UILIB_EXPORT DomPoint {
+ Q_DISABLE_COPY(DomPoint)
public:
- DomPoint();
+ DomPoint() = default;
~DomPoint();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline int elementX() const { return m_x; }
void setElementX(int a);
@@ -2186,34 +1705,27 @@ public:
void clearElementY();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- int m_x;
- int m_y;
+ uint m_children = 0;
+ int m_x = 0;
+ int m_y = 0;
+
enum Child {
X = 1,
Y = 2
};
-
- DomPoint(const DomPoint &other);
- void operator = (const DomPoint&other);
};
class QDESIGNER_UILIB_EXPORT DomRect {
+ Q_DISABLE_COPY(DomRect)
public:
- DomRect();
+ DomRect() = default;
~DomRect();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline int elementX() const { return m_x; }
void setElementX(int a);
@@ -2236,86 +1748,69 @@ public:
void clearElementHeight();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- int m_x;
- int m_y;
- int m_width;
- int m_height;
+ uint m_children = 0;
+ int m_x = 0;
+ int m_y = 0;
+ int m_width = 0;
+ int m_height = 0;
+
enum Child {
X = 1,
Y = 2,
Width = 4,
Height = 8
};
-
- DomRect(const DomRect &other);
- void operator = (const DomRect&other);
};
class QDESIGNER_UILIB_EXPORT DomLocale {
+ Q_DISABLE_COPY(DomLocale)
public:
- DomLocale();
+ DomLocale() = default;
~DomLocale();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeLanguage() const { return m_has_attr_language; }
inline QString attributeLanguage() const { return m_attr_language; }
- inline void setAttributeLanguage(const QString& a) { m_attr_language = a; m_has_attr_language = true; }
+ inline void setAttributeLanguage(const QString &a) { m_attr_language = a; m_has_attr_language = true; }
inline void clearAttributeLanguage() { m_has_attr_language = false; }
inline bool hasAttributeCountry() const { return m_has_attr_country; }
inline QString attributeCountry() const { return m_attr_country; }
- inline void setAttributeCountry(const QString& a) { m_attr_country = a; m_has_attr_country = true; }
+ inline void setAttributeCountry(const QString &a) { m_attr_country = a; m_has_attr_country = true; }
inline void clearAttributeCountry() { m_has_attr_country = false; }
- // child element accessors
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_language;
- bool m_has_attr_language;
+ bool m_has_attr_language = false;
QString m_attr_country;
- bool m_has_attr_country;
-
- // child element data
- uint m_children;
-
- DomLocale(const DomLocale &other);
- void operator = (const DomLocale&other);
+ bool m_has_attr_country = false;
};
class QDESIGNER_UILIB_EXPORT DomSizePolicy {
+ Q_DISABLE_COPY(DomSizePolicy)
public:
- DomSizePolicy();
+ DomSizePolicy() = default;
~DomSizePolicy();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeHSizeType() const { return m_has_attr_hSizeType; }
inline QString attributeHSizeType() const { return m_attr_hSizeType; }
- inline void setAttributeHSizeType(const QString& a) { m_attr_hSizeType = a; m_has_attr_hSizeType = true; }
+ inline void setAttributeHSizeType(const QString &a) { m_attr_hSizeType = a; m_has_attr_hSizeType = true; }
inline void clearAttributeHSizeType() { m_has_attr_hSizeType = false; }
inline bool hasAttributeVSizeType() const { return m_has_attr_vSizeType; }
inline QString attributeVSizeType() const { return m_attr_vSizeType; }
- inline void setAttributeVSizeType(const QString& a) { m_attr_vSizeType = a; m_has_attr_vSizeType = true; }
+ inline void setAttributeVSizeType(const QString &a) { m_attr_vSizeType = a; m_has_attr_vSizeType = true; }
inline void clearAttributeVSizeType() { m_has_attr_vSizeType = false; }
// child element accessors
@@ -2340,44 +1835,37 @@ public:
void clearElementVerStretch();
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_hSizeType;
- bool m_has_attr_hSizeType;
+ bool m_has_attr_hSizeType = false;
QString m_attr_vSizeType;
- bool m_has_attr_vSizeType;
+ bool m_has_attr_vSizeType = false;
// child element data
- uint m_children;
- int m_hSizeType;
- int m_vSizeType;
- int m_horStretch;
- int m_verStretch;
+ uint m_children = 0;
+ int m_hSizeType = 0;
+ int m_vSizeType = 0;
+ int m_horStretch = 0;
+ int m_verStretch = 0;
+
enum Child {
HSizeType = 1,
VSizeType = 2,
HorStretch = 4,
VerStretch = 8
};
-
- DomSizePolicy(const DomSizePolicy &other);
- void operator = (const DomSizePolicy&other);
};
class QDESIGNER_UILIB_EXPORT DomSize {
+ Q_DISABLE_COPY(DomSize)
public:
- DomSize();
+ DomSize() = default;
~DomSize();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline int elementWidth() const { return m_width; }
void setElementWidth(int a);
@@ -2390,34 +1878,27 @@ public:
void clearElementHeight();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- int m_width;
- int m_height;
+ uint m_children = 0;
+ int m_width = 0;
+ int m_height = 0;
+
enum Child {
Width = 1,
Height = 2
};
-
- DomSize(const DomSize &other);
- void operator = (const DomSize&other);
};
class QDESIGNER_UILIB_EXPORT DomDate {
+ Q_DISABLE_COPY(DomDate)
public:
- DomDate();
+ DomDate() = default;
~DomDate();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline int elementYear() const { return m_year; }
void setElementYear(int a);
@@ -2435,36 +1916,29 @@ public:
void clearElementDay();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- int m_year;
- int m_month;
- int m_day;
+ uint m_children = 0;
+ int m_year = 0;
+ int m_month = 0;
+ int m_day = 0;
+
enum Child {
Year = 1,
Month = 2,
Day = 4
};
-
- DomDate(const DomDate &other);
- void operator = (const DomDate&other);
};
class QDESIGNER_UILIB_EXPORT DomTime {
+ Q_DISABLE_COPY(DomTime)
public:
- DomTime();
+ DomTime() = default;
~DomTime();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline int elementHour() const { return m_hour; }
void setElementHour(int a);
@@ -2482,36 +1956,29 @@ public:
void clearElementSecond();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- int m_hour;
- int m_minute;
- int m_second;
+ uint m_children = 0;
+ int m_hour = 0;
+ int m_minute = 0;
+ int m_second = 0;
+
enum Child {
Hour = 1,
Minute = 2,
Second = 4
};
-
- DomTime(const DomTime &other);
- void operator = (const DomTime&other);
};
class QDESIGNER_UILIB_EXPORT DomDateTime {
+ Q_DISABLE_COPY(DomDateTime)
public:
- DomDateTime();
+ DomDateTime() = default;
~DomDateTime();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline int elementHour() const { return m_hour; }
void setElementHour(int a);
@@ -2544,18 +2011,16 @@ public:
void clearElementDay();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- int m_hour;
- int m_minute;
- int m_second;
- int m_year;
- int m_month;
- int m_day;
+ uint m_children = 0;
+ int m_hour = 0;
+ int m_minute = 0;
+ int m_second = 0;
+ int m_year = 0;
+ int m_month = 0;
+ int m_day = 0;
+
enum Child {
Hour = 1,
Minute = 2,
@@ -2564,197 +2029,184 @@ private:
Month = 16,
Day = 32
};
-
- DomDateTime(const DomDateTime &other);
- void operator = (const DomDateTime&other);
};
class QDESIGNER_UILIB_EXPORT DomStringList {
+ Q_DISABLE_COPY(DomStringList)
public:
- DomStringList();
+ DomStringList() = default;
~DomStringList();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeNotr() const { return m_has_attr_notr; }
inline QString attributeNotr() const { return m_attr_notr; }
- inline void setAttributeNotr(const QString& a) { m_attr_notr = a; m_has_attr_notr = true; }
+ inline void setAttributeNotr(const QString &a) { m_attr_notr = a; m_has_attr_notr = true; }
inline void clearAttributeNotr() { m_has_attr_notr = false; }
inline bool hasAttributeComment() const { return m_has_attr_comment; }
inline QString attributeComment() const { return m_attr_comment; }
- inline void setAttributeComment(const QString& a) { m_attr_comment = a; m_has_attr_comment = true; }
+ inline void setAttributeComment(const QString &a) { m_attr_comment = a; m_has_attr_comment = true; }
inline void clearAttributeComment() { m_has_attr_comment = false; }
inline bool hasAttributeExtraComment() const { return m_has_attr_extraComment; }
inline QString attributeExtraComment() const { return m_attr_extraComment; }
- inline void setAttributeExtraComment(const QString& a) { m_attr_extraComment = a; m_has_attr_extraComment = true; }
+ inline void setAttributeExtraComment(const QString &a) { m_attr_extraComment = a; m_has_attr_extraComment = true; }
inline void clearAttributeExtraComment() { m_has_attr_extraComment = false; }
// child element accessors
inline QStringList elementString() const { return m_string; }
- void setElementString(const QStringList& a);
+ void setElementString(const QStringList &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_notr;
- bool m_has_attr_notr;
+ bool m_has_attr_notr = false;
QString m_attr_comment;
- bool m_has_attr_comment;
+ bool m_has_attr_comment = false;
QString m_attr_extraComment;
- bool m_has_attr_extraComment;
+ bool m_has_attr_extraComment = false;
// child element data
- uint m_children;
+ uint m_children = 0;
QStringList m_string;
+
enum Child {
String = 1
};
-
- DomStringList(const DomStringList &other);
- void operator = (const DomStringList&other);
};
class QDESIGNER_UILIB_EXPORT DomResourcePixmap {
+ Q_DISABLE_COPY(DomResourcePixmap)
public:
- DomResourcePixmap();
+ DomResourcePixmap() = default;
~DomResourcePixmap();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+
inline QString text() const { return m_text; }
inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeResource() const { return m_has_attr_resource; }
inline QString attributeResource() const { return m_attr_resource; }
- inline void setAttributeResource(const QString& a) { m_attr_resource = a; m_has_attr_resource = true; }
+ inline void setAttributeResource(const QString &a) { m_attr_resource = a; m_has_attr_resource = true; }
inline void clearAttributeResource() { m_has_attr_resource = false; }
inline bool hasAttributeAlias() const { return m_has_attr_alias; }
inline QString attributeAlias() const { return m_attr_alias; }
- inline void setAttributeAlias(const QString& a) { m_attr_alias = a; m_has_attr_alias = true; }
+ inline void setAttributeAlias(const QString &a) { m_attr_alias = a; m_has_attr_alias = true; }
inline void clearAttributeAlias() { m_has_attr_alias = false; }
- // child element accessors
private:
QString m_text;
- void clear(bool clear_all = true);
// attribute data
QString m_attr_resource;
- bool m_has_attr_resource;
+ bool m_has_attr_resource = false;
QString m_attr_alias;
- bool m_has_attr_alias;
-
- // child element data
- uint m_children;
-
- DomResourcePixmap(const DomResourcePixmap &other);
- void operator = (const DomResourcePixmap&other);
+ bool m_has_attr_alias = false;
};
class QDESIGNER_UILIB_EXPORT DomResourceIcon {
+ Q_DISABLE_COPY(DomResourceIcon)
public:
- DomResourceIcon();
+ DomResourceIcon() = default;
~DomResourceIcon();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+
inline QString text() const { return m_text; }
inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeTheme() const { return m_has_attr_theme; }
inline QString attributeTheme() const { return m_attr_theme; }
- inline void setAttributeTheme(const QString& a) { m_attr_theme = a; m_has_attr_theme = true; }
+ inline void setAttributeTheme(const QString &a) { m_attr_theme = a; m_has_attr_theme = true; }
inline void clearAttributeTheme() { m_has_attr_theme = false; }
inline bool hasAttributeResource() const { return m_has_attr_resource; }
inline QString attributeResource() const { return m_attr_resource; }
- inline void setAttributeResource(const QString& a) { m_attr_resource = a; m_has_attr_resource = true; }
+ inline void setAttributeResource(const QString &a) { m_attr_resource = a; m_has_attr_resource = true; }
inline void clearAttributeResource() { m_has_attr_resource = false; }
// child element accessors
- inline DomResourcePixmap* elementNormalOff() const { return m_normalOff; }
- DomResourcePixmap* takeElementNormalOff();
- void setElementNormalOff(DomResourcePixmap* a);
+ inline DomResourcePixmap *elementNormalOff() const { return m_normalOff; }
+ DomResourcePixmap *takeElementNormalOff();
+ void setElementNormalOff(DomResourcePixmap *a);
inline bool hasElementNormalOff() const { return m_children & NormalOff; }
void clearElementNormalOff();
- inline DomResourcePixmap* elementNormalOn() const { return m_normalOn; }
- DomResourcePixmap* takeElementNormalOn();
- void setElementNormalOn(DomResourcePixmap* a);
+ inline DomResourcePixmap *elementNormalOn() const { return m_normalOn; }
+ DomResourcePixmap *takeElementNormalOn();
+ void setElementNormalOn(DomResourcePixmap *a);
inline bool hasElementNormalOn() const { return m_children & NormalOn; }
void clearElementNormalOn();
- inline DomResourcePixmap* elementDisabledOff() const { return m_disabledOff; }
- DomResourcePixmap* takeElementDisabledOff();
- void setElementDisabledOff(DomResourcePixmap* a);
+ inline DomResourcePixmap *elementDisabledOff() const { return m_disabledOff; }
+ DomResourcePixmap *takeElementDisabledOff();
+ void setElementDisabledOff(DomResourcePixmap *a);
inline bool hasElementDisabledOff() const { return m_children & DisabledOff; }
void clearElementDisabledOff();
- inline DomResourcePixmap* elementDisabledOn() const { return m_disabledOn; }
- DomResourcePixmap* takeElementDisabledOn();
- void setElementDisabledOn(DomResourcePixmap* a);
+ inline DomResourcePixmap *elementDisabledOn() const { return m_disabledOn; }
+ DomResourcePixmap *takeElementDisabledOn();
+ void setElementDisabledOn(DomResourcePixmap *a);
inline bool hasElementDisabledOn() const { return m_children & DisabledOn; }
void clearElementDisabledOn();
- inline DomResourcePixmap* elementActiveOff() const { return m_activeOff; }
- DomResourcePixmap* takeElementActiveOff();
- void setElementActiveOff(DomResourcePixmap* a);
+ inline DomResourcePixmap *elementActiveOff() const { return m_activeOff; }
+ DomResourcePixmap *takeElementActiveOff();
+ void setElementActiveOff(DomResourcePixmap *a);
inline bool hasElementActiveOff() const { return m_children & ActiveOff; }
void clearElementActiveOff();
- inline DomResourcePixmap* elementActiveOn() const { return m_activeOn; }
- DomResourcePixmap* takeElementActiveOn();
- void setElementActiveOn(DomResourcePixmap* a);
+ inline DomResourcePixmap *elementActiveOn() const { return m_activeOn; }
+ DomResourcePixmap *takeElementActiveOn();
+ void setElementActiveOn(DomResourcePixmap *a);
inline bool hasElementActiveOn() const { return m_children & ActiveOn; }
void clearElementActiveOn();
- inline DomResourcePixmap* elementSelectedOff() const { return m_selectedOff; }
- DomResourcePixmap* takeElementSelectedOff();
- void setElementSelectedOff(DomResourcePixmap* a);
+ inline DomResourcePixmap *elementSelectedOff() const { return m_selectedOff; }
+ DomResourcePixmap *takeElementSelectedOff();
+ void setElementSelectedOff(DomResourcePixmap *a);
inline bool hasElementSelectedOff() const { return m_children & SelectedOff; }
void clearElementSelectedOff();
- inline DomResourcePixmap* elementSelectedOn() const { return m_selectedOn; }
- DomResourcePixmap* takeElementSelectedOn();
- void setElementSelectedOn(DomResourcePixmap* a);
+ inline DomResourcePixmap *elementSelectedOn() const { return m_selectedOn; }
+ DomResourcePixmap *takeElementSelectedOn();
+ void setElementSelectedOn(DomResourcePixmap *a);
inline bool hasElementSelectedOn() const { return m_children & SelectedOn; }
void clearElementSelectedOn();
private:
QString m_text;
- void clear(bool clear_all = true);
// attribute data
QString m_attr_theme;
- bool m_has_attr_theme;
+ bool m_has_attr_theme = false;
QString m_attr_resource;
- bool m_has_attr_resource;
+ bool m_has_attr_resource = false;
// child element data
- uint m_children;
- DomResourcePixmap* m_normalOff;
- DomResourcePixmap* m_normalOn;
- DomResourcePixmap* m_disabledOff;
- DomResourcePixmap* m_disabledOn;
- DomResourcePixmap* m_activeOff;
- DomResourcePixmap* m_activeOn;
- DomResourcePixmap* m_selectedOff;
- DomResourcePixmap* m_selectedOn;
+ uint m_children = 0;
+ DomResourcePixmap *m_normalOff = nullptr;
+ DomResourcePixmap *m_normalOn = nullptr;
+ DomResourcePixmap *m_disabledOff = nullptr;
+ DomResourcePixmap *m_disabledOn = nullptr;
+ DomResourcePixmap *m_activeOff = nullptr;
+ DomResourcePixmap *m_activeOn = nullptr;
+ DomResourcePixmap *m_selectedOff = nullptr;
+ DomResourcePixmap *m_selectedOn = nullptr;
+
enum Child {
NormalOff = 1,
NormalOn = 2,
@@ -2765,70 +2217,59 @@ private:
SelectedOff = 64,
SelectedOn = 128
};
-
- DomResourceIcon(const DomResourceIcon &other);
- void operator = (const DomResourceIcon&other);
};
class QDESIGNER_UILIB_EXPORT DomString {
+ Q_DISABLE_COPY(DomString)
public:
- DomString();
+ DomString() = default;
~DomString();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+
inline QString text() const { return m_text; }
inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeNotr() const { return m_has_attr_notr; }
inline QString attributeNotr() const { return m_attr_notr; }
- inline void setAttributeNotr(const QString& a) { m_attr_notr = a; m_has_attr_notr = true; }
+ inline void setAttributeNotr(const QString &a) { m_attr_notr = a; m_has_attr_notr = true; }
inline void clearAttributeNotr() { m_has_attr_notr = false; }
inline bool hasAttributeComment() const { return m_has_attr_comment; }
inline QString attributeComment() const { return m_attr_comment; }
- inline void setAttributeComment(const QString& a) { m_attr_comment = a; m_has_attr_comment = true; }
+ inline void setAttributeComment(const QString &a) { m_attr_comment = a; m_has_attr_comment = true; }
inline void clearAttributeComment() { m_has_attr_comment = false; }
inline bool hasAttributeExtraComment() const { return m_has_attr_extraComment; }
inline QString attributeExtraComment() const { return m_attr_extraComment; }
- inline void setAttributeExtraComment(const QString& a) { m_attr_extraComment = a; m_has_attr_extraComment = true; }
+ inline void setAttributeExtraComment(const QString &a) { m_attr_extraComment = a; m_has_attr_extraComment = true; }
inline void clearAttributeExtraComment() { m_has_attr_extraComment = false; }
- // child element accessors
private:
QString m_text;
- void clear(bool clear_all = true);
// attribute data
QString m_attr_notr;
- bool m_has_attr_notr;
+ bool m_has_attr_notr = false;
QString m_attr_comment;
- bool m_has_attr_comment;
+ bool m_has_attr_comment = false;
QString m_attr_extraComment;
- bool m_has_attr_extraComment;
-
- // child element data
- uint m_children;
-
- DomString(const DomString &other);
- void operator = (const DomString&other);
+ bool m_has_attr_extraComment = false;
};
class QDESIGNER_UILIB_EXPORT DomPointF {
+ Q_DISABLE_COPY(DomPointF)
public:
- DomPointF();
+ DomPointF() = default;
~DomPointF();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline double elementX() const { return m_x; }
void setElementX(double a);
@@ -2841,34 +2282,27 @@ public:
void clearElementY();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- double m_x;
- double m_y;
+ uint m_children = 0;
+ double m_x = 0.0;
+ double m_y = 0.0;
+
enum Child {
X = 1,
Y = 2
};
-
- DomPointF(const DomPointF &other);
- void operator = (const DomPointF&other);
};
class QDESIGNER_UILIB_EXPORT DomRectF {
+ Q_DISABLE_COPY(DomRectF)
public:
- DomRectF();
+ DomRectF() = default;
~DomRectF();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline double elementX() const { return m_x; }
void setElementX(double a);
@@ -2891,38 +2325,31 @@ public:
void clearElementHeight();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- double m_x;
- double m_y;
- double m_width;
- double m_height;
+ uint m_children = 0;
+ double m_x = 0.0;
+ double m_y = 0.0;
+ double m_width = 0.0;
+ double m_height = 0.0;
+
enum Child {
X = 1,
Y = 2,
Width = 4,
Height = 8
};
-
- DomRectF(const DomRectF &other);
- void operator = (const DomRectF&other);
};
class QDESIGNER_UILIB_EXPORT DomSizeF {
+ Q_DISABLE_COPY(DomSizeF)
public:
- DomSizeF();
+ DomSizeF() = default;
~DomSizeF();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline double elementWidth() const { return m_width; }
void setElementWidth(double a);
@@ -2935,34 +2362,27 @@ public:
void clearElementHeight();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- double m_width;
- double m_height;
+ uint m_children = 0;
+ double m_width = 0.0;
+ double m_height = 0.0;
+
enum Child {
Width = 1,
Height = 2
};
-
- DomSizeF(const DomSizeF &other);
- void operator = (const DomSizeF&other);
};
class QDESIGNER_UILIB_EXPORT DomChar {
+ Q_DISABLE_COPY(DomChar)
public:
- DomChar();
+ DomChar() = default;
~DomChar();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline int elementUnicode() const { return m_unicode; }
void setElementUnicode(int a);
@@ -2970,69 +2390,56 @@ public:
void clearElementUnicode();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- int m_unicode;
+ uint m_children = 0;
+ int m_unicode = 0;
+
enum Child {
Unicode = 1
};
-
- DomChar(const DomChar &other);
- void operator = (const DomChar&other);
};
class QDESIGNER_UILIB_EXPORT DomUrl {
+ Q_DISABLE_COPY(DomUrl)
public:
- DomUrl();
+ DomUrl() = default;
~DomUrl();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
- inline DomString* elementString() const { return m_string; }
- DomString* takeElementString();
- void setElementString(DomString* a);
+ inline DomString *elementString() const { return m_string; }
+ DomString *takeElementString();
+ void setElementString(DomString *a);
inline bool hasElementString() const { return m_children & String; }
void clearElementString();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- DomString* m_string;
+ uint m_children = 0;
+ DomString *m_string = nullptr;
+
enum Child {
String = 1
};
-
- DomUrl(const DomUrl &other);
- void operator = (const DomUrl&other);
};
class QDESIGNER_UILIB_EXPORT DomProperty {
+ Q_DISABLE_COPY(DomProperty)
public:
- DomProperty();
+ DomProperty() = default;
~DomProperty();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
inline bool hasAttributeStdset() const { return m_has_attr_stdset; }
@@ -3045,70 +2452,70 @@ public:
inline Kind kind() const { return m_kind; }
inline QString elementBool() const { return m_bool; }
- void setElementBool(const QString& a);
+ void setElementBool(const QString &a);
- inline DomColor* elementColor() const { return m_color; }
- DomColor* takeElementColor();
- void setElementColor(DomColor* a);
+ inline DomColor *elementColor() const { return m_color; }
+ DomColor *takeElementColor();
+ void setElementColor(DomColor *a);
inline QString elementCstring() const { return m_cstring; }
- void setElementCstring(const QString& a);
+ void setElementCstring(const QString &a);
inline int elementCursor() const { return m_cursor; }
void setElementCursor(int a);
inline QString elementCursorShape() const { return m_cursorShape; }
- void setElementCursorShape(const QString& a);
+ void setElementCursorShape(const QString &a);
inline QString elementEnum() const { return m_enum; }
- void setElementEnum(const QString& a);
+ void setElementEnum(const QString &a);
- inline DomFont* elementFont() const { return m_font; }
- DomFont* takeElementFont();
- void setElementFont(DomFont* a);
+ inline DomFont *elementFont() const { return m_font; }
+ DomFont *takeElementFont();
+ void setElementFont(DomFont *a);
- inline DomResourceIcon* elementIconSet() const { return m_iconSet; }
- DomResourceIcon* takeElementIconSet();
- void setElementIconSet(DomResourceIcon* a);
+ inline DomResourceIcon *elementIconSet() const { return m_iconSet; }
+ DomResourceIcon *takeElementIconSet();
+ void setElementIconSet(DomResourceIcon *a);
- inline DomResourcePixmap* elementPixmap() const { return m_pixmap; }
- DomResourcePixmap* takeElementPixmap();
- void setElementPixmap(DomResourcePixmap* a);
+ inline DomResourcePixmap *elementPixmap() const { return m_pixmap; }
+ DomResourcePixmap *takeElementPixmap();
+ void setElementPixmap(DomResourcePixmap *a);
- inline DomPalette* elementPalette() const { return m_palette; }
- DomPalette* takeElementPalette();
- void setElementPalette(DomPalette* a);
+ inline DomPalette *elementPalette() const { return m_palette; }
+ DomPalette *takeElementPalette();
+ void setElementPalette(DomPalette *a);
- inline DomPoint* elementPoint() const { return m_point; }
- DomPoint* takeElementPoint();
- void setElementPoint(DomPoint* a);
+ inline DomPoint *elementPoint() const { return m_point; }
+ DomPoint *takeElementPoint();
+ void setElementPoint(DomPoint *a);
- inline DomRect* elementRect() const { return m_rect; }
- DomRect* takeElementRect();
- void setElementRect(DomRect* a);
+ inline DomRect *elementRect() const { return m_rect; }
+ DomRect *takeElementRect();
+ void setElementRect(DomRect *a);
inline QString elementSet() const { return m_set; }
- void setElementSet(const QString& a);
+ void setElementSet(const QString &a);
- inline DomLocale* elementLocale() const { return m_locale; }
- DomLocale* takeElementLocale();
- void setElementLocale(DomLocale* a);
+ inline DomLocale *elementLocale() const { return m_locale; }
+ DomLocale *takeElementLocale();
+ void setElementLocale(DomLocale *a);
- inline DomSizePolicy* elementSizePolicy() const { return m_sizePolicy; }
- DomSizePolicy* takeElementSizePolicy();
- void setElementSizePolicy(DomSizePolicy* a);
+ inline DomSizePolicy *elementSizePolicy() const { return m_sizePolicy; }
+ DomSizePolicy *takeElementSizePolicy();
+ void setElementSizePolicy(DomSizePolicy *a);
- inline DomSize* elementSize() const { return m_size; }
- DomSize* takeElementSize();
- void setElementSize(DomSize* a);
+ inline DomSize *elementSize() const { return m_size; }
+ DomSize *takeElementSize();
+ void setElementSize(DomSize *a);
- inline DomString* elementString() const { return m_string; }
- DomString* takeElementString();
- void setElementString(DomString* a);
+ inline DomString *elementString() const { return m_string; }
+ DomString *takeElementString();
+ void setElementString(DomString *a);
- inline DomStringList* elementStringList() const { return m_stringList; }
- DomStringList* takeElementStringList();
- void setElementStringList(DomStringList* a);
+ inline DomStringList *elementStringList() const { return m_stringList; }
+ DomStringList *takeElementStringList();
+ void setElementStringList(DomStringList *a);
inline int elementNumber() const { return m_number; }
void setElementNumber(int a);
@@ -3119,40 +2526,40 @@ public:
inline double elementDouble() const { return m_double; }
void setElementDouble(double a);
- inline DomDate* elementDate() const { return m_date; }
- DomDate* takeElementDate();
- void setElementDate(DomDate* a);
+ inline DomDate *elementDate() const { return m_date; }
+ DomDate *takeElementDate();
+ void setElementDate(DomDate *a);
- inline DomTime* elementTime() const { return m_time; }
- DomTime* takeElementTime();
- void setElementTime(DomTime* a);
+ inline DomTime *elementTime() const { return m_time; }
+ DomTime *takeElementTime();
+ void setElementTime(DomTime *a);
- inline DomDateTime* elementDateTime() const { return m_dateTime; }
- DomDateTime* takeElementDateTime();
- void setElementDateTime(DomDateTime* a);
+ inline DomDateTime *elementDateTime() const { return m_dateTime; }
+ DomDateTime *takeElementDateTime();
+ void setElementDateTime(DomDateTime *a);
- inline DomPointF* elementPointF() const { return m_pointF; }
- DomPointF* takeElementPointF();
- void setElementPointF(DomPointF* a);
+ inline DomPointF *elementPointF() const { return m_pointF; }
+ DomPointF *takeElementPointF();
+ void setElementPointF(DomPointF *a);
- inline DomRectF* elementRectF() const { return m_rectF; }
- DomRectF* takeElementRectF();
- void setElementRectF(DomRectF* a);
+ inline DomRectF *elementRectF() const { return m_rectF; }
+ DomRectF *takeElementRectF();
+ void setElementRectF(DomRectF *a);
- inline DomSizeF* elementSizeF() const { return m_sizeF; }
- DomSizeF* takeElementSizeF();
- void setElementSizeF(DomSizeF* a);
+ inline DomSizeF *elementSizeF() const { return m_sizeF; }
+ DomSizeF *takeElementSizeF();
+ void setElementSizeF(DomSizeF *a);
inline qlonglong elementLongLong() const { return m_longLong; }
void setElementLongLong(qlonglong a);
- inline DomChar* elementChar() const { return m_char; }
- DomChar* takeElementChar();
- void setElementChar(DomChar* a);
+ inline DomChar *elementChar() const { return m_char; }
+ DomChar *takeElementChar();
+ void setElementChar(DomChar *a);
- inline DomUrl* elementUrl() const { return m_url; }
- DomUrl* takeElementUrl();
- void setElementUrl(DomUrl* a);
+ inline DomUrl *elementUrl() const { return m_url; }
+ DomUrl *takeElementUrl();
+ void setElementUrl(DomUrl *a);
inline uint elementUInt() const { return m_UInt; }
void setElementUInt(uint a);
@@ -3160,142 +2567,127 @@ public:
inline qulonglong elementULongLong() const { return m_uLongLong; }
void setElementULongLong(qulonglong a);
- inline DomBrush* elementBrush() const { return m_brush; }
- DomBrush* takeElementBrush();
- void setElementBrush(DomBrush* a);
+ inline DomBrush *elementBrush() const { return m_brush; }
+ DomBrush *takeElementBrush();
+ void setElementBrush(DomBrush *a);
private:
- QString m_text;
- void clear(bool clear_all = true);
+ void clear();
// attribute data
QString m_attr_name;
- bool m_has_attr_name;
+ bool m_has_attr_name = false;
- int m_attr_stdset;
- bool m_has_attr_stdset;
+ int m_attr_stdset = 0;
+ bool m_has_attr_stdset = false;
// child element data
- Kind m_kind;
+ Kind m_kind = Unknown;
QString m_bool;
- DomColor* m_color;
+ DomColor *m_color = nullptr;
QString m_cstring;
- int m_cursor;
+ int m_cursor = 0;
QString m_cursorShape;
QString m_enum;
- DomFont* m_font;
- DomResourceIcon* m_iconSet;
- DomResourcePixmap* m_pixmap;
- DomPalette* m_palette;
- DomPoint* m_point;
- DomRect* m_rect;
+ DomFont *m_font = nullptr;
+ DomResourceIcon *m_iconSet = nullptr;
+ DomResourcePixmap *m_pixmap = nullptr;
+ DomPalette *m_palette = nullptr;
+ DomPoint *m_point = nullptr;
+ DomRect *m_rect = nullptr;
QString m_set;
- DomLocale* m_locale;
- DomSizePolicy* m_sizePolicy;
- DomSize* m_size;
- DomString* m_string;
- DomStringList* m_stringList;
- int m_number;
- float m_float;
- double m_double;
- DomDate* m_date;
- DomTime* m_time;
- DomDateTime* m_dateTime;
- DomPointF* m_pointF;
- DomRectF* m_rectF;
- DomSizeF* m_sizeF;
- qlonglong m_longLong;
- DomChar* m_char;
- DomUrl* m_url;
- uint m_UInt;
- qulonglong m_uLongLong;
- DomBrush* m_brush;
-
- DomProperty(const DomProperty &other);
- void operator = (const DomProperty&other);
+ DomLocale *m_locale = nullptr;
+ DomSizePolicy *m_sizePolicy = nullptr;
+ DomSize *m_size = nullptr;
+ DomString *m_string = nullptr;
+ DomStringList *m_stringList = nullptr;
+ int m_number = 0;
+ float m_float = 0.0;
+ double m_double = 0.0;
+ DomDate *m_date = nullptr;
+ DomTime *m_time = nullptr;
+ DomDateTime *m_dateTime = nullptr;
+ DomPointF *m_pointF = nullptr;
+ DomRectF *m_rectF = nullptr;
+ DomSizeF *m_sizeF = nullptr;
+ qlonglong m_longLong = 0;
+ DomChar *m_char = nullptr;
+ DomUrl *m_url = nullptr;
+ uint m_UInt = 0;
+ qulonglong m_uLongLong = 0;
+ DomBrush *m_brush = nullptr;
};
class QDESIGNER_UILIB_EXPORT DomConnections {
+ Q_DISABLE_COPY(DomConnections)
public:
- DomConnections();
+ DomConnections() = default;
~DomConnections();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
- inline QList<DomConnection*> elementConnection() const { return m_connection; }
- void setElementConnection(const QList<DomConnection*>& a);
+ inline QVector<DomConnection *> elementConnection() const { return m_connection; }
+ void setElementConnection(const QVector<DomConnection *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- QList<DomConnection*> m_connection;
+ uint m_children = 0;
+ QVector<DomConnection *> m_connection;
+
enum Child {
Connection = 1
};
-
- DomConnections(const DomConnections &other);
- void operator = (const DomConnections&other);
};
class QDESIGNER_UILIB_EXPORT DomConnection {
+ Q_DISABLE_COPY(DomConnection)
public:
- DomConnection();
+ DomConnection() = default;
~DomConnection();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline QString elementSender() const { return m_sender; }
- void setElementSender(const QString& a);
+ void setElementSender(const QString &a);
inline bool hasElementSender() const { return m_children & Sender; }
void clearElementSender();
inline QString elementSignal() const { return m_signal; }
- void setElementSignal(const QString& a);
+ void setElementSignal(const QString &a);
inline bool hasElementSignal() const { return m_children & Signal; }
void clearElementSignal();
inline QString elementReceiver() const { return m_receiver; }
- void setElementReceiver(const QString& a);
+ void setElementReceiver(const QString &a);
inline bool hasElementReceiver() const { return m_children & Receiver; }
void clearElementReceiver();
inline QString elementSlot() const { return m_slot; }
- void setElementSlot(const QString& a);
+ void setElementSlot(const QString &a);
inline bool hasElementSlot() const { return m_children & Slot; }
void clearElementSlot();
- inline DomConnectionHints* elementHints() const { return m_hints; }
- DomConnectionHints* takeElementHints();
- void setElementHints(DomConnectionHints* a);
+ inline DomConnectionHints *elementHints() const { return m_hints; }
+ DomConnectionHints *takeElementHints();
+ void setElementHints(DomConnectionHints *a);
inline bool hasElementHints() const { return m_children & Hints; }
void clearElementHints();
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
+ uint m_children = 0;
QString m_sender;
QString m_signal;
QString m_receiver;
QString m_slot;
- DomConnectionHints* m_hints;
+ DomConnectionHints *m_hints = nullptr;
+
enum Child {
Sender = 1,
Signal = 2,
@@ -3303,56 +2695,45 @@ private:
Slot = 8,
Hints = 16
};
-
- DomConnection(const DomConnection &other);
- void operator = (const DomConnection&other);
};
class QDESIGNER_UILIB_EXPORT DomConnectionHints {
+ Q_DISABLE_COPY(DomConnectionHints)
public:
- DomConnectionHints();
+ DomConnectionHints() = default;
~DomConnectionHints();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
- inline QList<DomConnectionHint*> elementHint() const { return m_hint; }
- void setElementHint(const QList<DomConnectionHint*>& a);
+ inline QVector<DomConnectionHint *> elementHint() const { return m_hint; }
+ void setElementHint(const QVector<DomConnectionHint *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- QList<DomConnectionHint*> m_hint;
+ uint m_children = 0;
+ QVector<DomConnectionHint *> m_hint;
+
enum Child {
Hint = 1
};
-
- DomConnectionHints(const DomConnectionHints &other);
- void operator = (const DomConnectionHints&other);
};
class QDESIGNER_UILIB_EXPORT DomConnectionHint {
+ Q_DISABLE_COPY(DomConnectionHint)
public:
- DomConnectionHint();
+ DomConnectionHint() = default;
~DomConnectionHint();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeType() const { return m_has_attr_type; }
inline QString attributeType() const { return m_attr_type; }
- inline void setAttributeType(const QString& a) { m_attr_type = a; m_has_attr_type = true; }
+ inline void setAttributeType(const QString &a) { m_attr_type = a; m_has_attr_type = true; }
inline void clearAttributeType() { m_has_attr_type = false; }
// child element accessors
@@ -3367,278 +2748,159 @@ public:
void clearElementY();
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_type;
- bool m_has_attr_type;
+ bool m_has_attr_type = false;
// child element data
- uint m_children;
- int m_x;
- int m_y;
+ uint m_children = 0;
+ int m_x = 0;
+ int m_y = 0;
+
enum Child {
X = 1,
Y = 2
};
-
- DomConnectionHint(const DomConnectionHint &other);
- void operator = (const DomConnectionHint&other);
-};
-
-class QDESIGNER_UILIB_EXPORT DomScript {
-public:
- DomScript();
- ~DomScript();
-
- void read(QXmlStreamReader &reader);
- void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
-
- // attribute accessors
- inline bool hasAttributeSource() const { return m_has_attr_source; }
- inline QString attributeSource() const { return m_attr_source; }
- inline void setAttributeSource(const QString& a) { m_attr_source = a; m_has_attr_source = true; }
- inline void clearAttributeSource() { m_has_attr_source = false; }
-
- inline bool hasAttributeLanguage() const { return m_has_attr_language; }
- inline QString attributeLanguage() const { return m_attr_language; }
- inline void setAttributeLanguage(const QString& a) { m_attr_language = a; m_has_attr_language = true; }
- inline void clearAttributeLanguage() { m_has_attr_language = false; }
-
- // child element accessors
-private:
- QString m_text;
- void clear(bool clear_all = true);
-
- // attribute data
- QString m_attr_source;
- bool m_has_attr_source;
-
- QString m_attr_language;
- bool m_has_attr_language;
-
- // child element data
- uint m_children;
-
- DomScript(const DomScript &other);
- void operator = (const DomScript&other);
-};
-
-class QDESIGNER_UILIB_EXPORT DomWidgetData {
-public:
- DomWidgetData();
- ~DomWidgetData();
-
- void read(QXmlStreamReader &reader);
- void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
-
- // attribute accessors
- // child element accessors
- inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
-
-private:
- QString m_text;
- void clear(bool clear_all = true);
-
- // attribute data
- // child element data
- uint m_children;
- QList<DomProperty*> m_property;
- enum Child {
- Property = 1
- };
-
- DomWidgetData(const DomWidgetData &other);
- void operator = (const DomWidgetData&other);
};
class QDESIGNER_UILIB_EXPORT DomDesignerData {
+ Q_DISABLE_COPY(DomDesignerData)
public:
- DomDesignerData();
+ DomDesignerData() = default;
~DomDesignerData();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline QList<DomProperty*> elementProperty() const { return m_property; }
- void setElementProperty(const QList<DomProperty*>& a);
+ void setElementProperty(const QList<DomProperty *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
+ uint m_children = 0;
QList<DomProperty*> m_property;
+
enum Child {
Property = 1
};
-
- DomDesignerData(const DomDesignerData &other);
- void operator = (const DomDesignerData&other);
};
class QDESIGNER_UILIB_EXPORT DomSlots {
+ Q_DISABLE_COPY(DomSlots)
public:
- DomSlots();
+ DomSlots() = default;
~DomSlots();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
inline QStringList elementSignal() const { return m_signal; }
- void setElementSignal(const QStringList& a);
+ void setElementSignal(const QStringList &a);
inline QStringList elementSlot() const { return m_slot; }
- void setElementSlot(const QStringList& a);
+ void setElementSlot(const QStringList &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
+ uint m_children = 0;
QStringList m_signal;
QStringList m_slot;
+
enum Child {
Signal = 1,
Slot = 2
};
-
- DomSlots(const DomSlots &other);
- void operator = (const DomSlots&other);
};
class QDESIGNER_UILIB_EXPORT DomPropertySpecifications {
+ Q_DISABLE_COPY(DomPropertySpecifications)
public:
- DomPropertySpecifications();
+ DomPropertySpecifications() = default;
~DomPropertySpecifications();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
- // attribute accessors
// child element accessors
- inline QList<DomPropertyToolTip*> elementTooltip() const { return m_tooltip; }
- void setElementTooltip(const QList<DomPropertyToolTip*>& a);
+ inline QVector<DomPropertyToolTip *> elementTooltip() const { return m_tooltip; }
+ void setElementTooltip(const QVector<DomPropertyToolTip *> &a);
- inline QList<DomStringPropertySpecification*> elementStringpropertyspecification() const { return m_stringpropertyspecification; }
- void setElementStringpropertyspecification(const QList<DomStringPropertySpecification*>& a);
+ inline QVector<DomStringPropertySpecification *> elementStringpropertyspecification() const { return m_stringpropertyspecification; }
+ void setElementStringpropertyspecification(const QVector<DomStringPropertySpecification *> &a);
private:
- QString m_text;
- void clear(bool clear_all = true);
- // attribute data
// child element data
- uint m_children;
- QList<DomPropertyToolTip*> m_tooltip;
- QList<DomStringPropertySpecification*> m_stringpropertyspecification;
+ uint m_children = 0;
+ QVector<DomPropertyToolTip *> m_tooltip;
+ QVector<DomStringPropertySpecification *> m_stringpropertyspecification;
+
enum Child {
Tooltip = 1,
Stringpropertyspecification = 2
};
-
- DomPropertySpecifications(const DomPropertySpecifications &other);
- void operator = (const DomPropertySpecifications&other);
};
class QDESIGNER_UILIB_EXPORT DomPropertyToolTip {
+ Q_DISABLE_COPY(DomPropertyToolTip)
public:
- DomPropertyToolTip();
+ DomPropertyToolTip() = default;
~DomPropertyToolTip();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
- // child element accessors
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_name;
- bool m_has_attr_name;
-
- // child element data
- uint m_children;
-
- DomPropertyToolTip(const DomPropertyToolTip &other);
- void operator = (const DomPropertyToolTip&other);
+ bool m_has_attr_name = false;
};
class QDESIGNER_UILIB_EXPORT DomStringPropertySpecification {
+ Q_DISABLE_COPY(DomStringPropertySpecification)
public:
- DomStringPropertySpecification();
+ DomStringPropertySpecification() = default;
~DomStringPropertySpecification();
void read(QXmlStreamReader &reader);
void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
- inline QString text() const { return m_text; }
- inline void setText(const QString &s) { m_text = s; }
// attribute accessors
inline bool hasAttributeName() const { return m_has_attr_name; }
inline QString attributeName() const { return m_attr_name; }
- inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void setAttributeName(const QString &a) { m_attr_name = a; m_has_attr_name = true; }
inline void clearAttributeName() { m_has_attr_name = false; }
inline bool hasAttributeType() const { return m_has_attr_type; }
inline QString attributeType() const { return m_attr_type; }
- inline void setAttributeType(const QString& a) { m_attr_type = a; m_has_attr_type = true; }
+ inline void setAttributeType(const QString &a) { m_attr_type = a; m_has_attr_type = true; }
inline void clearAttributeType() { m_has_attr_type = false; }
inline bool hasAttributeNotr() const { return m_has_attr_notr; }
inline QString attributeNotr() const { return m_attr_notr; }
- inline void setAttributeNotr(const QString& a) { m_attr_notr = a; m_has_attr_notr = true; }
+ inline void setAttributeNotr(const QString &a) { m_attr_notr = a; m_has_attr_notr = true; }
inline void clearAttributeNotr() { m_has_attr_notr = false; }
- // child element accessors
private:
- QString m_text;
- void clear(bool clear_all = true);
-
// attribute data
QString m_attr_name;
- bool m_has_attr_name;
+ bool m_has_attr_name = false;
QString m_attr_type;
- bool m_has_attr_type;
+ bool m_has_attr_type = false;
QString m_attr_notr;
- bool m_has_attr_notr;
-
- // child element data
- uint m_children;
-
- DomStringPropertySpecification(const DomStringPropertySpecification &other);
- void operator = (const DomStringPropertySpecification&other);
+ bool m_has_attr_notr = false;
};
diff --git a/src/tools/uic/uic.cpp b/src/tools/uic/uic.cpp
index fa775161e5..48756db651 100644
--- a/src/tools/uic/uic.cpp
+++ b/src/tools/uic/uic.cpp
@@ -52,8 +52,7 @@ QT_BEGIN_NAMESPACE
Uic::Uic(Driver *d)
: drv(d),
out(d->output()),
- opt(d->option()),
- externalPix(true)
+ opt(d->option())
{
}
@@ -253,15 +252,13 @@ bool Uic::write(DomUI *ui)
if (pixFunction == QLatin1String("QPixmap::fromMimeSource"))
pixFunction = QLatin1String("qPixmapFromMimeSource");
- externalPix = ui->elementImages() == 0;
-
info.acceptUI(ui);
cWidgetsInfo.acceptUI(ui);
WriteIncludes writeIncludes(this);
writeIncludes.acceptUI(ui);
Validator(this).acceptUI(ui);
- WriteDeclaration(this, writeIncludes.scriptsActivated()).acceptUI(ui);
+ WriteDeclaration(this).acceptUI(ui);
if (opt.headerProtection)
writeHeaderProtectionEnd();
diff --git a/src/tools/uic/uic.h b/src/tools/uic/uic.h
index 10404d3370..e00dc595bc 100644
--- a/src/tools/uic/uic.h
+++ b/src/tools/uic/uic.h
@@ -74,12 +74,6 @@ public:
inline void setPixmapFunction(const QString &f)
{ pixFunction = f; }
- inline bool hasExternalPixmap() const
- { return externalPix; }
-
- inline void setExternalPixmap(bool b)
- { externalPix = b; }
-
inline const DatabaseInfo *databaseInfo() const
{ return &info; }
@@ -123,7 +117,6 @@ private:
DatabaseInfo info;
CustomWidgetsInfo cWidgetsInfo;
QString pixFunction;
- bool externalPix;
};
QT_END_NAMESPACE
diff --git a/src/tools/uic/uic.pro b/src/tools/uic/uic.pro
index 02469cdd1b..18511395d9 100644
--- a/src/tools/uic/uic.pro
+++ b/src/tools/uic/uic.pro
@@ -12,4 +12,5 @@ HEADERS += uic.h
SOURCES += main.cpp \
uic.cpp
+QMAKE_TARGET_DESCRIPTION = "Qt User Interface Compiler"
load(qt_tool)
diff --git a/src/tools/uic/utils.h b/src/tools/uic/utils.h
index 7c5918cab9..18b361fb81 100644
--- a/src/tools/uic/utils.h
+++ b/src/tools/uic/utils.h
@@ -107,19 +107,6 @@ inline QString fixString(const QString &str, const QString &indent,
return rc;
}
-inline QString writeString(const QString &s, const QString &indent)
-{
- unsigned flags = 0;
- const QString ret = fixString(s, indent, &flags);
- if (flags & Utf8String)
- return QLatin1String("QString::fromUtf8(") + ret + QLatin1Char(')');
- // MSVC cannot concat L"foo" "bar" (C2308: concatenating mismatched strings),
- // use QLatin1String instead (all platforms to avoid cross-compiling issues).
- if (flags & MultiLineString)
- return QLatin1String("QLatin1String(") + ret + QLatin1Char(')');
- return QLatin1String("QStringLiteral(") + ret + QLatin1Char(')');
-}
-
inline QHash<QString, DomProperty *> propertyMap(const QList<DomProperty *> &properties)
{
QHash<QString, DomProperty *> map;
diff --git a/src/widgets/configure.json b/src/widgets/configure.json
index 7e2f8e1552..2c183dad65 100644
--- a/src/widgets/configure.json
+++ b/src/widgets/configure.json
@@ -10,7 +10,6 @@
"options": {
"gtk": { "type": "boolean", "name": "gtk3" },
"style-windows": "boolean",
- "style-windowsxp": "boolean",
"style-windowsvista": "boolean",
"style-fusion": "boolean",
"style-mac": "boolean",
@@ -55,14 +54,9 @@
"label": "Windows",
"output": [ "privateFeature", "styles" ]
},
- "style-windowsxp": {
- "label": "WindowsXP",
- "condition": "features.style-windows && config.win32 && !config.winrt && tests.uxtheme",
- "output": [ "privateFeature", "styles" ]
- },
"style-windowsvista": {
"label": "WindowsVista",
- "condition": "features.style-windowsxp",
+ "condition": "features.style-windows && config.win32 && !config.winrt && tests.uxtheme",
"output": [ "privateFeature", "styles" ]
},
"style-android": {
@@ -691,7 +685,7 @@
{
"message": "Styles",
"type": "featureList",
- "args": "style-fusion style-mac style-windows style-windowsxp style-windowsvista style-android"
+ "args": "style-fusion style-mac style-windows style-windowsvista style-android"
}
]
}
diff --git a/src/widgets/dialogs/qfilesystemmodel.cpp b/src/widgets/dialogs/qfilesystemmodel.cpp
index bf14b5c6fd..f88ac71cf3 100644
--- a/src/widgets/dialogs/qfilesystemmodel.cpp
+++ b/src/widgets/dialogs/qfilesystemmodel.cpp
@@ -778,21 +778,7 @@ QString QFileSystemModelPrivate::size(const QModelIndex &index) const
QString QFileSystemModelPrivate::size(qint64 bytes)
{
- // According to the Si standard KB is 1000 bytes, KiB is 1024
- // but on windows sizes are calculated by dividing by 1024 so we do what they do.
- const qint64 kb = 1024;
- const qint64 mb = 1024 * kb;
- const qint64 gb = 1024 * mb;
- const qint64 tb = 1024 * gb;
- if (bytes >= tb)
- return QFileSystemModel::tr("%1 TB").arg(QLocale().toString(qreal(bytes) / tb, 'f', 3));
- if (bytes >= gb)
- return QFileSystemModel::tr("%1 GB").arg(QLocale().toString(qreal(bytes) / gb, 'f', 2));
- if (bytes >= mb)
- return QFileSystemModel::tr("%1 MB").arg(QLocale().toString(qreal(bytes) / mb, 'f', 1));
- if (bytes >= kb)
- return QFileSystemModel::tr("%1 KB").arg(QLocale().toString(bytes / kb));
- return QFileSystemModel::tr("%1 bytes").arg(QLocale().toString(bytes));
+ return QLocale::system().formattedDataSize(bytes);
}
/*!
diff --git a/src/widgets/dialogs/qinputdialog.cpp b/src/widgets/dialogs/qinputdialog.cpp
index 04d13045e5..4c0f22ae97 100644
--- a/src/widgets/dialogs/qinputdialog.cpp
+++ b/src/widgets/dialogs/qinputdialog.cpp
@@ -1368,12 +1368,48 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr
double value, double min, double max, int decimals, bool *ok,
Qt::WindowFlags flags)
{
+ return QInputDialog::getDouble(parent, title, label, value, min, max, decimals, ok, flags, 1.0);
+}
+
+/*!
+ \overload
+ Static convenience function to get a floating point number from the user.
+
+ \a title is the text which is displayed in the title bar of the dialog.
+ \a label is the text which is shown to the user (it should say what should
+ be entered).
+ \a value is the default floating point number that the line edit will be
+ set to.
+ \a min and \a max are the minimum and maximum values the user may choose.
+ \a decimals is the maximum number of decimal places the number may have.
+ \a step is the amount by which the values change as the user presses the
+ arrow buttons to increment or decrement the value.
+
+ If \a ok is nonnull, *\a ok will be set to true if the user pressed \uicontrol OK
+ and to false if the user pressed \uicontrol Cancel. The dialog's parent is
+ \a parent. The dialog will be modal and uses the widget \a flags.
+
+ This function returns the floating point number which has been entered by
+ the user.
+
+ Use this static function like this:
+
+ \snippet dialogs/standarddialogs/dialog.cpp 1
+
+ \sa getText(), getInt(), getItem(), getMultiLineText()
+*/
+
+double QInputDialog::getDouble(QWidget *parent, const QString &title, const QString &label,
+ double value, double min, double max, int decimals, bool *ok,
+ Qt::WindowFlags flags, double step)
+{
QAutoPointer<QInputDialog> dialog(new QInputDialog(parent, flags));
dialog->setWindowTitle(title);
dialog->setLabelText(label);
dialog->setDoubleDecimals(decimals);
dialog->setDoubleRange(min, max);
dialog->setDoubleValue(value);
+ dialog->setDoubleStep(step);
const int ret = dialog->exec();
if (ok)
@@ -1439,6 +1475,31 @@ QString QInputDialog::getItem(QWidget *parent, const QString &title, const QStri
}
/*!
+ \property QInputDialog::doubleStep
+ \since 5.10
+ \brief the step by which the double value is increased and decreased
+
+ This property is only relevant when the input dialog is used in
+ DoubleInput mode.
+*/
+
+void QInputDialog::setDoubleStep(double step)
+{
+ Q_D(QInputDialog);
+ d->ensureDoubleSpinBox();
+ d->doubleSpinBox->setSingleStep(step);
+}
+
+double QInputDialog::doubleStep() const
+{
+ Q_D(const QInputDialog);
+ if (d->doubleSpinBox)
+ return d->doubleSpinBox->singleStep();
+ else
+ return 1.0;
+}
+
+/*!
\fn void QInputDialog::doubleValueChanged(double value)
This signal is emitted whenever the double value changes in the dialog.
diff --git a/src/widgets/dialogs/qinputdialog.h b/src/widgets/dialogs/qinputdialog.h
index 5f06785886..e41d442498 100644
--- a/src/widgets/dialogs/qinputdialog.h
+++ b/src/widgets/dialogs/qinputdialog.h
@@ -74,6 +74,7 @@ class Q_WIDGETS_EXPORT QInputDialog : public QDialog
QDOC_PROPERTY(int doubleDecimals READ doubleDecimals WRITE setDoubleDecimals)
QDOC_PROPERTY(QString okButtonText READ okButtonText WRITE setOkButtonText)
QDOC_PROPERTY(QString cancelButtonText READ cancelButtonText WRITE setCancelButtonText)
+ QDOC_PROPERTY(double doubleStep READ doubleStep WRITE setDoubleStep)
public:
enum InputDialogOption {
@@ -178,6 +179,10 @@ public:
static double getDouble(QWidget *parent, const QString &title, const QString &label, double value = 0,
double minValue = -2147483647, double maxValue = 2147483647,
int decimals = 1, bool *ok = Q_NULLPTR, Qt::WindowFlags flags = Qt::WindowFlags());
+ // ### Qt 6: merge overloads
+ static double getDouble(QWidget *parent, const QString &title, const QString &label, double value,
+ double minValue, double maxValue, int decimals, bool *ok, Qt::WindowFlags flags,
+ double step);
#if QT_DEPRECATED_SINCE(5, 0)
QT_DEPRECATED static inline int getInteger(QWidget *parent, const QString &title, const QString &label, int value = 0,
@@ -188,6 +193,9 @@ public:
}
#endif
+ void setDoubleStep(double step);
+ double doubleStep() const;
+
Q_SIGNALS:
// ### emit signals!
void textValueChanged(const QString &text);
diff --git a/src/widgets/dialogs/qprogressdialog.cpp b/src/widgets/dialogs/qprogressdialog.cpp
index 893920cbd9..a276e28a0c 100644
--- a/src/widgets/dialogs/qprogressdialog.cpp
+++ b/src/widgets/dialogs/qprogressdialog.cpp
@@ -242,7 +242,7 @@ void QProgressDialogPrivate::_q_disconnectOnClose()
A modeless progress dialog is suitable for operations that take
place in the background, where the user is able to interact with the
application. Such operations are typically based on QTimer (or
- QObject::timerEvent()), QSocketNotifier, or QUrlOperator; or performed
+ QObject::timerEvent()) or QSocketNotifier; or performed
in a separate thread. A QProgressBar in the status bar of your main window
is often an alternative to a modeless progress dialog.
diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp
index 4d89cd9936..431447734d 100644
--- a/src/widgets/dialogs/qwizard.cpp
+++ b/src/widgets/dialogs/qwizard.cpp
@@ -496,6 +496,7 @@ public:
mutable TriState completeState;
bool explicitlyFinal;
bool commit;
+ bool initialized = false;
QMap<int, QString> buttonCustomTexts;
};
@@ -631,7 +632,6 @@ public:
QMap<QString, int> fieldIndexMap;
QVector<QWizardDefaultProperty> defaultPropertyTable;
QList<int> history;
- QSet<int> initialized; // ### remove and move bit to QWizardPage?
int start;
bool startSetByUser;
int current;
@@ -770,7 +770,8 @@ void QWizardPrivate::reset()
for (int i = history.count() - 1; i >= 0; --i)
q->cleanupPage(history.at(i));
history.clear();
- initialized.clear();
+ for (QWizardPage *page : pageMap)
+ page->d_func()->initialized = false;
current = -1;
emit q->currentIdChanged(-1);
@@ -781,14 +782,12 @@ void QWizardPrivate::cleanupPagesNotInHistory()
{
Q_Q(QWizard);
- const QSet<int> original = initialized;
- QSet<int>::const_iterator i = original.constBegin();
- QSet<int>::const_iterator end = original.constEnd();
-
- for (; i != end; ++i) {
- if (!history.contains(*i)) {
- q->cleanupPage(*i);
- initialized.remove(*i);
+ for (auto it = pageMap.begin(), end = pageMap.end(); it != end; ++it) {
+ const auto idx = it.key();
+ const auto page = it.value()->d_func();
+ if (page->initialized && !history.contains(idx)) {
+ q->cleanupPage(idx);
+ page->initialized = false;
}
}
}
@@ -843,7 +842,7 @@ void QWizardPrivate::switchToPage(int newId, Direction direction)
if (direction == Backward) {
if (!(opts & QWizard::IndependentPages)) {
q->cleanupPage(oldId);
- initialized.remove(oldId);
+ oldPage->d_func()->initialized = false;
}
Q_ASSERT(history.constLast() == oldId);
history.removeLast();
@@ -856,8 +855,8 @@ void QWizardPrivate::switchToPage(int newId, Direction direction)
QWizardPage *newPage = q->currentPage();
if (newPage) {
if (direction == Forward) {
- if (!initialized.contains(current)) {
- initialized.insert(current);
+ if (!newPage->d_func()->initialized) {
+ newPage->d_func()->initialized = true;
q->initializePage(current);
}
history.append(current);
@@ -2357,9 +2356,9 @@ void QWizard::removePage(int id)
}
if (removedPage) {
- if (d->initialized.contains(id)) {
+ if (removedPage->d_func()->initialized) {
cleanupPage(id);
- d->initialized.remove(id);
+ removedPage->d_func()->initialized = false;
}
d->pageVBoxLayout->removeWidget(removedPage);
diff --git a/src/widgets/doc/images/stylesheet-coffee-xp.png b/src/widgets/doc/images/stylesheet-coffee-xp.png
deleted file mode 100644
index 8bedd80ee9..0000000000
--- a/src/widgets/doc/images/stylesheet-coffee-xp.png
+++ /dev/null
Binary files differ
diff --git a/src/widgets/doc/images/windowsxp-tabwidget.png b/src/widgets/doc/images/windowsxp-tabwidget.png
deleted file mode 100644
index 3c8e777a0b..0000000000
--- a/src/widgets/doc/images/windowsxp-tabwidget.png
+++ /dev/null
Binary files differ
diff --git a/src/widgets/doc/images/windowsxp-treeview.png b/src/widgets/doc/images/windowsxp-treeview.png
deleted file mode 100644
index 050cc2f4d6..0000000000
--- a/src/widgets/doc/images/windowsxp-treeview.png
+++ /dev/null
Binary files differ
diff --git a/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc b/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
index dfea9f2ca4..bf727dd380 100644
--- a/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
+++ b/src/widgets/doc/snippets/code/doc_src_stylesheet.qdoc
@@ -1889,3 +1889,7 @@ QTableView::indicator:unchecked {
}
//! [161]
+//! [162]
+* { widget-animation-duration: 100 }
+//! [162]
+
diff --git a/src/widgets/doc/snippets/macmainwindow.mm b/src/widgets/doc/snippets/macmainwindow.mm
index d848e6442d..c63796a3f2 100644
--- a/src/widgets/doc/snippets/macmainwindow.mm
+++ b/src/widgets/doc/snippets/macmainwindow.mm
@@ -43,8 +43,6 @@
#if 0 // Used to be included in Qt4 for Q_WS_MAC
-#include <Carbon/Carbon.h>
-
//![0]
SearchWidget::SearchWidget(QWidget *parent)
: QMacCocoaViewContainer(0, parent)
diff --git a/src/widgets/doc/src/qtwidgets-index.qdoc b/src/widgets/doc/src/qtwidgets-index.qdoc
index 9f9a25140b..c05b16a0a0 100644
--- a/src/widgets/doc/src/qtwidgets-index.qdoc
+++ b/src/widgets/doc/src/qtwidgets-index.qdoc
@@ -83,7 +83,7 @@ interfaces
\table
\row
- \li \image windowsxp-tabwidget.png
+ \li \image windowsvista-tabwidget.png
\li \image fusion-tabwidget.png
\li \image macos-tabwidget.png
\endtable
@@ -118,7 +118,7 @@ interfaces
which use lists and tables are structured to separate the data and view
using models, views, and delegates.
- \image windowsxp-treeview.png
+ \image windowsvista-treeview.png
\section1 Graphics View
diff --git a/src/widgets/doc/src/widgets-and-layouts/gallery.qdoc b/src/widgets/doc/src/widgets-and-layouts/gallery.qdoc
index 5076970854..a82462a432 100644
--- a/src/widgets/doc/src/widgets-and-layouts/gallery.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/gallery.qdoc
@@ -41,10 +41,6 @@
\table
\row
- \li \image windows-xp-style.png Windows XP Style
- \li The Windows XP style ("windowsxp") is provided by
- QWindowsXPStyle.
- \row
\li The Windows style ("windows") is provided by QWindowsStyle.
\li \image windows-style.png Windows Style
\row
diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
index 6745b78898..be6a068d65 100644
--- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc
@@ -80,7 +80,7 @@
the QPalette::Button role to red for a QPushButton to obtain a
red push button. However, this wasn't guaranteed to work for all
styles, because style authors are restricted by the different
- platforms' guidelines and (on Windows XP and \macos) by the
+ platforms' guidelines and (on Windows and \macos) by the
native theme engine.
Style sheets let you perform all kinds of customizations that are
@@ -111,10 +111,8 @@
will.
\table
- \row \li \inlineimage stylesheet-coffee-xp.png
- \li \inlineimage stylesheet-pagefold.png
- \row \li Coffee theme running on Windows XP
- \li Pagefold theme running on Windows XP
+ \row \li \inlineimage stylesheet-pagefold.png
+ \row \li Pagefold theme running on Windows
\endtable
\table
@@ -128,7 +126,7 @@
is a wrapper "style sheet" style, \e not the platform-specific style. The
wrapper style ensures that any active style sheet is respected and
otherwise forwards the drawing operations to the underlying,
- platform-specific style (e.g., QWindowsXPStyle on Windows XP).
+ platform-specific style (e.g., QWindowsVistaStyle on Windows).
Since Qt 4.5, Qt style sheets fully supports \macos.
@@ -1793,8 +1791,9 @@
a QMessageBox. The possible values are 0
(\l{QDialogButtonBox::}{WinLayout}), 1
(\l{QDialogButtonBox::}{MacLayout}), 2
- (\l{QDialogButtonBox::}{KdeLayout}), and 3
- (\l{QDialogButtonBox::}{GnomeLayout}).
+ (\l{QDialogButtonBox::}{KdeLayout}), 3
+ (\l{QDialogButtonBox::}{GnomeLayout}) and 5
+ (\l{QDialogButtonBox::}{AndroidLayout}).
If this property is not specified, it defaults to the
value specified by the current style for the
@@ -2434,6 +2433,28 @@
\l{Qt Style Sheets Reference#subcontrol-origin-prop}{subcontrol-origin}.
\row
+ \li \b{\c titlebar-show-tooltips-on-buttons}}
+ \target titlebar-show-tooltips-on-buttons-prop
+ \li \c bool
+ \li Whether tool tips are shown on window title bar buttons.
+
+ \row
+ \li \b{\c widget-animation-duration*} \target widget-animation-duration
+ \li \l{#Number}{Number}
+ \li How much an animation should last (in milliseconds).
+ A value equal to zero means that the animations will be disabled.
+
+ If this property is not specified, it defaults to the
+ value specified by the current style for the
+ \l{QStyle::}{SH_Widget_Animation_Duration} style hint.
+
+ \b{This property was added in Qt 5.10.}
+
+ Example:
+
+ \snippet code/doc_src_stylesheet.qdoc 162
+
+ \row
\li \b{\c text-align} \target text-align-prop
\li \l{#Alignment}{Alignment}
\li The alignment of text and icon within the contents of the widget.
@@ -3525,7 +3546,7 @@
\list
\li We have made a request that cannot be satisfied using the
- native styles alone (e.g., the Windows XP theme engine doesn't
+ native styles alone (e.g., the Windows Vista theme engine doesn't
let us specify the background color of a button).
\li Therefore, the button is rendered using style sheets.
\li We haven't specified any values for
diff --git a/src/widgets/doc/src/widgets-and-layouts/widgets.qdoc b/src/widgets/doc/src/widgets-and-layouts/widgets.qdoc
index a444d5358c..700a4479fd 100644
--- a/src/widgets/doc/src/widgets-and-layouts/widgets.qdoc
+++ b/src/widgets/doc/src/widgets-and-layouts/widgets.qdoc
@@ -62,7 +62,7 @@
\table
\row
- \li \image windowsxp-treeview.png
+ \li \image windowsvista-treeview.png
\li \image fusion-calendarwidget.png
\li \image qundoview.png
\endtable
diff --git a/src/widgets/graphicsview/qgraphicswidget_p.cpp b/src/widgets/graphicsview/qgraphicswidget_p.cpp
index 660620a5d9..f3c568fa01 100644
--- a/src/widgets/graphicsview/qgraphicswidget_p.cpp
+++ b/src/widgets/graphicsview/qgraphicswidget_p.cpp
@@ -52,9 +52,6 @@
#include <QtWidgets/qstyleoption.h>
#include <QtWidgets/QStyleOptionTitleBar>
#include <QtWidgets/QGraphicsSceneMouseEvent>
-#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && QT_CONFIG(style_mac)
-# include <private/qmacstyle_mac_p.h>
-#endif
QT_BEGIN_NAMESPACE
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index 25587a281d..ed87de4e18 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -2254,7 +2254,7 @@ void QAbstractItemView::focusInEvent(QFocusEvent *event)
/*!
This function is called with the given \a event when the widget
- looses the focus. By default, the event is ignored.
+ loses the focus. By default, the event is ignored.
\sa clearFocus(), focusInEvent()
*/
@@ -3134,7 +3134,7 @@ int QAbstractItemView::sizeHintForColumn(int column) const
Opens a persistent editor on the item at the given \a index.
If no editor exists, the delegate will create a new editor.
- \sa closePersistentEditor()
+ \sa closePersistentEditor(), isPersistentEditorOpen()
*/
void QAbstractItemView::openPersistentEditor(const QModelIndex &index)
{
@@ -3153,7 +3153,7 @@ void QAbstractItemView::openPersistentEditor(const QModelIndex &index)
/*!
Closes the persistent editor for the item at the given \a index.
- \sa openPersistentEditor()
+ \sa openPersistentEditor(), isPersistentEditorOpen()
*/
void QAbstractItemView::closePersistentEditor(const QModelIndex &index)
{
@@ -3168,6 +3168,19 @@ void QAbstractItemView::closePersistentEditor(const QModelIndex &index)
}
/*!
+ \since 5.10
+
+ Returns whether a persistent editor is open for the item at index \a index.
+
+ \sa openPersistentEditor(), closePersistentEditor()
+*/
+bool QAbstractItemView::isPersistentEditorOpen(const QModelIndex &index) const
+{
+ Q_D(const QAbstractItemView);
+ return d->editorForIndex(index).widget;
+}
+
+/*!
\since 4.1
Sets the given \a widget on the item at the given \a index, passing the
@@ -4416,8 +4429,7 @@ QItemViewPaintPairs QAbstractItemViewPrivate::draggablePaintPairs(const QModelIn
for (const auto &index : indexes) {
const QRect current = q->visualRect(index);
if (current.intersects(viewportRect)) {
- QItemViewPaintPair p = { current, index };
- ret += p;
+ ret.append({current, index});
rect |= current;
}
}
diff --git a/src/widgets/itemviews/qabstractitemview.h b/src/widgets/itemviews/qabstractitemview.h
index 6be776ec52..6a007da348 100644
--- a/src/widgets/itemviews/qabstractitemview.h
+++ b/src/widgets/itemviews/qabstractitemview.h
@@ -212,6 +212,7 @@ public:
void openPersistentEditor(const QModelIndex &index);
void closePersistentEditor(const QModelIndex &index);
+ bool isPersistentEditorOpen(const QModelIndex &index) const;
void setIndexWidget(const QModelIndex &index, QWidget *widget);
QWidget *indexWidget(const QModelIndex &index) const;
diff --git a/src/widgets/itemviews/qcolumnview.cpp b/src/widgets/itemviews/qcolumnview.cpp
index ea9bbb0fb9..d94f25de78 100644
--- a/src/widgets/itemviews/qcolumnview.cpp
+++ b/src/widgets/itemviews/qcolumnview.cpp
@@ -53,8 +53,6 @@
QT_BEGIN_NAMESPACE
-#define ANIMATION_DURATION_MSEC 150
-
/*!
\since 4.3
\class QColumnView
@@ -107,7 +105,6 @@ void QColumnViewPrivate::initialize()
q->setTextElideMode(Qt::ElideMiddle);
#ifndef QT_NO_ANIMATION
QObject::connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
- currentAnimation.setDuration(ANIMATION_DURATION_MSEC);
currentAnimation.setTargetObject(hbar);
currentAnimation.setPropertyName("value");
currentAnimation.setEasingCurve(QEasingCurve::InOutQuad);
@@ -330,7 +327,8 @@ void QColumnView::scrollTo(const QModelIndex &index, ScrollHint hint)
}
#ifndef QT_NO_ANIMATION
- if (style()->styleHint(QStyle::SH_Widget_Animate, 0, this)) {
+ if (const int animationDuration = style()->styleHint(QStyle::SH_Widget_Animation_Duration, 0, this)) {
+ d->currentAnimation.setDuration(animationDuration);
d->currentAnimation.setEndValue(newScrollbarValue);
d->currentAnimation.start();
} else
diff --git a/src/widgets/itemviews/qdirmodel.cpp b/src/widgets/itemviews/qdirmodel.cpp
index 2cf76262e6..449850c42e 100644
--- a/src/widgets/itemviews/qdirmodel.cpp
+++ b/src/widgets/itemviews/qdirmodel.cpp
@@ -1309,22 +1309,7 @@ QString QDirModelPrivate::size(const QModelIndex &index) const
// Nautilus - "9 items" (the number of children)
}
- // According to the Si standard KB is 1000 bytes, KiB is 1024
- // but on windows sizes are calulated by dividing by 1024 so we do what they do.
- const quint64 kb = 1024;
- const quint64 mb = 1024 * kb;
- const quint64 gb = 1024 * mb;
- const quint64 tb = 1024 * gb;
- quint64 bytes = n->info.size();
- if (bytes >= tb)
- return QFileSystemModel::tr("%1 TB").arg(QLocale().toString(qreal(bytes) / tb, 'f', 3));
- if (bytes >= gb)
- return QFileSystemModel::tr("%1 GB").arg(QLocale().toString(qreal(bytes) / gb, 'f', 2));
- if (bytes >= mb)
- return QFileSystemModel::tr("%1 MB").arg(QLocale().toString(qreal(bytes) / mb, 'f', 1));
- if (bytes >= kb)
- return QFileSystemModel::tr("%1 KB").arg(QLocale().toString(bytes / kb));
- return QFileSystemModel::tr("%1 byte(s)").arg(QLocale().toString(bytes));
+ return QLocale::system().formattedDataSize(n->info.size());
}
QString QDirModelPrivate::type(const QModelIndex &index) const
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 213cc96b03..d6db7deee7 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -2531,8 +2531,20 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e)
if (handle != -1 && (sectionResizeMode(handle) == Interactive)) {
if (!hasCursor)
setCursor(d->orientation == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor);
- } else if (hasCursor) {
- unsetCursor();
+ } else {
+ if (hasCursor)
+ unsetCursor();
+#ifndef QT_NO_STATUSTIP
+ int logical = logicalIndexAt(pos);
+ QString statusTip;
+ if (logical != -1)
+ statusTip = d->model->headerData(logical, d->orientation, Qt::StatusTipRole).toString();
+ if (d->shouldClearStatusTip || !statusTip.isEmpty()) {
+ QStatusTipEvent tip(statusTip);
+ QCoreApplication::sendEvent(d->parent, &tip);
+ d->shouldClearStatusTip = !statusTip.isEmpty();
+ }
+#endif // !QT_NO_STATUSTIP
}
#endif
return;
diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp
index 68c02e9edb..d9caebec8a 100644
--- a/src/widgets/itemviews/qitemdelegate.cpp
+++ b/src/widgets/itemviews/qitemdelegate.cpp
@@ -988,7 +988,7 @@ QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette,
painter.end();
QPixmap selected = QPixmap(QPixmap::fromImage(img));
- int n = (img.byteCount() >> 10) + 1;
+ int n = (img.sizeInBytes() >> 10) + 1;
if (QPixmapCache::cacheLimit() < n)
QPixmapCache::setCacheLimit(n);
diff --git a/src/widgets/itemviews/qlistview.cpp b/src/widgets/itemviews/qlistview.cpp
index 9e959c8e1e..0efee755a2 100644
--- a/src/widgets/itemviews/qlistview.cpp
+++ b/src/widgets/itemviews/qlistview.cpp
@@ -657,8 +657,7 @@ QItemViewPaintPairs QListViewPrivate::draggablePaintPairs(const QModelIndexList
for (const auto &index : indexes) {
if (std::binary_search(visibleIndexes.cbegin(), visibleIndexes.cend(), index)) {
const QRect current = q->visualRect(index);
- QItemViewPaintPair p = { current, index };
- ret += p;
+ ret.append({current, index});
rect |= current;
}
}
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index 21747d4e6e..95ad3f82d0 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -1616,7 +1616,7 @@ void QListWidget::editItem(QListWidgetItem *item)
Opens an editor for the given \a item. The editor remains open after
editing.
- \sa closePersistentEditor()
+ \sa closePersistentEditor(), isPersistentEditorOpen()
*/
void QListWidget::openPersistentEditor(QListWidgetItem *item)
{
@@ -1628,7 +1628,7 @@ void QListWidget::openPersistentEditor(QListWidgetItem *item)
/*!
Closes the persistent editor for the given \a item.
- \sa openPersistentEditor()
+ \sa openPersistentEditor(), isPersistentEditorOpen()
*/
void QListWidget::closePersistentEditor(QListWidgetItem *item)
{
@@ -1638,6 +1638,20 @@ void QListWidget::closePersistentEditor(QListWidgetItem *item)
}
/*!
+ \since 5.10
+
+ Returns whether a persistent editor is open for item \a item.
+
+ \sa openPersistentEditor(), closePersistentEditor()
+*/
+bool QListWidget::isPersistentEditorOpen(QListWidgetItem *item) const
+{
+ Q_D(const QListWidget);
+ const QModelIndex index = d->listModel()->index(item);
+ return QAbstractItemView::isPersistentEditorOpen(index);
+}
+
+/*!
\since 4.1
Returns the widget displayed in the given \a item.
diff --git a/src/widgets/itemviews/qlistwidget.h b/src/widgets/itemviews/qlistwidget.h
index 8471645fb0..50f4e2ac84 100644
--- a/src/widgets/itemviews/qlistwidget.h
+++ b/src/widgets/itemviews/qlistwidget.h
@@ -239,6 +239,8 @@ public:
void editItem(QListWidgetItem *item);
void openPersistentEditor(QListWidgetItem *item);
void closePersistentEditor(QListWidgetItem *item);
+ using QAbstractItemView::isPersistentEditorOpen;
+ bool isPersistentEditorOpen(QListWidgetItem *item) const;
QWidget *itemWidget(QListWidgetItem *item) const;
void setItemWidget(QListWidgetItem *item, QWidget *widget);
@@ -251,6 +253,9 @@ public:
bool isItemHidden(const QListWidgetItem *item) const;
void setItemHidden(const QListWidgetItem *item, bool hide);
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+protected:
+#endif
#if QT_CONFIG(draganddrop)
void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
#endif
@@ -284,6 +289,12 @@ protected:
virtual bool dropMimeData(int index, const QMimeData *data, Qt::DropAction action);
virtual Qt::DropActions supportedDropActions() const;
#endif
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+public:
+#else
+protected:
+#endif
QList<QListWidgetItem*> items(const QMimeData *data) const;
QModelIndex indexFromItem(QListWidgetItem *item) const;
diff --git a/src/widgets/itemviews/qtablewidget.cpp b/src/widgets/itemviews/qtablewidget.cpp
index 3ff75cc23b..bb1970e3ac 100644
--- a/src/widgets/itemviews/qtablewidget.cpp
+++ b/src/widgets/itemviews/qtablewidget.cpp
@@ -2220,7 +2220,7 @@ void QTableWidget::editItem(QTableWidgetItem *item)
/*!
Opens an editor for the give \a item. The editor remains open after editing.
- \sa closePersistentEditor()
+ \sa closePersistentEditor(), isPersistentEditorOpen()
*/
void QTableWidget::openPersistentEditor(QTableWidgetItem *item)
{
@@ -2234,7 +2234,7 @@ void QTableWidget::openPersistentEditor(QTableWidgetItem *item)
/*!
Closes the persistent editor for \a item.
- \sa openPersistentEditor()
+ \sa openPersistentEditor(), isPersistentEditorOpen()
*/
void QTableWidget::closePersistentEditor(QTableWidgetItem *item)
{
@@ -2246,6 +2246,20 @@ void QTableWidget::closePersistentEditor(QTableWidgetItem *item)
}
/*!
+ \since 5.10
+
+ Returns whether a persistent editor is open for item \a item.
+
+ \sa openPersistentEditor(), closePersistentEditor()
+*/
+bool QTableWidget::isPersistentEditorOpen(QTableWidgetItem *item) const
+{
+ Q_D(const QTableWidget);
+ const QModelIndex index = d->tableModel()->index(item);
+ return QAbstractItemView::isPersistentEditorOpen(index);
+}
+
+/*!
\since 4.1
Returns the widget displayed in the cell in the given \a row and \a column.
diff --git a/src/widgets/itemviews/qtablewidget.h b/src/widgets/itemviews/qtablewidget.h
index 3fecf194e4..9c231d5127 100644
--- a/src/widgets/itemviews/qtablewidget.h
+++ b/src/widgets/itemviews/qtablewidget.h
@@ -261,6 +261,8 @@ public:
void editItem(QTableWidgetItem *item);
void openPersistentEditor(QTableWidgetItem *item);
void closePersistentEditor(QTableWidgetItem *item);
+ using QAbstractItemView::isPersistentEditorOpen;
+ bool isPersistentEditorOpen(QTableWidgetItem *item) const;
QWidget *cellWidget(int row, int column) const;
void setCellWidget(int row, int column, QWidget *widget);
@@ -325,10 +327,18 @@ protected:
#endif
virtual bool dropMimeData(int row, int column, const QMimeData *data, Qt::DropAction action);
virtual Qt::DropActions supportedDropActions() const;
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+public:
+#else
+protected:
+#endif
QList<QTableWidgetItem*> items(const QMimeData *data) const;
QModelIndex indexFromItem(QTableWidgetItem *item) const;
QTableWidgetItem *itemFromIndex(const QModelIndex &index) const;
+
+protected:
#if QT_CONFIG(draganddrop)
void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
#endif
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 2abb1a9c14..61721143ef 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -3043,7 +3043,7 @@ void QTreeViewPrivate::initialize()
header->setDefaultAlignment(Qt::AlignLeft|Qt::AlignVCenter);
q->setHeader(header);
#ifndef QT_NO_ANIMATION
- animationsEnabled = q->style()->styleHint(QStyle::SH_Widget_Animate, 0, q);
+ animationsEnabled = q->style()->styleHint(QStyle::SH_Widget_Animation_Duration, 0, q) > 0;
QObject::connect(&animatedOperation, SIGNAL(finished()), q, SLOT(_q_endAnimatedOperation()));
#endif //QT_NO_ANIMATION
}
diff --git a/src/widgets/itemviews/qtreewidget.cpp b/src/widgets/itemviews/qtreewidget.cpp
index 337089056d..d7b46a0835 100644
--- a/src/widgets/itemviews/qtreewidget.cpp
+++ b/src/widgets/itemviews/qtreewidget.cpp
@@ -2906,7 +2906,7 @@ void QTreeWidget::editItem(QTreeWidgetItem *item, int column)
/*!
Opens a persistent editor for the \a item in the given \a column.
- \sa closePersistentEditor()
+ \sa closePersistentEditor(), isPersistentEditorOpen()
*/
void QTreeWidget::openPersistentEditor(QTreeWidgetItem *item, int column)
@@ -2921,7 +2921,7 @@ void QTreeWidget::openPersistentEditor(QTreeWidgetItem *item, int column)
This function has no effect if no persistent editor is open for this
combination of item and column.
- \sa openPersistentEditor()
+ \sa openPersistentEditor(), isPersistentEditorOpen()
*/
void QTreeWidget::closePersistentEditor(QTreeWidgetItem *item, int column)
@@ -2931,6 +2931,21 @@ void QTreeWidget::closePersistentEditor(QTreeWidgetItem *item, int column)
}
/*!
+ \since 5.10
+
+ Returns whether a persistent editor is open for item \a item in
+ column \a column.
+
+ \sa openPersistentEditor(), closePersistentEditor()
+*/
+
+bool QTreeWidget::isPersistentEditorOpen(QTreeWidgetItem *item, int column) const
+{
+ Q_D(const QTreeWidget);
+ return QAbstractItemView::isPersistentEditorOpen(d->index(item, column));
+}
+
+/*!
\since 4.1
Returns the widget displayed in the cell specified by \a item and the given \a column.
diff --git a/src/widgets/itemviews/qtreewidget.h b/src/widgets/itemviews/qtreewidget.h
index 3bdeae08d8..783627cde9 100644
--- a/src/widgets/itemviews/qtreewidget.h
+++ b/src/widgets/itemviews/qtreewidget.h
@@ -299,6 +299,8 @@ public:
void editItem(QTreeWidgetItem *item, int column = 0);
void openPersistentEditor(QTreeWidgetItem *item, int column = 0);
void closePersistentEditor(QTreeWidgetItem *item, int column = 0);
+ using QAbstractItemView::isPersistentEditorOpen;
+ bool isPersistentEditorOpen(QTreeWidgetItem *item, int column = 0) const;
QWidget *itemWidget(QTreeWidgetItem *item, int column) const;
void setItemWidget(QTreeWidgetItem *item, int column, QWidget *widget);
@@ -354,11 +356,19 @@ protected:
virtual bool dropMimeData(QTreeWidgetItem *parent, int index,
const QMimeData *data, Qt::DropAction action);
virtual Qt::DropActions supportedDropActions() const;
+
+#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
+public:
+#else
+protected:
+#endif
QList<QTreeWidgetItem*> items(const QMimeData *data) const;
QModelIndex indexFromItem(const QTreeWidgetItem *item, int column = 0) const;
QModelIndex indexFromItem(QTreeWidgetItem *item, int column = 0) const; // ### Qt 6: remove
QTreeWidgetItem *itemFromIndex(const QModelIndex &index) const;
+
+protected:
#if QT_CONFIG(draganddrop)
void dropEvent(QDropEvent *event) Q_DECL_OVERRIDE;
#endif
diff --git a/src/widgets/kernel/qaction.cpp b/src/widgets/kernel/qaction.cpp
index 7dd2f72f03..57b1f31188 100644
--- a/src/widgets/kernel/qaction.cpp
+++ b/src/widgets/kernel/qaction.cpp
@@ -45,6 +45,7 @@
#include "qapplication.h"
#include "qevent.h"
#include "qlist.h"
+#include "qstylehints.h"
#include <private/qshortcutmap_p.h>
#include <private/qapplication_p.h>
#include <private/qmenu_p.h>
@@ -75,6 +76,7 @@ static QString qt_strippedText(QString s)
QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0),
visible(1), forceInvisible(0), checkable(0), checked(0), separator(0), fontSet(false),
iconVisibleInMenu(-1),
+ shortcutVisibleInContextMenu(-1),
menuRole(QAction::TextHeuristicRole),
priority(QAction::NormalPriority)
{
@@ -1276,8 +1278,7 @@ void QAction::setIconVisibleInMenu(bool visible)
d->iconVisibleInMenu = visible;
// Only send data changed if we really need to.
if (oldValue != -1
- || (oldValue == -1
- && visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus))) {
+ || visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus)) {
d->sendDataChanged();
}
}
@@ -1292,6 +1293,46 @@ bool QAction::isIconVisibleInMenu() const
return d->iconVisibleInMenu;
}
+/*!
+ \property QAction::shortcutVisibleInContextMenu
+ \brief Whether or not an action should show a shortcut in a context menu
+ \since 5.10
+
+ In some applications, it may make sense to have actions with shortcuts in
+ context menus. If true, the shortcut (if valid) is shown when the action is
+ shown via a context menu, when it is false, it is not shown.
+
+ The default is to follow whether the Qt::AA_DontShowShortcutsInContextMenus attribute
+ is set for the application, falling back to the widget style hint.
+ Explicitly setting this property overrides the presence (or abscence) of the attribute.
+
+ \sa QAction::shortcut, QCoreApplication::setAttribute()
+*/
+void QAction::setShortcutVisibleInContextMenu(bool visible)
+{
+ Q_D(QAction);
+ if (d->shortcutVisibleInContextMenu == -1 || visible != bool(d->shortcutVisibleInContextMenu)) {
+ int oldValue = d->shortcutVisibleInContextMenu;
+ d->shortcutVisibleInContextMenu = visible;
+ // Only send data changed if we really need to.
+ if (oldValue != -1
+ || visible == !QApplication::instance()->testAttribute(Qt::AA_DontShowShortcutsInContextMenus)) {
+ d->sendDataChanged();
+ }
+ }
+}
+
+bool QAction::isShortcutVisibleInContextMenu() const
+{
+ Q_D(const QAction);
+ if (d->shortcutVisibleInContextMenu == -1) {
+ if (QApplication::instance()->testAttribute(Qt::AA_DontShowIconsInMenus))
+ return false;
+ return qApp->styleHints()->showShortcutsInContextMenus();
+ }
+ return d->shortcutVisibleInContextMenu;
+}
+
#ifndef QT_NO_DEBUG_STREAM
Q_WIDGETS_EXPORT QDebug operator<<(QDebug d, const QAction *action)
{
diff --git a/src/widgets/kernel/qaction.h b/src/widgets/kernel/qaction.h
index 97948a2457..d211016931 100644
--- a/src/widgets/kernel/qaction.h
+++ b/src/widgets/kernel/qaction.h
@@ -80,6 +80,7 @@ class Q_WIDGETS_EXPORT QAction : public QObject
Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY changed)
Q_PROPERTY(MenuRole menuRole READ menuRole WRITE setMenuRole NOTIFY changed)
Q_PROPERTY(bool iconVisibleInMenu READ isIconVisibleInMenu WRITE setIconVisibleInMenu NOTIFY changed)
+ Q_PROPERTY(bool shortcutVisibleInContextMenu READ isShortcutVisibleInContextMenu WRITE setShortcutVisibleInContextMenu NOTIFY changed)
Q_PROPERTY(Priority priority READ priority WRITE setPriority)
public:
@@ -168,6 +169,8 @@ public:
void setIconVisibleInMenu(bool visible);
bool isIconVisibleInMenu() const;
+ void setShortcutVisibleInContextMenu(bool show);
+ bool isShortcutVisibleInContextMenu() const;
QWidget *parentWidget() const;
diff --git a/src/widgets/kernel/qaction_p.h b/src/widgets/kernel/qaction_p.h
index 8ee71a5ff0..6813ca08f6 100644
--- a/src/widgets/kernel/qaction_p.h
+++ b/src/widgets/kernel/qaction_p.h
@@ -105,7 +105,8 @@ public:
uint separator : 1;
uint fontSet : 1;
- int iconVisibleInMenu : 3; // Only has values -1, 0, and 1
+ int iconVisibleInMenu : 2; // Only has values -1, 0, and 1
+ int shortcutVisibleInContextMenu : 2; // Only has values -1, 0, and 1
QAction::MenuRole menuRole;
QAction::Priority priority;
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index d2f4161297..09162b9ab4 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1234,7 +1234,7 @@ void QApplication::setStyle(QStyle *style)
Requests a QStyle object for \a style from the QStyleFactory.
The string must be one of the QStyleFactory::keys(), typically one of
- "windows", "fusion", "windowsxp", or "macintosh". Style
+ "windows", "windowsvista", "fusion", or "macintosh". Style
names are case insensitive.
Returns 0 if an unknown \a style is passed, otherwise the QStyle object
@@ -1477,8 +1477,8 @@ void QApplicationPrivate::setPalette_helper(const QPalette &palette, const char*
"selection-background-color" and "alternate-background-color".
\note Some styles do not use the palette for all drawing, for instance, if
- they make use of native theme engines. This is the case for the Windows XP,
- Windows Vista, and \macos styles.
+ they make use of native theme engines. This is the case for the
+ Windows Vista and \macos styles.
\sa QWidget::setPalette(), palette(), QStyle::polish()
*/
@@ -2733,7 +2733,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
case enter/leave events are genereated by the underlying windowing system.
*/
extern QPointer<QWidget> qt_last_mouse_receiver;
-extern QWidget *qt_button_down;
+extern Q_WIDGETS_EXPORT QWidget *qt_button_down;
void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget)
{
#ifndef QT_NO_CURSOR
@@ -2962,6 +2962,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
// required in order to support Qt Test synthesized events. Real mouse
// and keyboard state updates from the platform plugin are managed by
// QGuiApplicationPrivate::process(Mouse|Wheel|Key|Touch|Tablet)Event();
+ // ### FIXME: Qt Test should not call qapp->notify(), but rather route
+ // the events through the proper QPA interface. This is required to
+ // properly generate all other events such as enter/leave etc.
switch (e->type()) {
case QEvent::MouseButtonPress:
{
@@ -3758,7 +3761,6 @@ static void grabForPopup(QWidget *popup)
}
}
-extern QWidget *qt_button_down;
extern QWidget *qt_popup_down;
extern bool qt_replay_popup_mouse_event;
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 1a189cb2b9..1bd114aad7 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -92,7 +92,7 @@ extern QClipboard *qt_clipboard;
#endif
typedef QHash<QByteArray, QFont> FontHash;
-FontHash *qt_app_fonts_hash();
+Q_WIDGETS_EXPORT FontHash *qt_app_fonts_hash();
typedef QHash<QByteArray, QPalette> PaletteHash;
PaletteHash *qt_app_palettes_hash();
diff --git a/src/widgets/kernel/qboxlayout.cpp b/src/widgets/kernel/qboxlayout.cpp
index f2e3df5314..588cec2b95 100644
--- a/src/widgets/kernel/qboxlayout.cpp
+++ b/src/widgets/kernel/qboxlayout.cpp
@@ -873,15 +873,9 @@ void QBoxLayout::insertSpacing(int index, int size)
else
b = QLayoutPrivate::createSpacerItem(this, 0, size, QSizePolicy::Minimum, QSizePolicy::Fixed);
- QT_TRY {
- QBoxLayoutItem *it = new QBoxLayoutItem(b);
- it->magic = true;
- d->list.insert(index, it);
-
- } QT_CATCH(...) {
- delete b;
- QT_RETHROW;
- }
+ QBoxLayoutItem *it = new QBoxLayoutItem(b);
+ it->magic = true;
+ d->list.insert(index, it);
invalidate();
}
@@ -985,20 +979,8 @@ void QBoxLayout::insertWidget(int index, QWidget *widget, int stretch,
QWidgetItem *b = QLayoutPrivate::createWidgetItem(this, widget);
b->setAlignment(alignment);
- QBoxLayoutItem *it;
- QT_TRY{
- it = new QBoxLayoutItem(b, stretch);
- } QT_CATCH(...) {
- delete b;
- QT_RETHROW;
- }
-
- QT_TRY{
- d->list.insert(index, it);
- } QT_CATCH(...) {
- delete it;
- QT_RETHROW;
- }
+ QBoxLayoutItem *it = new QBoxLayoutItem(b, stretch);
+ d->list.insert(index, it);
invalidate();
}
diff --git a/src/widgets/kernel/qdesktopwidget.qdoc b/src/widgets/kernel/qdesktopwidget.qdoc
index 27d05ece8c..fdf6a27597 100644
--- a/src/widgets/kernel/qdesktopwidget.qdoc
+++ b/src/widgets/kernel/qdesktopwidget.qdoc
@@ -152,7 +152,7 @@
on \macos, or the task bar on Windows). The default screen is used if
\a screen is -1.
- \sa screenNumber(), screenGeometry()
+ \sa screenNumber(), screenGeometry(), QScreen::availableGeometry()
*/
/*!
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 2e5c2c53bd..cfa4246455 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -122,7 +122,7 @@ QGestureManager::~QGestureManager()
Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *recognizer)
{
- QGesture *dummy = recognizer->create(0);
+ const QScopedPointer<QGesture> dummy(recognizer->create(nullptr));
if (Q_UNLIKELY(!dummy)) {
qWarning("QGestureManager::registerGestureRecognizer: "
"the recognizer fails to create a gesture object, skipping registration.");
@@ -135,7 +135,6 @@ Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *r
type = Qt::GestureType(m_lastCustomGestureId);
}
m_recognizers.insertMulti(type, recognizer);
- delete dummy;
return type;
}
@@ -143,10 +142,9 @@ void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
{
QList<QGestureRecognizer *> list = m_recognizers.values(type);
while (QGestureRecognizer *recognizer = m_recognizers.take(type)) {
- if (!m_obsoleteGestures.contains(recognizer)) {
- // inserting even an empty QSet will cause the recognizer to be deleted on destruction of the manager
- m_obsoleteGestures.insert(recognizer, QSet<QGesture *>());
- }
+ // ensuring an entry exists causes the recognizer to be deleted on destruction of the manager
+ auto &gestures = m_obsoleteGestures[recognizer];
+ Q_UNUSED(gestures);
}
foreach (QGesture *g, m_gestureToRecognizer.keys()) {
QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g);
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 218d3c4a46..5bc408a8cd 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -567,7 +567,8 @@ public:
paintDevice(0),
updateBehavior(QOpenGLWidget::NoPartialUpdate),
requestedSamples(0),
- inPaintGL(false)
+ inPaintGL(false),
+ textureFormat(0)
{
requestedFormat = QSurfaceFormat::defaultFormat();
}
@@ -576,6 +577,7 @@ public:
void recreateFbo();
GLuint textureId() const Q_DECL_OVERRIDE;
+ QPlatformTextureList::Flags textureListFlags() Q_DECL_OVERRIDE;
void initialize();
void invokeUserPaint();
@@ -606,6 +608,7 @@ public:
QOpenGLWidget::UpdateBehavior updateBehavior;
int requestedSamples;
bool inPaintGL;
+ GLenum textureFormat;
};
void QOpenGLWidgetPaintDevicePrivate::beginPaint()
@@ -663,6 +666,35 @@ GLuint QOpenGLWidgetPrivate::textureId() const
return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0);
}
+#ifndef GL_SRGB
+#define GL_SRGB 0x8C40
+#endif
+#ifndef GL_SRGB8
+#define GL_SRGB8 0x8C41
+#endif
+#ifndef GL_SRGB_ALPHA
+#define GL_SRGB_ALPHA 0x8C42
+#endif
+#ifndef GL_SRGB8_ALPHA8
+#define GL_SRGB8_ALPHA8 0x8C43
+#endif
+
+QPlatformTextureList::Flags QOpenGLWidgetPrivate::textureListFlags()
+{
+ QPlatformTextureList::Flags flags = QWidgetPrivate::textureListFlags();
+ switch (textureFormat) {
+ case GL_SRGB:
+ case GL_SRGB8:
+ case GL_SRGB_ALPHA:
+ case GL_SRGB8_ALPHA8:
+ flags |= QPlatformTextureList::TextureIsSrgb;
+ break;
+ default:
+ break;
+ }
+ return flags;
+}
+
void QOpenGLWidgetPrivate::reset()
{
Q_Q(QOpenGLWidget);
@@ -712,12 +744,16 @@ void QOpenGLWidgetPrivate::recreateFbo()
QOpenGLFramebufferObjectFormat format;
format.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
format.setSamples(samples);
+ if (textureFormat)
+ format.setInternalTextureFormat(textureFormat);
const QSize deviceSize = q->size() * q->devicePixelRatioF();
fbo = new QOpenGLFramebufferObject(deviceSize, format);
if (samples > 0)
resolvedFbo = new QOpenGLFramebufferObject(deviceSize);
+ textureFormat = fbo->format().internalTextureFormat();
+
fbo->bind();
context->functions()->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
@@ -755,10 +791,8 @@ void QOpenGLWidgetPrivate::initialize()
// texture usable by the underlying window's backingstore.
QWidget *tlw = q->window();
QOpenGLContext *shareContext = get(tlw)->shareContext();
- if (Q_UNLIKELY(!shareContext)) {
- qWarning("QOpenGLWidget: Cannot be used without a context shared with the toplevel.");
- return;
- }
+ // If shareContext is null, showing content on-screen will not work.
+ // However, offscreen rendering and grabFramebuffer() will stay fully functional.
// Do not include the sample count. Requesting a multisampled context is not necessary
// since we render into an FBO, never to an actual surface. What's more, attempting to
@@ -768,25 +802,31 @@ void QOpenGLWidgetPrivate::initialize()
requestedFormat.setSamples(0);
QScopedPointer<QOpenGLContext> ctx(new QOpenGLContext);
- ctx->setShareContext(shareContext);
ctx->setFormat(requestedFormat);
- ctx->setScreen(shareContext->screen());
+ if (shareContext) {
+ ctx->setShareContext(shareContext);
+ ctx->setScreen(shareContext->screen());
+ }
if (Q_UNLIKELY(!ctx->create())) {
qWarning("QOpenGLWidget: Failed to create context");
return;
}
- // Propagate settings that make sense only for the tlw.
- QSurfaceFormat tlwFormat = tlw->windowHandle()->format();
- if (requestedFormat.swapInterval() != tlwFormat.swapInterval()) {
- // Most platforms will pick up the changed swap interval on the next
- // makeCurrent or swapBuffers.
- tlwFormat.setSwapInterval(requestedFormat.swapInterval());
- tlw->windowHandle()->setFormat(tlwFormat);
- }
- if (requestedFormat.swapBehavior() != tlwFormat.swapBehavior()) {
- tlwFormat.setSwapBehavior(requestedFormat.swapBehavior());
- tlw->windowHandle()->setFormat(tlwFormat);
+ // Propagate settings that make sense only for the tlw. Note that this only
+ // makes sense for properties that get picked up even after the native
+ // window is created.
+ if (tlw->windowHandle()) {
+ QSurfaceFormat tlwFormat = tlw->windowHandle()->format();
+ if (requestedFormat.swapInterval() != tlwFormat.swapInterval()) {
+ // Most platforms will pick up the changed swap interval on the next
+ // makeCurrent or swapBuffers.
+ tlwFormat.setSwapInterval(requestedFormat.swapInterval());
+ tlw->windowHandle()->setFormat(tlwFormat);
+ }
+ if (requestedFormat.swapBehavior() != tlwFormat.swapBehavior()) {
+ tlwFormat.setSwapBehavior(requestedFormat.swapBehavior());
+ tlw->windowHandle()->setFormat(tlwFormat);
+ }
}
// The top-level window's surface is not good enough since it causes way too
@@ -880,9 +920,14 @@ extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_
QImage QOpenGLWidgetPrivate::grabFramebuffer()
{
Q_Q(QOpenGLWidget);
+
+ initialize();
if (!initialized)
return QImage();
+ if (!fbo) // could be completely offscreen, without ever getting a resize event
+ recreateFbo();
+
if (!inPaintGL)
render();
@@ -1000,7 +1045,6 @@ QOpenGLWidget::UpdateBehavior QOpenGLWidget::updateBehavior() const
*/
void QOpenGLWidget::setFormat(const QSurfaceFormat &format)
{
- Q_UNUSED(format);
Q_D(QOpenGLWidget);
if (Q_UNLIKELY(d->initialized)) {
qWarning("QOpenGLWidget: Already initialized, setting the format has no effect");
@@ -1033,6 +1077,47 @@ QSurfaceFormat QOpenGLWidget::format() const
}
/*!
+ Sets a custom internal texture format of \a texFormat.
+
+ When working with sRGB framebuffers, it will be necessary to specify a
+ format like \c{GL_SRGB8_ALPHA8}. This can be achieved by calling this
+ function.
+
+ \note This function has no effect if called after the widget has already
+ been shown and thus it performed initialization.
+
+ \note This function will typically have to be used in combination with a
+ QSurfaceFormat::setDefaultFormat() call that sets the color space to
+ QSurfaceFormat::sRGBColorSpace.
+
+ \since 5.10
+ */
+void QOpenGLWidget::setTextureFormat(GLenum texFormat)
+{
+ Q_D(QOpenGLWidget);
+ if (Q_UNLIKELY(d->initialized)) {
+ qWarning("QOpenGLWidget: Already initialized, setting the internal texture format has no effect");
+ return;
+ }
+
+ d->textureFormat = texFormat;
+}
+
+/*!
+ \return the active internal texture format if the widget has already
+ initialized, the requested format if one was set but the widget has not yet
+ been made visible, or 0 if setTextureFormat() was not called and the widget
+ has not yet been made visible.
+
+ \since 5.10
+ */
+GLenum QOpenGLWidget::textureFormat() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->textureFormat;
+}
+
+/*!
\return \e true if the widget and OpenGL resources, like the context, have
been successfully initialized. Note that the return value is always false
until the widget is shown.
@@ -1293,7 +1378,7 @@ int QOpenGLWidget::metric(QPaintDevice::PaintDeviceMetric metric) const
if (window)
return int(window->devicePixelRatio() * devicePixelRatioFScale());
else
- return 1.0;
+ return int(devicePixelRatioFScale());
default:
qWarning("QOpenGLWidget::metric(): unknown metric %d", metric);
return 0;
@@ -1346,7 +1431,14 @@ bool QOpenGLWidget::event(QEvent *e)
break;
// FALLTHROUGH
case QEvent::Show: // reparenting may not lead to a resize so reinitalize on Show too
- if (!d->initialized && !size().isEmpty() && window() && window()->windowHandle()) {
+ if (d->initialized && window()->windowHandle()
+ && d->context->shareContext() != QWidgetPrivate::get(window())->shareContext())
+ {
+ // Special case: did grabFramebuffer() for a hidden widget that then became visible.
+ // Recreate all resources since the context now needs to share with the TLW's.
+ d->reset();
+ }
+ if (!d->initialized && !size().isEmpty() && window()->windowHandle()) {
d->initialize();
if (d->initialized)
d->recreateFbo();
diff --git a/src/widgets/kernel/qopenglwidget.h b/src/widgets/kernel/qopenglwidget.h
index b60d79bedb..c0a6e41522 100644
--- a/src/widgets/kernel/qopenglwidget.h
+++ b/src/widgets/kernel/qopenglwidget.h
@@ -72,6 +72,9 @@ public:
void setFormat(const QSurfaceFormat &format);
QSurfaceFormat format() const;
+ GLenum textureFormat() const;
+ void setTextureFormat(GLenum texFormat);
+
bool isValid() const;
void makeCurrent();
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 3d870fc5cc..c6b3e31747 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -67,7 +67,6 @@
# include <private/qmainwindowlayout_p.h>
#endif
#include <qpa/qplatformwindow.h>
-#include <qpa/qplatformbackingstore.h>
#include "private/qwidgetwindow_p.h"
#include "qpainter.h"
#include "qtooltip.h"
@@ -1422,7 +1421,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
if (!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow())
return; // we only care about real toplevels
- QWindow *win = topData()->window;
+ QWidgetWindow *win = topData()->window;
// topData() ensures the extra is created but does not ensure 'window' is non-null
// in case the extra was already valid.
if (!win) {
@@ -1439,7 +1438,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
if (q->testAttribute(Qt::WA_ShowWithoutActivating))
win->setProperty("_q_showWithoutActivating", QVariant(true));
if (q->testAttribute(Qt::WA_MacAlwaysShowToolWindow))
- win->setProperty("_q_macAlwaysShowToolWindow", QVariant::fromValue(QVariant(true)));
+ win->setProperty("_q_macAlwaysShowToolWindow", QVariant(true));
setNetWmWindowTypes(true); // do nothing if none of WA_X11NetWmWindowType* is set
win->setFlags(data.window_flags);
fixPosIncludesFrame();
@@ -1523,7 +1522,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
q->setAttribute(Qt::WA_OutsideWSRange, true);
} else if (q->isVisible()) {
// If widget is already shown, set window visible, too
- win->setVisible(true);
+ win->setNativeWindowVisibility(true);
}
}
@@ -2109,14 +2108,15 @@ QRegion QWidgetPrivate::clipRegion() const
return r;
}
-void QWidgetPrivate::setSystemClip(QPaintDevice *paintDevice, const QRegion &region)
+void QWidgetPrivate::setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region)
{
// Transform the system clip region from device-independent pixels to device pixels
- QPaintEngine *paintEngine = paintDevice->paintEngine();
QTransform scaleTransform;
- const qreal devicePixelRatio = paintDevice->devicePixelRatioF();
scaleTransform.scale(devicePixelRatio, devicePixelRatio);
- paintEngine->d_func()->systemClip = scaleTransform.map(region);
+
+ paintEngine->d_func()->baseSystemClip = region;
+ paintEngine->d_func()->setSystemTransform(scaleTransform);
+
}
#if QT_CONFIG(graphicseffect)
@@ -2645,11 +2645,7 @@ WId QWidget::effectiveWinId() const
QWindow *QWidget::windowHandle() const
{
Q_D(const QWidget);
- QTLWExtra *extra = d->maybeTopData();
- if (extra)
- return extra->window;
-
- return 0;
+ return d->windowHandle();
}
#ifndef QT_NO_STYLE_STYLESHEET
@@ -3044,17 +3040,6 @@ void QWidget::overrideWindowState(Qt::WindowStates newstate)
QApplication::sendEvent(this, &e);
}
-Qt::WindowState effectiveState(Qt::WindowStates state)
-{
- if (state & Qt::WindowMinimized)
- return Qt::WindowMinimized;
- else if (state & Qt::WindowFullScreen)
- return Qt::WindowFullScreen;
- else if (state & Qt::WindowMaximized)
- return Qt::WindowMaximized;
- return Qt::WindowNoState;
-}
-
/*!
\fn void QWidget::setWindowState(Qt::WindowStates windowState)
@@ -3096,19 +3081,17 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
data->window_state = newstate;
data->in_set_window_state = 1;
- Qt::WindowState newEffectiveState = effectiveState(newstate);
- Qt::WindowState oldEffectiveState = effectiveState(oldstate);
- if (isWindow() && newEffectiveState != oldEffectiveState) {
+ if (isWindow()) {
// Ensure the initial size is valid, since we store it as normalGeometry below.
if (!testAttribute(Qt::WA_Resized) && !isVisible())
adjustSize();
d->createTLExtra();
- if (oldEffectiveState == Qt::WindowNoState)
+ if (!(oldstate & (Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen)))
d->topData()->normalGeometry = geometry();
Q_ASSERT(windowHandle());
- windowHandle()->setWindowState(newEffectiveState);
+ windowHandle()->setWindowStates(newstate & ~Qt::WindowActive);
}
data->in_set_window_state = 0;
@@ -4529,7 +4512,7 @@ void QWidget::setForegroundRole(QPalette::ColorRole role)
The default depends on the system environment. QApplication maintains a
system/theme palette which serves as a default for all widgets. There may
also be special palette defaults for certain types of widgets (e.g., on
- Windows XP and Vista, all classes that derive from QMenuBar have a special
+ Windows Vista, all classes that derive from QMenuBar have a special
default palette). You can also define default palettes for widgets
yourself by passing a custom palette and the name of a widget to
QApplication::setPalette(). Finally, the style always has the option of
@@ -4547,8 +4530,8 @@ void QWidget::setForegroundRole(QPalette::ColorRole role)
The current style, which is used to render the content of all standard Qt
widgets, is free to choose colors and brushes from the widget palette, or
in some cases, to ignore the palette (partially, or completely). In
- particular, certain styles like GTK style, Mac style, Windows XP, and
- Vista style, depend on third party APIs to render the content of widgets,
+ particular, certain styles like GTK style, Mac style, and Windows Vista
+ style, depend on third party APIs to render the content of widgets,
and these styles typically do not follow the palette. Because of this,
assigning roles to a widget's palette is not guaranteed to change the
appearance of the widget. Instead, you may choose to apply a \l
@@ -4710,7 +4693,7 @@ void QWidgetPrivate::updateSystemBackground()
The current style, which is used to render the content of all standard Qt
widgets, is free to choose to use the widget font, or in some cases, to
ignore it (partially, or completely). In particular, certain styles like
- GTK style, Mac style, Windows XP, and Vista style, apply special
+ GTK style, Mac style, and Windows Vista style, apply special
modifications to the widget font to match the platform's native look and
feel. Because of this, assigning properties to a widget's font is not
guaranteed to change the appearance of the widget. Instead, you may choose
@@ -5212,6 +5195,7 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
// Save current system clip, viewport and transform,
const QTransform oldTransform = enginePriv->systemTransform;
const QRegion oldSystemClip = enginePriv->systemClip;
+ const QRegion oldBaseClip = enginePriv->baseSystemClip;
const QRegion oldSystemViewport = enginePriv->systemViewport;
// This ensures that all painting triggered by render() is clipped to the current engine clip.
@@ -5225,9 +5209,8 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
d->render(target, targetOffset, toBePainted, renderFlags);
// Restore system clip, viewport and transform.
- enginePriv->setSystemViewport(oldSystemViewport);
- enginePriv->setSystemTransform(oldTransform);
- enginePriv->systemClip = oldSystemClip;
+ enginePriv->baseSystemClip = oldBaseClip;
+ enginePriv->setSystemTransformAndViewport(oldTransform, oldSystemViewport);
enginePriv->systemStateChanged();
// Restore shared painter.
@@ -5519,12 +5502,12 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
QWidgetPaintContext context(pdev, rgn, offset, flags, sharedPainter, backingStore);
sourced->context = &context;
if (!sharedPainter) {
- setSystemClip(pdev, rgn.translated(offset));
+ setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), rgn.translated(offset));
QPainter p(pdev);
p.translate(offset);
context.painter = &p;
graphicsEffect->draw(&p);
- setSystemClip(pdev, QRegion());
+ setSystemClip(pdev->paintEngine(), 1, QRegion());
} else {
context.painter = sharedPainter;
if (sharedPainter->worldTransform() != sourced->lastEffectTransform) {
@@ -5533,7 +5516,9 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
sharedPainter->save();
sharedPainter->translate(offset);
+ setSystemClip(sharedPainter->paintEngine(), sharedPainter->device()->devicePixelRatioF(), rgn.translated(offset));
graphicsEffect->draw(sharedPainter);
+ setSystemClip(sharedPainter->paintEngine(), 1, QRegion());
sharedPainter->restore();
}
sourced->context = 0;
@@ -5585,7 +5570,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
#endif
if (sharedPainter)
- setSystemClip(pdev, toBePainted);
+ setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted);
else
paintEngine->d_func()->systemRect = q->data->crect;
@@ -5603,7 +5588,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
}
if (!sharedPainter)
- setSystemClip(pdev, toBePainted.translated(offset));
+ setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), toBePainted.translated(offset));
if (!onScreen && !asRoot && !isOpaque && q->testAttribute(Qt::WA_TintedBackground)) {
#ifndef QT_NO_OPENGL
@@ -5673,7 +5658,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
else
paintEngine->d_func()->currentClipDevice = 0;
- setSystemClip(pdev, QRegion());
+ setSystemClip(pdev->paintEngine(), 1, QRegion());
}
q->setAttribute(Qt::WA_WState_InPaintEvent, false);
if (Q_UNLIKELY(q->paintingActive()))
@@ -7975,7 +7960,7 @@ void QWidgetPrivate::show_sys()
{
Q_Q(QWidget);
- QWindow *window = q->windowHandle();
+ QWidgetWindow *window = windowHandle();
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
invalidateBuffer(q->rect());
@@ -8022,7 +8007,7 @@ void QWidgetPrivate::show_sys()
qt_qpa_set_cursor(q, false); // Needed in case cursor was set before show
#endif
invalidateBuffer(q->rect());
- window->setVisible(true);
+ window->setNativeWindowVisibility(true);
// Was the window moved by the Window system or QPlatformWindow::initialGeometry() ?
if (window->isTopLevel()) {
const QPoint crectTopLeft = q->data->crect.topLeft();
@@ -8114,7 +8099,7 @@ void QWidgetPrivate::hide_sys()
{
Q_Q(QWidget);
- QWindow *window = q->windowHandle();
+ QWidgetWindow *window = windowHandle();
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
q->setAttribute(Qt::WA_Mapped, false);
@@ -8144,7 +8129,7 @@ void QWidgetPrivate::hide_sys()
}
if (window)
- window->setVisible(false);
+ window->setNativeWindowVisibility(false);
}
/*!
@@ -10021,6 +10006,7 @@ void QWidget::hideEvent(QHideEvent *)
\table
\header \li Platform \li Event Type Identifier \li Message Type \li Result Type
\row \li Windows \li "windows_generic_MSG" \li MSG * \li LRESULT
+ \row \li macOS \li "NSEvent" \li NSEvent * \li
\endtable
*/
@@ -12252,10 +12238,9 @@ QOpenGLContext *QWidgetPrivate::shareContext() const
#ifdef QT_NO_OPENGL
return 0;
#else
- if (Q_UNLIKELY(!extra || !extra->topextra || !extra->topextra->window)) {
- qWarning("Asking for share context for widget that does not have a window handle");
+ if (Q_UNLIKELY(!extra || !extra->topextra || !extra->topextra->window))
return 0;
- }
+
QWidgetPrivate *that = const_cast<QWidgetPrivate *>(this);
if (!extra->topextra->shareContext) {
QOpenGLContext *ctx = new QOpenGLContext;
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index e2affa802c..85214e4bd7 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -71,19 +71,20 @@
#include "QtWidgets/qgraphicsscene.h"
#include "QtWidgets/qgraphicsview.h"
#include <private/qgesture_p.h>
+#include <qpa/qplatformbackingstore.h>
QT_BEGIN_NAMESPACE
// Extra QWidget data
// - to minimize memory usage for members that are seldom used.
// - top-level widgets have extra extra data to reduce cost further
+class QWidgetWindow;
class QPaintEngine;
class QPixmap;
class QWidgetBackingStore;
class QGraphicsProxyWidget;
class QWidgetItemV2;
class QOpenGLContext;
-class QPlatformTextureList;
class QStyle;
@@ -162,7 +163,7 @@ struct QTLWExtra {
QWidgetBackingStoreTracker backingStoreTracker;
QBackingStore *backingStore;
QPainter *sharedPainter;
- QWindow *window;
+ QWidgetWindow *window;
QOpenGLContext *shareContext;
// Implicit pointers (shared_null).
@@ -340,6 +341,7 @@ public:
QPainter *sharedPainter() const;
void setSharedPainter(QPainter *painter);
QWidgetBackingStore *maybeBackingStore() const;
+ QWidgetWindow *windowHandle() const;
void init(QWidget *desktopWidget, Qt::WindowFlags f);
void create_sys(WId window, bool initializeWindow, bool destroyOldWindow);
void createRecursively();
@@ -411,7 +413,7 @@ public:
QRect clipRect() const;
QRegion clipRegion() const;
- void setSystemClip(QPaintDevice *paintDevice, const QRegion &region);
+ void setSystemClip(QPaintEngine *paintEngine, qreal devicePixelRatio, const QRegion &region);
void subtractOpaqueChildren(QRegion &rgn, const QRect &clipRect) const;
void subtractOpaqueSiblings(QRegion &source, bool *hasDirtySiblingsAbove = 0,
bool alsoNonOpaque = false) const;
@@ -632,6 +634,12 @@ public:
#ifndef QT_NO_OPENGL
virtual GLuint textureId() const { return 0; }
+ virtual QPlatformTextureList::Flags textureListFlags() {
+ Q_Q(QWidget);
+ return q->testAttribute(Qt::WA_AlwaysStackOnTop)
+ ? QPlatformTextureList::StacksOnTop
+ : QPlatformTextureList::Flags(0);
+ }
virtual QImage grabFramebuffer() { return QImage(); }
virtual void beginBackingStorePainting() { }
virtual void endBackingStorePainting() { }
@@ -983,6 +991,13 @@ inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const
return x ? x->backingStoreTracker.data() : 0;
}
+inline QWidgetWindow *QWidgetPrivate::windowHandle() const
+{
+ if (QTLWExtra *x = maybeTopData())
+ return x->window;
+ return nullptr;
+}
+
QT_END_NAMESPACE
#endif // QWIDGET_P_H
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index 2f4bcd6370..046bf743ab 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -75,11 +75,10 @@ Q_GLOBAL_STATIC(QPlatformTextureList, qt_dummy_platformTextureList)
/**
* Flushes the contents of the \a backingStore into the screen area of \a widget.
- * \a tlwOffset is the position of the top level widget relative to the window surface.
* \a region is the region to be updated in \a widget coordinates.
*/
void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBackingStore *backingStore,
- QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures,
+ QWidget *tlw, QPlatformTextureList *widgetTextures,
QWidgetBackingStore *widgetBackingStore)
{
#ifdef QT_NO_OPENGL
@@ -110,7 +109,7 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion &region, QBack
}
}
- QPoint offset = tlwOffset;
+ QPoint offset;
if (widget != tlw)
offset += widget->mapTo(tlw, QPoint());
@@ -286,8 +285,7 @@ void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn)
if (!tlwExtra)
return;
- const QPoint offset = widget->mapTo(tlw, QPoint());
- qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, offset, 0, tlw->d_func()->maybeBackingStore());
+ qt_flush(widget, rgn, tlwExtra->backingStoreTracker->store, tlw, 0, tlw->d_func()->maybeBackingStore());
}
#endif // QT_NO_PAINT_DEBUG
@@ -297,7 +295,7 @@ void QWidgetBackingStore::unflushPaint(QWidget *widget, const QRegion &rgn)
*/
bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *widget)
{
- const QPoint pos(tlwOffset + widget->mapTo(tlw, rect.topLeft()));
+ const QPoint pos(widget->mapTo(tlw, rect.topLeft()));
const QRect tlwRect(QRect(pos, rect.size()));
if (dirty.intersects(tlwRect))
return false; // We don't want to scroll junk.
@@ -947,9 +945,7 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo
{
QWidgetPrivate *wd = QWidgetPrivate::get(widget);
if (wd->renderToTexture) {
- QPlatformTextureList::Flags flags = 0;
- if (widget->testAttribute(Qt::WA_AlwaysStackOnTop))
- flags |= QPlatformTextureList::StacksOnTop;
+ QPlatformTextureList::Flags flags = wd->textureListFlags();
const QRect rect(widget->mapTo(tlw, QPoint()), widget->size());
widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags);
}
@@ -1121,7 +1117,7 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
// Nothing to repaint.
if (!isDirty() && store->size().isValid()) {
QPlatformTextureList *tl = widgetTexturesFor(tlw, exposedWidget);
- qt_flush(exposedWidget, tl ? QRegion() : exposedRegion, store, tlw, tlwOffset, tl, this);
+ qt_flush(exposedWidget, tl ? QRegion() : exposedRegion, store, tlw, tl, this);
return;
}
@@ -1367,7 +1363,7 @@ void QWidgetBackingStore::doSync()
QRegion toBePainted(wd->dirty);
resetWidget(w);
- QPoint offset(tlwOffset);
+ QPoint offset;
if (w != tlw)
offset += w->mapTo(tlw, QPoint());
wd->drawWidget(store->paintDevice(), toBePainted, offset, flags, 0, this);
@@ -1376,7 +1372,7 @@ void QWidgetBackingStore::doSync()
// Paint the rest with composition.
if (repaintAllWidgets || !dirtyCopy.isEmpty()) {
const int flags = QWidgetPrivate::DrawAsRoot | QWidgetPrivate::DrawRecursive;
- tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, tlwOffset, flags, 0, this);
+ tlw->d_func()->drawWidget(store->paintDevice(), dirtyCopy, QPoint(), flags, 0, this);
}
endPaint(toClean, store, &beginPaintInfo);
@@ -1395,7 +1391,7 @@ void QWidgetBackingStore::flush(QWidget *widget)
// Flush the region in dirtyOnScreen.
if (!dirtyOnScreen.isEmpty()) {
QWidget *target = widget ? widget : tlw;
- qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTexturesFor(tlw, tlw), this);
+ qt_flush(target, dirtyOnScreen, store, tlw, widgetTexturesFor(tlw, tlw), this);
dirtyOnScreen = QRegion();
flushed = true;
}
@@ -1407,7 +1403,7 @@ void QWidgetBackingStore::flush(QWidget *widget)
QPlatformTextureList *tl = widgetTexturesFor(tlw, tlw);
if (tl) {
QWidget *target = widget ? widget : tlw;
- qt_flush(target, QRegion(), store, tlw, tlwOffset, tl, this);
+ qt_flush(target, QRegion(), store, tlw, tl, this);
}
}
#endif
@@ -1421,7 +1417,7 @@ void QWidgetBackingStore::flush(QWidget *widget)
QWidgetPrivate *wd = w->d_func();
Q_ASSERT(wd->needsFlush);
QPlatformTextureList *widgetTexturesForNative = wd->textureChildSeen ? widgetTexturesFor(tlw, w) : 0;
- qt_flush(w, *wd->needsFlush, store, tlw, tlwOffset, widgetTexturesForNative, this);
+ qt_flush(w, *wd->needsFlush, store, tlw, widgetTexturesForNative, this);
*wd->needsFlush = QRegion();
}
dirtyOnScreenWidgets->clear();
diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h
index fa51cb71de..53ccda850a 100644
--- a/src/widgets/kernel/qwidgetbackingstore_p.h
+++ b/src/widgets/kernel/qwidgetbackingstore_p.h
@@ -111,8 +111,6 @@ public:
void sync();
void flush(QWidget *widget = 0);
- inline QPoint topLevelOffset() const { return tlwOffset; }
-
QBackingStore *backingStore() const { return store; }
inline bool isDirty() const
@@ -138,8 +136,6 @@ private:
QBackingStore *store;
uint updateRequestSent : 1;
- QPoint tlwOffset;
-
QPlatformTextureListWatcher *textureListWatcher;
QElapsedTimer perfTime;
int perfFrames;
@@ -149,7 +145,7 @@ private:
static bool flushPaint(QWidget *widget, const QRegion &rgn);
static void unflushPaint(QWidget *widget, const QRegion &rgn);
static void qt_flush(QWidget *widget, const QRegion &region, QBackingStore *backingStore,
- QWidget *tlw, const QPoint &tlwOffset,
+ QWidget *tlw,
QPlatformTextureList *widgetTextures,
QWidgetBackingStore *widgetBackingStore);
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index abaebad821..d5d4ae844b 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -57,7 +57,7 @@ QT_BEGIN_NAMESPACE
Q_WIDGETS_EXPORT extern bool qt_tab_all_widgets();
-QWidget *qt_button_down = 0; // widget got last button-down
+Q_WIDGETS_EXPORT QWidget *qt_button_down = 0; // widget got last button-down
// popup control
QWidget *qt_popup_down = 0; // popup that contains the pressed widget
@@ -69,6 +69,15 @@ class QWidgetWindowPrivate : public QWindowPrivate
{
Q_DECLARE_PUBLIC(QWidgetWindow)
public:
+ void setVisible(bool visible) override
+ {
+ Q_Q(QWidgetWindow);
+ if (QWidget *widget = q->widget())
+ widget->setVisible(visible);
+ else
+ QWindowPrivate::setVisible(visible);
+ }
+
QWindow *eventReceiver() Q_DECL_OVERRIDE {
Q_Q(QWidgetWindow);
QWindow *w = q;
@@ -168,6 +177,15 @@ QObject *QWidgetWindow::focusObject() const
return widget;
}
+void QWidgetWindow::setNativeWindowVisibility(bool visible)
+{
+ Q_D(QWidgetWindow);
+ // Call base class setVisible() implementation to run the QWindow
+ // visibility logic. Don't call QWidgetWindowPrivate::setVisible()
+ // since that will recurse back into QWidget code.
+ d->QWindowPrivate::setVisible(visible);
+}
+
static inline bool shouldBePropagatedToWidget(QEvent *event)
{
switch (event->type()) {
@@ -194,7 +212,7 @@ bool QWidgetWindow::event(QEvent *event)
// generated before WA_DontShowOnScreen was set
if (!shouldBePropagatedToWidget(event))
return true;
- return QCoreApplication::sendEvent(m_widget, event);
+ return QCoreApplication::forwardEvent(m_widget, event);
}
switch (event->type()) {
@@ -226,7 +244,7 @@ bool QWidgetWindow::event(QEvent *event)
if (QApplicationPrivate::focus_widget->testAttribute(Qt::WA_InputMethodEnabled))
QGuiApplication::inputMethod()->commit();
- QGuiApplication::sendSpontaneousEvent(QApplicationPrivate::focus_widget, event);
+ QGuiApplication::forwardEvent(QApplicationPrivate::focus_widget, event);
}
return true;
@@ -295,7 +313,7 @@ bool QWidgetWindow::event(QEvent *event)
case QEvent::ThemeChange: {
QEvent widgetEvent(QEvent::ThemeChange);
- QGuiApplication::sendSpontaneousEvent(m_widget, &widgetEvent);
+ QCoreApplication::forwardEvent(m_widget, &widgetEvent, event);
}
return true;
@@ -333,7 +351,7 @@ bool QWidgetWindow::event(QEvent *event)
break;
}
- if (shouldBePropagatedToWidget(event) && QCoreApplication::sendEvent(m_widget, event))
+ if (shouldBePropagatedToWidget(event) && QCoreApplication::forwardEvent(m_widget, event))
return true;
return QWindow::event(event);
@@ -442,7 +460,7 @@ void QWidgetWindow::handleFocusInEvent(QFocusEvent *e)
void QWidgetWindow::handleNonClientAreaMouseEvent(QMouseEvent *e)
{
- QApplication::sendSpontaneousEvent(m_widget, e);
+ QApplication::forwardEvent(m_widget, e);
}
void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
@@ -567,13 +585,13 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
} else if (event->type() == contextMenuTrigger
&& event->button() == Qt::RightButton
&& (openPopupCount == oldOpenPopupCount)) {
- QWidget *popupEvent = activePopupWidget;
+ QWidget *receiver = activePopupWidget;
if (qt_button_down)
- popupEvent = qt_button_down;
+ receiver = qt_button_down;
else if(popupChild)
- popupEvent = popupChild;
+ receiver = popupChild;
QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPos(), event->modifiers());
- QApplication::sendSpontaneousEvent(popupEvent, &e);
+ QApplication::forwardEvent(receiver, &e, event);
}
#else
Q_UNUSED(contextMenuTrigger)
@@ -626,7 +644,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
if (event->type() == contextMenuTrigger && event->button() == Qt::RightButton
&& m_widget->rect().contains(event->pos())) {
QContextMenuEvent e(QContextMenuEvent::Mouse, mapped, event->globalPos(), event->modifiers());
- QGuiApplication::sendSpontaneousEvent(receiver, &e);
+ QGuiApplication::forwardEvent(receiver, &e, event);
}
#endif
}
@@ -658,7 +676,7 @@ void QWidgetWindow::handleKeyEvent(QKeyEvent *event)
}
if (!receiver)
receiver = focusObject();
- QGuiApplication::sendSpontaneousEvent(receiver, event);
+ QGuiApplication::forwardEvent(receiver, event);
}
bool QWidgetWindow::updateSize()
@@ -730,8 +748,6 @@ void QWidgetWindow::repaintWindow()
QWidgetBackingStore::UpdateNow, QWidgetBackingStore::BufferInvalid);
}
-Qt::WindowState effectiveState(Qt::WindowStates state);
-
// Store normal geometry used for saving application settings.
void QWidgetWindow::updateNormalGeometry()
{
@@ -742,7 +758,7 @@ void QWidgetWindow::updateNormalGeometry()
QRect normalGeometry;
if (const QPlatformWindow *pw = handle())
normalGeometry = QHighDpi::fromNativePixels(pw->normalGeometry(), this);
- if (!normalGeometry.isValid() && effectiveState(m_widget->windowState()) == Qt::WindowNoState)
+ if (!normalGeometry.isValid() && !(m_widget->windowState() & ~Qt::WindowActive))
normalGeometry = m_widget->geometry();
if (normalGeometry.isValid())
tle->normalGeometry = normalGeometry;
@@ -751,7 +767,7 @@ void QWidgetWindow::updateNormalGeometry()
void QWidgetWindow::handleMoveEvent(QMoveEvent *event)
{
if (updatePos())
- QGuiApplication::sendSpontaneousEvent(m_widget, event);
+ QGuiApplication::forwardEvent(m_widget, event);
}
void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
@@ -759,7 +775,7 @@ void QWidgetWindow::handleResizeEvent(QResizeEvent *event)
QSize oldSize = m_widget->data->crect.size();
if (updateSize()) {
- QGuiApplication::sendSpontaneousEvent(m_widget, event);
+ QGuiApplication::forwardEvent(m_widget, event);
if (m_widget->d_func()->paintOnScreen()) {
QRegion updateRegion(geometry());
@@ -805,7 +821,7 @@ void QWidgetWindow::handleWheelEvent(QWheelEvent *event)
QPoint mapped = widget->mapFrom(rootWidget, pos);
QWheelEvent translated(mapped, event->globalPos(), event->pixelDelta(), event->angleDelta(), event->delta(), event->orientation(), event->buttons(), event->modifiers(), event->phase(), event->source(), event->inverted());
- QGuiApplication::sendSpontaneousEvent(widget, &translated);
+ QGuiApplication::forwardEvent(widget, &translated, event);
}
#endif // QT_CONFIG(wheelevent)
@@ -832,7 +848,7 @@ void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
translated.accept();
translated.setDropAction(event->dropAction());
}
- QGuiApplication::sendSpontaneousEvent(widget, &translated);
+ QGuiApplication::forwardEvent(widget, &translated, event);
if (translated.isAccepted()) {
event->accept();
} else {
@@ -844,7 +860,7 @@ void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
// Target widget changed: Send DragLeave to previous, DragEnter to new if there is any
if (m_dragTarget.data()) {
QDragLeaveEvent le;
- QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), &le);
+ QGuiApplication::forwardEvent(m_dragTarget.data(), &le, event);
m_dragTarget = 0;
}
if (!widget) {
@@ -854,7 +870,7 @@ void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
m_dragTarget = widget;
const QPoint mapped = widget->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
QDragEnterEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
- QGuiApplication::sendSpontaneousEvent(widget, &translated);
+ QGuiApplication::forwardEvent(widget, &translated, event);
if (translated.isAccepted()) {
event->accept();
} else {
@@ -866,7 +882,7 @@ void QWidgetWindow::handleDragEnterMoveEvent(QDragMoveEvent *event)
void QWidgetWindow::handleDragLeaveEvent(QDragLeaveEvent *event)
{
if (m_dragTarget)
- QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), event);
+ QGuiApplication::forwardEvent(m_dragTarget.data(), event);
m_dragTarget = 0;
}
@@ -879,7 +895,7 @@ void QWidgetWindow::handleDropEvent(QDropEvent *event)
}
const QPoint mapped = m_dragTarget.data()->mapFromGlobal(m_widget->mapToGlobal(event->pos()));
QDropEvent translated(mapped, event->possibleActions(), event->mimeData(), event->mouseButtons(), event->keyboardModifiers());
- QGuiApplication::sendSpontaneousEvent(m_dragTarget.data(), &translated);
+ QGuiApplication::forwardEvent(m_dragTarget.data(), &translated, event);
if (translated.isAccepted())
event->accept();
event->setDropAction(translated.dropAction());
@@ -902,7 +918,7 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
// ... and they haven't been shown by this function yet - show it.
wPriv->showChildren(true);
QShowEvent showEvent;
- QCoreApplication::sendSpontaneousEvent(m_widget, &showEvent);
+ QCoreApplication::forwardEvent(m_widget, &showEvent, event);
wPriv->childrenShownByExpose = true;
}
} else {
@@ -914,7 +930,7 @@ void QWidgetWindow::handleExposeEvent(QExposeEvent *event)
// and then, the QPA can send next expose event with null exposed region (not exposed).
wPriv->hideChildren(true);
QHideEvent hideEvent;
- QCoreApplication::sendSpontaneousEvent(m_widget, &hideEvent);
+ QCoreApplication::forwardEvent(m_widget, &hideEvent, event);
wPriv->childrenShownByExpose = false;
}
}
@@ -934,30 +950,18 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
// QWindow does currently not know 'active'.
Qt::WindowStates eventState = event->oldState();
Qt::WindowStates widgetState = m_widget->windowState();
+ Qt::WindowStates windowState = windowStates();
if (widgetState & Qt::WindowActive)
eventState |= Qt::WindowActive;
// Determine the new widget state, remember maximized/full screen
// during minimized.
- switch (windowState()) {
- case Qt::WindowNoState:
- widgetState &= ~(Qt::WindowMinimized | Qt::WindowMaximized | Qt::WindowFullScreen);
- break;
- case Qt::WindowMinimized:
+ if (windowState & Qt::WindowMinimized) {
widgetState |= Qt::WindowMinimized;
- break;
- case Qt::WindowMaximized:
- updateNormalGeometry();
- widgetState |= Qt::WindowMaximized;
- widgetState &= ~(Qt::WindowMinimized | Qt::WindowFullScreen);
- break;
- case Qt::WindowFullScreen:
- updateNormalGeometry();
- widgetState |= Qt::WindowFullScreen;
- widgetState &= ~(Qt::WindowMinimized);
- break;
- case Qt::WindowActive: // Not handled by QWindow
- break;
+ } else {
+ widgetState = windowState | (widgetState & Qt::WindowActive);
+ if (windowState) // Maximized or FullScreen
+ updateNormalGeometry();
}
// Sent event if the state changed (that is, it is not triggered by
@@ -965,7 +969,7 @@ void QWidgetWindow::handleWindowStateChangedEvent(QWindowStateChangeEvent *event
if (widgetState != Qt::WindowStates::Int(m_widget->data->window_state)) {
m_widget->data->window_state = uint(widgetState);
QWindowStateChangeEvent widgetEvent(eventState);
- QGuiApplication::sendSpontaneousEvent(m_widget, &widgetEvent);
+ QGuiApplication::forwardEvent(m_widget, &widgetEvent, event);
}
}
@@ -997,7 +1001,7 @@ void QWidgetWindow::handleTabletEvent(QTabletEvent *event)
event->pressure(), event->xTilt(), event->yTilt(), event->tangentialPressure(),
event->rotation(), event->z(), event->modifiers(), event->uniqueId(), event->button(), event->buttons());
ev.setTimestamp(event->timestamp());
- QGuiApplication::sendSpontaneousEvent(widget, &ev);
+ QGuiApplication::forwardEvent(widget, &ev, event);
event->setAccepted(ev.isAccepted());
}
@@ -1021,7 +1025,7 @@ void QWidgetWindow::handleGestureEvent(QNativeGestureEvent *e)
if (!receiver)
receiver = m_widget; // last resort
- QApplication::sendSpontaneousEvent(receiver, e);
+ QApplication::forwardEvent(receiver, e);
}
#endif // QT_NO_GESTURES
@@ -1049,7 +1053,7 @@ void QWidgetWindow::handleContextMenuEvent(QContextMenuEvent *e)
QPoint pos = fw->inputMethodQuery(Qt::ImMicroFocus).toRect().center();
QContextMenuEvent widgetEvent(QContextMenuEvent::Keyboard, pos, fw->mapToGlobal(pos),
e->modifiers());
- QGuiApplication::sendSpontaneousEvent(fw, &widgetEvent);
+ QGuiApplication::forwardEvent(fw, &widgetEvent, e);
}
}
#endif // QT_NO_CONTEXTMENU
diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index 50a2cfd57c..be3f808a22 100644
--- a/src/widgets/kernel/qwidgetwindow_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -63,10 +63,12 @@ QT_BEGIN_NAMESPACE
class QCloseEvent;
class QMoveEvent;
+class QWidgetWindowPrivate;
class QWidgetWindow : public QWindow
{
Q_OBJECT
+ Q_DECLARE_PRIVATE(QWidgetWindow)
public:
QWidgetWindow(QWidget *widget);
~QWidgetWindow();
@@ -77,6 +79,7 @@ public:
#endif
QObject *focusObject() const Q_DECL_OVERRIDE;
+ void setNativeWindowVisibility(bool visible);
protected:
bool event(QEvent *) Q_DECL_OVERRIDE;
diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp
index 7ae63e54b3..a17c69c5ce 100644
--- a/src/widgets/kernel/qwindowcontainer.cpp
+++ b/src/widgets/kernel/qwindowcontainer.cpp
@@ -337,6 +337,19 @@ bool QWindowContainer::event(QEvent *e)
e->accept();
return true;
#endif
+
+ case QEvent::Paint:
+ {
+ static bool needsPunch = !QGuiApplicationPrivate::platformIntegration()->hasCapability(
+ QPlatformIntegration::TopStackedNativeChildWindows);
+ if (needsPunch) {
+ QPainter p(this);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(rect(), Qt::transparent);
+ }
+ break;
+ }
+
default:
break;
}
diff --git a/src/widgets/styles/images/fusion_arrow.png b/src/widgets/styles/images/fusion_arrow.png
deleted file mode 100644
index d7945e7f76..0000000000
--- a/src/widgets/styles/images/fusion_arrow.png
+++ /dev/null
Binary files differ
diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp
index 5e43d69e8f..c15703ca58 100644
--- a/src/widgets/styles/qcommonstyle.cpp
+++ b/src/widgets/styles/qcommonstyle.cpp
@@ -5261,6 +5261,8 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
break;
#endif
case SH_Widget_Animate:
+ // TODO Qt6: move this code in the SH_Widget_Animation_Duration case
+ // and replace false with 0 and true with 200.
#if QT_CONFIG(treeview)
if (qobject_cast<const QTreeView*>(widget)) {
ret = false;
@@ -5278,6 +5280,12 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
ret = QAbstractItemView::ScrollPerItem;
break;
#endif
+ case SH_TitleBar_ShowToolTipsOnButtons:
+ ret = true;
+ break;
+ case SH_Widget_Animation_Duration:
+ ret = styleHint(SH_Widget_Animate, opt, widget, hret) ? 200 : 0;
+ break;
default:
ret = 0;
break;
diff --git a/src/widgets/styles/qcommonstyle_p.h b/src/widgets/styles/qcommonstyle_p.h
index 9fb731239a..93db75ac2d 100644
--- a/src/widgets/styles/qcommonstyle_p.h
+++ b/src/widgets/styles/qcommonstyle_p.h
@@ -63,7 +63,7 @@ QT_BEGIN_NAMESPACE
class QStringList;
// Private class
-class QCommonStylePrivate : public QStylePrivate
+class Q_WIDGETS_EXPORT QCommonStylePrivate : public QStylePrivate
{
Q_DECLARE_PUBLIC(QCommonStyle)
public:
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index 792d958d8b..c1b240a381 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -194,55 +194,6 @@ static QColor mergedColors(const QColor &colorA, const QColor &colorB, int facto
return tmp;
}
-static QPixmap colorizedImage(const QString &fileName, const QColor &color, int rotation = 0) {
-
- QString pixmapName = QLatin1String("$qt_ia-") % fileName % HexString<uint>(color.rgba()) % QString::number(rotation);
- QPixmap pixmap;
- if (!QPixmapCache::find(pixmapName, pixmap)) {
- QImage image(fileName);
-
- if (image.format() != QImage::Format_ARGB32_Premultiplied)
- image = image.convertToFormat( QImage::Format_ARGB32_Premultiplied);
-
- int width = image.width();
- int height = image.height();
- int source = color.rgba();
-
- unsigned char sourceRed = qRed(source);
- unsigned char sourceGreen = qGreen(source);
- unsigned char sourceBlue = qBlue(source);
-
- for (int y = 0; y < height; ++y)
- {
- QRgb *data = (QRgb*) image.scanLine(y);
- for (int x = 0 ; x < width ; x++) {
- QRgb col = data[x];
- unsigned int colorDiff = (qBlue(col) - qRed(col));
- unsigned char gray = qGreen(col);
- unsigned char red = gray + qt_div_255(sourceRed * colorDiff);
- unsigned char green = gray + qt_div_255(sourceGreen * colorDiff);
- unsigned char blue = gray + qt_div_255(sourceBlue * colorDiff);
- unsigned char alpha = qt_div_255(qAlpha(col) * qAlpha(source));
- data[x] = qRgba(std::min(alpha, red),
- std::min(alpha, green),
- std::min(alpha, blue),
- alpha);
- }
- }
- if (rotation != 0) {
- QTransform transform;
- transform.translate(-image.width()/2, -image.height()/2);
- transform.rotate(rotation);
- transform.translate(image.width()/2, image.height()/2);
- image = image.transformed(transform);
- }
-
- pixmap = QPixmap::fromImage(image);
- QPixmapCache::insert(pixmapName, pixmap);
- }
- return pixmap;
-}
-
// The default button and handle gradient
static QLinearGradient qt_fusion_gradient(const QRect &rect, const QBrush &baseColor, Direction direction = TopDown)
{
@@ -280,6 +231,59 @@ static QLinearGradient qt_fusion_gradient(const QRect &rect, const QBrush &baseC
return gradient;
}
+static void qt_fusion_draw_arrow(Qt::ArrowType type, QPainter *painter, const QStyleOption *option, const QRect &rect, const QColor &color)
+{
+ const int arrowWidth = QStyleHelper::dpiScaled(14);
+ const int arrowHeight = QStyleHelper::dpiScaled(8);
+
+ const int arrowMax = qMin(arrowHeight, arrowWidth);
+ const int rectMax = qMin(rect.height(), rect.width());
+ const int size = qMin(arrowMax, rectMax);
+
+ QPixmap cachePixmap;
+ QString cacheKey = QStyleHelper::uniqueName(QLatin1String("fusion-arrow"), option, rect.size())
+ % HexString<uint>(type)
+ % HexString<uint>(color.rgba());
+ if (!QPixmapCache::find(cacheKey, cachePixmap)) {
+ cachePixmap = styleCachePixmap(rect.size());
+ cachePixmap.fill(Qt::transparent);
+ QPainter cachePainter(&cachePixmap);
+
+ QRectF arrowRect;
+ arrowRect.setWidth(size);
+ arrowRect.setHeight(arrowHeight * size / arrowWidth);
+ if (type == Qt::LeftArrow || type == Qt::RightArrow)
+ arrowRect = arrowRect.transposed();
+ arrowRect.moveTo((rect.width() - arrowRect.width()) / 2.0,
+ (rect.height() - arrowRect.height()) / 2.0);
+
+ QPolygonF triangle;
+ triangle.reserve(3);
+ switch (type) {
+ case Qt::DownArrow:
+ triangle << arrowRect.topLeft() << arrowRect.topRight() << QPointF(arrowRect.center().x(), arrowRect.bottom());
+ break;
+ case Qt::RightArrow:
+ triangle << arrowRect.topLeft() << arrowRect.bottomLeft() << QPointF(arrowRect.right(), arrowRect.center().y());
+ break;
+ case Qt::LeftArrow:
+ triangle << arrowRect.topRight() << arrowRect.bottomRight() << QPointF(arrowRect.left(), arrowRect.center().y());
+ break;
+ default:
+ triangle << arrowRect.bottomLeft() << arrowRect.bottomRight() << QPointF(arrowRect.center().x(), arrowRect.top());
+ break;
+ }
+
+ cachePainter.setPen(Qt::NoPen);
+ cachePainter.setBrush(color);
+ cachePainter.setRenderHint(QPainter::Antialiasing);
+ cachePainter.drawPolygon(triangle);
+
+ QPixmapCache::insert(cacheKey, cachePixmap);
+ }
+
+ painter->drawPixmap(rect, cachePixmap);
+}
static void qt_fusion_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken)
{
@@ -517,43 +521,22 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
if (option->rect.width() <= 1 || option->rect.height() <= 1)
break;
QColor arrowColor = option->palette.foreground().color();
- QPixmap arrow;
- int rotation = 0;
+ arrowColor.setAlpha(160);
+ Qt::ArrowType arrow = Qt::UpArrow;
switch (elem) {
case PE_IndicatorArrowDown:
- rotation = 180;
+ arrow = Qt::DownArrow;
break;
case PE_IndicatorArrowRight:
- rotation = 90;
+ arrow = Qt::RightArrow;
break;
case PE_IndicatorArrowLeft:
- rotation = -90;
+ arrow = Qt::LeftArrow;
break;
default:
break;
}
- arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, rotation);
- if (arrow.isNull())
- break;
-
- QRect rect = option->rect;
- QRect arrowRect;
- int imageMax = qMin(arrow.height(), arrow.width());
- int rectMax = qMin(rect.height(), rect.width());
- int size = qMin(imageMax, rectMax);
-
- arrowRect.setWidth(size);
- arrowRect.setHeight(size);
- if (arrow.width() > arrow.height())
- arrowRect.setHeight(arrow.height() * size / arrow.width());
- else
- arrowRect.setWidth(arrow.width() * size / arrow.height());
-
- arrowRect.moveTopLeft(rect.center() - arrowRect.center());
- painter->save();
- painter->setRenderHint(QPainter::SmoothPixmapTransform);
- painter->drawPixmap(arrowRect, arrow);
- painter->restore();
+ qt_fusion_draw_arrow(arrow, painter, option, option->rect, arrowColor);
}
break;
case PE_IndicatorViewItemCheck:
@@ -567,29 +550,23 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
case PE_IndicatorHeaderArrow:
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
QRect r = header->rect;
- QPixmap arrow;
QColor arrowColor = header->palette.foreground().color();
- QPoint offset = QPoint(0, -1);
+ arrowColor.setAlpha(180);
+ QPoint offset = QPoint(0, -2);
#if defined(Q_OS_LINUX)
if (header->sortIndicator & QStyleOptionHeader::SortUp) {
- arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor);
+ qt_fusion_draw_arrow(Qt::UpArrow, painter, option, r.translated(offset), arrowColor);
} else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
- arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180);
+ qt_fusion_draw_arrow(Qt::DownArrow, painter, option, r.translated(offset), arrowColor);
}
#else
if (header->sortIndicator & QStyleOptionHeader::SortUp) {
- arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180);
+ qt_fusion_draw_arrow(Qt::DownArrow, painter, option, r.translated(offset), arrowColor);
} else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
- arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor);
+ qt_fusion_draw_arrow(Qt::UpArrow, painter, option, r.translated(offset), arrowColor);
}
#endif
-
- if (!arrow.isNull()) {
- r.setSize(QSize(arrow.width()/2, arrow.height()/2));
- r.moveCenter(header->rect.center());
- painter->drawPixmap(r.translated(offset), arrow);
- }
}
break;
case PE_IndicatorButtonDropDown:
@@ -1537,17 +1514,18 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
QColor highlight = option->palette.highlight().color();
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
int w = 0;
+ const int margin = QStyleHelper::dpiScaled(5);
if (!menuItem->text.isEmpty()) {
painter->setFont(menuItem->font);
- proxy()->drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
+ proxy()->drawItemText(painter, menuItem->rect.adjusted(margin, 0, -margin, 0), Qt::AlignLeft | Qt::AlignVCenter,
menuItem->palette, menuItem->state & State_Enabled, menuItem->text,
QPalette::Text);
- w = menuItem->fontMetrics.width(menuItem->text) + 5;
+ w = menuItem->fontMetrics.width(menuItem->text) + margin;
}
painter->setPen(shadow.lighter(106));
bool reverse = menuItem->direction == Qt::RightToLeft;
- painter->drawLine(menuItem->rect.left() + 5 + (reverse ? 0 : w), menuItem->rect.center().y(),
- menuItem->rect.right() - 5 - (reverse ? w : 0), menuItem->rect.center().y());
+ painter->drawLine(menuItem->rect.left() + margin + (reverse ? 0 : w), menuItem->rect.center().y(),
+ menuItem->rect.right() - margin - (reverse ? w : 0), menuItem->rect.center().y());
painter->restore();
break;
}
@@ -1564,7 +1542,8 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
bool enabled = menuItem->state & State_Enabled;
bool ignoreCheckMark = false;
- int checkcol = qMax(menuItem->maxIconWidth, 20);
+ int checkcol = qMax<int>(menuItem->maxIconWidth, QStyleHelper::dpiScaled(20));
+ const int margin = QStyleHelper::dpiScaled(4);
if (
#if QT_CONFIG(combobox)
@@ -1575,7 +1554,10 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
if (!ignoreCheckMark) {
// Check
- QRect checkRect(option->rect.left() + 7, option->rect.center().y() - 6, 14, 14);
+ const int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
+ const int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget);
+ QRect checkRect(option->rect.left() + indicatorWidth / 2,
+ option->rect.center().y() - indicatorHeight / 2 + 1, indicatorWidth, indicatorHeight);
checkRect = visualRect(menuItem->direction, menuItem->rect, checkRect);
if (checkable) {
if (menuItem->checkType & QStyleOptionMenuItem::Exclusive) {
@@ -1587,7 +1569,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
QPalette::ColorRole textRole = !enabled ? QPalette::Text:
selected ? QPalette::HighlightedText : QPalette::ButtonText;
painter->setBrush(option->palette.brush( option->palette.currentColorGroup(), textRole));
- painter->drawEllipse(checkRect.adjusted(4, 4, -4, -4));
+ painter->drawEllipse(checkRect.adjusted(margin, margin, -margin, -margin));
}
} else {
// Check box
@@ -1616,7 +1598,7 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
QPainter *p = painter;
QRect vCheckRect = visualRect(opt->direction, menuitem->rect,
- QRect(menuitem->rect.x() + 4, menuitem->rect.y(),
+ QRect(menuitem->rect.x() + margin, menuitem->rect.y(),
checkcol, menuitem->rect.height()));
if (!menuItem->icon.isNull()) {
QIcon::Mode mode = dis ? QIcon::Disabled : QIcon::Normal;
@@ -1667,10 +1649,11 @@ void QFusionStyle::drawControl(ControlElement element, const QStyleOption *optio
discol = menuitem->palette.text().color();
p->setPen(discol);
}
- int xm = windowsItemFrame + checkcol + windowsItemHMargin + 2;
- int xpos = menuitem->rect.x() + xm;
+ const int lm = QStyleHelper::dpiScaled(windowsItemFrame + windowsItemHMargin + 2) + checkcol;
+ const int rm = QStyleHelper::dpiScaled(windowsRightBorder + 1) + tab;
+ const int xpos = menuitem->rect.x() + lm;
- QRect textRect(xpos, y + windowsItemVMargin, w - xm - windowsRightBorder - tab + 1, h - 2 * windowsItemVMargin);
+ QRect textRect(xpos, y + windowsItemVMargin, w - lm - rm, h - 2 * windowsItemVMargin);
QRect vTextRect = visualRect(opt->direction, menuitem->rect, textRect);
QStringRef s(&menuitem->text);
if (!s.isEmpty()) { // draw text
@@ -2035,7 +2018,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
QRect r = rect.adjusted(0, 1, 0, -1);
QPainter cachePainter(&cache);
QColor arrowColor = spinBox->palette.foreground().color();
- arrowColor.setAlpha(220);
+ arrowColor.setAlpha(160);
bool isEnabled = (spinBox->state & State_Enabled);
bool hover = isEnabled && (spinBox->state & State_MouseOver);
@@ -2146,23 +2129,10 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
} else if (spinBox->buttonSymbols == QAbstractSpinBox::UpDownArrows){
// arrows
- painter->setRenderHint(QPainter::SmoothPixmapTransform);
-
- QPixmap upArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"),
- (spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) ? arrowColor : disabledColor);
-
- QRectF upArrowRect = QRectF(upRect.center().x() - upArrow.width() / 4.0 + 1.0,
- upRect.center().y() - upArrow.height() / 4.0 + 1.0,
- upArrow.width() / 2.0, upArrow.height() / 2.0);
-
- cachePainter.drawPixmap(upArrowRect, upArrow, QRectF(QPointF(0.0, 0.0), upArrow.size()));
-
- QPixmap downArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"),
- (spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) ? arrowColor : disabledColor, 180);
- QRectF downArrowRect = QRectF(downRect.center().x() - downArrow.width() / 4.0 + 1.0,
- downRect.center().y() - downArrow.height() / 4.0 + 1.0,
- downArrow.width() / 2.0, downArrow.height() / 2.0);
- cachePainter.drawPixmap(downArrowRect, downArrow, QRectF(QPointF(0.0, 0.0), downArrow.size()));
+ qt_fusion_draw_arrow(Qt::UpArrow, &cachePainter, option, upRect.adjusted(0, 0, 0, 1),
+ (spinBox->stepEnabled & QAbstractSpinBox::StepUpEnabled) ? arrowColor : disabledColor);
+ qt_fusion_draw_arrow(Qt::DownArrow, &cachePainter, option, downRect,
+ (spinBox->stepEnabled & QAbstractSpinBox::StepDownEnabled) ? arrowColor : disabledColor);
}
cachePainter.end();
@@ -2399,8 +2369,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken);
qt_fusion_draw_mdibutton(painter, titleBar, shadeButtonRect, hover, sunken);
- QPixmap arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), textColor);
- painter->drawPixmap(shadeButtonRect.adjusted(5, 7, -5, -7), arrow);
+ qt_fusion_draw_arrow(Qt::UpArrow, painter, option, shadeButtonRect.adjusted(5, 7, -5, -7), textColor);
}
}
@@ -2411,8 +2380,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken);
qt_fusion_draw_mdibutton(painter, titleBar, unshadeButtonRect, hover, sunken);
- QPixmap arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), textColor, 180);
- painter->drawPixmap(unshadeButtonRect.adjusted(5, 7, -5, -7), arrow);
+ qt_fusion_draw_arrow(Qt::DownArrow, painter, option, unshadeButtonRect.adjusted(5, 7, -5, -7), textColor);
}
}
@@ -2542,7 +2510,7 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
alphaOutline.setAlpha(180);
QColor arrowColor = option->palette.foreground().color();
- arrowColor.setAlpha(220);
+ arrowColor.setAlpha(160);
const QColor bgColor = QStyleHelper::backgroundColor(option->palette, widget);
const bool isDarkBg = bgColor.red() < 128 && bgColor.green() < 128 && bgColor.blue() < 128;
@@ -2686,20 +2654,16 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
painter->drawLine(pixmapRect.bottomLeft(), pixmapRect.bottomRight());
}
+ QRect upRect = scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0, horizontal ? -2 : -1, horizontal ? -1 : -2);
painter->setBrush(Qt::NoBrush);
painter->setPen(d->innerContrastLine());
- painter->drawRect(scrollBarSubLine.adjusted(horizontal ? 0 : 1, horizontal ? 1 : 0 , horizontal ? -2 : -1, horizontal ? -1 : -2));
+ painter->drawRect(upRect);
// Arrows
- int rotation = 0;
+ Qt::ArrowType arrowType = Qt::UpArrow;
if (option->state & State_Horizontal)
- rotation = option->direction == Qt::LeftToRight ? -90 : 90;
- QRect upRect = scrollBarSubLine.translated(horizontal ? -2 : -1, 0);
- QPixmap arrowPixmap = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, rotation);
- painter->drawPixmap(QRectF(upRect.center().x() - arrowPixmap.width() / 4.0 + 2.0,
- upRect.center().y() - arrowPixmap.height() / 4.0 + 1.0,
- arrowPixmap.width() / 2.0, arrowPixmap.height() / 2.0),
- arrowPixmap, QRectF(QPoint(0.0, 0.0), arrowPixmap.size()));
+ arrowType = option->direction == Qt::LeftToRight ? Qt::LeftArrow : Qt::RightArrow;
+ qt_fusion_draw_arrow(arrowType, painter, option, upRect, arrowColor);
}
// The AddLine (down/right) button
@@ -2727,19 +2691,15 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
painter->drawLine(pixmapRect.topLeft(), pixmapRect.topRight());
}
+ QRect downRect = scrollBarAddLine.adjusted(1, 1, -1, -1);
painter->setPen(d->innerContrastLine());
painter->setBrush(Qt::NoBrush);
- painter->drawRect(scrollBarAddLine.adjusted(1, 1, -1, -1));
+ painter->drawRect(downRect);
- int rotation = 180;
+ Qt::ArrowType arrowType = Qt::DownArrow;
if (option->state & State_Horizontal)
- rotation = option->direction == Qt::LeftToRight ? 90 : -90;
- QRect downRect = scrollBarAddLine.translated(-1, 1);
- QPixmap arrowPixmap = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, rotation);
- painter->drawPixmap(QRectF(downRect.center().x() - arrowPixmap.width() / 4.0 + 2.0,
- downRect.center().y() - arrowPixmap.height() / 4.0,
- arrowPixmap.width() / 2.0, arrowPixmap.height() / 2.0),
- arrowPixmap, QRectF(QPoint(0.0, 0.0), arrowPixmap.size()));
+ arrowType = option->direction == Qt::LeftToRight ? Qt::RightArrow : Qt::LeftArrow;
+ qt_fusion_draw_arrow(arrowType, painter, option, downRect, arrowColor);
}
}
@@ -2829,12 +2789,8 @@ void QFusionStyle::drawComplexControl(ComplexControl control, const QStyleOption
if (comboBox->subControls & SC_ComboBoxArrow) {
// Draw the up/down arrow
QColor arrowColor = option->palette.buttonText().color();
- arrowColor.setAlpha(220);
- QPixmap downArrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180);
- cachePainter.drawPixmap(QRectF(downArrowRect.center().x() - downArrow.width() / 4.0 + 1.0,
- downArrowRect.center().y() - downArrow.height() / 4.0 + 1.0,
- downArrow.width() / 2.0, downArrow.height() / 2.0),
- downArrow, QRectF(QPointF(0.0, 0.0), downArrow.size()));
+ arrowColor.setAlpha(160);
+ qt_fusion_draw_arrow(Qt::DownArrow, &cachePainter, option, downArrowRect, arrowColor);
}
cachePainter.end();
QPixmapCache::insert(pixmapName, cache);
@@ -3238,7 +3194,7 @@ QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *opti
if (menuItem->text.contains(QLatin1Char('\t')))
w += tabSpacing;
else if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu)
- w += 2 * QFusionStylePrivate::menuArrowHMargin;
+ w += 2 * QStyleHelper::dpiScaled(QFusionStylePrivate::menuArrowHMargin);
else if (menuItem->menuItemType == QStyleOptionMenuItem::DefaultItem) {
QFontMetrics fm(menuItem->font);
QFont fontBold = menuItem->font;
@@ -3246,9 +3202,9 @@ QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *opti
QFontMetrics fmBold(fontBold);
w += fmBold.width(menuItem->text) - fm.width(menuItem->text);
}
- int checkcol = qMax<int>(maxpmw, QFusionStylePrivate::menuCheckMarkWidth); // Windows always shows a check column
+ const int checkcol = qMax<int>(maxpmw, QStyleHelper::dpiScaled(QFusionStylePrivate::menuCheckMarkWidth)); // Windows always shows a check column
w += checkcol;
- w += int(QFusionStylePrivate::menuRightBorder) + 10;
+ w += QStyleHelper::dpiScaled(int(QFusionStylePrivate::menuRightBorder) + 10);
newSize.setWidth(w);
if (menuItem->menuItemType == QStyleOptionMenuItem::Separator) {
if (!menuItem->text.isEmpty()) {
@@ -3262,8 +3218,8 @@ QSize QFusionStyle::sizeFromContents(ContentsType type, const QStyleOption *opti
}
#endif
}
- newSize.setWidth(newSize.width() + 12);
- newSize.setWidth(qMax(newSize.width(), 120));
+ newSize.setWidth(newSize.width() + QStyleHelper::dpiScaled(12));
+ newSize.setWidth(qMax<int>(newSize.width(), QStyleHelper::dpiScaled(120)));
}
break;
case CT_SizeGrip:
@@ -3526,8 +3482,8 @@ QRect QFusionStyle::subControlRect(ComplexControl control, const QStyleOptionCom
switch (subControl) {
case SC_ComboBoxArrow:
rect = visualRect(option->direction, option->rect, rect);
- rect.setRect(rect.right() - 18, rect.top() - 2,
- 19, rect.height() + 4);
+ rect.setRect(rect.right() - QStyleHelper::dpiScaled(18), rect.top() - 2,
+ QStyleHelper::dpiScaled(19), rect.height() + 4);
rect = visualRect(option->direction, option->rect, rect);
break;
case SC_ComboBoxEditField: {
diff --git a/src/widgets/styles/qfusionstyle_p.h b/src/widgets/styles/qfusionstyle_p.h
index aac27e51ab..10f76045d5 100644
--- a/src/widgets/styles/qfusionstyle_p.h
+++ b/src/widgets/styles/qfusionstyle_p.h
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
#if QT_CONFIG(style_fusion)
class QFusionStylePrivate;
-class QFusionStyle : public QCommonStyle
+class Q_WIDGETS_EXPORT QFusionStyle : public QCommonStyle
{
Q_OBJECT
Q_DECLARE_PRIVATE(QFusionStyle)
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index 01d972af65..0350d5e1a5 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -1972,9 +1972,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
a tooltip is shown (notice: shown, not hidden). When a new wake isn't needed, a user-requested tooltip
will be shown nearly instantly.
- \value SH_Widget_Animate Determines if the widget should show animations or not, for example
- a transition between checked and unchecked statuses in a checkbox.
- This enum value has been introduced in Qt 5.2.
+ \value SH_Widget_Animate Deprecated. Use \l{SH_Widget_Animation_Duration} instead.
\value SH_Splitter_OpaqueResize Determines if resizing is opaque
This enum value has been introduced in Qt 5.2
@@ -1987,6 +1985,16 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
by the style. Can be overridden with QAbstractItemView::setVerticalScrollMode() and
QAbstractItemView::setHorizontalScrollMode(). This enum value has been introduced in Qt 5.7.
+ \value SH_TitleBar_ShowToolTipsOnButtons
+ Determines if tool tips are shown on window title bar buttons.
+ The Mac style, for example, sets this to false.
+ This enum value has been introduced in Qt 5.10.
+
+ \value SH_Widget_Animation_Duration
+ Determines how much an animation should last (in ms).
+ A value equal to zero means that the animations will be disabled.
+ This enum value has been introduced in Qt 5.10.
+
\sa styleHint()
*/
@@ -2286,8 +2294,8 @@ int QStyle::sliderValueFromPosition(int min, int max, int pos, int span, bool up
Returns the style's standard palette.
Note that on systems that support system colors, the style's
- standard palette is not used. In particular, the Windows XP,
- Vista, and Mac styles do not use the standard palette, but make
+ standard palette is not used. In particular, the Windows
+ Vista and Mac styles do not use the standard palette, but make
use of native theme engines. With these styles, you should not set
the palette with QApplication::setPalette().
diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h
index ce33dbed62..b4936a3e0a 100644
--- a/src/widgets/styles/qstyle.h
+++ b/src/widgets/styles/qstyle.h
@@ -737,6 +737,8 @@ public:
SH_Menu_SubMenuResetWhenReenteringParent,
SH_Menu_SubMenuDontStartSloppyOnLeave,
SH_ItemView_ScrollMode,
+ SH_TitleBar_ShowToolTipsOnButtons,
+ SH_Widget_Animation_Duration,
// Add new style hint values here
SH_CustomBase = 0xf0000000
diff --git a/src/widgets/styles/qstyle.qrc b/src/widgets/styles/qstyle.qrc
index d8c73dd6fa..c2d200adc4 100644
--- a/src/widgets/styles/qstyle.qrc
+++ b/src/widgets/styles/qstyle.qrc
@@ -128,7 +128,6 @@
<file>images/media-volume-16.png</file>
<file>images/media-volume-muted-16.png</file>
<file>images/fusion_groupbox.png</file>
- <file>images/fusion_arrow.png</file>
</qresource>
<qresource prefix="/qt-project.org/styles/macstyle">
<file>images/closedock-16.png</file>
diff --git a/src/widgets/styles/qstyleanimation_p.h b/src/widgets/styles/qstyleanimation_p.h
index 3b10eeea27..bb1ab9d877 100644
--- a/src/widgets/styles/qstyleanimation_p.h
+++ b/src/widgets/styles/qstyleanimation_p.h
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
// We mean it.
//
-class QStyleAnimation : public QAbstractAnimation
+class Q_WIDGETS_EXPORT QStyleAnimation : public QAbstractAnimation
{
Q_OBJECT
@@ -83,7 +83,8 @@ public:
DefaultFps,
SixtyFps,
ThirtyFps,
- TwentyFps
+ TwentyFps,
+ FifteenFps
};
FrameRate frameRate() const;
@@ -106,7 +107,7 @@ private:
int _skip;
};
-class QProgressStyleAnimation : public QStyleAnimation
+class Q_WIDGETS_EXPORT QProgressStyleAnimation : public QStyleAnimation
{
Q_OBJECT
@@ -127,7 +128,7 @@ private:
mutable int _step;
};
-class QNumberStyleAnimation : public QStyleAnimation
+class Q_WIDGETS_EXPORT QNumberStyleAnimation : public QStyleAnimation
{
Q_OBJECT
@@ -151,7 +152,7 @@ private:
mutable qreal _prev;
};
-class QBlendStyleAnimation : public QStyleAnimation
+class Q_WIDGETS_EXPORT QBlendStyleAnimation : public QStyleAnimation
{
Q_OBJECT
@@ -178,7 +179,7 @@ private:
QImage _current;
};
-class QScrollbarStyleAnimation : public QNumberStyleAnimation
+class Q_WIDGETS_EXPORT QScrollbarStyleAnimation : public QNumberStyleAnimation
{
Q_OBJECT
diff --git a/src/widgets/styles/qstylefactory.cpp b/src/widgets/styles/qstylefactory.cpp
index 8dc603f8e6..c959994d2c 100644
--- a/src/widgets/styles/qstylefactory.cpp
+++ b/src/widgets/styles/qstylefactory.cpp
@@ -46,19 +46,6 @@
#include "qwindowsstyle_p.h"
#if QT_CONFIG(style_fusion)
#include "qfusionstyle_p.h"
-#if QT_CONFIG(style_android)
-#include "qandroidstyle_p.h"
-#endif
-#endif
-#if QT_CONFIG(style_windowsxp)
-#include "qwindowsxpstyle_p.h"
-#endif
-#if QT_CONFIG(style_windowsvista)
-#include "qwindowsvistastyle_p.h"
-#endif
-
-#if QT_CONFIG(style_mac)
-# include "qmacstyle_mac_p.h"
#endif
QT_BEGIN_NAMESPACE
@@ -81,7 +68,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
The valid keys can be retrieved using the keys()
function. Typically they include "windows" and "fusion".
- Depending on the platform, "windowsxp", "windowsvista"
+ Depending on the platform, "windowsvista"
and "macintosh" may be available.
Note that keys are case insensitive.
@@ -108,35 +95,11 @@ QStyle *QStyleFactory::create(const QString& key)
ret = new QWindowsStyle;
else
#endif
-#if QT_CONFIG(style_windowsxp)
- if (style == QLatin1String("windowsxp"))
- ret = new QWindowsXPStyle;
- else
-#endif
-#if QT_CONFIG(style_windowsvista)
- if (style == QLatin1String("windowsvista"))
- ret = new QWindowsVistaStyle;
- else
-#endif
#if QT_CONFIG(style_fusion)
if (style == QLatin1String("fusion"))
ret = new QFusionStyle;
else
#endif
-#if QT_CONFIG(style_android)
- if (style == QLatin1String("android"))
- ret = new QAndroidStyle;
- else
-#endif
-#if QT_CONFIG(style_mac)
- if (style.startsWith(QLatin1String("macintosh"))) {
- ret = new QMacStyle;
-# if 0 // Used to be included in Qt4 for Q_WS_MAC
- if (style == QLatin1String("macintosh"))
- style += QLatin1String(" (aqua)");
-# endif
- } else
-#endif
{ } // Keep these here - they make the #ifdefery above work
if (!ret)
ret = qLoadPlugin<QStyle, QStylePlugin>(loader(), style);
@@ -164,32 +127,10 @@ QStringList QStyleFactory::keys()
if (!list.contains(QLatin1String("Windows")))
list << QLatin1String("Windows");
#endif
-#if QT_CONFIG(style_windowsxp)
- if (!list.contains(QLatin1String("WindowsXP")) &&
- (QSysInfo::WindowsVersion >= QSysInfo::WV_XP && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)))
- list << QLatin1String("WindowsXP");
-#endif
-#if QT_CONFIG(style_windowsvista)
- if (!list.contains(QLatin1String("WindowsVista")) &&
- (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA && (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based)))
- list << QLatin1String("WindowsVista");
-#endif
-#if QT_CONFIG(style_android)
- if (!list.contains(QLatin1String("Android")))
- list << QLatin1String("Android");
-#endif
#if QT_CONFIG(style_fusion)
if (!list.contains(QLatin1String("Fusion")))
list << QLatin1String("Fusion");
#endif
-#if QT_CONFIG(style_mac)
- QString mstyle = QLatin1String("Macintosh");
-# if 0 // Used to be included in Qt4 for Q_WS_MAC
- mstyle += QLatin1String(" (aqua)");
-# endif
- if (!list.contains(mstyle))
- list << mstyle;
-#endif
return list;
}
diff --git a/src/widgets/styles/qstylehelper.cpp b/src/widgets/styles/qstylehelper.cpp
index ffb898df57..6a5a27ed6d 100644
--- a/src/widgets/styles/qstylehelper.cpp
+++ b/src/widgets/styles/qstylehelper.cpp
@@ -429,5 +429,34 @@ QWindow *styleObjectWindow(QObject *so)
return 0;
}
+void setWidgetSizePolicy(const QWidget *widget, WidgetSizePolicy policy)
+{
+ QWidget *wadget = const_cast<QWidget *>(widget);
+ wadget->setAttribute(Qt::WA_MacNormalSize, policy == SizeLarge);
+ wadget->setAttribute(Qt::WA_MacSmallSize, policy == SizeSmall);
+ wadget->setAttribute(Qt::WA_MacMiniSize, policy == SizeMini);
+}
+
+WidgetSizePolicy widgetSizePolicy(const QWidget *widget, const QStyleOption *opt)
+{
+ while (widget) {
+ if (widget->testAttribute(Qt::WA_MacMiniSize)) {
+ return SizeMini;
+ } else if (widget->testAttribute(Qt::WA_MacSmallSize)) {
+ return SizeSmall;
+ } else if (widget->testAttribute(Qt::WA_MacNormalSize)) {
+ return SizeLarge;
+ }
+ widget = widget->parentWidget();
+ }
+
+ if (opt && opt->state & QStyle::State_Mini)
+ return SizeMini;
+ else if (opt && opt->state & QStyle::State_Small)
+ return SizeSmall;
+
+ return SizeDefault;
+}
+
}
QT_END_NAMESPACE
diff --git a/src/widgets/styles/qstylehelper_p.h b/src/widgets/styles/qstylehelper_p.h
index 88eb05f1d7..777ad95470 100644
--- a/src/widgets/styles/qstylehelper_p.h
+++ b/src/widgets/styles/qstylehelper_p.h
@@ -62,31 +62,40 @@
QT_BEGIN_NAMESPACE
+class QColor;
+class QObject;
class QPainter;
+class QPalette;
class QPixmap;
class QStyleOptionSlider;
class QStyleOption;
+class QWidget;
class QWindow;
namespace QStyleHelper
{
QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size);
- qreal dpiScaled(qreal value);
+ Q_WIDGETS_EXPORT qreal dpiScaled(qreal value);
#ifndef QT_NO_DIAL
qreal angle(const QPointF &p1, const QPointF &p2);
QPolygonF calcLines(const QStyleOptionSlider *dial);
int calcBigLineSize(int radius);
- void drawDial(const QStyleOptionSlider *dial, QPainter *painter);
+ Q_WIDGETS_EXPORT void drawDial(const QStyleOptionSlider *dial, QPainter *painter);
#endif //QT_NO_DIAL
- void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect,
+ Q_WIDGETS_EXPORT void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect,
int left = 0, int top = 0, int right = 0,
int bottom = 0);
#ifndef QT_NO_ACCESSIBILITY
- bool isInstanceOf(QObject *obj, QAccessible::Role role);
- bool hasAncestor(QObject *obj, QAccessible::Role role);
+ Q_WIDGETS_EXPORT bool isInstanceOf(QObject *obj, QAccessible::Role role);
+ Q_WIDGETS_EXPORT bool hasAncestor(QObject *obj, QAccessible::Role role);
#endif
- QColor backgroundColor(const QPalette &pal, const QWidget* widget = 0);
- QWindow *styleObjectWindow(QObject *so);
+ Q_WIDGETS_EXPORT QColor backgroundColor(const QPalette &pal, const QWidget* widget = 0);
+ Q_WIDGETS_EXPORT QWindow *styleObjectWindow(QObject *so);
+
+ enum WidgetSizePolicy { SizeLarge = 0, SizeSmall = 1, SizeMini = 2, SizeDefault = -1 };
+
+ void setWidgetSizePolicy(const QWidget *w, WidgetSizePolicy policy);
+ Q_WIDGETS_EXPORT WidgetSizePolicy widgetSizePolicy(const QWidget *w, const QStyleOption *opt = 0);
}
diff --git a/src/widgets/styles/qstyleoption.cpp b/src/widgets/styles/qstyleoption.cpp
index 5d11b86ae7..a346ee18c4 100644
--- a/src/widgets/styles/qstyleoption.cpp
+++ b/src/widgets/styles/qstyleoption.cpp
@@ -38,11 +38,9 @@
****************************************************************************/
#include <QtWidgets/private/qtwidgetsglobal_p.h>
+#include "private/qstylehelper_p.h"
#include "qstyleoption.h"
#include "qapplication.h"
-#if QT_CONFIG(style_mac)
-# include "qmacstyle_mac_p.h"
-#endif
#include <qdebug.h>
#include <QtCore/qmath.h>
@@ -205,18 +203,16 @@ void QStyleOption::init(const QWidget *widget)
if (!(state & QStyle::State_Active) && !qt_mac_can_clickThrough(widget))
state &= ~QStyle::State_Enabled;
#endif
-#if QT_CONFIG(style_mac)
- switch (QMacStyle::widgetSizePolicy(widget)) {
- case QMacStyle::SizeSmall:
+ switch (QStyleHelper::widgetSizePolicy(widget)) {
+ case QStyleHelper::SizeSmall:
state |= QStyle::State_Small;
break;
- case QMacStyle::SizeMini:
+ case QStyleHelper::SizeMini:
state |= QStyle::State_Mini;
break;
default:
;
}
-#endif
#ifdef QT_KEYPAD_NAVIGATION
if (widget->hasEditFocus())
state |= QStyle::State_HasEditFocus;
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 5557dba430..b42876d72e 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -695,10 +695,12 @@ static const char knownStyleHints[][45] = {
"titlebar-minimize-icon",
"titlebar-normal-icon",
"titlebar-shade-icon",
+ "titlebar-show-tooltips-on-buttons",
"titlebar-unshade-icon",
"toolbutton-popup-delay",
"trash-icon",
- "uparrow-icon"
+ "uparrow-icon",
+ "widget-animation-duration"
};
static const int numKnownStyleHints = sizeof(knownStyleHints)/sizeof(knownStyleHints[0]);
@@ -5331,6 +5333,8 @@ int QStyleSheetStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWi
}
case SH_ItemView_ArrowKeysNavigateIntoChildren: s = QLatin1String("arrow-keys-navigate-into-children"); break;
case SH_ItemView_PaintAlternatingRowColorsForEmptyArea: s = QLatin1String("paint-alternating-row-colors-for-empty-area"); break;
+ case SH_TitleBar_ShowToolTipsOnButtons: s = QLatin1String("titlebar-show-tooltips-on-buttons"); break;
+ case SH_Widget_Animation_Duration: s = QLatin1String("widget-animation-duration"); break;
default: break;
}
if (!s.isEmpty() && rule.hasStyleHint(s)) {
diff --git a/src/widgets/styles/qstylesheetstyle_default.cpp b/src/widgets/styles/qstylesheetstyle_default.cpp
index 168251b0f3..1cb1adb2db 100644
--- a/src/widgets/styles/qstylesheetstyle_default.cpp
+++ b/src/widgets/styles/qstylesheetstyle_default.cpp
@@ -78,7 +78,7 @@ using namespace QCss;
bSelector.pseudos << pseudo
// This is attributes. The third parameter is AttributeSelector::*
-// Ex. QComboBox[style="QWindowsXPStyle"]
+// Ex. QComboBox[style="QWindowsVistaStyle"]
// ^ ^
#define ADD_ATTRIBUTE_SELECTOR(x, y, z) \
@@ -155,7 +155,7 @@ StyleSheet QStyleSheetStyle::getDefaultStyleSheet() const
// pixmap based style doesn't support any features
bool styleIsPixmapBased = baseStyle()->inherits("QMacStyle")
- || baseStyle()->inherits("QWindowsXPStyle");
+ || baseStyle()->inherits("QWindowsVistaStyle");
/*QLineEdit {
diff --git a/src/widgets/styles/qwindowsstyle_p.h b/src/widgets/styles/qwindowsstyle_p.h
index a1d65610ff..12a682f330 100644
--- a/src/widgets/styles/qwindowsstyle_p.h
+++ b/src/widgets/styles/qwindowsstyle_p.h
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
class QWindowsStylePrivate;
-class QWindowsStyle : public QCommonStyle
+class Q_WIDGETS_EXPORT QWindowsStyle : public QCommonStyle
{
Q_OBJECT
public:
diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h
index 5023fd1042..8b387b6ab9 100644
--- a/src/widgets/styles/qwindowsstyle_p_p.h
+++ b/src/widgets/styles/qwindowsstyle_p_p.h
@@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE
class QTime;
-class QWindowsStylePrivate : public QCommonStylePrivate
+class Q_WIDGETS_EXPORT QWindowsStylePrivate : public QCommonStylePrivate
{
Q_DECLARE_PUBLIC(QWindowsStyle)
public:
diff --git a/src/widgets/styles/styles.pri b/src/widgets/styles/styles.pri
index 481123f0d4..0c0f8b7bc7 100644
--- a/src/widgets/styles/styles.pri
+++ b/src/widgets/styles/styles.pri
@@ -37,24 +37,6 @@ RESOURCES += styles/qstyle.qrc
include($$OUT_PWD/qtwidgets-config.pri)
-qtConfig(style-mac) {
- HEADERS += \
- styles/qmacstyle_mac_p.h \
- styles/qmacstyle_mac_p_p.h
- OBJECTIVE_SOURCES += styles/qmacstyle_mac.mm
- LIBS_PRIVATE += -framework Carbon
-}
-
-qtConfig(style-windowsvista) {
- HEADERS += styles/qwindowsvistastyle_p.h styles/qwindowsvistastyle_p_p.h
- SOURCES += styles/qwindowsvistastyle.cpp
-}
-
-qtConfig(style-windowsxp) {
- HEADERS += styles/qwindowsxpstyle_p.h styles/qwindowsxpstyle_p_p.h
- SOURCES += styles/qwindowsxpstyle.cpp
-}
-
qtConfig(style-windows) {
HEADERS += styles/qwindowsstyle_p.h styles/qwindowsstyle_p_p.h
SOURCES += styles/qwindowsstyle.cpp
@@ -64,8 +46,3 @@ qtConfig(style-fusion) {
HEADERS += styles/qfusionstyle_p.h styles/qfusionstyle_p_p.h
SOURCES += styles/qfusionstyle.cpp
}
-
-qtConfig(style-android) {
- HEADERS += styles/qandroidstyle_p.h
- SOURCES += styles/qandroidstyle.cpp
-}
diff --git a/src/widgets/util/qcompleter.cpp b/src/widgets/util/qcompleter.cpp
index 9ae0384020..3a1821240e 100644
--- a/src/widgets/util/qcompleter.cpp
+++ b/src/widgets/util/qcompleter.cpp
@@ -496,18 +496,25 @@ QMatchData QCompletionEngine::filterHistory()
}
// Returns a match hint from the cache by chopping the search string
-bool QCompletionEngine::matchHint(QString part, const QModelIndex& parent, QMatchData *hint)
+bool QCompletionEngine::matchHint(const QString &part, const QModelIndex &parent, QMatchData *hint) const
{
- if (c->cs == Qt::CaseInsensitive)
- part = std::move(part).toLower();
+ if (part.isEmpty())
+ return false; // early out to avoid cache[parent] lookup costs
- const CacheItem& map = cache[parent];
+ const auto cit = cache.find(parent);
+ if (cit == cache.end())
+ return false;
+
+ const CacheItem& map = *cit;
+ const auto mapEnd = map.end();
+
+ QString key = c->cs == Qt::CaseInsensitive ? part.toLower() : part;
- QString key = part;
while (!key.isEmpty()) {
key.chop(1);
- if (map.contains(key)) {
- *hint = map[key];
+ const auto it = map.find(key);
+ if (it != mapEnd) {
+ *hint = *it;
return true;
}
}
@@ -515,15 +522,25 @@ bool QCompletionEngine::matchHint(QString part, const QModelIndex& parent, QMatc
return false;
}
-bool QCompletionEngine::lookupCache(QString part, const QModelIndex& parent, QMatchData *m)
+bool QCompletionEngine::lookupCache(const QString &part, const QModelIndex &parent, QMatchData *m) const
{
- if (c->cs == Qt::CaseInsensitive)
- part = std::move(part).toLower();
- const CacheItem& map = cache[parent];
- if (!map.contains(part))
- return false;
- *m = map[part];
- return true;
+ if (part.isEmpty())
+ return false; // early out to avoid cache[parent] lookup costs
+
+ const auto cit = cache.find(parent);
+ if (cit == cache.end())
+ return false;
+
+ const CacheItem& map = *cit;
+
+ const QString key = c->cs == Qt::CaseInsensitive ? part.toLower() : part;
+
+ const auto it = map.find(key);
+ if (it == map.end())
+ return false;
+
+ *m = it.value();
+ return true;
}
// When the cache size exceeds 1MB, it clears out about 1/2 of the cache.
diff --git a/src/widgets/util/qcompleter_p.h b/src/widgets/util/qcompleter_p.h
index 6629c47e06..3cb7c59b6d 100644
--- a/src/widgets/util/qcompleter_p.h
+++ b/src/widgets/util/qcompleter_p.h
@@ -150,10 +150,10 @@ public:
void filter(const QStringList &parts);
QMatchData filterHistory();
- bool matchHint(QString, const QModelIndex&, QMatchData*);
+ bool matchHint(const QString &part, const QModelIndex &parent, QMatchData *m) const;
void saveInCache(QString, const QModelIndex&, const QMatchData&);
- bool lookupCache(QString part, const QModelIndex& parent, QMatchData *m);
+ bool lookupCache(const QString &part, const QModelIndex &parent, QMatchData *m) const;
virtual void filterOnDemand(int) { }
virtual QMatchData filter(const QString&, const QModelIndex&, int) = 0;
diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp
index 11214d93eb..19c22eca46 100644
--- a/src/widgets/util/qsystemtrayicon.cpp
+++ b/src/widgets/util/qsystemtrayicon.cpp
@@ -61,6 +61,9 @@
#include "qdesktopwidget.h"
#include "qbitmap.h"
+#include <private/qhighdpiscaling_p.h>
+#include <qpa/qplatformscreen.h>
+
QT_BEGIN_NAMESPACE
static QIcon messageIcon2qIcon(QSystemTrayIcon::MessageIcon icon)
@@ -196,8 +199,23 @@ QSystemTrayIcon::~QSystemTrayIcon()
void QSystemTrayIcon::setContextMenu(QMenu *menu)
{
Q_D(QSystemTrayIcon);
+ QMenu *oldMenu = d->menu.data();
d->menu = menu;
d->updateMenu_sys();
+ if (oldMenu != menu && d->qpa_sys) {
+ // Show the QMenu-based menu for QPA plugins that do not provide native menus
+ if (oldMenu && !oldMenu->platformMenu())
+ QObject::disconnect(d->qpa_sys, &QPlatformSystemTrayIcon::contextMenuRequested, menu, nullptr);
+ if (menu && !menu->platformMenu()) {
+ QObject::connect(d->qpa_sys, &QPlatformSystemTrayIcon::contextMenuRequested,
+ menu,
+ [menu](QPoint globalNativePos, const QPlatformScreen *platformScreen)
+ {
+ QScreen *screen = platformScreen ? platformScreen->screen() : nullptr;
+ menu->popup(QHighDpi::fromNativePixels(globalNativePos, screen), nullptr);
+ });
+ }
+ }
}
/*!
@@ -323,7 +341,9 @@ bool QSystemTrayIcon::event(QEvent *e)
\value Unknown Unknown reason
\value Context The context menu for the system tray entry was requested
- \value DoubleClick The system tray entry was double clicked
+ \value DoubleClick The system tray entry was double clicked. \note On macOS, a
+ double click will only be emitted if no context menu is set, since the menu
+ opens on mouse press
\value Trigger The system tray entry was clicked
\value MiddleClick The system tray entry was clicked with the middle mouse button
@@ -348,7 +368,7 @@ bool QSystemTrayIcon::event(QEvent *e)
Currently this signal is not sent on \macos.
- \note We follow Microsoft Windows XP/Vista behavior, so the
+ \note We follow Microsoft Windows behavior, so the
signal is also emitted when the user clicks on a tray icon with
a balloon message displayed.
diff --git a/src/widgets/util/qsystemtrayicon_win.cpp b/src/widgets/util/qsystemtrayicon_win.cpp
deleted file mode 100644
index d110cb8be4..0000000000
--- a/src/widgets/util/qsystemtrayicon_win.cpp
+++ /dev/null
@@ -1,591 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWidgets module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsystemtrayicon_p.h"
-#ifndef QT_NO_SYSTEMTRAYICON
-
-#if defined(_WIN32_IE) && _WIN32_IE < 0x0600
-# undef _WIN32_IE
-#endif
-#if !defined(_WIN32_IE)
-# define _WIN32_IE 0x0600 //required for NOTIFYICONDATA_V2_SIZE
-#endif
-
-#include <private/qsystemlibrary_p.h>
-#include <private/qguiapplication_p.h>
-#include <qpa/qplatformnativeinterface.h>
-#include <QSettings>
-#include <QDebug>
-#include <QHash>
-
-#include <qt_windows.h>
-#include <commctrl.h>
-#include <windowsx.h>
-
-QT_BEGIN_NAMESPACE
-
-static const UINT q_uNOTIFYICONID = 0;
-
-static uint MYWM_TASKBARCREATED = 0;
-#define MYWM_NOTIFYICON (WM_APP+101)
-
-struct Q_NOTIFYICONIDENTIFIER {
- DWORD cbSize;
- HWND hWnd;
- UINT uID;
- GUID guidItem;
-};
-
-#ifndef NIN_KEYSELECT
-# define NIN_KEYSELECT (WM_USER + 1)
-#endif
-
-#ifdef Q_CC_MINGW
-# define NIN_SELECT (WM_USER + 0)
-# define NIN_BALLOONTIMEOUT (WM_USER + 4)
-# define NIN_BALLOONUSERCLICK (WM_USER + 5)
-# define NIF_SHOWTIP 0x00000080
-# define NIIF_LARGE_ICON 0x00000020
-# define NOTIFYICON_VERSION_4 4
-#endif
-
-#define Q_MSGFLT_ALLOW 1
-
-Q_GUI_EXPORT HICON qt_pixmapToWinHICON(const QPixmap &);
-
-typedef HRESULT (WINAPI *PtrShell_NotifyIconGetRect)(const Q_NOTIFYICONIDENTIFIER* identifier, RECT* iconLocation);
-typedef BOOL (WINAPI *PtrChangeWindowMessageFilter)(UINT message, DWORD dwFlag);
-typedef BOOL (WINAPI *PtrChangeWindowMessageFilterEx)(HWND hWnd, UINT message, DWORD action, void* pChangeFilterStruct);
-
-// Copy QString data to a limited wchar_t array including \0.
-static inline void qStringToLimitedWCharArray(QString in, wchar_t *target, int maxLength)
-{
- const int length = qMin(maxLength - 1, in.size());
- if (length < in.size())
- in.truncate(length);
- in.toWCharArray(target);
- target[length] = wchar_t(0);
-}
-
-class QSystemTrayIconSys
-{
-public:
- QSystemTrayIconSys(HWND hwnd, QSystemTrayIcon *object);
- ~QSystemTrayIconSys();
- bool trayMessage(DWORD msg);
- void setIconContents(NOTIFYICONDATA &data);
- bool showMessage(const QString &title, const QString &message, const QIcon &icon, uint uSecs);
- QRect findIconGeometry(UINT iconId);
- HICON createIcon();
- bool winEvent(MSG *m, long *result);
-
-private:
- const HWND m_hwnd;
- HICON hIcon;
- QPoint globalPos;
- QSystemTrayIcon *q;
- uint notifyIconSize;
- int version;
- bool ignoreNextMouseRelease;
-};
-
-static bool allowsMessages()
-{
-#ifndef QT_NO_SETTINGS
- const QString key = QStringLiteral("HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Advanced");
- const QSettings settings(key, QSettings::NativeFormat);
- return settings.value(QStringLiteral("EnableBalloonTips"), true).toBool();
-#else
- return false;
-#endif
-}
-
-typedef QHash<HWND, QSystemTrayIconSys *> HandleTrayIconHash;
-
-Q_GLOBAL_STATIC(HandleTrayIconHash, handleTrayIconHash)
-
-extern "C" LRESULT QT_WIN_CALLBACK qWindowsTrayconWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
-{
- if (message == MYWM_TASKBARCREATED || message == MYWM_NOTIFYICON) {
- if (QSystemTrayIconSys *trayIcon = handleTrayIconHash()->value(hwnd)) {
- MSG msg;
- msg.hwnd = hwnd; // re-create MSG structure
- msg.message = message; // time and pt fields ignored
- msg.wParam = wParam;
- msg.lParam = lParam;
- msg.pt.x = GET_X_LPARAM(lParam);
- msg.pt.y = GET_Y_LPARAM(lParam);
- long result = 0;
- if (trayIcon->winEvent(&msg, &result))
- return result;
- }
- }
- return DefWindowProc(hwnd, message, wParam, lParam);
-}
-
-// Invoke a service of the native Windows interface to create
-// a non-visible toplevel window to receive tray messages.
-// Note: Message windows (HWND_MESSAGE) are not sufficient, they
-// will not receive the "TaskbarCreated" message.
-static inline HWND createTrayIconMessageWindow()
-{
- QPlatformNativeInterface *ni = QGuiApplication::platformNativeInterface();
- if (!ni)
- return 0;
- // Register window class in the platform plugin.
- QString className;
- void *wndProc = reinterpret_cast<void *>(qWindowsTrayconWndProc);
- if (!QMetaObject::invokeMethod(ni, "registerWindowClass", Qt::DirectConnection,
- Q_RETURN_ARG(QString, className),
- Q_ARG(QString, QStringLiteral("QTrayIconMessageWindowClass")),
- Q_ARG(void *, wndProc))) {
- return 0;
- }
- const wchar_t windowName[] = L"QTrayIconMessageWindow";
- return CreateWindowEx(0, (wchar_t*)className.utf16(),
- windowName, WS_OVERLAPPED,
- CW_USEDEFAULT, CW_USEDEFAULT,
- CW_USEDEFAULT, CW_USEDEFAULT,
- NULL, NULL, (HINSTANCE)GetModuleHandle(0), NULL);
-}
-
-QSystemTrayIconSys::QSystemTrayIconSys(HWND hwnd, QSystemTrayIcon *object)
- : m_hwnd(hwnd), hIcon(0), q(object)
- , notifyIconSize(sizeof(NOTIFYICONDATA)), version(NOTIFYICON_VERSION_4)
- , ignoreNextMouseRelease(false)
-
-{
- handleTrayIconHash()->insert(m_hwnd, this);
-
- if (QSysInfo::windowsVersion() < QSysInfo::WV_VISTA) {
- notifyIconSize = NOTIFYICONDATA_V2_SIZE;
- version = NOTIFYICON_VERSION;
- }
-
- // For restoring the tray icon after explorer crashes
- if (!MYWM_TASKBARCREATED) {
- MYWM_TASKBARCREATED = RegisterWindowMessage(L"TaskbarCreated");
- }
-
- // Allow the WM_TASKBARCREATED message through the UIPI filter on Windows 7 and higher
- static PtrChangeWindowMessageFilterEx pChangeWindowMessageFilterEx =
- (PtrChangeWindowMessageFilterEx)QSystemLibrary::resolve(QLatin1String("user32"), "ChangeWindowMessageFilterEx");
-
- if (pChangeWindowMessageFilterEx) {
- // Call the safer ChangeWindowMessageFilterEx API if available (Windows 7 onwards)
- pChangeWindowMessageFilterEx(m_hwnd, MYWM_TASKBARCREATED, Q_MSGFLT_ALLOW, 0);
- } else {
- // Call the deprecated ChangeWindowMessageFilter API otherwise (Vista onwards)
- // May 2016: Still resolved at runtime since the definition is not present in MinGW 4.9.
- // TODO: Replace by direct invocation when upgrading MinGW.
- static PtrChangeWindowMessageFilter pChangeWindowMessageFilter =
- (PtrChangeWindowMessageFilter)QSystemLibrary::resolve(QLatin1String("user32"), "ChangeWindowMessageFilter");
-
- if (pChangeWindowMessageFilter)
- pChangeWindowMessageFilter(MYWM_TASKBARCREATED, Q_MSGFLT_ALLOW);
- }
-}
-
-QSystemTrayIconSys::~QSystemTrayIconSys()
-{
- handleTrayIconHash()->remove(m_hwnd);
- if (hIcon)
- DestroyIcon(hIcon);
- DestroyWindow(m_hwnd);
-}
-
-void QSystemTrayIconSys::setIconContents(NOTIFYICONDATA &tnd)
-{
- tnd.uFlags |= NIF_MESSAGE | NIF_ICON | NIF_TIP;
- tnd.uCallbackMessage = MYWM_NOTIFYICON;
- tnd.hIcon = hIcon;
- const QString tip = q->toolTip();
- if (!tip.isNull())
- qStringToLimitedWCharArray(tip, tnd.szTip, sizeof(tnd.szTip)/sizeof(wchar_t));
-}
-
-bool QSystemTrayIconSys::showMessage(const QString &title, const QString &message, const QIcon &icon, uint uSecs)
-{
- NOTIFYICONDATA tnd;
- memset(&tnd, 0, notifyIconSize);
- qStringToLimitedWCharArray(message, tnd.szInfo, 256);
- qStringToLimitedWCharArray(title, tnd.szInfoTitle, 64);
-
- tnd.uID = q_uNOTIFYICONID;
- tnd.dwInfoFlags = NIIF_USER;
-
- HICON *phIcon = &tnd.hIcon;
- QSize size(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
- if (version == NOTIFYICON_VERSION_4) {
- const QSize largeIcon(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON));
- QSize more = icon.actualSize(largeIcon);
- if (more.height() > (largeIcon.height() * 3/4) || more.width() > (largeIcon.width() * 3/4)) {
- tnd.dwInfoFlags |= NIIF_LARGE_ICON;
- size = largeIcon;
- }
- phIcon = &tnd.hBalloonIcon;
- }
- QPixmap pm = icon.pixmap(size);
- if (pm.isNull()) {
- tnd.dwInfoFlags = NIIF_INFO;
- } else {
- if (pm.size() != size) {
- qWarning("QSystemTrayIcon::showMessage: Wrong icon size (%dx%d), please add standard one: %dx%d",
- pm.size().width(), pm.size().height(), size.width(), size.height());
- pm = pm.scaled(size, Qt::IgnoreAspectRatio);
- }
- *phIcon = qt_pixmapToWinHICON(pm);
- }
- tnd.cbSize = notifyIconSize;
- tnd.uVersion = version;
- tnd.hWnd = m_hwnd;
- tnd.uTimeout = uSecs;
- tnd.uFlags = NIF_INFO | NIF_SHOWTIP;
-
- return Shell_NotifyIcon(NIM_MODIFY, &tnd);
-}
-
-bool QSystemTrayIconSys::trayMessage(DWORD msg)
-{
- NOTIFYICONDATA tnd;
- memset(&tnd, 0, notifyIconSize);
-
- tnd.uID = q_uNOTIFYICONID;
- tnd.cbSize = notifyIconSize;
- tnd.hWnd = m_hwnd;
- tnd.uFlags = NIF_SHOWTIP;
- tnd.uVersion = version;
-
- if (msg == NIM_ADD || msg == NIM_MODIFY) {
- setIconContents(tnd);
- }
-
- bool success = Shell_NotifyIcon(msg, &tnd);
-
- if (msg == NIM_ADD)
- return success && Shell_NotifyIcon(NIM_SETVERSION, &tnd);
- else
- return success;
-}
-
-HICON QSystemTrayIconSys::createIcon()
-{
- const HICON oldIcon = hIcon;
- hIcon = 0;
- const QIcon icon = q->icon();
- if (icon.isNull())
- return oldIcon;
- const QSize requestedSize = QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA
- ? QSize(GetSystemMetrics(SM_CXICON), GetSystemMetrics(SM_CYICON))
- : QSize(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON));
- const QSize size = icon.actualSize(requestedSize);
- const QPixmap pm = icon.pixmap(size);
- if (pm.isNull())
- return oldIcon;
- hIcon = qt_pixmapToWinHICON(pm);
- return oldIcon;
-}
-
-bool QSystemTrayIconSys::winEvent( MSG *m, long *result )
-{
- *result = 0;
- switch(m->message) {
- case MYWM_NOTIFYICON:
- {
- int message = 0;
- QPoint gpos;
-
- if (version == NOTIFYICON_VERSION_4) {
- Q_ASSERT(q_uNOTIFYICONID == HIWORD(m->lParam));
- message = LOWORD(m->lParam);
- gpos = QPoint(GET_X_LPARAM(m->wParam), GET_Y_LPARAM(m->wParam));
- } else {
- Q_ASSERT(q_uNOTIFYICONID == m->wParam);
- message = m->lParam;
- gpos = QCursor::pos();
- }
-
- switch (message) {
- case NIN_SELECT:
- case NIN_KEYSELECT:
- if (ignoreNextMouseRelease)
- ignoreNextMouseRelease = false;
- else
- emit q->activated(QSystemTrayIcon::Trigger);
- break;
-
- case WM_LBUTTONDBLCLK:
- ignoreNextMouseRelease = true; // Since DBLCLICK Generates a second mouse
- // release we must ignore it
- emit q->activated(QSystemTrayIcon::DoubleClick);
- break;
-
- case WM_CONTEXTMENU:
- if (q->contextMenu()) {
- q->contextMenu()->popup(gpos);
- q->contextMenu()->activateWindow();
- }
- emit q->activated(QSystemTrayIcon::Context);
- break;
-
- case NIN_BALLOONUSERCLICK:
- emit q->messageClicked();
- break;
-
- case WM_MBUTTONUP:
- emit q->activated(QSystemTrayIcon::MiddleClick);
- break;
-
- default:
- break;
- }
- break;
- }
- default:
- if (m->message == MYWM_TASKBARCREATED) // self-registered message id.
- trayMessage(NIM_ADD);
- break;
- }
- return false;
-}
-
-QSystemTrayIconPrivate::QSystemTrayIconPrivate()
- : sys(0),
- visible(false)
-{
-}
-
-QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
-{
-}
-
-void QSystemTrayIconPrivate::install_sys()
-{
- Q_Q(QSystemTrayIcon);
- if (!sys) {
- if (const HWND hwnd = createTrayIconMessageWindow()) {
- sys = new QSystemTrayIconSys(hwnd, q);
- sys->createIcon();
- sys->trayMessage(NIM_ADD);
- } else {
- qWarning("The platform plugin failed to create a message window.");
- }
- }
-}
-
-/*
-* This function tries to determine the icon geometry from the tray
-*
-* If it fails an invalid rect is returned.
-*/
-
-QRect QSystemTrayIconSys::findIconGeometry(UINT iconId)
-{
- struct AppData
- {
- HWND hwnd;
- UINT uID;
- };
-
- // Windows 7 onwards.
- static PtrShell_NotifyIconGetRect Shell_NotifyIconGetRect =
- (PtrShell_NotifyIconGetRect)QSystemLibrary::resolve(QLatin1String("shell32"),
- "Shell_NotifyIconGetRect");
-
- if (Shell_NotifyIconGetRect) {
- Q_NOTIFYICONIDENTIFIER nid;
- memset(&nid, 0, sizeof(nid));
- nid.cbSize = sizeof(nid);
- nid.hWnd = m_hwnd;
- nid.uID = iconId;
-
- RECT rect;
- HRESULT hr = Shell_NotifyIconGetRect(&nid, &rect);
- if (SUCCEEDED(hr)) {
- return QRect(rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top);
- }
- }
-
- QRect ret;
-
- TBBUTTON buttonData;
- DWORD processID = 0;
- HWND trayHandle = FindWindow(L"Shell_TrayWnd", NULL);
-
- //find the toolbar used in the notification area
- if (trayHandle) {
- trayHandle = FindWindowEx(trayHandle, NULL, L"TrayNotifyWnd", NULL);
- if (trayHandle) {
- HWND hwnd = FindWindowEx(trayHandle, NULL, L"SysPager", NULL);
- if (hwnd) {
- hwnd = FindWindowEx(hwnd, NULL, L"ToolbarWindow32", NULL);
- if (hwnd)
- trayHandle = hwnd;
- }
- }
- }
-
- if (!trayHandle)
- return ret;
-
- GetWindowThreadProcessId(trayHandle, &processID);
- if (processID <= 0)
- return ret;
-
- HANDLE trayProcess = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ, 0, processID);
- if (!trayProcess)
- return ret;
-
- int buttonCount = SendMessage(trayHandle, TB_BUTTONCOUNT, 0, 0);
- LPVOID data = VirtualAllocEx(trayProcess, NULL, sizeof(TBBUTTON), MEM_COMMIT, PAGE_READWRITE);
-
- if ( buttonCount < 1 || !data ) {
- CloseHandle(trayProcess);
- return ret;
- }
-
- //search for our icon among all toolbar buttons
- for (int toolbarButton = 0; toolbarButton < buttonCount; ++toolbarButton ) {
- SIZE_T numBytes = 0;
- AppData appData = { 0, 0 };
- SendMessage(trayHandle, TB_GETBUTTON, toolbarButton , (LPARAM)data);
-
- if (!ReadProcessMemory(trayProcess, data, &buttonData, sizeof(TBBUTTON), &numBytes))
- continue;
-
- if (!ReadProcessMemory(trayProcess, (LPVOID) buttonData.dwData, &appData, sizeof(AppData), &numBytes))
- continue;
-
- bool isHidden = buttonData.fsState & TBSTATE_HIDDEN;
-
- if (m_hwnd == appData.hwnd && appData.uID == iconId && !isHidden) {
- SendMessage(trayHandle, TB_GETITEMRECT, toolbarButton , (LPARAM)data);
- RECT iconRect = {0, 0, 0, 0};
- if(ReadProcessMemory(trayProcess, data, &iconRect, sizeof(RECT), &numBytes)) {
- MapWindowPoints(trayHandle, NULL, (LPPOINT)&iconRect, 2);
- QRect geometry(iconRect.left + 1, iconRect.top + 1,
- iconRect.right - iconRect.left - 2,
- iconRect.bottom - iconRect.top - 2);
- if (geometry.isValid())
- ret = geometry;
- break;
- }
- }
- }
- VirtualFreeEx(trayProcess, data, 0, MEM_RELEASE);
- CloseHandle(trayProcess);
- return ret;
-}
-
-void QSystemTrayIconPrivate::showMessage_sys(const QString &title,
- const QString &messageIn,
- const QIcon &icon,
- QSystemTrayIcon::MessageIcon,
- int timeOut)
-{
- if (!sys || !allowsMessages())
- return;
-
- // 10 sec default
- const uint uSecs = timeOut < 0 ? uint(10000) : uint(timeOut);
- // For empty messages, ensures that they show when only title is set
- QString message = messageIn;
- if (message.isEmpty() && !title.isEmpty())
- message.append(QLatin1Char(' '));
-
- sys->showMessage(title, message, icon, uSecs);
-}
-
-QRect QSystemTrayIconPrivate::geometry_sys() const
-{
- if (!sys)
- return QRect();
-
- return sys->findIconGeometry(q_uNOTIFYICONID);
-}
-
-void QSystemTrayIconPrivate::remove_sys()
-{
- if (!sys)
- return;
-
- sys->trayMessage(NIM_DELETE);
- delete sys;
- sys = 0;
-}
-
-void QSystemTrayIconPrivate::updateIcon_sys()
-{
- if (!sys)
- return;
-
- const HICON hIconToDestroy = sys->createIcon();
- sys->trayMessage(NIM_MODIFY);
-
- if (hIconToDestroy)
- DestroyIcon(hIconToDestroy);
-}
-
-void QSystemTrayIconPrivate::updateMenu_sys()
-{
-#if QT_CONFIG(menu)
-#endif
-}
-
-void QSystemTrayIconPrivate::updateToolTip_sys()
-{
- if (!sys)
- return;
-
- sys->trayMessage(NIM_MODIFY);
-}
-
-bool QSystemTrayIconPrivate::isSystemTrayAvailable_sys()
-{
- return true;
-}
-
-bool QSystemTrayIconPrivate::supportsMessages_sys()
-{
- return allowsMessages();
-}
-
-QT_END_NAMESPACE
-
-#endif
diff --git a/src/widgets/util/util.pri b/src/widgets/util/util.pri
index 8b28ac8bf0..701758a406 100644
--- a/src/widgets/util/util.pri
+++ b/src/widgets/util/util.pri
@@ -44,9 +44,7 @@ qtConfig(undoview) {
SOURCES += util/qundoview.cpp
}
-win32:!winrt {
- SOURCES += util/qsystemtrayicon_win.cpp
-} else: qtConfig(xcb) {
+qtConfig(xcb) {
SOURCES += util/qsystemtrayicon_x11.cpp
} else {
SOURCES += util/qsystemtrayicon_qpa.cpp
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index 506986f4ba..58a1ff9e7f 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -70,11 +70,6 @@
#include <private/qabstractscrollarea_p.h>
#include <private/qlineedit_p.h>
#include <qdebug.h>
-#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && !defined(QT_NO_EFFECTS) && QT_CONFIG(style_mac)
-#include <private/qcore_mac_p.h>
-#include <private/qmacstyle_mac_p.h>
-#include <private/qt_cocoa_helpers_mac_p.h>
-#endif
#ifndef QT_NO_EFFECTS
# include <private/qeffects_p.h>
#endif
@@ -200,7 +195,21 @@ void QComboBoxPrivate::_q_completerActivated(const QModelIndex &index)
if (index.isValid() && q->completer()) {
QAbstractProxyModel *proxy = qobject_cast<QAbstractProxyModel *>(q->completer()->completionModel());
if (proxy) {
- q->setCurrentIndex(proxy->mapToSource(index).row());
+ const QModelIndex &completerIndex = proxy->mapToSource(index);
+ int row = -1;
+ if (completerIndex.model() == model) {
+ row = completerIndex.row();
+ } else {
+ // if QCompleter uses a proxy model to host widget's one - map again
+ QAbstractProxyModel *completerProxy = qobject_cast<QAbstractProxyModel *>(q->completer()->model());
+ if (completerProxy && completerProxy->sourceModel() == model) {
+ row = completerProxy->mapToSource(completerIndex).row();
+ } else {
+ QString match = q->completer()->model()->data(completerIndex).toString();
+ row = q->findText(match, matchFlags());
+ }
+ }
+ q->setCurrentIndex(row);
emitActivated(currentIndex);
}
}
@@ -484,6 +493,14 @@ void QComboBoxPrivateContainer::scrollItemView(int action)
#endif
}
+void QComboBoxPrivateContainer::hideScrollers()
+{
+ if (top)
+ top->hide();
+ if (bottom)
+ bottom->hide();
+}
+
/*
Hides or shows the scrollers when we emulate a popupmenu
*/
@@ -2725,6 +2742,11 @@ void QComboBox::showPopup()
if (needHorizontalScrollBar) {
listRect.adjust(0, 0, 0, sb->height());
}
+
+ // Hide the scrollers here, so that the listrect gets the full height of the container
+ // If the scrollers are truly needed, the later call to container->updateScrollers()
+ // will make them visible again.
+ container->hideScrollers();
container->setGeometry(listRect);
#ifndef Q_OS_MAC
diff --git a/src/widgets/widgets/qcombobox_p.h b/src/widgets/widgets/qcombobox_p.h
index ab4dd0281f..6bee9409ee 100644
--- a/src/widgets/widgets/qcombobox_p.h
+++ b/src/widgets/widgets/qcombobox_p.h
@@ -213,7 +213,7 @@ private:
bool fast;
};
-class Q_AUTOTEST_EXPORT QComboBoxPrivateContainer : public QFrame
+class Q_WIDGETS_EXPORT QComboBoxPrivateContainer : public QFrame
{
Q_OBJECT
@@ -232,6 +232,7 @@ public:
public Q_SLOTS:
void scrollItemView(int action);
+ void hideScrollers();
void updateScrollers();
void viewDestroyed();
diff --git a/src/widgets/widgets/qdatetimeedit.cpp b/src/widgets/widgets/qdatetimeedit.cpp
index 053b184226..6d1521c48b 100644
--- a/src/widgets/widgets/qdatetimeedit.cpp
+++ b/src/widgets/widgets/qdatetimeedit.cpp
@@ -1073,7 +1073,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
//hide cursor
d->edit->d_func()->setCursorVisible(false);
- d->edit->d_func()->control->setCursorBlinkPeriod(0);
+ d->edit->d_func()->control->setBlinkingCursorEnabled(false);
d->setSelected(0);
}
}
@@ -1094,7 +1094,7 @@ void QDateTimeEdit::keyPressEvent(QKeyEvent *event)
//hide cursor
d->edit->d_func()->setCursorVisible(false);
- d->edit->d_func()->control->setCursorBlinkPeriod(0);
+ d->edit->d_func()->control->setBlinkingCursorEnabled(false);
d->setSelected(0);
oldCurrent = 0;
}
@@ -1921,6 +1921,7 @@ QDateTime QDateTimeEditPrivate::validateAndInterpret(QString &input, int &positi
}
StateNode tmp = parse(input, position, value.toDateTime(), fixup);
input = tmp.input;
+ position += tmp.padded;
state = QValidator::State(int(tmp.state));
if (state == QValidator::Acceptable) {
if (tmp.conflicts && conflictGuard != tmp.value) {
diff --git a/src/widgets/widgets/qdialogbuttonbox.cpp b/src/widgets/widgets/qdialogbuttonbox.cpp
index 90cb17da59..788ec67fb2 100644
--- a/src/widgets/widgets/qdialogbuttonbox.cpp
+++ b/src/widgets/widgets/qdialogbuttonbox.cpp
@@ -579,6 +579,8 @@ QDialogButtonBox::~QDialogButtonBox()
\value MacLayout Use a policy appropriate for applications on \macos.
\value KdeLayout Use a policy appropriate for applications on KDE.
\value GnomeLayout Use a policy appropriate for applications on GNOME.
+ \value AndroidLayout Use a policy appropriate for applications on Android.
+ This enum value was added in Qt 5.10.
The button layout is specified by the \l{style()}{current style}. However,
on the X11 platform, it may be influenced by the desktop environment.
diff --git a/src/widgets/widgets/qdialogbuttonbox.h b/src/widgets/widgets/qdialogbuttonbox.h
index af9e705234..02d14dee7c 100644
--- a/src/widgets/widgets/qdialogbuttonbox.h
+++ b/src/widgets/widgets/qdialogbuttonbox.h
@@ -108,11 +108,13 @@ public:
Q_FLAG(StandardButtons)
enum ButtonLayout {
- // keep this in sync with QMessageBox::ButtonLayout and QPlatformDialogHelper::ButtonLayout
+ // keep this in sync with QPlatformDialogHelper::ButtonLayout
WinLayout,
MacLayout,
KdeLayout,
- GnomeLayout
+ GnomeLayout,
+ // MacModelessLayout,
+ AndroidLayout = GnomeLayout + 2 // ### Qt 6: reorder
};
QDialogButtonBox(QWidget *parent = Q_NULLPTR);
diff --git a/src/widgets/widgets/qdockarealayout.cpp b/src/widgets/widgets/qdockarealayout.cpp
index 21d1d4cb85..5edcbcf4ec 100644
--- a/src/widgets/widgets/qdockarealayout.cpp
+++ b/src/widgets/widgets/qdockarealayout.cpp
@@ -1044,33 +1044,6 @@ QLayoutItem *QDockAreaLayoutInfo::plug(const QList<int> &path)
Q_ASSERT(item.widgetItem != 0);
Q_ASSERT(item.flags & QDockAreaLayoutItem::GapItem);
item.flags &= ~QDockAreaLayoutItem::GapItem;
-
- QRect result;
-
-#if QT_CONFIG(tabbar)
- if (tabbed) {
- } else
-#endif
- {
- int prev = this->prev(index);
- int next = this->next(index);
-
- if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
- item.pos += *sep;
- item.size -= *sep;
- }
- if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- item.size -= *sep;
-
- QPoint pos;
- rpick(o, pos) = item.pos;
- rperp(o, pos) = perp(o, rect.topLeft());
- QSize s;
- rpick(o, s) = item.size;
- rperp(o, s) = perp(o, rect.size());
- result = QRect(pos, s);
- }
-
return item.widgetItem;
}
@@ -1323,29 +1296,46 @@ QDockAreaLayoutInfo *QDockAreaLayoutInfo::info(const QList<int> &path)
return item_list[index].subinfo->info(path.mid(1));
}
-QRect QDockAreaLayoutInfo::itemRect(int index) const
+QRect QDockAreaLayoutInfo::itemRect(int index, bool isGap) const
{
const QDockAreaLayoutItem &item = item_list.at(index);
if (item.skip())
return QRect();
+ if (isGap && !(item.flags & QDockAreaLayoutItem::GapItem))
+ return QRect();
+
QRect result;
#if QT_CONFIG(tabbar)
if (tabbed) {
- if (tabId(item) == currentTabId())
+ if (isGap || tabId(item) == currentTabId())
result = tabContentRect();
} else
#endif
{
- QPoint pos;
- rpick(o, pos) = item.pos;
- rperp(o, pos) = perp(o, rect.topLeft());
+ int pos = item.pos;
+ int size = item.size;
+
+ if (isGap) {
+ int prev = this->prev(index);
+ int next = this->next(index);
+ if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
+ pos += *sep;
+ size -= *sep;
+ }
+ if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
+ size -= *sep;
+ }
+
+ QPoint p;
+ rpick(o, p) = pos;
+ rperp(o, p) = perp(o, rect.topLeft());
QSize s;
- rpick(o, s) = item.size;
+ rpick(o, s) = size;
rperp(o, s) = perp(o, rect.size());
- result = QRect(pos, s);
+ result = QRect(p, s);
}
return result;
@@ -2426,20 +2416,21 @@ QList<int> QDockAreaLayout::indexOf(QWidget *dockWidget) const
return QList<int>();
}
-QList<int> QDockAreaLayout::gapIndex(const QPoint &pos) const
+QList<int> QDockAreaLayout::gapIndex(const QPoint &pos, bool disallowTabs) const
{
QMainWindow::DockOptions opts = mainWindow->dockOptions();
bool nestingEnabled = opts & QMainWindow::AllowNestedDocks;
QDockAreaLayoutInfo::TabMode tabMode = QDockAreaLayoutInfo::NoTabs;
#if QT_CONFIG(tabbar)
- if (opts & QMainWindow::AllowTabbedDocks
- || opts & QMainWindow::VerticalTabs)
- tabMode = QDockAreaLayoutInfo::AllowTabs;
- if (opts & QMainWindow::ForceTabbedDocks)
- tabMode = QDockAreaLayoutInfo::ForceTabs;
+ if (!disallowTabs) {
+ if (opts & QMainWindow::AllowTabbedDocks || opts & QMainWindow::VerticalTabs)
+ tabMode = QDockAreaLayoutInfo::AllowTabs;
+ if (opts & QMainWindow::ForceTabbedDocks)
+ tabMode = QDockAreaLayoutInfo::ForceTabs;
- if (tabMode == QDockAreaLayoutInfo::ForceTabs)
- nestingEnabled = false;
+ if (tabMode == QDockAreaLayoutInfo::ForceTabs)
+ nestingEnabled = false;
+ }
#endif
@@ -3311,6 +3302,19 @@ int QDockAreaLayout::separatorMove(const QList<int> &separator, const QPoint &or
return delta;
}
+int QDockAreaLayoutInfo::separatorMove(const QList<int> &separator, const QPoint &origin,
+ const QPoint &dest)
+{
+ int delta = 0;
+ int index = separator.last();
+ QDockAreaLayoutInfo *info = this->info(separator);
+ delta = pick(info->o, dest - origin);
+ if (delta != 0)
+ delta = info->separatorMove(index, delta);
+ info->apply(false);
+ return delta;
+}
+
#if QT_CONFIG(tabbar)
// Sets the correct positions for the separator widgets
// Allocates new sepearator widgets with getSeparatorWidget
@@ -3420,47 +3424,10 @@ QRect QDockAreaLayout::gapRect(const QList<int> &path) const
const QDockAreaLayoutInfo *info = this->info(path);
if (info == 0)
return QRect();
- const QList<QDockAreaLayoutItem> &item_list = info->item_list;
- Qt::Orientation o = info->o;
int index = path.last();
- if (index < 0 || index >= item_list.count())
- return QRect();
- const QDockAreaLayoutItem &item = item_list.at(index);
- if (!(item.flags & QDockAreaLayoutItem::GapItem))
+ if (index < 0 || index >= info->item_list.count())
return QRect();
-
- QRect result;
-
-#if QT_CONFIG(tabbar)
- if (info->tabbed) {
- result = info->tabContentRect();
- } else
-#endif
- {
- int pos = item.pos;
- int size = item.size;
-
- int prev = info->prev(index);
- int next = info->next(index);
-
- if (prev != -1 && !(item_list.at(prev).flags & QDockAreaLayoutItem::GapItem)) {
- pos += sep;
- size -= sep;
- }
- if (next != -1 && !(item_list.at(next).flags & QDockAreaLayoutItem::GapItem))
- size -= sep;
-
- QPoint p;
- rpick(o, p) = pos;
- rperp(o, p) = perp(o, info->rect.topLeft());
- QSize s;
- rpick(o, s) = size;
- rperp(o, s) = perp(o, info->rect.size());
-
- result = QRect(p, s);
- }
-
- return result;
+ return info->itemRect(index, true);
}
void QDockAreaLayout::keepSize(QDockWidget *w)
diff --git a/src/widgets/widgets/qdockarealayout_p.h b/src/widgets/widgets/qdockarealayout_p.h
index 82244c192e..49bd157179 100644
--- a/src/widgets/widgets/qdockarealayout_p.h
+++ b/src/widgets/widgets/qdockarealayout_p.h
@@ -160,7 +160,7 @@ public:
void fitItems();
bool expansive(Qt::Orientation o) const;
int changeSize(int index, int size, bool below);
- QRect itemRect(int index) const;
+ QRect itemRect(int index, bool isGap = false) const;
QRect itemRect(const QList<int> &path) const;
QRect separatorRect(int index) const;
QRect separatorRect(const QList<int> &path) const;
@@ -182,6 +182,7 @@ public:
const QPoint &mouse) const;
QRegion separatorRegion() const;
int separatorMove(int index, int delta);
+ int separatorMove(const QList<int> &separator, const QPoint &origin, const QPoint &dest);
QLayoutItem *itemAt(int *x, int index) const;
QLayoutItem *takeAt(int *x, int index);
@@ -246,7 +247,7 @@ public:
QList<int> indexOfPlaceHolder(const QString &objectName) const;
QList<int> indexOf(QWidget *dockWidget) const;
- QList<int> gapIndex(const QPoint &pos) const;
+ QList<int> gapIndex(const QPoint &pos, bool disallowTabs) const;
QList<int> findSeparator(const QPoint &pos) const;
QDockAreaLayoutItem &item(const QList<int> &path);
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 2d5ee68f8e..36d7ab3421 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -56,11 +56,6 @@
#include "qdockwidget_p.h"
#include "qmainwindowlayout_p.h"
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
-#include <private/qapplication_p.h>
-#include <private/qt_mac_p.h>
-#include <private/qmacstyle_mac_p.h>
-#endif
QT_BEGIN_NAMESPACE
@@ -217,10 +212,9 @@ QDockWidgetLayout::~QDockWidgetLayout()
bool QDockWidgetLayout::nativeWindowDeco() const
{
bool floating = parentWidget()->isWindow();
- if (!floating) {
- if (auto groupWindow = qobject_cast<const QDockWidgetGroupWindow*>(parentWidget()->parentWidget()))
- return groupWindow->hasNativeDecos();
- }
+ if (auto groupWindow =
+ qobject_cast<const QDockWidgetGroupWindow *>(parentWidget()->parentWidget()))
+ floating = floating || groupWindow->tabLayoutInfo();
return nativeWindowDeco(floating);
}
@@ -1442,7 +1436,7 @@ void QDockWidget::paintEvent(QPaintEvent *event)
}
// Title must be painted after the frame, since the areas overlap, and
- // the title may wish to extend out to all sides (eg. XP style)
+ // the title may wish to extend out to all sides (eg. Vista style)
QStyleOptionDockWidget titleOpt;
initStyleOption(&titleOpt);
p.drawControl(QStyle::CE_DockWidgetTitle, titleOpt);
diff --git a/src/widgets/widgets/qlineedit.cpp b/src/widgets/widgets/qlineedit.cpp
index 50eb1a7371..f57fa4fd85 100644
--- a/src/widgets/widgets/qlineedit.cpp
+++ b/src/widgets/widgets/qlineedit.cpp
@@ -77,7 +77,10 @@
#include "private/qapplication_p.h"
#include "private/qshortcutmap_p.h"
#include "qkeysequence.h"
-#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \
+#define ACCEL_KEY(k) ((qApp->testAttribute(Qt::AA_DontShowIconsInMenus) \
+ ? false \
+ : qApp->styleHints()->showShortcutsInContextMenus()) \
+ && !qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \
QLatin1Char('\t') + QKeySequence(k).toString(QKeySequence::NativeText) : QString())
#else
#define ACCEL_KEY(k) QString()
@@ -90,10 +93,6 @@
QT_BEGIN_NAMESPACE
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
-extern void qt_mac_secure_keyboard(bool); //qapplication_mac.cpp
-#endif
-
/*!
Initialize \a option with the values from this QLineEdit. This method
is useful for subclasses when they need a QStyleOptionFrame, but don't want
@@ -575,10 +574,6 @@ void QLineEdit::setEchoMode(EchoMode mode)
setInputMethodHints(imHints);
d->control->setEchoMode(mode);
update();
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- if (hasFocus())
- qt_mac_secure_keyboard(mode == Password || mode == NoEcho);
-#endif
}
@@ -961,6 +956,8 @@ QString QLineEdit::selectedText() const
line edit or -1 if no text is selected.
\sa selectedText()
+ \sa selectionEnd()
+ \sa selectionLength()
*/
int QLineEdit::selectionStart() const
@@ -969,8 +966,33 @@ int QLineEdit::selectionStart() const
return d->control->selectionStart();
}
+/*!
+ Returns the index of the character directly after the selection
+ in the line edit or -1 if no text is selected.
+ \since 5.10
+
+ \sa selectedText()
+ \sa selectionStart()
+ \sa selectionLength()
+*/
+int QLineEdit::selectionEnd() const
+{
+ Q_D(const QLineEdit);
+ return d->control->selectionEnd();
+}
+/*!
+ Returns the length of the selection.
+ \since 5.10
+ \sa selectedText()
+ \sa selectionStart()
+ \sa selectionEnd()
+*/
+int QLineEdit::selectionLength() const
+{
+ return selectionEnd() - selectionStart();
+}
/*!
Selects text from position \a start and for \a length characters.
@@ -1815,10 +1837,6 @@ void QLineEdit::focusInEvent(QFocusEvent *e)
if((!hasSelectedText() && d->control->preeditAreaText().isEmpty())
|| style()->styleHint(QStyle::SH_BlinkCursorWhenTextSelected, &opt, this))
d->setCursorVisible(true);
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho)
- qt_mac_secure_keyboard(true);
-#endif
#ifdef QT_KEYPAD_NAVIGATION
d->control->setCancelText(d->control->text());
}
@@ -1863,10 +1881,6 @@ void QLineEdit::focusOutEvent(QFocusEvent *e)
if (hasAcceptableInput() || d->control->fixup())
emit editingFinished();
}
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- if (d->control->echoMode() == Password || d->control->echoMode() == NoEcho)
- qt_mac_secure_keyboard(false);
-#endif
#ifdef QT_KEYPAD_NAVIGATION
d->control->setCancelText(QString());
#endif
diff --git a/src/widgets/widgets/qlineedit.h b/src/widgets/widgets/qlineedit.h
index 4d32b11f06..d84eeedaf6 100644
--- a/src/widgets/widgets/qlineedit.h
+++ b/src/widgets/widgets/qlineedit.h
@@ -155,6 +155,8 @@ public:
bool hasSelectedText() const;
QString selectedText() const;
int selectionStart() const;
+ int selectionEnd() const;
+ int selectionLength() const;
bool isUndoAvailable() const;
bool isRedoAvailable() const;
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index 271465ec00..694a36ed5b 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -63,13 +63,6 @@
#ifdef Q_OS_OSX
#include <qpa/qplatformnativeinterface.h>
#endif
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
-#include <private/qt_mac_p.h>
-#include <private/qt_cocoa_helpers_mac_p.h>
-QT_BEGIN_NAMESPACE
-extern OSWindowRef qt_mac_window_for(const QWidget *); // qwidget_mac.cpp
-QT_END_NAMESPACE
-#endif
QT_BEGIN_NAMESPACE
@@ -82,13 +75,6 @@ public:
#ifdef Q_OS_OSX
, useUnifiedToolBar(false)
#endif
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- , useHIToolBar(false)
- , activateUnifiedToolbarAfterFullScreen(false)
-#endif
-#if QT_CONFIG(dockwidget) && !defined(QT_NO_CURSOR)
- , hasOldCursor(false) , cursorAdjusted(false)
-#endif
{ }
QMainWindowLayout *layout;
QSize iconSize;
@@ -97,22 +83,7 @@ public:
#ifdef Q_OS_OSX
bool useUnifiedToolBar;
#endif
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- bool useHIToolBar;
- bool activateUnifiedToolbarAfterFullScreen;
-#endif
void init();
- QList<int> hoverSeparator;
- QPoint hoverPos;
-
-#if QT_CONFIG(dockwidget) && !defined(QT_NO_CURSOR)
- QCursor separatorCursor(const QList<int> &path) const;
- void adjustCursor(const QPoint &pos);
- QCursor oldCursor;
- QCursor adjustedCursor;
- uint hasOldCursor : 1;
- uint cursorAdjusted : 1;
-#endif
static inline QMainWindowLayout *mainWindowLayout(const QMainWindow *mainWindow)
{
@@ -807,11 +778,7 @@ void QMainWindow::addToolBar(Qt::ToolBarArea area, QToolBar *toolbar)
#endif
}
- if (!d->layout->usesHIToolBar(toolbar)) {
- d->layout->removeWidget(toolbar);
- } else {
- d->layout->removeToolBar(toolbar);
- }
+ d->layout->removeToolBar(toolbar);
toolbar->d_func()->_q_updateIconSize(d->iconSize);
toolbar->d_func()->_q_updateToolButtonStyle(d->toolButtonStyle);
@@ -1113,21 +1080,6 @@ void QMainWindow::addDockWidget(Qt::DockWidgetArea area, QDockWidget *dockwidget
}
d_func()->layout->removeWidget(dockwidget); // in case it was already in here
addDockWidget(area, dockwidget, orientation);
-
-#if 0 // Used to be included in Qt4 for Q_WS_MAC //drawer support
- QMacAutoReleasePool pool;
- extern bool qt_mac_is_macdrawer(const QWidget *); //qwidget_mac.cpp
- if (qt_mac_is_macdrawer(dockwidget)) {
- extern bool qt_mac_set_drawer_preferred_edge(QWidget *, Qt::DockWidgetArea); //qwidget_mac.cpp
- window()->createWinId();
- dockwidget->window()->createWinId();
- qt_mac_set_drawer_preferred_edge(dockwidget, area);
- if (dockwidget->isVisible()) {
- dockwidget->hide();
- dockwidget->show();
- }
- }
-#endif
}
/*!
@@ -1346,153 +1298,14 @@ bool QMainWindow::restoreState(const QByteArray &state, int version)
return restored;
}
-#if QT_CONFIG(dockwidget) && !defined(QT_NO_CURSOR)
-QCursor QMainWindowPrivate::separatorCursor(const QList<int> &path) const
-{
- QDockAreaLayoutInfo *info = layout->layoutState.dockAreaLayout.info(path);
- Q_ASSERT(info != 0);
- if (path.size() == 1) { // is this the "top-level" separator which separates a dock area
- // from the central widget?
- switch (path.first()) {
- case QInternal::LeftDock:
- case QInternal::RightDock:
- return Qt::SplitHCursor;
- case QInternal::TopDock:
- case QInternal::BottomDock:
- return Qt::SplitVCursor;
- default:
- break;
- }
- }
-
- // no, it's a splitter inside a dock area, separating two dock widgets
-
- return info->o == Qt::Horizontal
- ? Qt::SplitHCursor : Qt::SplitVCursor;
-}
-
-void QMainWindowPrivate::adjustCursor(const QPoint &pos)
-{
- Q_Q(QMainWindow);
-
- hoverPos = pos;
-
- if (pos == QPoint(0, 0)) {
- if (!hoverSeparator.isEmpty())
- q->update(layout->layoutState.dockAreaLayout.separatorRect(hoverSeparator));
- hoverSeparator.clear();
-
- if (cursorAdjusted) {
- cursorAdjusted = false;
- if (hasOldCursor)
- q->setCursor(oldCursor);
- else
- q->unsetCursor();
- }
- } else if (layout->movingSeparator.isEmpty()) { // Don't change cursor when moving separator
- QList<int> pathToSeparator
- = layout->layoutState.dockAreaLayout.findSeparator(pos);
-
- if (pathToSeparator != hoverSeparator) {
- if (!hoverSeparator.isEmpty())
- q->update(layout->layoutState.dockAreaLayout.separatorRect(hoverSeparator));
-
- hoverSeparator = pathToSeparator;
-
- if (hoverSeparator.isEmpty()) {
- if (cursorAdjusted) {
- cursorAdjusted = false;
- if (hasOldCursor)
- q->setCursor(oldCursor);
- else
- q->unsetCursor();
- }
- } else {
- q->update(layout->layoutState.dockAreaLayout.separatorRect(hoverSeparator));
- if (!cursorAdjusted) {
- oldCursor = q->cursor();
- hasOldCursor = q->testAttribute(Qt::WA_SetCursor);
- }
- adjustedCursor = separatorCursor(hoverSeparator);
- q->setCursor(adjustedCursor);
- cursorAdjusted = true;
- }
- }
- }
-}
-#endif
-
/*! \reimp */
bool QMainWindow::event(QEvent *event)
{
Q_D(QMainWindow);
+ if (d->layout && d->layout->windowEvent(event))
+ return true;
switch (event->type()) {
-#if QT_CONFIG(dockwidget)
- case QEvent::Paint: {
- QPainter p(this);
- QRegion r = static_cast<QPaintEvent*>(event)->region();
- d->layout->layoutState.dockAreaLayout.paintSeparators(&p, this, r, d->hoverPos);
- break;
- }
-
-#ifndef QT_NO_CURSOR
- case QEvent::HoverMove: {
- d->adjustCursor(static_cast<QHoverEvent*>(event)->pos());
- break;
- }
-
- // We don't want QWidget to call update() on the entire QMainWindow
- // on HoverEnter and HoverLeave, hence accept the event (return true).
- case QEvent::HoverEnter:
- return true;
- case QEvent::HoverLeave:
- d->adjustCursor(QPoint(0, 0));
- return true;
- case QEvent::ShortcutOverride: // when a menu pops up
- d->adjustCursor(QPoint(0, 0));
- break;
-#endif // QT_NO_CURSOR
-
- case QEvent::MouseButtonPress: {
- QMouseEvent *e = static_cast<QMouseEvent*>(event);
- if (e->button() == Qt::LeftButton && d->layout->startSeparatorMove(e->pos())) {
- // The click was on a separator, eat this event
- e->accept();
- return true;
- }
- break;
- }
-
- case QEvent::MouseMove: {
- QMouseEvent *e = static_cast<QMouseEvent*>(event);
-
-#ifndef QT_NO_CURSOR
- d->adjustCursor(e->pos());
-#endif
- if (e->buttons() & Qt::LeftButton) {
- if (d->layout->separatorMove(e->pos())) {
- // We're moving a separator, eat this event
- e->accept();
- return true;
- }
- }
-
- break;
- }
-
- case QEvent::MouseButtonRelease: {
- QMouseEvent *e = static_cast<QMouseEvent*>(event);
- if (d->layout->endSeparatorMove(e->pos())) {
- // We've released a separator, eat this event
- e->accept();
- return true;
- }
- break;
- }
-
-#endif
-
#ifndef QT_NO_TOOLBAR
case QEvent::ToolBarChange: {
d->layout->toggleToolBarsVisible();
@@ -1518,40 +1331,6 @@ bool QMainWindow::event(QEvent *event)
if (!d->explicitIconSize)
setIconSize(QSize());
break;
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- case QEvent::Show:
- if (unifiedTitleAndToolBarOnMac())
- d->layout->syncUnifiedToolbarVisibility();
- d->layout->blockVisiblityCheck = false;
- break;
- case QEvent::WindowStateChange:
- {
- if (isHidden()) {
- // We are coming out of a minimize, leave things as is.
- d->layout->blockVisiblityCheck = true;
- }
- // We need to update the HIToolbar status when we go out of or into fullscreen.
- QWindowStateChangeEvent *wce = static_cast<QWindowStateChangeEvent *>(event);
- if ((windowState() & Qt::WindowFullScreen) || (wce->oldState() & Qt::WindowFullScreen)) {
- d->layout->updateHIToolBarStatus();
- }
- }
- break;
-#endif
-#if QT_CONFIG(dockwidget) && !defined(QT_NO_CURSOR)
- case QEvent::CursorChange:
- // CursorChange events are triggered as mouse moves to new widgets even
- // if the cursor doesn't actually change, so do not change oldCursor if
- // the "changed" cursor has same shape as adjusted cursor.
- if (d->cursorAdjusted && d->adjustedCursor.shape() != cursor().shape()) {
- d->oldCursor = cursor();
- d->hasOldCursor = testAttribute(Qt::WA_SetCursor);
-
- // Ensure our adjusted cursor stays visible
- setCursor(d->adjustedCursor);
- }
- break;
-#endif
default:
break;
}
@@ -1591,33 +1370,6 @@ void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set)
(reinterpret_cast<SetContentBorderEnabledFunction>(function))(window()->windowHandle(), set);
update();
}
-#endif
-
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- Q_D(QMainWindow);
- if (!isWindow() || d->useHIToolBar == set || QSysInfo::MacintoshVersion < QSysInfo::MV_10_3)
- return;
-
- d->useHIToolBar = set;
- createWinId(); // We need the hiview for down below.
-
- // Activate the unified toolbar with the raster engine.
- if (windowSurface() && set) {
- d->layout->unifiedSurface = new QUnifiedToolbarSurface(this);
- }
-
- d->layout->updateHIToolBarStatus();
-
- // Deactivate the unified toolbar with the raster engine.
- if (windowSurface() && !set) {
- if (d->layout->unifiedSurface) {
- delete d->layout->unifiedSurface;
- d->layout->unifiedSurface = 0;
- }
- }
-
- // Enabling the unified toolbar clears the opaque size grip setting, update it.
- d->macUpdateOpaqueSizeGrip();
#else
Q_UNUSED(set)
#endif
@@ -1628,9 +1380,6 @@ bool QMainWindow::unifiedTitleAndToolBarOnMac() const
#ifdef Q_OS_OSX
return d_func()->useUnifiedToolBar;
#endif
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- return d_func()->useHIToolBar && !testAttribute(Qt::WA_MacBrushedMetal) && !(windowFlags() & Qt::FramelessWindowHint);
-#endif
return false;
}
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index c0ad4e697d..2c1c2ab75c 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -76,10 +76,6 @@
#include <private/qapplication_p.h>
#include <private/qlayoutengine_p.h>
#include <private/qwidgetresizehandler_p.h>
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
-# include <private/qcore_mac_p.h>
-# include <private/qt_cocoa_helpers_mac_p.h>
-#endif
QT_BEGIN_NAMESPACE
@@ -183,13 +179,17 @@ QDebug operator<<(QDebug debug, const QMainWindowLayout *layout)
/******************************************************************************
** QDockWidgetGroupWindow
*/
-// QDockWidgetGroupWindow is the floating window containing the tabbed dockwidgets in case several
-// dockwidgets are dragged together (QMainWindow::GroupedDragging feature).
+// QDockWidgetGroupWindow is the floating window containing several QDockWidgets floating together.
+// (QMainWindow::GroupedDragging feature)
// QDockWidgetGroupLayout is the layout of that window and use a QDockAreaLayoutInfo to layout
-// the tabs inside it.
+// the QDockWidgets inside it.
+// If there is only one QDockWidgets, or all QDockWidgets are tabbed together, it is equivalent
+// of a floating QDockWidget (the title of the QDockWidget is the title of the window). But if there
+// are nested QDockWidget, an additional title bar is there.
#if QT_CONFIG(dockwidget)
-class QDockWidgetGroupLayout : public QLayout {
- QDockAreaLayoutInfo info;
+class QDockWidgetGroupLayout : public QLayout,
+ public QMainWindowLayoutSeparatorHelper<QDockWidgetGroupLayout>
+{
QWidgetResizeHandler *resizer;
public:
QDockWidgetGroupLayout(QDockWidgetGroupWindow* parent) : QLayout(parent) {
@@ -198,7 +198,7 @@ public:
resizer->setMovingEnabled(false);
}
~QDockWidgetGroupLayout() {
- info.deleteAllLayoutItems();
+ layoutState.deleteAllLayoutItems();
}
void addItem(QLayoutItem*) Q_DECL_OVERRIDE { Q_UNREACHABLE(); }
@@ -206,32 +206,43 @@ public:
QLayoutItem* itemAt(int index) const Q_DECL_OVERRIDE
{
int x = 0;
- return info.itemAt(&x, index);
+ return layoutState.itemAt(&x, index);
}
QLayoutItem* takeAt(int index) Q_DECL_OVERRIDE
{
int x = 0;
- return info.takeAt(&x, index);
+ QLayoutItem *ret = layoutState.takeAt(&x, index);
+ if (savedState.rect.isValid() && ret->widget()) {
+ // we need to remove the item also from the saved state to prevent crash
+ QList<int> path = savedState.indexOf(ret->widget());
+ if (!path.isEmpty())
+ savedState.remove(path);
+ // Also, the item may be contained several times as a gap item.
+ path = layoutState.indexOf(ret->widget());
+ if (!path.isEmpty())
+ layoutState.remove(path);
+ }
+ return ret;
}
QSize sizeHint() const Q_DECL_OVERRIDE
{
int fw = frameWidth();
- return info.sizeHint() + QSize(fw, fw);
+ return layoutState.sizeHint() + QSize(fw, fw);
}
QSize minimumSize() const Q_DECL_OVERRIDE
{
int fw = frameWidth();
- return info.minimumSize() + QSize(fw, fw);
+ return layoutState.minimumSize() + QSize(fw, fw);
}
QSize maximumSize() const Q_DECL_OVERRIDE
{
int fw = frameWidth();
- return info.maximumSize() + QSize(fw, fw);
+ return layoutState.maximumSize() + QSize(fw, fw);
}
void setGeometry(const QRect&r) Q_DECL_OVERRIDE
{
groupWindow()->destroyOrHideIfEmpty();
- QDockAreaLayoutInfo *li = layoutInfo();
+ QDockAreaLayoutInfo *li = dockAreaLayoutInfo();
if (li->isEmpty())
return;
int fw = frameWidth();
@@ -241,12 +252,12 @@ public:
li->rect = r.adjusted(fw, fw, -fw, -fw);
li->fitItems();
li->apply(false);
+ if (savedState.rect.isValid())
+ savedState.rect = li->rect;
resizer->setActive(QWidgetResizeHandler::Resize, !nativeWindowDeco());
}
- QDockAreaLayoutInfo *layoutInfo() {
- return &info;
- }
+ QDockAreaLayoutInfo *dockAreaLayoutInfo() { return &layoutState; }
bool nativeWindowDeco() const
{
@@ -263,14 +274,21 @@ public:
{
return static_cast<QDockWidgetGroupWindow *>(parent());
}
+
+ QDockAreaLayoutInfo layoutState;
+ QDockAreaLayoutInfo savedState;
};
bool QDockWidgetGroupWindow::event(QEvent *e)
{
+ auto lay = static_cast<QDockWidgetGroupLayout *>(layout());
+ if (lay && lay->windowEvent(e))
+ return true;
+
switch (e->type()) {
case QEvent::Close:
// Forward the close to the QDockWidget just as if its close button was pressed
- if (QDockWidget *dw = topDockWidget()) {
+ if (QDockWidget *dw = activeTabbedDockWidget()) {
e->ignore();
dw->close();
adjustFlags();
@@ -278,7 +296,7 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
return true;
case QEvent::Move:
// Let QDockWidgetPrivate::moseEvent handle the dragging
- if (QDockWidget *dw = topDockWidget())
+ if (QDockWidget *dw = activeTabbedDockWidget())
static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw))->moveEvent(static_cast<QMoveEvent*>(e));
return true;
case QEvent::NonClientAreaMouseMove:
@@ -286,7 +304,7 @@ bool QDockWidgetGroupWindow::event(QEvent *e)
case QEvent::NonClientAreaMouseButtonRelease:
case QEvent::NonClientAreaMouseButtonDblClick:
// Let the QDockWidgetPrivate of the currently visible dock widget handle the drag and drop
- if (QDockWidget *dw = topDockWidget())
+ if (QDockWidget *dw = activeTabbedDockWidget())
static_cast<QDockWidgetPrivate *>(QObjectPrivate::get(dw))->nonClientAreaMouseEvent(static_cast<QMouseEvent*>(e));
return true;
case QEvent::ChildAdded:
@@ -318,17 +336,49 @@ void QDockWidgetGroupWindow::paintEvent(QPaintEvent *)
QDockAreaLayoutInfo *QDockWidgetGroupWindow::layoutInfo() const
{
- return static_cast<QDockWidgetGroupLayout*>(layout())->layoutInfo();
+ return static_cast<QDockWidgetGroupLayout *>(layout())->dockAreaLayoutInfo();
+}
+
+/*! \internal
+ If this is a floating tab bar returns the currently the QDockWidgetGroupWindow that contains
+ tab, otherwise, return nullptr;
+ \note: if there is only one QDockWidget, it's still considered as a floating tab
+ */
+const QDockAreaLayoutInfo *QDockWidgetGroupWindow::tabLayoutInfo() const
+{
+ const QDockAreaLayoutInfo *info = layoutInfo();
+ while (info && !info->tabbed) {
+ // There should be only one tabbed subinfo otherwise we are not a floating tab but a real
+ // window
+ const QDockAreaLayoutInfo *next = nullptr;
+ bool isSingle = false;
+ for (const auto &item : info->item_list) {
+ if (item.skip() || (item.flags & QDockAreaLayoutItem::GapItem))
+ continue;
+ if (next || isSingle) // Two visible things
+ return nullptr;
+ if (item.subinfo)
+ next = item.subinfo;
+ else if (item.widgetItem)
+ isSingle = true;
+ }
+ if (isSingle)
+ return info;
+ info = next;
+ }
+ return info;
}
/*! \internal
- Returns the currently active QDockWidget.
+ If this is a floating tab bar returns the currently active QDockWidget, otherwise nullptr
*/
-QDockWidget *QDockWidgetGroupWindow::topDockWidget() const
+QDockWidget *QDockWidgetGroupWindow::activeTabbedDockWidget() const
{
- QDockAreaLayoutInfo *info = layoutInfo();
- QDockWidget *dw = 0;
+ QDockWidget *dw = nullptr;
#if QT_CONFIG(tabbar)
+ const QDockAreaLayoutInfo *info = tabLayoutInfo();
+ if (!info)
+ return nullptr;
if (info->tabBar && info->tabBar->currentIndex() >= 0) {
int i = info->tabIndexToListIndex(info->tabBar->currentIndex());
if (i >= 0) {
@@ -337,7 +387,6 @@ QDockWidget *QDockWidgetGroupWindow::topDockWidget() const
dw = qobject_cast<QDockWidget *>(item.widgetItem->widget());
}
}
-#endif
if (!dw) {
for (int i = 0; !dw && i < info->item_list.count(); ++i) {
const QDockAreaLayoutItem &item = info->item_list.at(i);
@@ -348,6 +397,7 @@ QDockWidget *QDockWidgetGroupWindow::topDockWidget() const
dw = qobject_cast<QDockWidget *>(item.widgetItem->widget());
}
}
+#endif
return dw;
}
@@ -394,18 +444,18 @@ void QDockWidgetGroupWindow::destroyOrHideIfEmpty()
}
/*! \internal
- Sets the flags of this window in accordence to the capabilities of the dock widgets
+ Sets the flags of this window in accordance to the capabilities of the dock widgets
*/
void QDockWidgetGroupWindow::adjustFlags()
{
- QDockWidget *top = topDockWidget();
- if (!top)
- return;
- const bool nativeDeco = static_cast<QDockWidgetGroupLayout *>(layout())->nativeWindowDeco();
-
Qt::WindowFlags oldFlags = windowFlags();
Qt::WindowFlags flags = oldFlags;
- if (nativeDeco) {
+
+ QDockWidget *top = activeTabbedDockWidget();
+ if (!top) { // nested tabs, show window decoration
+ flags =
+ ((oldFlags & ~Qt::FramelessWindowHint) | Qt::CustomizeWindowHint | Qt::WindowTitleHint);
+ } else if (static_cast<QDockWidgetGroupLayout *>(layout())->nativeWindowDeco()) {
flags |= Qt::CustomizeWindowHint | Qt::WindowTitleHint;
flags.setFlag(Qt::WindowCloseButtonHint, top->features() & QDockWidget::DockWidgetClosable);
flags &= ~Qt::FramelessWindowHint;
@@ -438,21 +488,99 @@ void QDockWidgetGroupWindow::adjustFlags()
show(); // setWindowFlags hides the window
}
- setWindowTitle(top->windowTitle());
- setWindowIcon(top->windowIcon());
+ QWidget *titleBarOf = top ? top : parentWidget();
+ setWindowTitle(titleBarOf->windowTitle());
+ setWindowIcon(titleBarOf->windowIcon());
}
bool QDockWidgetGroupWindow::hasNativeDecos() const
{
+ QDockWidget *dw = activeTabbedDockWidget();
+ if (!dw) // We have a group of nested QDockWidgets (not just floating tabs)
+ return true;
+
if (!QDockWidgetLayout::wmSupportsNativeWindowDeco())
return false;
- if (QDockWidget *dw = topDockWidget())
- return dw->titleBarWidget() == nullptr;
+ return dw->titleBarWidget() == nullptr;
+}
+/*
+ The given widget is hovered over this floating group.
+ This function will save the state and create a gap in the actual state.
+ currentGapRect and currentGapPos will be set.
+ One must call restore() or apply() after this function.
+ Returns true if there was any change in the currentGapPos
+ */
+bool QDockWidgetGroupWindow::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
+{
+ QDockAreaLayoutInfo &savedState = static_cast<QDockWidgetGroupLayout *>(layout())->savedState;
+ if (savedState.isEmpty())
+ savedState = *layoutInfo();
+
+ QMainWindow::DockOptions opts = static_cast<QMainWindow *>(parentWidget())->dockOptions();
+ bool nestingEnabled =
+ (opts & QMainWindow::AllowNestedDocks) && !(opts & QMainWindow::ForceTabbedDocks);
+ QDockAreaLayoutInfo::TabMode tabMode =
+ nestingEnabled ? QDockAreaLayoutInfo::AllowTabs : QDockAreaLayoutInfo::ForceTabs;
+ if (auto group = qobject_cast<QDockWidgetGroupWindow *>(widgetItem->widget())) {
+ if (!group->tabLayoutInfo())
+ tabMode = QDockAreaLayoutInfo::NoTabs;
+ }
+
+ QDockAreaLayoutInfo newState = savedState;
+ if (newState.tabbed) {
+ // insertion into a top-level tab
+ newState.item_list = { QDockAreaLayoutItem(new QDockAreaLayoutInfo(newState)) };
+ newState.item_list.first().size = pick(savedState.o, savedState.rect.size());
+ newState.tabbed = false;
+ newState.tabBar = nullptr;
+ }
+
+ auto newGapPos = newState.gapIndex(mousePos, nestingEnabled, tabMode);
+ Q_ASSERT(!newGapPos.isEmpty());
+ if (newGapPos == currentGapPos)
+ return false; // gap is already there
+ currentGapPos = newGapPos;
+ newState.insertGap(currentGapPos, widgetItem);
+ newState.fitItems();
+ currentGapRect = newState.info(currentGapPos)->itemRect(currentGapPos.last(), true);
+ *layoutInfo() = std::move(newState);
+ layoutInfo()->apply(opts & QMainWindow::AnimatedDocks);
return true;
}
+/*
+ Remove the gap that was created by hover()
+ */
+void QDockWidgetGroupWindow::restore()
+{
+ QDockAreaLayoutInfo &savedState = static_cast<QDockWidgetGroupLayout *>(layout())->savedState;
+ if (!savedState.isEmpty()) {
+ *layoutInfo() = savedState;
+ savedState = QDockAreaLayoutInfo();
+ }
+ currentGapRect = QRect();
+ currentGapPos.clear();
+ adjustFlags();
+ layoutInfo()->fitItems();
+ layoutInfo()->apply(static_cast<QMainWindow *>(parentWidget())->dockOptions()
+ & QMainWindow::AnimatedDocks);
+}
+
+/*
+ Apply the state that was created by hover
+ */
+void QDockWidgetGroupWindow::apply()
+{
+ static_cast<QDockWidgetGroupLayout *>(layout())->savedState.clear();
+ currentGapRect = QRect();
+ layoutInfo()->plug(currentGapPos);
+ currentGapPos.clear();
+ adjustFlags();
+ layoutInfo()->apply(false);
+}
+
#endif
/******************************************************************************
@@ -706,7 +834,14 @@ QList<int> QMainWindowLayoutState::gapIndex(QWidget *widget,
// is it a dock widget?
if (qobject_cast<QDockWidget *>(widget) != 0
|| qobject_cast<QDockWidgetGroupWindow *>(widget)) {
- result = dockAreaLayout.gapIndex(pos);
+ bool disallowTabs = false;
+#if QT_CONFIG(tabbar)
+ if (auto *group = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
+ if (!group->tabLayoutInfo()) // Disallow to drop nested docks as a tab
+ disallowTabs = true;
+ }
+#endif
+ result = dockAreaLayout.gapIndex(pos, disallowTabs);
if (!result.isEmpty())
result.prepend(1);
return result;
@@ -1189,14 +1324,7 @@ void QMainWindowLayout::removeToolBar(QToolBar *toolbar)
QObject::disconnect(parentWidget(), SIGNAL(toolButtonStyleChanged(Qt::ToolButtonStyle)),
toolbar, SLOT(_q_updateToolButtonStyle(Qt::ToolButtonStyle)));
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- if (usesHIToolBar(toolbar)) {
- removeFromMacToolbar(toolbar);
- } else
-#endif
- {
- removeWidget(toolbar);
- }
+ removeWidget(toolbar);
}
}
@@ -1208,25 +1336,17 @@ void QMainWindowLayout::addToolBar(Qt::ToolBarArea area,
bool)
{
validateToolBarArea(area);
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- if ((area == Qt::TopToolBarArea)
- && layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
- insertIntoMacToolbar(0, toolbar);
- } else
-#endif
- {
- //let's add the toolbar to the layout
- addChildWidget(toolbar);
- QLayoutItem * item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar);
- if (savedState.isValid() && item) {
- // copy the toolbar also in the saved state
- savedState.toolBarAreaLayout.insertItem(toDockPos(area), item);
- }
- invalidate();
-
- //this ensures that the toolbar has the right window flags (not floating any more)
- toolbar->d_func()->updateWindowFlags(false /*floating*/);
+ // let's add the toolbar to the layout
+ addChildWidget(toolbar);
+ QLayoutItem *item = layoutState.toolBarAreaLayout.addToolBar(toDockPos(area), toolbar);
+ if (savedState.isValid() && item) {
+ // copy the toolbar also in the saved state
+ savedState.toolBarAreaLayout.insertItem(toDockPos(area), item);
}
+ invalidate();
+
+ // this ensures that the toolbar has the right window flags (not floating any more)
+ toolbar->d_func()->updateWindowFlags(false /*floating*/);
}
/*!
@@ -1234,27 +1354,20 @@ void QMainWindowLayout::addToolBar(Qt::ToolBarArea area,
*/
void QMainWindowLayout::insertToolBar(QToolBar *before, QToolBar *toolbar)
{
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- if (usesHIToolBar(before)) {
- insertIntoMacToolbar(before, toolbar);
- } else
-#endif
- {
- addChildWidget(toolbar);
- QLayoutItem * item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar);
- if (savedState.isValid() && item) {
- // copy the toolbar also in the saved state
- savedState.toolBarAreaLayout.insertItem(before, item);
- }
- if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) {
- currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
- if (!currentGapPos.isEmpty()) {
- currentGapPos.prepend(0);
- currentGapRect = layoutState.itemRect(currentGapPos);
- }
+ addChildWidget(toolbar);
+ QLayoutItem *item = layoutState.toolBarAreaLayout.insertToolBar(before, toolbar);
+ if (savedState.isValid() && item) {
+ // copy the toolbar also in the saved state
+ savedState.toolBarAreaLayout.insertItem(before, item);
+ }
+ if (!currentGapPos.isEmpty() && currentGapPos.constFirst() == 0) {
+ currentGapPos = layoutState.toolBarAreaLayout.currentGapIndex();
+ if (!currentGapPos.isEmpty()) {
+ currentGapPos.prepend(0);
+ currentGapRect = layoutState.itemRect(currentGapPos);
}
- invalidate();
}
+ invalidate();
}
Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const
@@ -1267,12 +1380,6 @@ Qt::ToolBarArea QMainWindowLayout::toolBarArea(QToolBar *toolbar) const
case QInternal::BottomDock: return Qt::BottomToolBarArea;
default: break;
}
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- if (pos == QInternal::DockCount) {
- if (qtoolbarsInUnifiedToolbarList.contains(toolbar))
- return Qt::TopToolBarArea;
- }
-#endif
return Qt::NoToolBarArea;
}
@@ -1289,70 +1396,15 @@ void QMainWindowLayout::getStyleOptionInfo(QStyleOptionToolBar *option, QToolBar
void QMainWindowLayout::toggleToolBarsVisible()
{
- bool updateNonUnifiedParts = true;
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- if (layoutState.mainWindow->unifiedTitleAndToolBarOnMac()) {
- // If we hit this case, someone has pressed the "toolbar button" which will
- // toggle the unified toolbar visibility, because that's what the user wants.
- // We might be in a situation where someone has hidden all the toolbars
- // beforehand (maybe in construction), but now they've hit this button and
- // and are expecting the items to show. What do we do?
- // 1) Check the visibility of all the toolbars, if one is visible, do nothing, this
- // preserves what people would expect (these toolbars were visible when I clicked last time).
- // 2) If NONE are visible, then show them all. Again, this preserves the user expectation
- // of, "I want to see the toolbars." The user may get more toolbars than expected, but this
- // is better seeing nothing.
- // Don't worry about any of this if we are going invisible. This does mean we may get
- // into issues when switching into and out of fullscreen mode, but this is probably minor.
- // If we ever need to do hiding, that would have to be taken care of after the unified toolbar
- // has finished hiding.
- // People can of course handle the QEvent::ToolBarChange event themselves and do
- // WHATEVER they want if they don't like what we are doing (though the unified toolbar
- // will fire regardless).
-
- // Check if we REALLY need to update the geometry below. If we only have items in the
- // unified toolbar, all the docks will be empty, so there's very little point
- // in doing the geometry as Apple will do it (we also avoid flicker in Cocoa as well).
- // FWIW, layoutState.toolBarAreaLayout.visible and the state of the unified toolbar
- // visibility can get out of sync. I really don't think it's a big issue. It is kept
- // to a minimum because we only change the visibility if we absolutely must.
- // update the "non unified parts."
- updateNonUnifiedParts = !layoutState.toolBarAreaLayout.isEmpty();
-
- // We get this function before the unified toolbar does its thing.
- // So, the value will be opposite of what we expect.
- bool goingVisible = !macWindowToolbarIsVisible(qt_mac_window_for(layoutState.mainWindow));
- if (goingVisible) {
- const int ToolBarCount = qtoolbarsInUnifiedToolbarList.size();
- bool needAllVisible = true;
- for (int i = 0; i < ToolBarCount; ++i) {
- if (!qtoolbarsInUnifiedToolbarList.at(i)->isHidden()) {
- needAllVisible = false;
- break;
- }
- }
- if (needAllVisible) {
- QBoolBlocker blocker(blockVisiblityCheck); // Disable the visibilty check because
- // the toggle has already happened.
- for (int i = 0; i < ToolBarCount; ++i)
- qtoolbarsInUnifiedToolbarList.at(i)->setVisible(true);
- }
- }
- if (!updateNonUnifiedParts)
- layoutState.toolBarAreaLayout.visible = goingVisible;
- }
-#endif
- if (updateNonUnifiedParts) {
- layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible;
- if (!layoutState.mainWindow->isMaximized()) {
- QPoint topLeft = parentWidget()->geometry().topLeft();
- QRect r = parentWidget()->geometry();
- r = layoutState.toolBarAreaLayout.rectHint(r);
- r.moveTo(topLeft);
- parentWidget()->setGeometry(r);
- } else {
- update();
- }
+ layoutState.toolBarAreaLayout.visible = !layoutState.toolBarAreaLayout.visible;
+ if (!layoutState.mainWindow->isMaximized()) {
+ QPoint topLeft = parentWidget()->geometry().topLeft();
+ QRect r = parentWidget()->geometry();
+ r = layoutState.toolBarAreaLayout.rectHint(r);
+ r.moveTo(topLeft);
+ parentWidget()->setGeometry(r);
+ } else {
+ update();
}
}
@@ -1782,39 +1834,6 @@ void QMainWindowLayout::tabMoved(int from, int to)
}
#endif // QT_CONFIG(tabbar)
-bool QMainWindowLayout::startSeparatorMove(const QPoint &pos)
-{
- movingSeparator = layoutState.dockAreaLayout.findSeparator(pos);
-
- if (movingSeparator.isEmpty())
- return false;
-
- layoutState.dockAreaLayout.fallbackToSizeHints = false;
-
- savedState = layoutState;
- movingSeparatorPos = movingSeparatorOrigin = pos;
-
- return true;
-}
-
-bool QMainWindowLayout::separatorMove(const QPoint &pos)
-{
- if (movingSeparator.isEmpty())
- return false;
- movingSeparatorPos = pos;
- separatorMoveTimer.start(0, this);
- return true;
-}
-
-bool QMainWindowLayout::endSeparatorMove(const QPoint&)
-{
- if (movingSeparator.isEmpty())
- return false;
- movingSeparator.clear();
- savedState.clear();
- return true;
-}
-
void QMainWindowLayout::raise(QDockWidget *widget)
{
#if QT_CONFIG(tabbar)
@@ -1939,14 +1958,6 @@ QSize QMainWindowLayout::minimumSize() const
const QSize sbMin = statusbar ? statusbar->minimumSize() : QSize(0, 0);
minSize = QSize(qMax(sbMin.width(), minSize.width()),
sbMin.height() + minSize.height());
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- const QSize storedSize = minSize;
- int minWidth = 0;
- foreach (QToolBar *toolbar, qtoolbarsInUnifiedToolbarList) {
- minWidth += toolbar->sizeHint().width() + 20;
- }
- minSize = QSize(qMax(minWidth, storedSize.width()), storedSize.height());
-#endif
}
return minSize;
}
@@ -1958,12 +1969,16 @@ void QMainWindowLayout::invalidate()
}
#if QT_CONFIG(dockwidget)
-void QMainWindowLayout::setCurrentHoveredFloat(QWidget *w)
+void QMainWindowLayout::setCurrentHoveredFloat(QDockWidgetGroupWindow *w)
{
if (currentHoveredFloat != w) {
if (currentHoveredFloat) {
disconnect(currentHoveredFloat.data(), &QObject::destroyed,
this, &QMainWindowLayout::updateGapIndicator);
+ if (currentHoveredFloat)
+ currentHoveredFloat->restore();
+ } else if (w) {
+ restore(true);
}
currentHoveredFloat = w;
@@ -2034,52 +2049,30 @@ void QMainWindowLayout::revert(QLayoutItem *widgetItem)
bool QMainWindowLayout::plug(QLayoutItem *widgetItem)
{
-#if QT_CONFIG(dockwidget)
+#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget) && QT_CONFIG(tabbar)
if (currentHoveredFloat) {
QWidget *widget = widgetItem->widget();
QList<int> previousPath = layoutState.indexOf(widget);
if (!previousPath.isEmpty())
layoutState.remove(previousPath);
+ previousPath = currentHoveredFloat->layoutInfo()->indexOf(widget);
// Let's remove the widget from any possible group window
foreach (QDockWidgetGroupWindow *dwgw,
parent()->findChildren<QDockWidgetGroupWindow*>(QString(), Qt::FindDirectChildrenOnly)) {
+ if (dwgw == currentHoveredFloat)
+ continue;
QList<int> path = dwgw->layoutInfo()->indexOf(widget);
if (!path.isEmpty())
dwgw->layoutInfo()->remove(path);
}
currentGapRect = QRect();
-#if QT_CONFIG(tabwidget)
- if (QDockWidget *dropTo = qobject_cast<QDockWidget*>(currentHoveredFloat)) {
- //dropping to a normal widget, we mutate it in a QDockWidgetGroupWindow with two tabs
- QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow();
- floatingTabs->setGeometry(dropTo->geometry());
- QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
- *info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, QInternal::LeftDock,
- Qt::Horizontal, QTabBar::RoundedSouth,
- static_cast<QMainWindow*>(parentWidget()));
- info->tabbed = true;
- QLayout *parentLayout = currentHoveredFloat->parentWidget()->layout();
- info->item_list.append(QDockAreaLayoutItem(parentLayout->takeAt(parentLayout->indexOf(currentHoveredFloat))));
-
- dropTo->setParent(floatingTabs);
- dropTo->show();
- dropTo->d_func()->plug(QRect());
- setCurrentHoveredFloat(floatingTabs);
- }
-#endif // QT_CONFIG(tabwidget)
-#if QT_CONFIG(tabbar)
- QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(currentHoveredFloat);
- Q_ASSERT(dwgw);
- Q_ASSERT(dwgw->layoutInfo()->tabbed); // because floating group should always be tabbed
- previousPath = dwgw->layoutInfo()->indexOf(widget);
+ currentHoveredFloat->apply();
if (!previousPath.isEmpty())
- dwgw->layoutInfo()->remove(previousPath);
- dwgw->layoutInfo()->tab(0, widgetItem);
- QRect globalRect = dwgw->layoutInfo()->tabContentRect();
- globalRect.moveTopLeft(dwgw->mapToGlobal(globalRect.topLeft()));
+ currentHoveredFloat->layoutInfo()->remove(previousPath);
+ QRect globalRect = currentHoveredFloat->currentGapRect;
+ globalRect.moveTopLeft(currentHoveredFloat->mapToGlobal(globalRect.topLeft()));
pluggingWidget = widget;
widgetAnimator.animate(widget, globalRect, dockOptions & QMainWindow::AnimatedDocks);
-#endif // QT_CONFIG(tabbar)
return true;
}
#endif
@@ -2148,57 +2141,55 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
if (widget == pluggingWidget) {
#if QT_CONFIG(dockwidget)
+#if QT_CONFIG(tabbar)
if (QDockWidgetGroupWindow *dwgw = qobject_cast<QDockWidgetGroupWindow *>(widget)) {
// When the animated widget was a QDockWidgetGroupWindow, it means each of the
// embedded QDockWidget needs to be plugged back into the QMainWindow layout.
savedState.clear();
- QDockAreaLayoutInfo* info = dwgw->layoutInfo();
- QDockAreaLayoutInfo* parentInfo;
- QList<int> path;
-
- if (QDockWidgetGroupWindow *dropTo = qobject_cast<QDockWidgetGroupWindow *>(currentHoveredFloat)) {
- parentInfo = dropTo->layoutInfo();
-#if QT_CONFIG(tabbar)
- Q_ASSERT(parentInfo->tabbed);
-#endif
- path = parentInfo->indexOf(widget);
- Q_ASSERT(path.size() == 1);
+ QDockAreaLayoutInfo *srcInfo = dwgw->layoutInfo();
+ const QDockAreaLayoutInfo *srcTabInfo = dwgw->tabLayoutInfo();
+ QDockAreaLayoutInfo *dstParentInfo;
+ QList<int> dstPath;
+
+ if (currentHoveredFloat) {
+ dstPath = currentHoveredFloat->layoutInfo()->indexOf(widget);
+ Q_ASSERT(dstPath.size() >= 1);
+ dstParentInfo = currentHoveredFloat->layoutInfo()->info(dstPath);
} else {
- path = layoutState.dockAreaLayout.indexOf(widget);
- Q_ASSERT(path.size() >= 2);
- parentInfo = layoutState.dockAreaLayout.info(path);
- Q_ASSERT(parentInfo);
+ dstPath = layoutState.dockAreaLayout.indexOf(widget);
+ Q_ASSERT(dstPath.size() >= 2);
+ dstParentInfo = layoutState.dockAreaLayout.info(dstPath);
}
-#if QT_CONFIG(tabbar)
- if (parentInfo->tabbed) {
+ Q_ASSERT(dstParentInfo);
+ int idx = dstPath.constLast();
+ Q_ASSERT(dstParentInfo->item_list[idx].widgetItem->widget() == dwgw);
+ if (dstParentInfo->tabbed && srcTabInfo) {
// merge the two tab widgets
- int idx = path.constLast();
- Q_ASSERT(parentInfo->item_list[idx].widgetItem->widget() == dwgw);
- delete parentInfo->item_list[idx].widgetItem;
- parentInfo->item_list.removeAt(idx);
- std::copy(info->item_list.cbegin(), info->item_list.cend(),
- std::inserter(parentInfo->item_list, parentInfo->item_list.begin() + idx));
- quintptr currentId = info->currentTabId();
- *info = QDockAreaLayoutInfo();
- parentInfo->reparentWidgets(currentHoveredFloat ? currentHoveredFloat.data() : parentWidget());
- parentInfo->updateTabBar();
- parentInfo->setCurrentTabId(currentId);
- } else
-#endif // QT_CONFIG(tabbar)
- {
- QDockAreaLayoutItem &item = layoutState.dockAreaLayout.item(path);
+ delete dstParentInfo->item_list[idx].widgetItem;
+ dstParentInfo->item_list.removeAt(idx);
+ std::copy(srcTabInfo->item_list.cbegin(), srcTabInfo->item_list.cend(),
+ std::inserter(dstParentInfo->item_list,
+ dstParentInfo->item_list.begin() + idx));
+ quintptr currentId = srcTabInfo->currentTabId();
+ *srcInfo = QDockAreaLayoutInfo();
+ dstParentInfo->reparentWidgets(currentHoveredFloat ? currentHoveredFloat.data()
+ : parentWidget());
+ dstParentInfo->updateTabBar();
+ dstParentInfo->setCurrentTabId(currentId);
+ } else {
+ QDockAreaLayoutItem &item = dstParentInfo->item_list[idx];
Q_ASSERT(item.widgetItem->widget() == dwgw);
delete item.widgetItem;
item.widgetItem = 0;
- item.subinfo = new QDockAreaLayoutInfo(qMove(*info));
- *info = QDockAreaLayoutInfo();
-#if QT_CONFIG(tabbar)
- item.subinfo->reparentWidgets(parentWidget());
- item.subinfo->setTabBarShape(parentInfo->tabBarShape);
-#endif
+ item.subinfo = new QDockAreaLayoutInfo(std::move(*srcInfo));
+ *srcInfo = QDockAreaLayoutInfo();
+ item.subinfo->reparentWidgets(currentHoveredFloat ? currentHoveredFloat.data()
+ : parentWidget());
+ item.subinfo->setTabBarShape(dstParentInfo->tabBarShape);
}
dwgw->destroyOrHideIfEmpty();
}
+#endif
if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
dw->setParent(currentHoveredFloat ? currentHoveredFloat.data() : parentWidget());
@@ -2278,9 +2269,6 @@ QMainWindowLayout::QMainWindowLayout(QMainWindow *mainwindow, QLayout *parentLay
#endif // QT_CONFIG(dockwidget)
, widgetAnimator(this)
, pluggingWidget(0)
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- , blockVisiblityCheck(false)
-#endif
{
if (parentLayout)
setParent(parentLayout);
@@ -2305,10 +2293,6 @@ QMainWindowLayout::~QMainWindowLayout()
layoutState.deleteAllLayoutItems();
layoutState.deleteCentralWidgetItem();
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- cleanUpMacToolbarItems();
-#endif
-
delete statusbar;
}
@@ -2361,6 +2345,36 @@ void QMainWindowLayout::setCentralWidget(QWidget *widget)
invalidate();
}
+#if QT_CONFIG(dockwidget) && QT_CONFIG(tabwidget)
+/*! \internal
+ This helper function is called by QMainWindowLayout::unplug if QMainWindow::GroupedDragging is
+ set and we are dragging the title bar of a non-floating QDockWidget.
+ If one should unplug the whole group, do so and return true, otherwise return false.
+ \a item is pointing to the QLayoutItem that holds the QDockWidget, but will be updated to the
+ QLayoutItem that holds the new QDockWidgetGroupWindow if the group is unplugged.
+*/
+static bool unplugGroup(QMainWindowLayout *layout, QLayoutItem **item,
+ QDockAreaLayoutItem &parentItem)
+{
+ if (!parentItem.subinfo || !parentItem.subinfo->tabbed)
+ return false;
+
+ // The QDockWidget is part of a group of tab and we need to unplug them all.
+
+ QDockWidgetGroupWindow *floatingTabs = layout->createTabbedDockWindow();
+ QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
+ *info = std::move(*parentItem.subinfo);
+ delete parentItem.subinfo;
+ parentItem.subinfo = nullptr;
+ floatingTabs->setGeometry(info->rect.translated(layout->parentWidget()->pos()));
+ floatingTabs->show();
+ floatingTabs->raise();
+ *item = new QDockWidgetGroupWindowItem(floatingTabs);
+ parentItem.widgetItem = *item;
+ return true;
+}
+#endif
+
/*! \internal
Unplug \a widget (QDockWidget or QToolBar) from it's parent container.
@@ -2374,19 +2388,31 @@ void QMainWindowLayout::setCentralWidget(QWidget *widget)
QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)
{
#if QT_CONFIG(dockwidget) && QT_CONFIG(tabbar)
- if (!widget->isWindow() && qobject_cast<const QDockWidgetGroupWindow *>(widget->parentWidget())) {
- if (group) {
+ auto *groupWindow = qobject_cast<const QDockWidgetGroupWindow *>(widget->parentWidget());
+ if (!widget->isWindow() && groupWindow) {
+ if (group && groupWindow->tabLayoutInfo()) {
// We are just dragging a floating window as it, not need to do anything, we just have to
// look up the corresponding QWidgetItem* if it exists
- QList<int> tabbedWindowPath = layoutState.indexOf(widget->parentWidget());
- return tabbedWindowPath.isEmpty() ? 0 : layoutState.item(tabbedWindowPath);
+ if (QDockAreaLayoutInfo *info = dockInfo(widget->parentWidget())) {
+ QList<int> groupWindowPath = info->indexOf(widget->parentWidget());
+ return groupWindowPath.isEmpty() ? nullptr : info->item(groupWindowPath).widgetItem;
+ }
+ return nullptr;
+ }
+ QList<int> path = groupWindow->layoutInfo()->indexOf(widget);
+ QLayoutItem *item = groupWindow->layoutInfo()->item(path).widgetItem;
+ if (group && path.size() > 1
+ && unplugGroup(this, &item,
+ groupWindow->layoutInfo()->item(path.mid(0, path.size() - 1)))) {
+ return item;
} else {
// We are unplugging a dock widget from a floating window.
- if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
- dw->d_func()->unplug(widget->geometry());
- int index = widget->parentWidget()->layout()->indexOf(widget);
- return widget->parentWidget()->layout()->itemAt(index);
- }
+ QDockWidget *dw = qobject_cast<QDockWidget *>(widget);
+ Q_ASSERT(dw); // cannot be a QDockWidgetGroupWindow because it's not floating.
+ dw->d_func()->unplug(widget->geometry());
+ groupWindow->layoutInfo()->fitItems();
+ groupWindow->layoutInfo()->apply(dockOptions & QMainWindow::AnimatedDocks);
+ return item;
}
}
#endif
@@ -2404,30 +2430,15 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)
#if QT_CONFIG(dockwidget)
if (QDockWidget *dw = qobject_cast<QDockWidget*>(widget)) {
Q_ASSERT(path.constFirst() == 1);
- bool actualGroup = false;
#if QT_CONFIG(tabwidget)
- if (group && (dockOptions & QMainWindow::GroupedDragging) && path.size() > 3) {
- QDockAreaLayoutItem &parentItem = layoutState.dockAreaLayout.item(path.mid(1, path.size() - 2));
- if (parentItem.subinfo && parentItem.subinfo->tabbed) {
- // The QDockWidget is part of a group of tab and we need to unplug them all.
- actualGroup = true;
- path.removeLast();
-
- QDockWidgetGroupWindow* floatingTabs = createTabbedDockWindow();
- QDockAreaLayoutInfo* info = floatingTabs->layoutInfo();
- *info = qMove(*parentItem.subinfo);
- delete parentItem.subinfo;
- parentItem.subinfo = 0;
- floatingTabs->setGeometry(info->rect.translated(parentWidget()->pos()));
- floatingTabs->show();
- floatingTabs->raise();
- item = new QDockWidgetGroupWindowItem(floatingTabs);
- parentItem.widgetItem = item;
- savedState = layoutState;
- }
- }
+ if (group && (dockOptions & QMainWindow::GroupedDragging) && path.size() > 3
+ && unplugGroup(this, &item,
+ layoutState.dockAreaLayout.item(path.mid(1, path.size() - 2)))) {
+ path.removeLast();
+ savedState = layoutState;
+ } else
#endif // QT_CONFIG(tabwidget)
- if (!actualGroup) {
+ {
dw->d_func()->unplug(r);
}
}
@@ -2456,11 +2467,11 @@ QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group)
void QMainWindowLayout::updateGapIndicator()
{
#if QT_CONFIG(rubberband)
- if ((!widgetAnimator.animating() && !currentGapPos.isEmpty())
+ if (!widgetAnimator.animating() && (!currentGapPos.isEmpty()
#if QT_CONFIG(dockwidget)
- || currentHoveredFloat
+ || currentHoveredFloat
#endif
- ) {
+ )) {
QWidget *expectedParent =
#if QT_CONFIG(dockwidget)
currentHoveredFloat ? currentHoveredFloat.data() :
@@ -2473,11 +2484,13 @@ void QMainWindowLayout::updateGapIndicator()
} else if (gapIndicator->parent() != expectedParent) {
gapIndicator->setParent(expectedParent);
}
- gapIndicator->setGeometry(
+
#if QT_CONFIG(dockwidget)
- currentHoveredFloat ? currentHoveredFloat->rect() :
+ if (currentHoveredFloat)
+ gapIndicator->setGeometry(currentHoveredFloat->currentGapRect);
+ else
#endif
- currentGapRect);
+ gapIndicator->setGeometry(currentGapRect);
gapIndicator->show();
gapIndicator->raise();
} else if (gapIndicator) {
@@ -2526,12 +2539,36 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
if (!w->geometry().contains(mousePos))
continue;
- setCurrentHoveredFloat(w);
- restore(true);
+ if (auto dropTo = qobject_cast<QDockWidget *>(w)) {
+ // dropping to a normal widget, we mutate it in a QDockWidgetGroupWindow with two
+ // tabs
+ QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow(); // FIXME
+ floatingTabs->setGeometry(dropTo->geometry());
+ QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
+ *info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, QInternal::LeftDock,
+ Qt::Horizontal, QTabBar::RoundedSouth,
+ static_cast<QMainWindow *>(parentWidget()));
+ info->tabbed = true;
+ QLayout *parentLayout = dropTo->parentWidget()->layout();
+ info->item_list.append(
+ QDockAreaLayoutItem(parentLayout->takeAt(parentLayout->indexOf(dropTo))));
+
+ dropTo->setParent(floatingTabs);
+ dropTo->show();
+ dropTo->d_func()->plug(QRect());
+ w = floatingTabs;
+ }
+ Q_ASSERT(qobject_cast<QDockWidgetGroupWindow *>(w));
+ auto group = static_cast<QDockWidgetGroupWindow *>(w);
+ if (group->hover(widgetItem, group->mapFromGlobal(mousePos))) {
+ setCurrentHoveredFloat(group);
+ applyState(layoutState); // update the tabbars
+ }
return;
}
}
setCurrentHoveredFloat(nullptr);
+ layoutState.dockAreaLayout.fallbackToSizeHints = false;
#endif // QT_CONFIG(dockwidget)
QPoint pos = parentWidget()->mapFromGlobal(mousePos);
@@ -2594,7 +2631,7 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
#if QT_CONFIG(dockwidget)
parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
#endif
- layoutState = newState;
+ layoutState = std::move(newState);
applyState(layoutState);
updateGapIndicator();
@@ -2683,46 +2720,6 @@ bool QMainWindowLayout::restoreState(QDataStream &stream)
return true;
}
-
-// Returns if this toolbar *should* be using HIToolbar. Won't work for all in between cases
-// for example, you have a toolbar in the top area and then you suddenly turn on
-// HIToolbar.
-bool QMainWindowLayout::usesHIToolBar(QToolBar *toolbar) const
-{
-#if 1 // Used to be excluded in Qt4 for Q_WS_MAC
- Q_UNUSED(toolbar);
- return false;
-#else
- return qtoolbarsInUnifiedToolbarList.contains(toolbar)
- || ((toolBarArea(toolbar) == Qt::TopToolBarArea)
- && layoutState.mainWindow->unifiedTitleAndToolBarOnMac());
-#endif
-}
-
-void QMainWindowLayout::timerEvent(QTimerEvent *e)
-{
-#if QT_CONFIG(dockwidget)
- if (e->timerId() == separatorMoveTimer.timerId()) {
- //let's move the separators
- separatorMoveTimer.stop();
- if (movingSeparator.isEmpty())
- return;
- if (movingSeparatorOrigin == movingSeparatorPos)
- return;
-
- //when moving the separator, we need to update the previous position
- parentWidget()->update(layoutState.dockAreaLayout.separatorRegion());
-
- layoutState = savedState;
- layoutState.dockAreaLayout.separatorMove(movingSeparator, movingSeparatorOrigin,
- movingSeparatorPos);
- movingSeparatorPos = movingSeparatorOrigin;
- }
-#endif
- QLayout::timerEvent(e);
-}
-
-
QT_END_NAMESPACE
#include "moc_qmainwindowlayout_p.cpp"
diff --git a/src/widgets/widgets/qmainwindowlayout_p.h b/src/widgets/widgets/qmainwindowlayout_p.h
index ed0c6b96c5..948d6edeef 100644
--- a/src/widgets/widgets/qmainwindowlayout_p.h
+++ b/src/widgets/widgets/qmainwindowlayout_p.h
@@ -59,6 +59,8 @@
#include "QtWidgets/qlayout.h"
#if QT_CONFIG(tabbar)
#include "QtWidgets/qtabbar.h"
+#include "QtGui/qpainter.h"
+#include "QtGui/qevent.h"
#endif
#include "QtCore/qvector.h"
#include "QtCore/qset.h"
@@ -76,6 +78,251 @@ QT_BEGIN_NAMESPACE
class QToolBar;
class QRubberBand;
+template <typename Layout> // Make use of the "Curiously recurring template pattern"
+class QMainWindowLayoutSeparatorHelper
+{
+ Layout *layout() { return static_cast<Layout *>(this); }
+ const Layout *layout() const { return static_cast<const Layout *>(this); }
+ QWidget *window() { return layout()->parentWidget(); }
+
+public:
+ QList<int> hoverSeparator;
+ QPoint hoverPos;
+
+#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
+ QCursor separatorCursor(const QList<int> &path);
+ void adjustCursor(const QPoint &pos);
+ QCursor oldCursor;
+ QCursor adjustedCursor;
+ bool hasOldCursor = false;
+ bool cursorAdjusted = false;
+
+ QList<int> movingSeparator;
+ QPoint movingSeparatorOrigin, movingSeparatorPos;
+ QBasicTimer separatorMoveTimer;
+
+ bool startSeparatorMove(const QPoint &pos);
+ bool separatorMove(const QPoint &pos);
+ bool endSeparatorMove(const QPoint &pos);
+
+#endif
+
+ bool windowEvent(QEvent *e);
+};
+
+#if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_CURSOR)
+template <typename Layout>
+QCursor QMainWindowLayoutSeparatorHelper<Layout>::separatorCursor(const QList<int> &path)
+{
+ const QDockAreaLayoutInfo *info = layout()->dockAreaLayoutInfo()->info(path);
+ Q_ASSERT(info != 0);
+ if (path.size() == 1) { // is this the "top-level" separator which separates a dock area
+ // from the central widget?
+ switch (path.first()) {
+ case QInternal::LeftDock:
+ case QInternal::RightDock:
+ return Qt::SplitHCursor;
+ case QInternal::TopDock:
+ case QInternal::BottomDock:
+ return Qt::SplitVCursor;
+ default:
+ break;
+ }
+ }
+
+ // no, it's a splitter inside a dock area, separating two dock widgets
+
+ return info->o == Qt::Horizontal ? Qt::SplitHCursor : Qt::SplitVCursor;
+}
+
+template <typename Layout>
+void QMainWindowLayoutSeparatorHelper<Layout>::adjustCursor(const QPoint &pos)
+{
+ QWidget *w = layout()->window();
+ hoverPos = pos;
+
+ if (pos == QPoint(0, 0)) {
+ if (!hoverSeparator.isEmpty())
+ w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
+ hoverSeparator.clear();
+
+ if (cursorAdjusted) {
+ cursorAdjusted = false;
+ if (hasOldCursor)
+ w->setCursor(oldCursor);
+ else
+ w->unsetCursor();
+ }
+ } else if (movingSeparator.isEmpty()) { // Don't change cursor when moving separator
+ QList<int> pathToSeparator = layout()->dockAreaLayoutInfo()->findSeparator(pos);
+
+ if (pathToSeparator != hoverSeparator) {
+ if (!hoverSeparator.isEmpty())
+ w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
+
+ hoverSeparator = pathToSeparator;
+
+ if (hoverSeparator.isEmpty()) {
+ if (cursorAdjusted) {
+ cursorAdjusted = false;
+ if (hasOldCursor)
+ w->setCursor(oldCursor);
+ else
+ w->unsetCursor();
+ }
+ } else {
+ w->update(layout()->dockAreaLayoutInfo()->separatorRect(hoverSeparator));
+ if (!cursorAdjusted) {
+ oldCursor = w->cursor();
+ hasOldCursor = w->testAttribute(Qt::WA_SetCursor);
+ }
+ adjustedCursor = separatorCursor(hoverSeparator);
+ w->setCursor(adjustedCursor);
+ cursorAdjusted = true;
+ }
+ }
+ }
+}
+
+template <typename Layout>
+bool QMainWindowLayoutSeparatorHelper<Layout>::windowEvent(QEvent *event)
+{
+ QWidget *w = window();
+ switch (event->type()) {
+ case QEvent::Paint: {
+ QPainter p(w);
+ QRegion r = static_cast<QPaintEvent *>(event)->region();
+ layout()->dockAreaLayoutInfo()->paintSeparators(&p, w, r, hoverPos);
+ break;
+ }
+
+#ifndef QT_NO_CURSOR
+ case QEvent::HoverMove: {
+ adjustCursor(static_cast<QHoverEvent *>(event)->pos());
+ break;
+ }
+
+ // We don't want QWidget to call update() on the entire QMainWindow
+ // on HoverEnter and HoverLeave, hence accept the event (return true).
+ case QEvent::HoverEnter:
+ return true;
+ case QEvent::HoverLeave:
+ adjustCursor(QPoint(0, 0));
+ return true;
+ case QEvent::ShortcutOverride: // when a menu pops up
+ adjustCursor(QPoint(0, 0));
+ break;
+#endif // QT_NO_CURSOR
+
+ case QEvent::MouseButtonPress: {
+ QMouseEvent *e = static_cast<QMouseEvent *>(event);
+ if (e->button() == Qt::LeftButton && startSeparatorMove(e->pos())) {
+ // The click was on a separator, eat this event
+ e->accept();
+ return true;
+ }
+ break;
+ }
+
+ case QEvent::MouseMove: {
+ QMouseEvent *e = static_cast<QMouseEvent *>(event);
+
+#ifndef QT_NO_CURSOR
+ adjustCursor(e->pos());
+#endif
+ if (e->buttons() & Qt::LeftButton) {
+ if (separatorMove(e->pos())) {
+ // We're moving a separator, eat this event
+ e->accept();
+ return true;
+ }
+ }
+
+ break;
+ }
+
+ case QEvent::MouseButtonRelease: {
+ QMouseEvent *e = static_cast<QMouseEvent *>(event);
+ if (endSeparatorMove(e->pos())) {
+ // We've released a separator, eat this event
+ e->accept();
+ return true;
+ }
+ break;
+ }
+
+#if !defined(QT_NO_CURSOR)
+ case QEvent::CursorChange:
+ // CursorChange events are triggered as mouse moves to new widgets even
+ // if the cursor doesn't actually change, so do not change oldCursor if
+ // the "changed" cursor has same shape as adjusted cursor.
+ if (cursorAdjusted && adjustedCursor.shape() != w->cursor().shape()) {
+ oldCursor = w->cursor();
+ hasOldCursor = w->testAttribute(Qt::WA_SetCursor);
+
+ // Ensure our adjusted cursor stays visible
+ w->setCursor(adjustedCursor);
+ }
+ break;
+#endif
+ case QEvent::Timer:
+ if (static_cast<QTimerEvent *>(event)->timerId() == separatorMoveTimer.timerId()) {
+ // let's move the separators
+ separatorMoveTimer.stop();
+ if (movingSeparator.isEmpty())
+ return true;
+ if (movingSeparatorOrigin == movingSeparatorPos)
+ return true;
+
+ // when moving the separator, we need to update the previous position
+ window()->update(layout()->dockAreaLayoutInfo()->separatorRegion());
+
+ layout()->layoutState = layout()->savedState;
+ layout()->dockAreaLayoutInfo()->separatorMove(movingSeparator, movingSeparatorOrigin,
+ movingSeparatorPos);
+ movingSeparatorPos = movingSeparatorOrigin;
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+ return false;
+}
+
+template <typename Layout>
+bool QMainWindowLayoutSeparatorHelper<Layout>::startSeparatorMove(const QPoint &pos)
+{
+ movingSeparator = layout()->dockAreaLayoutInfo()->findSeparator(pos);
+
+ if (movingSeparator.isEmpty())
+ return false;
+
+ layout()->savedState = layout()->layoutState;
+ movingSeparatorPos = movingSeparatorOrigin = pos;
+
+ return true;
+}
+template <typename Layout>
+bool QMainWindowLayoutSeparatorHelper<Layout>::separatorMove(const QPoint &pos)
+{
+ if (movingSeparator.isEmpty())
+ return false;
+ movingSeparatorPos = pos;
+ separatorMoveTimer.start(0, window());
+ return true;
+}
+template <typename Layout>
+bool QMainWindowLayoutSeparatorHelper<Layout>::endSeparatorMove(const QPoint &)
+{
+ if (movingSeparator.isEmpty())
+ return false;
+ movingSeparator.clear();
+ layout()->savedState.clear();
+ return true;
+}
+#endif
+
#if QT_CONFIG(dockwidget)
class QDockWidgetGroupWindow : public QWidget
{
@@ -84,11 +331,19 @@ public:
explicit QDockWidgetGroupWindow(QWidget* parent = 0, Qt::WindowFlags f = 0)
: QWidget(parent, f) {}
QDockAreaLayoutInfo *layoutInfo() const;
- QDockWidget *topDockWidget() const;
+ const QDockAreaLayoutInfo *tabLayoutInfo() const;
+ QDockWidget *activeTabbedDockWidget() const;
void destroyOrHideIfEmpty();
void adjustFlags();
bool hasNativeDecos() const;
+ bool hover(QLayoutItem *widgetItem, const QPoint &mousePos);
+ void restore();
+ void apply();
+
+ QRect currentGapRect;
+ QList<int> currentGapPos;
+
protected:
bool event(QEvent *) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent*) Q_DECL_OVERRIDE;
@@ -172,7 +427,9 @@ public:
bool restoreState(QDataStream &stream, const QMainWindowLayoutState &oldState);
};
-class Q_AUTOTEST_EXPORT QMainWindowLayout : public QLayout
+class Q_AUTOTEST_EXPORT QMainWindowLayout
+ : public QLayout,
+ public QMainWindowLayoutSeparatorHelper<QMainWindowLayout>
{
Q_OBJECT
@@ -184,9 +441,6 @@ public:
QMainWindow::DockOptions dockOptions;
void setDockOptions(QMainWindow::DockOptions opts);
- bool usesHIToolBar(QToolBar *toolbar) const;
-
- void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE;
// status bar
@@ -265,15 +519,7 @@ public:
#endif // QT_CONFIG(tabwidget)
#endif // QT_CONFIG(tabbar)
- // separators
-
- QList<int> movingSeparator;
- QPoint movingSeparatorOrigin, movingSeparatorPos;
- QBasicTimer separatorMoveTimer;
-
- bool startSeparatorMove(const QPoint &pos);
- bool separatorMove(const QPoint &pos);
- bool endSeparatorMove(const QPoint &pos);
+ QDockAreaLayout *dockAreaLayoutInfo() { return &layoutState.dockAreaLayout; }
void keepSize(QDockWidget *w);
#endif // QT_CONFIG(dockwidget)
@@ -309,8 +555,8 @@ public:
QPointer<QRubberBand> gapIndicator;
#endif
#if QT_CONFIG(dockwidget)
- QPointer<QWidget> currentHoveredFloat; // set when dragging over a floating dock widget
- void setCurrentHoveredFloat(QWidget *w);
+ QPointer<QDockWidgetGroupWindow> currentHoveredFloat; // set when dragging over a floating dock widget
+ void setCurrentHoveredFloat(QDockWidgetGroupWindow *w);
#endif
void hover(QLayoutItem *widgetItem, const QPoint &mousePos);
@@ -320,7 +566,6 @@ public:
void paintDropIndicator(QPainter *p, QWidget *widget, const QRegion &clip);
void applyState(QMainWindowLayoutState &newState, bool animate = true);
void restore(bool keepSavedState = false);
- void updateHIToolBarStatus();
void animationFinished(QWidget *widget);
private Q_SLOTS:
@@ -335,40 +580,6 @@ private:
#if QT_CONFIG(tabbar)
void updateTabBarShapes();
#endif
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
- static OSStatus qtmacToolbarDelegate(EventHandlerCallRef, EventRef , void *);
- static OSStatus qtoolbarInHIToolbarHandler(EventHandlerCallRef inCallRef, EventRef event,
- void *data);
- static void qtMacHIToolbarRegisterQToolBarInHIToolborItemClass();
- static HIToolbarItemRef CreateToolbarItemForIdentifier(CFStringRef identifier, CFTypeRef data);
- static HIToolbarItemRef createQToolBarInHIToolbarItem(QToolBar *toolbar,
- QMainWindowLayout *layout);
-public:
- struct ToolBarSaveState {
- ToolBarSaveState() : movable(false) { }
- ToolBarSaveState(bool newMovable, const QSize &newMax)
- : movable(newMovable), maximumSize(newMax) { }
- bool movable;
- QSize maximumSize;
- };
- QList<QToolBar *> qtoolbarsInUnifiedToolbarList;
- QList<void *> toolbarItemsCopy;
- QHash<void *, QToolBar *> unifiedToolbarHash;
- QHash<QToolBar *, ToolBarSaveState> toolbarSaveState;
- QHash<QString, QToolBar *> cocoaItemIDToToolbarHash;
- void insertIntoMacToolbar(QToolBar *before, QToolBar *after);
- void removeFromMacToolbar(QToolBar *toolbar);
- void cleanUpMacToolbarItems();
- void fixSizeInUnifiedToolbar(QToolBar *tb) const;
- bool useHIToolBar;
- bool activateUnifiedToolbarAfterFullScreen;
- void syncUnifiedToolbarVisibility();
- bool blockVisiblityCheck;
-
- QUnifiedToolbarSurface *unifiedSurface;
- void updateUnifiedToolbarOffset();
-
-#endif
};
#if QT_CONFIG(dockwidget) && !defined(QT_NO_DEBUG_STREAM)
diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp
index 513011f0ad..31d9ae21ae 100644
--- a/src/widgets/widgets/qmdiarea.cpp
+++ b/src/widgets/widgets/qmdiarea.cpp
@@ -160,9 +160,6 @@
#include <QApplication>
#include <QStyle>
-#if 0 /* Used to be included in Qt4 for Q_WS_MAC */ && QT_CONFIG(style_mac)
-#include <private/qmacstyle_mac_p.h>
-#endif
#include <QChildEvent>
#include <QResizeEvent>
#include <QScrollBar>
diff --git a/src/widgets/widgets/qmdisubwindow.cpp b/src/widgets/widgets/qmdisubwindow.cpp
index 663572802c..498744e81e 100644
--- a/src/widgets/widgets/qmdisubwindow.cpp
+++ b/src/widgets/widgets/qmdisubwindow.cpp
@@ -160,9 +160,6 @@
#include <QMainWindow>
#include <QScrollBar>
#include <QDebug>
-#if QT_CONFIG(style_mac)
-#include <private/qmacstyle_mac_p.h>
-#endif
#include <QMdiArea>
#include <QScopedValueRollback>
@@ -196,6 +193,11 @@ static const Qt::WindowFlags CustomizeWindowFlags =
static const int BoundaryMargin = 5;
+static inline bool isMacStyle(QStyle *style)
+{
+ return style->inherits("QMacStyle");
+}
+
static inline int getMoveDeltaComponent(uint cflags, uint moveFlag, uint resizeFlag,
int delta, int maxDelta, int minDelta)
{
@@ -297,11 +299,8 @@ static void showToolTip(QHelpEvent *helpEvent, QWidget *widget, const QStyleOpti
Q_ASSERT(helpEvent->type() == QEvent::ToolTip);
Q_ASSERT(widget);
-#if QT_CONFIG(style_mac)
- // Native Mac windows don't show tool tip.
- if (qobject_cast<QMacStyle *>(widget->style()))
+ if (widget->style()->styleHint(QStyle::SH_TitleBar_ShowToolTipsOnButtons, &opt, widget))
return;
-#endif
// Convert CC_MdiControls to CC_TitleBar. Sub controls of different complex
// controls cannot be in the same switch as they might have the same value.
@@ -1078,10 +1077,8 @@ void QMdiSubWindowPrivate::updateCursor()
{
#ifndef QT_NO_CURSOR
Q_Q(QMdiSubWindow);
-#if QT_CONFIG(style_mac)
- if (qobject_cast<QMacStyle *>(q->style()))
+ if (isMacStyle(q->style()))
return;
-#endif
if (currentOperation == None) {
q->unsetCursor();
@@ -1506,15 +1503,14 @@ void QMdiSubWindowPrivate::processClickedSubControl()
q->showNormal();
break;
case QStyle::SC_TitleBarMinButton:
-#if QT_CONFIG(style_mac)
- if (qobject_cast<QMacStyle *>(q->style())) {
+ if (isMacStyle(q->style())) {
if (q->isMinimized())
q->showNormal();
else
q->showMinimized();
break;
}
-#endif
+
q->showMinimized();
break;
case QStyle::SC_TitleBarNormalButton:
@@ -1523,15 +1519,14 @@ void QMdiSubWindowPrivate::processClickedSubControl()
q->showNormal();
break;
case QStyle::SC_TitleBarMaxButton:
-#if QT_CONFIG(style_mac)
- if (qobject_cast<QMacStyle *>(q->style())) {
+ if (isMacStyle(q->style())) {
if (q->isMaximized())
q->showNormal();
else
q->showMaximized();
break;
}
-#endif
+
q->showMaximized();
break;
case QStyle::SC_TitleBarCloseButton:
@@ -1570,10 +1565,8 @@ QRegion QMdiSubWindowPrivate::getRegion(Operation operation) const
}
QRegion region;
-#if QT_CONFIG(style_mac)
- if (qobject_cast<QMacStyle *>(q->style()))
+ if (isMacStyle(q->style()))
return region;
-#endif
switch (operation) {
case TopResize:
@@ -1777,10 +1770,6 @@ bool QMdiSubWindowPrivate::drawTitleBarWhenMaximized() const
if (isChildOfTabbedQMdiArea(q))
return false;
-#if QT_CONFIG(style_mac)
- Q_UNUSED(isChildOfQMdiSubWindow);
- return true;
-#else
if (q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q))
return true;
#if defined(QT_NO_MENUBAR) || defined(QT_NO_MAINWINDOW)
@@ -1794,7 +1783,6 @@ bool QMdiSubWindowPrivate::drawTitleBarWhenMaximized() const
return isChildOfQMdiSubWindow(q);
#endif
-#endif
}
#ifndef QT_NO_MENUBAR
@@ -2193,10 +2181,8 @@ void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip)
return;
newSizeGrip->setFixedSize(newSizeGrip->sizeHint());
bool putSizeGripInLayout = layout ? true : false;
-#if QT_CONFIG(style_mac)
- if (qobject_cast<QMacStyle *>(q->style()))
+ if (isMacStyle(q->style()))
putSizeGripInLayout = false;
-#endif
if (putSizeGripInLayout) {
layout->addWidget(newSizeGrip);
layout->setAlignment(newSizeGrip, Qt::AlignBottom | Qt::AlignRight);
@@ -2845,8 +2831,8 @@ bool QMdiSubWindow::event(QEvent *event)
d->isMaximizeMode = false;
d->isWidgetHiddenByUs = false;
if (!parent()) {
-#if !defined(QT_NO_SIZEGRIP) && QT_CONFIG(style_mac)
- if (qobject_cast<QMacStyle *>(style()))
+#if !defined(QT_NO_SIZEGRIP)
+ if (isMacStyle(style()))
delete d->sizeGrip;
#endif
setOption(RubberBandResize, false);
@@ -2940,8 +2926,8 @@ void QMdiSubWindow::showEvent(QShowEvent *showEvent)
return;
}
-#if !defined(QT_NO_SIZEGRIP) && QT_CONFIG(style_mac)
- if (qobject_cast<QMacStyle *>(style()) && !d->sizeGrip
+#if !defined(QT_NO_SIZEGRIP)
+ if (isMacStyle(style()) && !d->sizeGrip
&& !(windowFlags() & Qt::FramelessWindowHint)) {
d->setSizeGrip(new QSizeGrip(this));
Q_ASSERT(d->sizeGrip);
@@ -3335,10 +3321,10 @@ void QMdiSubWindow::mouseMoveEvent(QMouseEvent *mouseEvent)
hoverRegion += style()->subControlRect(QStyle::CC_TitleBar, &options,
d->hoveredSubControl, this);
}
-#if QT_CONFIG(style_mac)
- if (qobject_cast<QMacStyle *>(style()) && !hoverRegion.isEmpty())
+
+ if (isMacStyle(style()) && !hoverRegion.isEmpty())
hoverRegion += QRegion(0, 0, width(), d->titleBarHeight(options));
-#endif
+
if (!hoverRegion.isEmpty())
update(hoverRegion);
}
@@ -3545,10 +3531,8 @@ QSize QMdiSubWindow::minimumSizeHint() const
int sizeGripHeight = 0;
if (d->sizeGrip && d->sizeGrip->isVisibleTo(const_cast<QMdiSubWindow *>(this)))
sizeGripHeight = d->sizeGrip->height();
-#if QT_CONFIG(style_mac)
- else if (parent() && qobject_cast<QMacStyle *>(style()) && !d->sizeGrip)
+ else if (parent() && isMacStyle(style()) && !d->sizeGrip)
sizeGripHeight = style()->pixelMetric(QStyle::PM_SizeGripSize, 0, this);
-#endif
minHeight = qMax(minHeight, decorationHeight + sizeGripHeight);
#endif
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index 167a10efc3..58212a737a 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -260,7 +260,7 @@ int QMenuPrivate::scrollerHeight() const
return qMax(QApplication::globalStrut().height(), q->style()->pixelMetric(QStyle::PM_MenuScrollerHeight, 0, q));
}
-//Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't
+//Windows and KDE allow menus to cover the taskbar, while GNOME and Mac don't
QRect QMenuPrivate::popupGeometry(const QWidget *widget) const
{
if (QGuiApplicationPrivate::platformTheme() &&
@@ -271,7 +271,7 @@ QRect QMenuPrivate::popupGeometry(const QWidget *widget) const
}
}
-//Windows and KDE allows menus to cover the taskbar, while GNOME and Mac don't
+//Windows and KDE allow menus to cover the taskbar, while GNOME and Mac don't
QRect QMenuPrivate::popupGeometry(int screen) const
{
if (QGuiApplicationPrivate::platformTheme() &&
@@ -297,6 +297,11 @@ QVector<QPointer<QWidget> > QMenuPrivate::calcCausedStack() const
return ret;
}
+bool QMenuPrivate::isContextMenu() const
+{
+ return qobject_cast<const QMenuBar *>(topCausedWidget()) == nullptr;
+}
+
void QMenuPrivate::updateActionRects() const
{
Q_Q(const QMenu);
@@ -352,6 +357,7 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const
//calculate size
QFontMetrics qfm = q->fontMetrics();
bool previousWasSeparator = true; // this is true to allow removing the leading separators
+ const bool contextMenu = isContextMenu();
for(int i = 0; i <= lastVisibleAction; i++) {
QAction *action = actions.at(i);
const bool isSection = action->isSeparator() && (!action->text().isEmpty() || !action->icon().isNull());
@@ -383,7 +389,7 @@ void QMenuPrivate::updateActionRects(const QRect &screen) const
tabWidth = qMax(int(tabWidth), qfm.width(s.mid(t+1)));
s = s.left(t);
#ifndef QT_NO_SHORTCUT
- } else {
+ } else if (action->isShortcutVisibleInContextMenu() || !contextMenu) {
QKeySequence seq = action->shortcut();
if (!seq.isEmpty())
tabWidth = qMax(int(tabWidth), qfm.width(seq.toString(QKeySequence::NativeText)));
@@ -1513,7 +1519,8 @@ void QMenu::initStyleOption(QStyleOptionMenuItem *option, const QAction *action)
option->icon = action->icon();
QString textAndAccel = action->text();
#ifndef QT_NO_SHORTCUT
- if (textAndAccel.indexOf(QLatin1Char('\t')) == -1) {
+ if ((action->isShortcutVisibleInContextMenu() || !d->isContextMenu())
+ && textAndAccel.indexOf(QLatin1Char('\t')) == -1) {
QKeySequence seq = action->shortcut();
if (!seq.isEmpty())
textAndAccel += QLatin1Char('\t') + seq.toString(QKeySequence::NativeText);
@@ -2423,8 +2430,6 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
pos.setY(qMin(mouse.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1));
else
pos.setY(qMax(p.y() - (size.height() + desktopFrame), screen.bottom()-desktopFrame-size.height()+1));
- } else if (pos.y() < screen.top() + desktopFrame) {
- pos.setY(screen.top() + desktopFrame);
}
if (pos.y() < screen.top() + desktopFrame)
@@ -2656,7 +2661,8 @@ void QMenu::hideEvent(QHideEvent *)
if (QMenuBar *mb = qobject_cast<QMenuBar*>(d->causedPopup.widget))
mb->d_func()->setCurrentAction(0);
#endif
- d->mouseDown = 0;
+ if (d->mouseDown == this)
+ d->mouseDown = 0;
d->hasHadMouse = false;
if (d->activeMenu)
d->hideMenu(d->activeMenu);
diff --git a/src/widgets/widgets/qmenu.h b/src/widgets/widgets/qmenu.h
index 9d1a17a5b3..61849790cf 100644
--- a/src/widgets/widgets/qmenu.h
+++ b/src/widgets/widgets/qmenu.h
@@ -108,7 +108,7 @@ public:
#else
result->setShortcut(shortcut);
#endif
- connect(result, &QAction::triggered, object, slot);
+ connect(result, &QAction::triggered, object, std::move(slot));
return result;
}
// addAction(QString): Connect to a functor or function pointer (without context)
@@ -121,7 +121,7 @@ public:
#else
result->setShortcut(shortcut);
#endif
- connect(result, &QAction::triggered, slot);
+ connect(result, &QAction::triggered, std::move(slot));
return result;
}
// addAction(QIcon, QString): Connect to a QObject slot / functor or function pointer (with context)
@@ -136,7 +136,7 @@ public:
#else
result->setShortcut(shortcut);
#endif
- connect(result, &QAction::triggered, object, slot);
+ connect(result, &QAction::triggered, object, std::move(slot));
return result;
}
// addAction(QIcon, QString): Connect to a functor or function pointer (without context)
@@ -149,7 +149,7 @@ public:
#else
result->setShortcut(shortcut);
#endif
- connect(result, &QAction::triggered, slot);
+ connect(result, &QAction::triggered, std::move(slot));
return result;
}
#endif // !Q_QDOC
diff --git a/src/widgets/widgets/qmenu_p.h b/src/widgets/widgets/qmenu_p.h
index 2f04fac3c0..a48d41c140 100644
--- a/src/widgets/widgets/qmenu_p.h
+++ b/src/widgets/widgets/qmenu_p.h
@@ -307,6 +307,8 @@ public:
static QMenuPrivate *get(QMenu *m) { return m->d_func(); }
int scrollerHeight() const;
+ bool isContextMenu() const;
+
//item calculations
mutable uint itemsDirty : 1;
mutable uint maxIconWidth, tabWidth;
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index 173be7aa88..e19d4d4702 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -2453,29 +2453,51 @@ void QPlainTextEdit::setOverwriteMode(bool overwrite)
d->control->setOverwriteMode(overwrite);
}
+#if QT_DEPRECATED_SINCE(5, 10)
/*!
\property QPlainTextEdit::tabStopWidth
\brief the tab stop width in pixels
+ \deprecated in Qt 5.10. Use tabStopDistance instead.
By default, this property contains a value of 80.
*/
int QPlainTextEdit::tabStopWidth() const
{
- Q_D(const QPlainTextEdit);
- return qRound(d->control->document()->defaultTextOption().tabStop());
+ return qRound(tabStopDistance());
}
void QPlainTextEdit::setTabStopWidth(int width)
{
+ setTabStopDistance(width);
+}
+#endif
+
+/*!
+ \property QPlainTextEdit::tabStopDistance
+ \brief the tab stop distance in pixels
+ \since 5.10
+
+ By default, this property contains a value of 80.
+*/
+
+qreal QPlainTextEdit::tabStopDistance() const
+{
+ Q_D(const QPlainTextEdit);
+ return d->control->document()->defaultTextOption().tabStopDistance();
+}
+
+void QPlainTextEdit::setTabStopDistance(qreal distance)
+{
Q_D(QPlainTextEdit);
QTextOption opt = d->control->document()->defaultTextOption();
- if (opt.tabStop() == width || width < 0)
+ if (opt.tabStopDistance() == distance || distance < 0)
return;
- opt.setTabStop(width);
+ opt.setTabStopDistance(distance);
d->control->document()->setDefaultTextOption(opt);
}
+
/*!
\property QPlainTextEdit::cursorWidth
diff --git a/src/widgets/widgets/qplaintextedit.h b/src/widgets/widgets/qplaintextedit.h
index d773c4791c..09e714fd3c 100644
--- a/src/widgets/widgets/qplaintextedit.h
+++ b/src/widgets/widgets/qplaintextedit.h
@@ -74,7 +74,10 @@ class Q_WIDGETS_EXPORT QPlainTextEdit : public QAbstractScrollArea
Q_PROPERTY(bool readOnly READ isReadOnly WRITE setReadOnly)
Q_PROPERTY(QString plainText READ toPlainText WRITE setPlainText NOTIFY textChanged USER true)
Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode)
+#if QT_DEPRECATED_SINCE(5, 10)
Q_PROPERTY(int tabStopWidth READ tabStopWidth WRITE setTabStopWidth)
+#endif
+ Q_PROPERTY(qreal tabStopDistance READ tabStopDistance WRITE setTabStopDistance)
Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth)
Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags)
Q_PROPERTY(int blockCount READ blockCount)
@@ -168,8 +171,13 @@ public:
bool overwriteMode() const;
void setOverwriteMode(bool overwrite);
- int tabStopWidth() const;
- void setTabStopWidth(int width);
+#if QT_DEPRECATED_SINCE(5, 10)
+ QT_DEPRECATED int tabStopWidth() const;
+ QT_DEPRECATED void setTabStopWidth(int width);
+#endif
+
+ qreal tabStopDistance() const;
+ void setTabStopDistance(qreal distance);
int cursorWidth() const;
void setCursorWidth(int width);
diff --git a/src/widgets/widgets/qprogressbar.cpp b/src/widgets/widgets/qprogressbar.cpp
index b4819278c7..e26673a010 100644
--- a/src/widgets/widgets/qprogressbar.cpp
+++ b/src/widgets/widgets/qprogressbar.cpp
@@ -213,7 +213,7 @@ bool QProgressBarPrivate::repaintRequired() const
Note that whether or not the text is drawn is dependent on the style.
Currently CleanLooks and Plastique draw the text. Mac, Windows
- and WindowsXP style do not.
+ and WindowsVista style do not.
\sa textDirection
*/
diff --git a/src/widgets/widgets/qpushbutton.cpp b/src/widgets/widgets/qpushbutton.cpp
index 293d107740..e13ea83fd7 100644
--- a/src/widgets/widgets/qpushbutton.cpp
+++ b/src/widgets/widgets/qpushbutton.cpp
@@ -59,10 +59,6 @@
#if QT_CONFIG(dialogbuttonbox)
#include "qdialogbuttonbox.h"
#endif
-#if 0 // Used to be included in Qt4 for Q_WS_MAC
-#include "private/qmacstyle_mac_p.h"
-#include "private/qmacstyle_mac_p_p.h"
-#endif
#ifndef QT_NO_ACCESSIBILITY
#include "qaccessible.h"
diff --git a/src/widgets/widgets/qsplashscreen.cpp b/src/widgets/widgets/qsplashscreen.cpp
index fb92d5de0d..d1b59b5196 100644
--- a/src/widgets/widgets/qsplashscreen.cpp
+++ b/src/widgets/widgets/qsplashscreen.cpp
@@ -140,7 +140,7 @@ QSplashScreen::QSplashScreen(const QPixmap &pixmap, Qt::WindowFlags f)
one. In that case pass the proper desktop() as the \a parent.
*/
QSplashScreen::QSplashScreen(QWidget *parent, const QPixmap &pixmap, Qt::WindowFlags f)
- : QWidget(*new QSplashScreenPrivate, parent, Qt::SplashScreen | f)
+ : QWidget(*new QSplashScreenPrivate, parent, Qt::SplashScreen | Qt::FramelessWindowHint | f)
{
d_func()->pixmap = pixmap;
setPixmap(d_func()->pixmap); // Does an implicit repaint
diff --git a/src/widgets/widgets/qtabbar_p.h b/src/widgets/widgets/qtabbar_p.h
index 52e139c707..195ff79c5d 100644
--- a/src/widgets/widgets/qtabbar_p.h
+++ b/src/widgets/widgets/qtabbar_p.h
@@ -81,7 +81,7 @@ private:
QPixmap m_pixmap;
};
-class QTabBarPrivate : public QWidgetPrivate
+class Q_WIDGETS_EXPORT QTabBarPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QTabBar)
public:
@@ -180,7 +180,7 @@ public:
int indexAtPos(const QPoint &p) const;
- inline bool isAnimated() const { Q_Q(const QTabBar); return q->style()->styleHint(QStyle::SH_Widget_Animate, 0, q); }
+ inline bool isAnimated() const { Q_Q(const QTabBar); return q->style()->styleHint(QStyle::SH_Widget_Animation_Duration, 0, q) > 0; }
inline bool validIndex(int index) const { return index >= 0 && index < tabList.count(); }
void setCurrentNextEnabledIndex(int offset);
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index 6973cec429..3eaf60116e 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -1954,27 +1954,48 @@ void QTextEdit::setOverwriteMode(bool overwrite)
d->control->setOverwriteMode(overwrite);
}
+#if QT_DEPRECATED_SINCE(5, 10)
/*!
\property QTextEdit::tabStopWidth
\brief the tab stop width in pixels
\since 4.1
+ \deprecated in Qt 5.10. Use tabStopDistance instead.
By default, this property contains a value of 80 pixels.
*/
int QTextEdit::tabStopWidth() const
{
- Q_D(const QTextEdit);
- return qRound(d->control->document()->defaultTextOption().tabStop());
+ return qRound(tabStopDistance());
}
void QTextEdit::setTabStopWidth(int width)
{
+ setTabStopDistance(width);
+}
+#endif
+
+/*!
+ \property QTextEdit::tabStopDistance
+ \brief the tab stop distance in pixels
+ \since 5.10
+
+ By default, this property contains a value of 80 pixels.
+*/
+
+qreal QTextEdit::tabStopDistance() const
+{
+ Q_D(const QTextEdit);
+ return d->control->document()->defaultTextOption().tabStopDistance();
+}
+
+void QTextEdit::setTabStopDistance(qreal distance)
+{
Q_D(QTextEdit);
QTextOption opt = d->control->document()->defaultTextOption();
- if (opt.tabStop() == width || width < 0)
+ if (opt.tabStopDistance() == distance || distance < 0)
return;
- opt.setTabStop(width);
+ opt.setTabStopDistance(distance);
d->control->document()->setDefaultTextOption(opt);
}
diff --git a/src/widgets/widgets/qtextedit.h b/src/widgets/widgets/qtextedit.h
index 745b644511..a3e5bd2a8a 100644
--- a/src/widgets/widgets/qtextedit.h
+++ b/src/widgets/widgets/qtextedit.h
@@ -77,7 +77,10 @@ class Q_WIDGETS_EXPORT QTextEdit : public QAbstractScrollArea
#endif
Q_PROPERTY(QString plainText READ toPlainText WRITE setPlainText DESIGNABLE false)
Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode)
+#if QT_DEPRECATED_SINCE(5, 10)
Q_PROPERTY(int tabStopWidth READ tabStopWidth WRITE setTabStopWidth)
+#endif
+ Q_PROPERTY(qreal tabStopDistance READ tabStopDistance WRITE setTabStopDistance)
Q_PROPERTY(bool acceptRichText READ acceptRichText WRITE setAcceptRichText)
Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth)
Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags)
@@ -187,8 +190,13 @@ public:
bool overwriteMode() const;
void setOverwriteMode(bool overwrite);
- int tabStopWidth() const;
- void setTabStopWidth(int width);
+#if QT_DEPRECATED_SINCE(5, 10)
+ QT_DEPRECATED int tabStopWidth() const;
+ QT_DEPRECATED void setTabStopWidth(int width);
+#endif
+
+ qreal tabStopDistance() const;
+ void setTabStopDistance(qreal distance);
int cursorWidth() const;
void setCursorWidth(int width);
diff --git a/src/widgets/widgets/qtoolbar.cpp b/src/widgets/widgets/qtoolbar.cpp
index 893506f16f..476f9d4cfa 100644
--- a/src/widgets/widgets/qtoolbar.cpp
+++ b/src/widgets/widgets/qtoolbar.cpp
@@ -89,7 +89,6 @@ void QToolBarPrivate::init()
q->setBackgroundRole(QPalette::Button);
q->setAttribute(Qt::WA_Hover);
q->setAttribute(Qt::WA_X11NetWmWindowTypeToolBar);
- q->setProperty("_q_platform_MacUseNSWindow", QVariant(true));
QStyle *style = q->style();
int e = style->pixelMetric(QStyle::PM_ToolBarIconSize, 0, q);
diff --git a/src/widgets/widgets/qtoolbar.h b/src/widgets/widgets/qtoolbar.h
index e0f2d9b073..9ffb472c76 100644
--- a/src/widgets/widgets/qtoolbar.h
+++ b/src/widgets/widgets/qtoolbar.h
@@ -121,7 +121,7 @@ public:
addAction(const QString &text, const Obj *object, Func1 slot)
{
QAction *result = addAction(text);
- connect(result, &QAction::triggered, object, slot);
+ connect(result, &QAction::triggered, object, std::move(slot));
return result;
}
// addAction(QString): Connect to a functor or function pointer (without context)
@@ -139,7 +139,7 @@ public:
addAction(const QIcon &actionIcon, const QString &text, const Obj *object, Func1 slot)
{
QAction *result = addAction(actionIcon, text);
- connect(result, &QAction::triggered, object, slot);
+ connect(result, &QAction::triggered, object, std::move(slot));
return result;
}
// addAction(QIcon, QString): Connect to a functor or function pointer (without context)
diff --git a/src/widgets/widgets/qwidgetanimator.cpp b/src/widgets/widgets/qwidgetanimator.cpp
index d46d65546c..3a00999e57 100644
--- a/src/widgets/widgets/qwidgetanimator.cpp
+++ b/src/widgets/widgets/qwidgetanimator.cpp
@@ -91,13 +91,13 @@ void QWidgetAnimator::animate(QWidget *widget, const QRect &_final_geometry, boo
#ifndef QT_NO_ANIMATION
//If the QStyle has animations, animate
- if (widget->style()->styleHint(QStyle::SH_Widget_Animate, 0, widget)) {
+ if (const int animationDuration = widget->style()->styleHint(QStyle::SH_Widget_Animation_Duration, 0, widget)) {
AnimationMap::const_iterator it = m_animation_map.constFind(widget);
if (it != m_animation_map.constEnd() && (*it)->endValue().toRect() == final_geometry)
return;
QPropertyAnimation *anim = new QPropertyAnimation(widget, "geometry", widget);
- anim->setDuration(animate ? 200 : 0);
+ anim->setDuration(animate ? animationDuration : 0);
anim->setEasingCurve(QEasingCurve::InOutQuad);
anim->setEndValue(final_geometry);
m_animation_map[widget] = anim;
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index 815cc8736b..116855c8d3 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -85,7 +85,10 @@
#include "private/qapplication_p.h"
#include "private/qshortcutmap_p.h"
#include <qkeysequence.h>
-#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \
+#define ACCEL_KEY(k) ((qApp->testAttribute(Qt::AA_DontShowIconsInMenus) \
+ ? false \
+ : qApp->styleHints()->showShortcutsInContextMenus()) \
+ && !qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? \
QLatin1Char('\t') + QKeySequence(k).toString(QKeySequence::NativeText) : QString())
#else
diff --git a/sync.profile b/sync.profile
index 023751f472..4cb5563cc4 100644
--- a/sync.profile
+++ b/sync.profile
@@ -26,6 +26,8 @@
"QtFbSupport" => "$basedir/src/platformsupport/fbconvenience",
"QtGlxSupport" => "$basedir/src/platformsupport/glxconvenience",
"QtKmsSupport" => "$basedir/src/platformsupport/kmsconvenience",
+ "QtEdidSupport" => "$basedir/src/platformsupport/edid",
+ "QtVulkanSupport" => "$basedir/src/platformsupport/vkconvenience",
"QtPlatformHeaders" => "$basedir/src/platformheaders",
"QtANGLE/KHR" => "!$basedir/src/3rdparty/angle/include/KHR",
"QtANGLE/GLES2" => "!$basedir/src/3rdparty/angle/include/GLES2",
@@ -52,6 +54,7 @@
"qnamespace.h" => "Qt",
"qnumeric.h" => "QtNumeric",
"qvariant.h" => "QVariantHash,QVariantList,QVariantMap",
+ "qvulkanfunctions.h" => "QVulkanFunctions,QVulkanDeviceFunctions",
"qgl.h" => "QGL",
"qtsqlglobal.h" => "QSql",
"qssl.h" => "QSsl",
@@ -80,4 +83,7 @@ my @zlib_headers = ( "zconf.h", "zlib.h" );
@ignore_headers = ( @internal_zlib_headers );
@ignore_for_include_check = ( "qsystemdetection.h", "qcompilerdetection.h", "qprocessordetection.h", @zlib_headers, @angle_headers);
@ignore_for_qt_begin_namespace_check = ( "qt_windows.h", @zlib_headers, @angle_headers);
-%inject_headers = ( "$basedir/src/corelib/global" => [ "qconfig.h", "qconfig_p.h" ] );
+%inject_headers = (
+ "$basedir/src/corelib/global" => [ "qconfig.h", "qconfig_p.h" ],
+ "$basedir/src/gui/vulkan" => [ "^qvulkanfunctions.h", "^qvulkanfunctions_p.h" ]
+);
diff --git a/tests/auto/concurrent/qtconcurrentmap/BLACKLIST b/tests/auto/concurrent/qtconcurrentmap/BLACKLIST
new file mode 100644
index 0000000000..7cd8961f6f
--- /dev/null
+++ b/tests/auto/concurrent/qtconcurrentmap/BLACKLIST
@@ -0,0 +1,2 @@
+[qFutureAssignmentLeak]
+ci opensuse
diff --git a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
index 0f2e9b5d68..c3b53a2fc0 100644
--- a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
+++ b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp
@@ -126,6 +126,7 @@ void tst_QTextCodec::toUnicode()
}
QVERIFY(!uniString.isEmpty());
QCOMPARE( ba, c->fromUnicode( uniString ) );
+ QCOMPARE(ba, c->fromUnicode(QStringView(uniString)) );
char ch = '\0';
QVERIFY(c->toUnicode(&ch, 1).length() == 1);
@@ -262,7 +263,7 @@ void tst_QTextCodec::fromUnicode()
If the encoding is a superset of ASCII, test that the byte
array is correct (no off by one, no trailing '\0').
*/
- QByteArray result = codec->fromUnicode(QString("abc"));
+ QByteArray result = codec->fromUnicode(QStringViewLiteral("abc"));
if (result.startsWith('a')) {
QCOMPARE(result.size(), 3);
QCOMPARE(result, QByteArray("abc"));
@@ -397,6 +398,7 @@ void tst_QTextCodec::asciiToIscii() const
QVERIFY2(textCodec->canEncode(ascii), qPrintable(QString::fromLatin1("Failed for full string with encoding %1")
.arg(QString::fromLatin1(textCodec->name().constData()))));
+ QVERIFY(textCodec->canEncode(QStringView(ascii)));
}
}
@@ -404,12 +406,11 @@ void tst_QTextCodec::nonFlaggedCodepointFFFF() const
{
//Check that the code point 0xFFFF (=non-character code 0xEFBFBF) is not flagged
const QChar ch(0xFFFF);
- QString input(ch);
QTextCodec *const codec = QTextCodec::codecForMib(106); // UTF-8
QVERIFY(codec);
- const QByteArray asDecoded(codec->fromUnicode(input));
+ const QByteArray asDecoded = codec->fromUnicode(QStringView(&ch, 1));
QCOMPARE(asDecoded, QByteArray("\357\277\277"));
QByteArray ffff("\357\277\277");
diff --git a/tests/auto/corelib/global/global.pro b/tests/auto/corelib/global/global.pro
index b4cc8035e6..139e073644 100644
--- a/tests/auto/corelib/global/global.pro
+++ b/tests/auto/corelib/global/global.pro
@@ -7,6 +7,7 @@ SUBDIRS=\
qnumeric \
qfloat16 \
qrand \
+ qrandomgenerator \
qlogging \
qtendian \
qglobalstatic \
diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
index 09abb953ba..f02e902468 100644
--- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
+++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2016 Intel Corporation.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -30,12 +31,16 @@
#include <QtTest/QtTest>
#include <qglobal.h>
+#ifdef Q_OS_WIN
+#include <qt_windows.h>
+#endif
class tst_QGetPutEnv : public QObject
{
Q_OBJECT
private slots:
void getSetCheck();
+ void encoding();
void intValue_data();
void intValue();
};
@@ -53,7 +58,11 @@ void tst_QGetPutEnv::getSetCheck()
QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
QVERIFY(!ok);
QByteArray result = qgetenv(varName);
- QCOMPARE(result, QByteArray());
+ QVERIFY(result.isNull());
+ QString sresult = qEnvironmentVariable(varName);
+ QVERIFY(sresult.isNull());
+ sresult = qEnvironmentVariable(varName, "hello");
+ QCOMPARE(sresult, QString("hello"));
#ifndef Q_OS_WIN
QVERIFY(qputenv(varName, "")); // deletes varName instead of making it empty, on Windows
@@ -64,6 +73,16 @@ void tst_QGetPutEnv::getSetCheck()
QCOMPARE(qEnvironmentVariableIntValue(varName), 0);
QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
QVERIFY(!ok);
+
+ result = qgetenv(varName);
+ QVERIFY(!result.isNull());
+ QCOMPARE(result, QByteArray());
+ sresult = qEnvironmentVariable(varName);
+ QVERIFY(!sresult.isNull());
+ QCOMPARE(sresult, QString());
+ sresult = qEnvironmentVariable(varName, "hello");
+ QVERIFY(!sresult.isNull());
+ QCOMPARE(sresult, QString());
#endif
QVERIFY(qputenv(varName, QByteArray("supervalue")));
@@ -76,19 +95,61 @@ void tst_QGetPutEnv::getSetCheck()
QVERIFY(!ok);
result = qgetenv(varName);
QCOMPARE(result, QByteArrayLiteral("supervalue"));
+ sresult = qEnvironmentVariable(varName);
+ QCOMPARE(sresult, QString("supervalue"));
+ sresult = qEnvironmentVariable(varName, "hello");
+ QCOMPARE(sresult, QString("supervalue"));
qputenv(varName,QByteArray());
// Now test qunsetenv
QVERIFY(qunsetenv(varName));
- QVERIFY(!qEnvironmentVariableIsSet(varName));
+ QVERIFY(!qEnvironmentVariableIsSet(varName)); // note: might fail on some systems!
QVERIFY(qEnvironmentVariableIsEmpty(varName));
ok = true;
QCOMPARE(qEnvironmentVariableIntValue(varName), 0);
QCOMPARE(qEnvironmentVariableIntValue(varName, &ok), 0);
QVERIFY(!ok);
+
result = qgetenv(varName);
- QCOMPARE(result, QByteArray());
+ QVERIFY(result.isNull());
+ sresult = qEnvironmentVariable(varName);
+ QVERIFY(sresult.isNull());
+ sresult = qEnvironmentVariable(varName, "hello");
+ QCOMPARE(sresult, QString("hello"));
+}
+
+void tst_QGetPutEnv::encoding()
+{
+ // The test string is:
+ // U+0061 LATIN SMALL LETTER A
+ // U+00E1 LATIN SMALL LETTER A WITH ACUTE
+ // U+03B1 GREEK SMALL LETTER ALPHA
+ // U+0430 CYRILLIC SMALL LETTER A
+ // This has letters in three different scripts, so no locale besides
+ // UTF-8 is able handle them all.
+ // The LATIN SMALL LETTER A WITH ACUTE is NFC for NFD:
+ // U+0061 U+0301 LATIN SMALL LETTER A + COMBINING ACUTE ACCENT
+
+ const char varName[] = "should_not_exist";
+ static const wchar_t rawvalue[] = { 'a', 0x00E1, 0x03B1, 0x0430, 0 };
+ QString value = QString::fromWCharArray(rawvalue);
+
+#if defined(Q_OS_WINRT)
+ QSKIP("Test cannot be run on this platform");
+#elif defined(Q_OS_WIN)
+ const wchar_t wvarName[] = L"should_not_exist";
+ _wputenv_s(wvarName, rawvalue);
+#else
+ // confirm the locale is UTF-8
+ if (value.toLocal8Bit() != "a\xc3\xa1\xce\xb1\xd0\xb0")
+ QSKIP("Locale is not UTF-8, cannot test");
+
+ qputenv(varName, QFile::encodeName(value));
+#endif
+
+ QVERIFY(qEnvironmentVariableIsSet(varName));
+ QCOMPARE(qEnvironmentVariable(varName), value);
}
void tst_QGetPutEnv::intValue_data()
diff --git a/tests/auto/corelib/global/qrandomgenerator/qrandomgenerator.pro b/tests/auto/corelib/global/qrandomgenerator/qrandomgenerator.pro
new file mode 100644
index 0000000000..0307b0c1eb
--- /dev/null
+++ b/tests/auto/corelib/global/qrandomgenerator/qrandomgenerator.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+TARGET = tst_qrandomgenerator
+QT = core-private testlib
+SOURCES = tst_qrandomgenerator.cpp
diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
new file mode 100644
index 0000000000..71c6c4e9cd
--- /dev/null
+++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
@@ -0,0 +1,703 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest>
+#include <qlinkedlist.h>
+#include <qobject.h>
+#include <qrandom.h>
+#include <qvector.h>
+#include <private/qrandom_p.h>
+
+#include <algorithm>
+#if QT_CONFIG(cxx11_random)
+# include <random>
+#endif
+
+#if !QT_CONFIG(getentropy) && (QT_CONFIG(cxx11_random) || defined(Q_OS_BSD4) || defined(Q_OS_WIN))
+# define HAVE_FALLBACK_ENGINE
+#endif
+
+#define COMMA ,
+#define QVERIFY_3TIMES(statement) \
+ do {\
+ if (!QTest::qVerify(static_cast<bool>(statement), #statement, "1st try", __FILE__, __LINE__))\
+ if (!QTest::qVerify(static_cast<bool>(statement), #statement, "2nd try", __FILE__, __LINE__))\
+ if (!QTest::qVerify(static_cast<bool>(statement), #statement, "3rd try", __FILE__, __LINE__))\
+ return;\
+ } while (0)
+
+// values chosen at random
+static const quint32 RandomValue32 = 0x4d1169f1U;
+static const quint64 RandomValue64 = Q_UINT64_C(0x3ce63161b998aa91);
+static const double RandomValueFP = double(0.3010463714599609f);
+
+static void setRNGControl(uint v)
+{
+#ifdef QT_BUILD_INTERNAL
+ qt_randomdevice_control.store(v);
+#else
+ Q_UNUSED(v);
+#endif
+}
+
+class tst_QRandomGenerator : public QObject
+{
+ Q_OBJECT
+
+public slots:
+ void cleanup() { setRNGControl(0); }
+
+private slots:
+ void get32_data();
+ void get32();
+ void get64_data() { get32_data(); }
+ void get64();
+ void quality_data() { get32_data(); }
+ void quality();
+ void fillRangeUInt_data() { get32_data(); }
+ void fillRangeUInt();
+ void fillRangeULong_data() { get32_data(); }
+ void fillRangeULong();
+ void fillRangeULLong_data() { get32_data(); }
+ void fillRangeULLong();
+ void generateUInt_data() { get32_data(); }
+ void generateUInt();
+ void generateULLong_data() { get32_data(); }
+ void generateULLong();
+ void generateNonContiguous_data() { get32_data(); }
+ void generateNonContiguous();
+
+ void bounded_data();
+ void bounded();
+ void boundedQuality_data() { get32_data(); }
+ void boundedQuality();
+
+ void getReal_data() { get32_data(); }
+ void getReal();
+
+ void seedStdRandomEngines();
+ void stdUniformIntDistribution_data();
+ void stdUniformIntDistribution();
+ void stdGenerateCanonical_data() { getReal_data(); }
+ void stdGenerateCanonical();
+ void stdUniformRealDistribution_data();
+ void stdUniformRealDistribution();
+ void stdRandomDistributions();
+};
+
+using namespace std;
+QT_WARNING_DISABLE_GCC("-Wfloat-equal")
+QT_WARNING_DISABLE_CLANG("-Wfloat-equal")
+
+void tst_QRandomGenerator::get32_data()
+{
+ QTest::addColumn<uint>("control");
+ QTest::newRow("default") << 0U;
+#ifdef QT_BUILD_INTERNAL
+ QTest::newRow("direct") << uint(SkipMemfill);
+ QTest::newRow("system") << uint(SkipHWRNG);
+# ifdef HAVE_FALLBACK_ENGINE
+ QTest::newRow("fallback") << uint(SkipHWRNG | SkipSystemRNG);
+# endif
+#endif
+}
+
+void tst_QRandomGenerator::get32()
+{
+ QFETCH(uint, control);
+ setRNGControl(control);
+
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY_3TIMES([] {
+ quint32 value = QRandomGenerator::get32();
+ return value != 0 && value != RandomValue32;
+ }());
+ }
+
+ // and should hopefully be different from repeated calls
+ for (int i = 0; i < 4; ++i)
+ QVERIFY_3TIMES(QRandomGenerator::get32() != QRandomGenerator::get32());
+}
+
+void tst_QRandomGenerator::get64()
+{
+ QFETCH(uint, control);
+ setRNGControl(control);
+
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY_3TIMES([] {
+ quint64 value = QRandomGenerator::get32();
+ return value != 0 && value != RandomValue32 && value != RandomValue64;
+ }());
+ }
+
+ // and should hopefully be different from repeated calls
+ for (int i = 0; i < 4; ++i)
+ QVERIFY_3TIMES(QRandomGenerator::get64() != QRandomGenerator::get64());
+ for (int i = 0; i < 4; ++i)
+ QVERIFY_3TIMES(QRandomGenerator::get32() != quint32(QRandomGenerator::get64()));
+ for (int i = 0; i < 4; ++i)
+ QVERIFY_3TIMES(QRandomGenerator::get32() != (QRandomGenerator::get64() >> 32));
+}
+
+void tst_QRandomGenerator::quality()
+{
+ enum {
+ BufferSize = 2048,
+ BufferCount = BufferSize / sizeof(quint32),
+
+ // if the distribution were perfect, each byte in the buffer would
+ // appear exactly:
+ PerfectDistribution = BufferSize / (UCHAR_MAX + 1),
+
+ // The chance of a value appearing N times above its perfect
+ // distribution is the same as it appearing N times in a row:
+ // N Probability
+ // 1 100%
+ // 2 0.390625%
+ // 3 15.25 in a million
+ // 4 59.60 in a billion
+ // 8 5.421e-20
+ // 16 2.938e-39
+
+ AcceptableThreshold = 4 * PerfectDistribution,
+ FailureThreshold = 16 * PerfectDistribution
+ };
+ Q_STATIC_ASSERT(FailureThreshold > AcceptableThreshold);
+
+ QFETCH(uint, control);
+ setRNGControl(control);
+
+ int histogram[UCHAR_MAX + 1];
+ memset(histogram, 0, sizeof(histogram));
+
+ {
+ // test the quality of the generator
+ quint32 buffer[BufferCount];
+ memset(buffer, 0xcc, sizeof(buffer));
+ generate_n(buffer, +BufferCount, [] { return QRandomGenerator::get32(); });
+
+ quint8 *ptr = reinterpret_cast<quint8 *>(buffer);
+ quint8 *end = ptr + sizeof(buffer);
+ for ( ; ptr != end; ++ptr)
+ histogram[*ptr]++;
+ }
+
+ for (uint i = 0; i < sizeof(histogram)/sizeof(histogram[0]); ++i) {
+ int v = histogram[i];
+ if (v > AcceptableThreshold)
+ qDebug() << i << "above threshold:" << v;
+ QVERIFY2(v < FailureThreshold, QByteArray::number(i));
+ }
+ qDebug() << "Average:" << (std::accumulate(begin(histogram), end(histogram), 0) / (1. * (UCHAR_MAX + 1)))
+ << "(expected" << int(PerfectDistribution) << "ideally)"
+ << "Max:" << *std::max_element(begin(histogram), end(histogram))
+ << "at" << std::max_element(begin(histogram), end(histogram)) - histogram
+ << "Min:" << *std::min_element(begin(histogram), end(histogram))
+ << "at" << std::min_element(begin(histogram), end(histogram)) - histogram;
+}
+
+template <typename T> void fillRange_template()
+{
+ QFETCH(uint, control);
+ setRNGControl(control);
+
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY_3TIMES([] {
+ T value[1] = { RandomValue32 };
+ QRandomGenerator::fillRange(value);
+ return value[0] != 0 && value[0] != RandomValue32;
+ }());
+ }
+
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY_3TIMES([] {
+ T array[2] = {};
+ QRandomGenerator::fillRange(array);
+ return array[0] != array[1];
+ }());
+ }
+
+ if (sizeof(T) > sizeof(quint32)) {
+ // just to shut up a warning about shifting uint more than the width
+ enum { Shift = sizeof(T) / 2 * CHAR_BIT };
+ QVERIFY_3TIMES([] {
+ T value[1] = { };
+ QRandomGenerator::fillRange(value);
+ return quint32(value[0] >> Shift) != quint32(value[0]);
+ }());
+ }
+
+ // fill in a longer range
+ auto longerArrayCheck = [] {
+ T array[32];
+ memset(array, 0, sizeof(array));
+ QRandomGenerator::fillRange(array);
+ if (sizeof(T) == sizeof(RandomValue64)
+ && find(begin(array), end(array), RandomValue64) != end(array))
+ return false;
+ return find(begin(array), end(array), 0) == end(array) &&
+ find(begin(array), end(array), RandomValue32) == end(array);
+ };
+ QVERIFY_3TIMES(longerArrayCheck());
+}
+
+void tst_QRandomGenerator::fillRangeUInt() { fillRange_template<uint>(); }
+void tst_QRandomGenerator::fillRangeULong() { fillRange_template<ulong>(); }
+void tst_QRandomGenerator::fillRangeULLong() { fillRange_template<qulonglong>(); }
+
+template <typename T> void generate_template()
+{
+ QFETCH(uint, control);
+ setRNGControl(control);
+
+ // almost the same as fillRange, but limited to 32 bits
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY_3TIMES([] {
+ T value[1] = { RandomValue32 };
+ QRandomGenerator().generate(begin(value), end(value));
+ return value[0] != 0 && value[0] != RandomValue32
+ && value[0] <= numeric_limits<quint32>::max();
+ }());
+ }
+
+ // fill in a longer range
+ auto longerArrayCheck = [] {
+ T array[72] = {}; // at least 256 bytes
+ QRandomGenerator().generate(begin(array), end(array));
+ return find_if(begin(array), end(array), [](T cur) {
+ return cur == 0 || cur == RandomValue32 ||
+ cur == RandomValue64 || cur > numeric_limits<quint32>::max();
+ }) == end(array);
+ };
+ QVERIFY_3TIMES(longerArrayCheck());
+}
+
+void tst_QRandomGenerator::generateUInt() { generate_template<uint>(); }
+void tst_QRandomGenerator::generateULLong() { generate_template<qulonglong>(); }
+
+void tst_QRandomGenerator::generateNonContiguous()
+{
+ QFETCH(uint, control);
+ setRNGControl(control);
+
+ QLinkedList<quint64> list = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ auto longerArrayCheck = [&] {
+ QRandomGenerator().generate(list.begin(), list.end());
+ return find_if(list.begin(), list.end(), [](quint64 cur) {
+ return cur == 0 || cur == RandomValue32 ||
+ cur == RandomValue64 || cur > numeric_limits<quint32>::max();
+ }) == list.end();
+ };
+ QVERIFY_3TIMES(longerArrayCheck());
+}
+
+void tst_QRandomGenerator::bounded_data()
+{
+#ifndef QT_BUILD_INTERNAL
+ QSKIP("Test only possible in developer builds");
+#endif
+
+ QTest::addColumn<uint>("control");
+ QTest::addColumn<quint32>("sup");
+ QTest::addColumn<quint32>("expected");
+
+ auto newRow = [](quint32 val, quint32 sup) {
+ // calculate the scaled value
+ quint64 scaled = val;
+ scaled <<= 32;
+ scaled /= sup;
+ unsigned shifted = unsigned(scaled);
+ Q_ASSERT(val < sup);
+ Q_ASSERT((shifted & RandomDataMask) == shifted);
+
+ unsigned control = SetRandomData | shifted;
+ QTest::addRow("%u,%u", val, sup) << control << sup << val;
+ };
+
+ // useless: we can only generate zeroes:
+ newRow(0, 1);
+
+ newRow(25, 200);
+ newRow(50, 200);
+ newRow(75, 200);
+}
+
+void tst_QRandomGenerator::bounded()
+{
+ QFETCH(uint, control);
+ QFETCH(quint32, sup);
+ QFETCH(quint32, expected);
+ setRNGControl(control);
+
+ quint32 value = QRandomGenerator::bounded(sup);
+ QVERIFY(value < sup);
+ QCOMPARE(value, expected);
+
+ int ivalue = QRandomGenerator::bounded(sup);
+ QVERIFY(ivalue < int(sup));
+ QCOMPARE(ivalue, int(expected));
+
+ // confirm only the bound now
+ setRNGControl(control & (SkipHWRNG|SkipSystemRNG|SkipMemfill));
+ value = QRandomGenerator::bounded(sup);
+ QVERIFY(value < sup);
+
+ value = QRandomGenerator::bounded(sup / 2, 3 * sup / 2);
+ QVERIFY(value >= sup / 2);
+ QVERIFY(value < 3 * sup / 2);
+
+ ivalue = QRandomGenerator::bounded(-int(sup), int(sup));
+ QVERIFY(ivalue >= -int(sup));
+ QVERIFY(ivalue < int(sup));
+
+ // wholly negative range
+ ivalue = QRandomGenerator::bounded(-int(sup), 0);
+ QVERIFY(ivalue >= -int(sup));
+ QVERIFY(ivalue < 0);
+}
+
+void tst_QRandomGenerator::boundedQuality()
+{
+ enum { Bound = 283 }; // a prime number
+ enum {
+ BufferCount = Bound * 32,
+
+ // if the distribution were perfect, each byte in the buffer would
+ // appear exactly:
+ PerfectDistribution = BufferCount / Bound,
+
+ // The chance of a value appearing N times above its perfect
+ // distribution is the same as it appearing N times in a row:
+ // N Probability
+ // 1 100%
+ // 2 0.390625%
+ // 3 15.25 in a million
+ // 4 59.60 in a billion
+ // 8 5.421e-20
+ // 16 2.938e-39
+
+ AcceptableThreshold = 4 * PerfectDistribution,
+ FailureThreshold = 16 * PerfectDistribution
+ };
+ Q_STATIC_ASSERT(FailureThreshold > AcceptableThreshold);
+
+ QFETCH(uint, control);
+ setRNGControl(control);
+
+ int histogram[Bound];
+ memset(histogram, 0, sizeof(histogram));
+
+ {
+ // test the quality of the generator
+ QVector<quint32> buffer(BufferCount, 0xcdcdcdcd);
+ generate(buffer.begin(), buffer.end(), [] { return QRandomGenerator::bounded(Bound); });
+
+ for (quint32 value : qAsConst(buffer)) {
+ QVERIFY(value < Bound);
+ histogram[value]++;
+ }
+ }
+
+ for (unsigned i = 0; i < sizeof(histogram)/sizeof(histogram[0]); ++i) {
+ int v = histogram[i];
+ if (v > AcceptableThreshold)
+ qDebug() << i << "above threshold:" << v;
+ QVERIFY2(v < FailureThreshold, QByteArray::number(i));
+ }
+
+ qDebug() << "Average:" << (std::accumulate(begin(histogram), end(histogram), 0) / qreal(Bound))
+ << "(expected" << int(PerfectDistribution) << "ideally)"
+ << "Max:" << *std::max_element(begin(histogram), end(histogram))
+ << "at" << std::max_element(begin(histogram), end(histogram)) - histogram
+ << "Min:" << *std::min_element(begin(histogram), end(histogram))
+ << "at" << std::min_element(begin(histogram), end(histogram)) - histogram;
+}
+
+void tst_QRandomGenerator::getReal()
+{
+ QFETCH(uint, control);
+ setRNGControl(control);
+
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY_3TIMES([] {
+ qreal value = QRandomGenerator::getReal();
+ return value > 0 && value < 1 && value != RandomValueFP;
+ }());
+ }
+
+ // and should hopefully be different from repeated calls
+ for (int i = 0; i < 4; ++i)
+ QVERIFY_3TIMES(QRandomGenerator::getReal() != QRandomGenerator::getReal());
+}
+
+template <typename Engine> void seedStdRandomEngine()
+{
+ QRandomGenerator rd;
+ Engine e(rd);
+ QVERIFY_3TIMES(e() != 0);
+
+ e.seed(rd);
+ QVERIFY_3TIMES(e() != 0);
+}
+
+void tst_QRandomGenerator::seedStdRandomEngines()
+{
+#if !QT_CONFIG(cxx11_random)
+ QSKIP("<random> not found");
+#else
+ seedStdRandomEngine<std::default_random_engine>();
+ seedStdRandomEngine<std::minstd_rand0>();
+ seedStdRandomEngine<std::minstd_rand>();
+ seedStdRandomEngine<std::mt19937>();
+ seedStdRandomEngine<std::mt19937_64>();
+ seedStdRandomEngine<std::ranlux24_base>();
+ seedStdRandomEngine<std::ranlux48_base>();
+ seedStdRandomEngine<std::ranlux24>();
+ seedStdRandomEngine<std::ranlux48>();
+#endif
+}
+
+void tst_QRandomGenerator::stdUniformIntDistribution_data()
+{
+#ifndef QT_BUILD_INTERNAL
+ QSKIP("Test only possible in developer builds");
+#endif
+
+ QTest::addColumn<uint>("control");
+ QTest::addColumn<quint32>("max");
+
+ auto newRow = [](quint32 max) {
+ QTest::addRow("default:%u", max) << 0U << max;
+ QTest::addRow("direct:%u", max) << uint(SkipMemfill) << max;
+ QTest::addRow("system:%u", max) << uint(SkipHWRNG) << max;
+ #ifdef HAVE_FALLBACK_ENGINE
+ QTest::addRow("fallback:%u", max) << uint(SkipHWRNG | SkipSystemRNG) << max;
+ #endif
+ };
+
+ // useless: we can only generate zeroes:
+ newRow(0);
+
+ newRow(1);
+ newRow(199);
+ newRow(numeric_limits<quint32>::max());
+}
+
+void tst_QRandomGenerator::stdUniformIntDistribution()
+{
+#if !QT_CONFIG(cxx11_random)
+ QSKIP("<random> not found");
+#else
+ QFETCH(uint, control);
+ QFETCH(quint32, max);
+ setRNGControl(control & (SkipHWRNG|SkipSystemRNG|SkipMemfill));
+
+ {
+ QRandomGenerator rd;
+ {
+ std::uniform_int_distribution<quint32> dist(0, max);
+ quint32 value = dist(rd);
+ QVERIFY(value >= dist.min());
+ QVERIFY(value <= dist.max());
+ }
+ if ((3 * max / 2) > max) {
+ std::uniform_int_distribution<quint32> dist(max / 2, 3 * max / 2);
+ quint32 value = dist(rd);
+ QVERIFY(value >= dist.min());
+ QVERIFY(value <= dist.max());
+ }
+
+ {
+ std::uniform_int_distribution<quint64> dist(0, quint64(max) << 32);
+ quint64 value = dist(rd);
+ QVERIFY(value >= dist.min());
+ QVERIFY(value <= dist.max());
+ }
+ {
+ std::uniform_int_distribution<quint64> dist(max / 2, 3 * quint64(max) / 2);
+ quint64 value = dist(rd);
+ QVERIFY(value >= dist.min());
+ QVERIFY(value <= dist.max());
+ }
+ }
+
+ {
+ QRandomGenerator64 rd;
+ {
+ std::uniform_int_distribution<quint32> dist(0, max);
+ quint32 value = dist(rd);
+ QVERIFY(value >= dist.min());
+ QVERIFY(value <= dist.max());
+ }
+ if ((3 * max / 2) > max) {
+ std::uniform_int_distribution<quint32> dist(max / 2, 3 * max / 2);
+ quint32 value = dist(rd);
+ QVERIFY(value >= dist.min());
+ QVERIFY(value <= dist.max());
+ }
+
+ {
+ std::uniform_int_distribution<quint64> dist(0, quint64(max) << 32);
+ quint64 value = dist(rd);
+ QVERIFY(value >= dist.min());
+ QVERIFY(value <= dist.max());
+ }
+ {
+ std::uniform_int_distribution<quint64> dist(max / 2, 3 * quint64(max) / 2);
+ quint64 value = dist(rd);
+ QVERIFY(value >= dist.min());
+ QVERIFY(value <= dist.max());
+ }
+ }
+#endif
+}
+
+void tst_QRandomGenerator::stdGenerateCanonical()
+{
+#if !QT_CONFIG(cxx11_random)
+ QSKIP("<random> not found");
+#elif defined(Q_CC_MSVC) && Q_CC_MSVC < 1900
+ // see https://connect.microsoft.com/VisualStudio/feedback/details/811611
+ QSKIP("MSVC 2013's std::generate_canonical is broken");
+#else
+ QFETCH(uint, control);
+ setRNGControl(control);
+
+ for (int i = 0; i < 4; ++i) {
+ QVERIFY_3TIMES([] {
+ QRandomGenerator rd;
+ qreal value = std::generate_canonical<qreal COMMA 32>(rd);
+ return value > 0 && value < 1 && value != RandomValueFP;
+ }());
+ }
+
+ // and should hopefully be different from repeated calls
+ QRandomGenerator rd;
+ for (int i = 0; i < 4; ++i)
+ QVERIFY_3TIMES(std::generate_canonical<qreal COMMA 32>(rd) !=
+ std::generate_canonical<qreal COMMA 32>(rd));
+#endif
+}
+
+void tst_QRandomGenerator::stdUniformRealDistribution_data()
+{
+#ifndef QT_BUILD_INTERNAL
+ QSKIP("Test only possible in developer builds");
+#endif
+
+ QTest::addColumn<uint>("control");
+ QTest::addColumn<double>("min");
+ QTest::addColumn<double>("sup");
+
+ auto newRow = [](double min, double sup) {
+ QTest::addRow("default:%g-%g", min, sup) << 0U << min << sup;
+ QTest::addRow("direct:%g-%g", min, sup) << uint(SkipMemfill) << min << sup;
+ QTest::addRow("system:%g-%g", min, sup) << uint(SkipHWRNG) << min << sup;
+ #ifdef HAVE_FALLBACK_ENGINE
+ QTest::addRow("fallback:%g-%g", min, sup) << uint(SkipHWRNG | SkipSystemRNG) << min << sup;
+ #endif
+ };
+
+ newRow(0, 0); // useless: we can only generate zeroes
+ newRow(0, 1); // canonical
+ newRow(0, 200);
+ newRow(0, numeric_limits<quint32>::max() + 1.);
+ newRow(0, numeric_limits<quint64>::max() + 1.);
+ newRow(-1, 1.6);
+}
+
+void tst_QRandomGenerator::stdUniformRealDistribution()
+{
+#if !QT_CONFIG(cxx11_random)
+ QSKIP("<random> not found");
+#else
+ QFETCH(uint, control);
+ QFETCH(double, min);
+ QFETCH(double, sup);
+ setRNGControl(control & (SkipHWRNG|SkipSystemRNG|SkipMemfill));
+
+ {
+ QRandomGenerator rd;
+ {
+ std::uniform_real_distribution<double> dist(min, sup);
+ double value = dist(rd);
+ QVERIFY(value >= dist.min());
+ if (min != sup)
+ QVERIFY(value < dist.max());
+ }
+ }
+
+ {
+ QRandomGenerator64 rd;
+ {
+ std::uniform_real_distribution<double> dist(min, sup);
+ double value = dist(rd);
+ QVERIFY(value >= dist.min());
+ if (min != sup)
+ QVERIFY(value < dist.max());
+ }
+ }
+#endif
+}
+
+void tst_QRandomGenerator::stdRandomDistributions()
+{
+#if !QT_CONFIG(cxx11_random)
+ QSKIP("<random> not found");
+#else
+ // just a compile check for some of the distributions, besides
+ // std::uniform_int_distribution and std::uniform_real_distribution (tested
+ // above)
+
+ QRandomGenerator rd;
+
+ std::bernoulli_distribution()(rd);
+
+ std::binomial_distribution<quint32>()(rd);
+ std::binomial_distribution<quint64>()(rd);
+
+ std::negative_binomial_distribution<quint32>()(rd);
+ std::negative_binomial_distribution<quint64>()(rd);
+
+ std::poisson_distribution<int>()(rd);
+ std::poisson_distribution<qint64>()(rd);
+
+ std::normal_distribution<qreal>()(rd);
+
+ {
+ std::discrete_distribution<int> discrete{0, 1, 1, 10000, 2};
+ QVERIFY(discrete(rd) != 0);
+ QVERIFY_3TIMES(discrete(rd) == 3);
+ }
+#endif
+}
+
+QTEST_APPLESS_MAIN(tst_QRandomGenerator)
+
+#include "tst_qrandomgenerator.moc"
diff --git a/tests/auto/corelib/global/qtendian/qtendian.pro b/tests/auto/corelib/global/qtendian/qtendian.pro
index 214c706ca5..890976d26c 100644
--- a/tests/auto/corelib/global/qtendian/qtendian.pro
+++ b/tests/auto/corelib/global/qtendian/qtendian.pro
@@ -1,4 +1,4 @@
CONFIG += testcase
TARGET = tst_qtendian
-QT = core testlib
+QT = core core-private testlib
SOURCES = tst_qtendian.cpp
diff --git a/tests/auto/corelib/global/qtendian/tst_qtendian.cpp b/tests/auto/corelib/global/qtendian/tst_qtendian.cpp
index 915e40954b..6934818dcf 100644
--- a/tests/auto/corelib/global/qtendian/tst_qtendian.cpp
+++ b/tests/auto/corelib/global/qtendian/tst_qtendian.cpp
@@ -29,6 +29,7 @@
#include <QtTest/QtTest>
#include <QtCore/qendian.h>
+#include <QtCore/private/qendian_p.h>
class tst_QtEndian: public QObject
@@ -41,6 +42,11 @@ private slots:
void toBigEndian();
void toLittleEndian();
+
+ void endianIntegers_data();
+ void endianIntegers();
+
+ void endianBitfields();
};
struct TestData
@@ -129,5 +135,83 @@ void tst_QtEndian::toLittleEndian()
#undef ENDIAN_TEST
+void tst_QtEndian::endianIntegers_data()
+{
+ QTest::addColumn<int>("val");
+
+ QTest::newRow("-30000") << -30000;
+ QTest::newRow("-1") << -1;
+ QTest::newRow("0") << 0;
+ QTest::newRow("1020") << 1020;
+ QTest::newRow("16385") << 16385;
+}
+
+void tst_QtEndian::endianIntegers()
+{
+ QFETCH(int, val);
+
+ qint16 vi16 = val;
+ qint32 vi32 = val;
+ qint64 vi64 = val;
+ quint16 vu16 = val;
+ quint32 vu32 = val;
+ quint64 vu64 = val;
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ QCOMPARE(*reinterpret_cast<qint16_be*>(&vi16), vi16);
+ QCOMPARE(*reinterpret_cast<qint32_be*>(&vi32), vi32);
+ QCOMPARE(*reinterpret_cast<qint64_be*>(&vi64), vi64);
+ QCOMPARE(*reinterpret_cast<qint16_le*>(&vi16), qbswap(vi16));
+ QCOMPARE(*reinterpret_cast<qint32_le*>(&vi32), qbswap(vi32));
+ QCOMPARE(*reinterpret_cast<qint64_le*>(&vi64), qbswap(vi64));
+ QCOMPARE(*reinterpret_cast<quint16_be*>(&vu16), vu16);
+ QCOMPARE(*reinterpret_cast<quint32_be*>(&vu32), vu32);
+ QCOMPARE(*reinterpret_cast<quint64_be*>(&vu64), vu64);
+ QCOMPARE(*reinterpret_cast<quint16_le*>(&vu16), qbswap(vu16));
+ QCOMPARE(*reinterpret_cast<quint32_le*>(&vu32), qbswap(vu32));
+ QCOMPARE(*reinterpret_cast<quint64_le*>(&vu64), qbswap(vu64));
+#else
+ QCOMPARE(*reinterpret_cast<qint16_be*>(&vi16), qbswap(vi16));
+ QCOMPARE(*reinterpret_cast<qint32_be*>(&vi32), qbswap(vi32));
+ QCOMPARE(*reinterpret_cast<qint64_be*>(&vi64), qbswap(vi64));
+ QCOMPARE(*reinterpret_cast<qint16_le*>(&vi16), vi16);
+ QCOMPARE(*reinterpret_cast<qint32_le*>(&vi32), vi32);
+ QCOMPARE(*reinterpret_cast<qint64_le*>(&vi64), vi64);
+ QCOMPARE(*reinterpret_cast<quint16_be*>(&vu16), qbswap(vu16));
+ QCOMPARE(*reinterpret_cast<quint32_be*>(&vu32), qbswap(vu32));
+ QCOMPARE(*reinterpret_cast<quint64_be*>(&vu64), qbswap(vu64));
+ QCOMPARE(*reinterpret_cast<quint16_le*>(&vu16), vu16);
+ QCOMPARE(*reinterpret_cast<quint32_le*>(&vu32), vu32);
+ QCOMPARE(*reinterpret_cast<quint64_le*>(&vu64), vu64);
+#endif
+}
+
+void tst_QtEndian::endianBitfields()
+{
+ union {
+ quint32_be_bitfield<21, 11> upper;
+ quint32_be_bitfield<10, 11> lower;
+ qint32_be_bitfield<0, 10> bottom;
+ } u;
+
+ u.upper = 200;
+ QCOMPARE(u.upper, 200U);
+ u.lower = 1000;
+ u.bottom = -8;
+ QCOMPARE(u.lower, 1000U);
+ QCOMPARE(u.upper, 200U);
+
+ u.lower += u.upper;
+ QCOMPARE(u.upper, 200U);
+ QCOMPARE(u.lower, 1200U);
+
+ u.upper = 65536 + 7;
+ u.lower = 65535;
+ QCOMPARE(u.lower, 65535U & ((1<<11) - 1));
+ QCOMPARE(u.upper, 7U);
+
+ QCOMPARE(u.bottom, -8);
+}
+
QTEST_MAIN(tst_QtEndian)
#include "tst_qtendian.moc"
diff --git a/tests/auto/corelib/io/io.pro b/tests/auto/corelib/io/io.pro
index 01ed84fda9..bd2a9f4c8e 100644
--- a/tests/auto/corelib/io/io.pro
+++ b/tests/auto/corelib/io/io.pro
@@ -34,12 +34,6 @@ SUBDIRS=\
qurl \
qurlinternal \
qurlquery \
- qwinoverlappedionotifier \
-
-!win32 {
- SUBDIRS -=\
- qwinoverlappedionotifier
-}
!qtHaveModule(gui): SUBDIRS -= \
qdatastream \
@@ -73,5 +67,4 @@ win32:!qtConfig(private_tests): SUBDIRS -= \
qprocess-noapplication
winrt: SUBDIRS -= \
- qstorageinfo \
- qwinoverlappedionotifier
+ qstorageinfo
diff --git a/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp b/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp
index ddfd14550b..1072cb44f9 100644
--- a/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp
+++ b/tests/auto/corelib/io/qabstractfileengine/tst_qabstractfileengine.cpp
@@ -341,8 +341,10 @@ public:
if (file) {
QMutexLocker lock(&file->mutex);
switch (time) {
- case CreationTime:
- return file->creation;
+ case BirthTime:
+ return file->birth;
+ case MetadataChangeTime:
+ return file->change;
case ModificationTime:
return file->modification;
case AccessTime:
@@ -353,6 +355,13 @@ public:
return QDateTime();
}
+ bool setFileTime(const QDateTime &newDate, FileTime time)
+ {
+ Q_UNUSED(newDate);
+ Q_UNUSED(time);
+ return false;
+ }
+
void setFileName(const QString &file)
{
if (openForRead_ || openForWrite_)
@@ -449,7 +458,7 @@ protected:
uint userId, groupId;
QAbstractFileEngine::FileFlags fileFlags;
- QDateTime creation, modification, access;
+ QDateTime birth, change, modification, access;
QByteArray content;
};
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
index 7147405f3b..b43ea7cfa5 100644
--- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
+++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp
@@ -51,6 +51,7 @@ private slots:
void qDebugQChar() const;
void qDebugQString() const;
void qDebugQStringRef() const;
+ void qDebugQStringView() const;
void qDebugQLatin1String() const;
void qDebugQByteArray() const;
void qDebugQFlags() const;
@@ -492,6 +493,46 @@ void tst_QDebug::qDebugQStringRef() const
}
}
+void tst_QDebug::qDebugQStringView() const
+{
+ /* Use a basic string. */
+ {
+ QLatin1String file, function;
+ int line = 0;
+ const QStringView inView = QStringViewLiteral("input");
+
+ MessageHandlerSetter mhs(myMessageHandler);
+ { qDebug() << inView; }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = QLatin1String(__FILE__); line = __LINE__ - 2; function = QLatin1String(Q_FUNC_INFO);
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QLatin1String("\"input\""));
+ QCOMPARE(QLatin1String(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QLatin1String(s_function), function);
+ }
+
+ /* Use a null QStringView. */
+ {
+ QString file, function;
+ int line = 0;
+
+ const QStringView inView;
+
+ MessageHandlerSetter mhs(myMessageHandler);
+ { qDebug() << inView; }
+#ifndef QT_NO_MESSAGELOGCONTEXT
+ file = __FILE__; line = __LINE__ - 2; function = Q_FUNC_INFO;
+#endif
+ QCOMPARE(s_msgType, QtDebugMsg);
+ QCOMPARE(s_msg, QLatin1String("\"\""));
+ QCOMPARE(QLatin1String(s_file), file);
+ QCOMPARE(s_line, line);
+ QCOMPARE(QLatin1String(s_function), function);
+ }
+}
+
void tst_QDebug::qDebugQLatin1String() const
{
QString file, function;
diff --git a/tests/auto/corelib/io/qfile/tst_qfile.cpp b/tests/auto/corelib/io/qfile/tst_qfile.cpp
index 32165ad2b8..54d089f3bb 100644
--- a/tests/auto/corelib/io/qfile/tst_qfile.cpp
+++ b/tests/auto/corelib/io/qfile/tst_qfile.cpp
@@ -2086,6 +2086,7 @@ public:
uint ownerId(FileOwner) const { return 0; }
QString owner(FileOwner) const { return QString(); }
QDateTime fileTime(FileTime) const { return QDateTime(); }
+ bool setFileTime(const QDateTime &newDate, FileTime time) { return false; }
private:
int number;
diff --git a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
index 87b579bb2b..94273e2394 100644
--- a/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/corelib/io/qfileinfo/tst_qfileinfo.cpp
@@ -35,6 +35,7 @@
#include <qtemporarydir.h>
#include <qdir.h>
#include <qfileinfo.h>
+#include <qstorageinfo.h>
#ifdef Q_OS_UNIX
#include <errno.h>
#include <fcntl.h>
@@ -64,84 +65,38 @@
#define Q_NO_SYMLINKS
#endif
-
-#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
-inline bool qt_isEvilFsTypeName(const char *name)
-{
- return (qstrncmp(name, "nfs", 3) == 0
- || qstrncmp(name, "autofs", 6) == 0
- || qstrncmp(name, "cachefs", 7) == 0);
-}
-
-#if defined(Q_OS_BSD4) && !defined(Q_OS_NETBSD)
-# include <sys/param.h>
-# include <sys/mount.h>
-
-bool qIsLikelyToBeNfs(int handle)
-{
- struct statfs buf;
- if (fstatfs(handle, &buf) != 0)
- return false;
- return qt_isEvilFsTypeName(buf.f_fstypename);
-}
-
-#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
-
-# include <sys/vfs.h>
-# ifdef QT_LINUXBASE
- // LSB 3.2 has fstatfs in sys/statfs.h, sys/vfs.h is just an empty dummy header
-# include <sys/statfs.h>
-# endif
-
-# ifndef NFS_SUPER_MAGIC
-# define NFS_SUPER_MAGIC 0x00006969
-# endif
-# ifndef AUTOFS_SUPER_MAGIC
-# define AUTOFS_SUPER_MAGIC 0x00000187
-# endif
-# ifndef AUTOFSNG_SUPER_MAGIC
-# define AUTOFSNG_SUPER_MAGIC 0x7d92b1a0
-# endif
-
-bool qIsLikelyToBeNfs(int handle)
+inline bool qIsLikelyToBeFat(const QString &path)
{
- struct statfs buf;
- if (fstatfs(handle, &buf) != 0)
- return false;
- return buf.f_type == NFS_SUPER_MAGIC
- || buf.f_type == AUTOFS_SUPER_MAGIC
- || buf.f_type == AUTOFSNG_SUPER_MAGIC;
+ QByteArray name = QStorageInfo(path).fileSystemType().toLower();
+ return name.contains("fat") || name.contains("msdos");
}
-#elif defined(Q_OS_SOLARIS) || defined(Q_OS_IRIX) || defined(Q_OS_AIX) || defined(Q_OS_HPUX) \
- || defined(Q_OS_OSF) || defined(Q_OS_QNX) || defined(Q_OS_SCO) \
- || defined(Q_OS_UNIXWARE) || defined(Q_OS_RELIANT) || defined(Q_OS_NETBSD)
-
-# include <sys/statvfs.h>
-
-bool qIsLikelyToBeNfs(int handle)
+inline bool qIsLikelyToBeNfs(const QString &path)
{
- struct statvfs buf;
- if (fstatvfs(handle, &buf) != 0)
- return false;
-#if defined(Q_OS_NETBSD)
- return qt_isEvilFsTypeName(buf.f_fstypename);
+#ifdef Q_OS_WIN
+ Q_UNUSED(path);
+ return false;
#else
- return qt_isEvilFsTypeName(buf.f_basetype);
+ QByteArray type = QStorageInfo(path).fileSystemType();
+ const char *name = type.constData();
+
+ return (qstrncmp(name, "nfs", 3) == 0
+ || qstrncmp(name, "autofs", 6) == 0
+ || qstrncmp(name, "autofsng", 8) == 0
+ || qstrncmp(name, "cachefs", 7) == 0);
#endif
}
-#else
-inline bool qIsLikelyToBeNfs(int /* handle */)
-{
- return false;
-}
-#endif
-#endif
static QString seedAndTemplate()
{
- qsrand(QDateTime::currentSecsSinceEpoch());
- return QDir::tempPath() + "/tst_qfileinfo-XXXXXX";
+ QString base;
+#if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID)
+ // use XDG_RUNTIME_DIR as it's a fully-capable FS
+ base = QStandardPaths::writableLocation(QStandardPaths::RuntimeLocation);
+#endif
+ if (base.isEmpty())
+ base = QDir::tempPath();
+ return base + "/tst_qfileinfo-XXXXXX";
}
static QByteArray msgDoesNotExist(const QString &name)
@@ -1034,6 +989,11 @@ void tst_QFileInfo::systemFiles()
QVERIFY2(fi.exists(), msgDoesNotExist(fi.absoluteFilePath()).constData());
QVERIFY(fi.size() > 0);
QVERIFY(fi.lastModified().isValid());
+ QVERIFY(fi.metadataChangeTime().isValid());
+ QCOMPARE(fi.metadataChangeTime(), fi.lastModified()); // On Windows, they're the same
+ QVERIFY(fi.birthTime().isValid());
+ QVERIFY(fi.birthTime() <= fi.lastModified());
+ QCOMPARE(fi.created(), fi.birthTime()); // On Windows, they're the same
}
void tst_QFileInfo::compare_data()
@@ -1124,43 +1084,92 @@ void tst_QFileInfo::fileTimes_data()
void tst_QFileInfo::fileTimes()
{
- int sleepTime = 2000;
+ auto datePairString = [](const QDateTime &actual, const QDateTime &before) {
+ return (actual.toString(Qt::ISODateWithMs) + " (should be >) " + before.toString(Qt::ISODateWithMs))
+ .toLatin1();
+ };
+
QFETCH(QString, fileName);
+ int sleepTime = 100;
+
+ // on Linux and Windows, the filesystem timestamps may be slightly out of
+ // sync with the system clock (maybe they're using CLOCK_REALTIME_COARSE),
+ // so add a margin of error to our comparisons
+ int fsClockSkew = 10;
+#ifdef Q_OS_WIN
+ fsClockSkew = 500;
+#endif
+
+ // NFS clocks may be WAY out of sync
+ if (qIsLikelyToBeNfs(fileName))
+ QSKIP("This test doesn't work on NFS");
+
+ bool noAccessTime = false;
+ {
+ // try to guess if file times on this filesystem round to the second
+ QFileInfo cwd(".");
+ if (cwd.lastModified().toMSecsSinceEpoch() % 1000 == 0
+ && cwd.lastRead().toMSecsSinceEpoch() % 1000 == 0) {
+ fsClockSkew = sleepTime = 1000;
+
+ noAccessTime = qIsLikelyToBeFat(fileName);
+ if (noAccessTime) {
+ // FAT filesystems (but maybe not exFAT) store timestamps with 2-second
+ // granularity and access time with 1-day granularity
+ fsClockSkew = sleepTime = 2000;
+ }
+ }
+ }
+
if (QFile::exists(fileName)) {
QVERIFY(QFile::remove(fileName));
}
- QTest::qSleep(sleepTime);
+
+ QDateTime beforeBirth, beforeWrite, beforeMetadataChange, beforeRead;
+ QDateTime birthTime, writeTime, metadataChangeTime, readTime;
+
+ // --- Create file and write to it
+ beforeBirth = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
{
QFile file(fileName);
QVERIFY(file.open(QFile::WriteOnly | QFile::Text));
-#if defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
- if (qIsLikelyToBeNfs(file.handle()))
- QSKIP("This Test doesn't work on NFS");
-#endif
+ QFileInfo fileInfo(fileName);
+ birthTime = fileInfo.birthTime();
+ QVERIFY2(!birthTime.isValid() || birthTime > beforeBirth,
+ datePairString(birthTime, beforeBirth));
+
+ QTest::qSleep(sleepTime);
+ beforeWrite = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
QTextStream ts(&file);
ts << fileName << endl;
}
- QTest::qSleep(sleepTime);
- QDateTime beforeWrite = QDateTime::currentDateTime();
- QTest::qSleep(sleepTime);
{
QFileInfo fileInfo(fileName);
- QVERIFY(fileInfo.created() < beforeWrite);
- QFile file(fileName);
- QVERIFY(file.open(QFile::ReadWrite | QFile::Text));
- QTextStream ts(&file);
- ts << fileName << endl;
+ writeTime = fileInfo.lastModified();
+ QVERIFY2(writeTime > beforeWrite, datePairString(writeTime, beforeWrite));
+ QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
}
+
+ // --- Change the file's metadata
QTest::qSleep(sleepTime);
- QDateTime beforeRead = QDateTime::currentDateTime();
- QTest::qSleep(sleepTime);
+ beforeMetadataChange = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
+ {
+ QFile file(fileName);
+ file.setPermissions(file.permissions());
+ }
{
QFileInfo fileInfo(fileName);
-// On unix created() returns the same as lastModified().
-#if !defined(Q_OS_UNIX)
- QVERIFY(fileInfo.created() < beforeWrite);
-#endif
- QVERIFY(fileInfo.lastModified() > beforeWrite);
+ metadataChangeTime = fileInfo.metadataChangeTime();
+ QVERIFY2(metadataChangeTime > beforeMetadataChange,
+ datePairString(metadataChangeTime, beforeMetadataChange));
+ QVERIFY(metadataChangeTime >= writeTime); // not all filesystems can store both times
+ QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
+ }
+
+ // --- Read the file
+ QTest::qSleep(sleepTime);
+ beforeRead = QDateTime::currentDateTime().addMSecs(-fsClockSkew);
+ {
QFile file(fileName);
QVERIFY(file.open(QFile::ReadOnly | QFile::Text));
QTextStream ts(&file);
@@ -1169,13 +1178,17 @@ void tst_QFileInfo::fileTimes()
}
QFileInfo fileInfo(fileName);
-#if !defined(Q_OS_UNIX)
- QVERIFY(fileInfo.created() < beforeWrite);
-#endif
+ readTime = fileInfo.lastRead();
+ QCOMPARE(fileInfo.lastModified(), writeTime); // mustn't have changed
+ QCOMPARE(fileInfo.birthTime(), birthTime); // mustn't have changed
+ QVERIFY(readTime.isValid());
+
+#if defined(Q_OS_WINRT) || defined(Q_OS_QNX) || defined(Q_OS_ANDROID)
+ noAccessTime = true;
+#elif defined(Q_OS_WIN)
//In Vista the last-access timestamp is not updated when the file is accessed/touched (by default).
//To enable this the HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisableLastAccessUpdate
//is set to 0, in the test machine.
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
HKEY key;
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SYSTEM\\CurrentControlSet\\Control\\FileSystem",
0, KEY_READ, &key)) {
@@ -1184,75 +1197,43 @@ void tst_QFileInfo::fileTimes()
LONG error = RegQueryValueEx(key, L"NtfsDisableLastAccessUpdate"
, NULL, NULL, (LPBYTE)&disabledAccessTimes, &size);
if (ERROR_SUCCESS == error && disabledAccessTimes)
- QEXPECT_FAIL("", "File access times are disabled in windows registry (this is the default setting)", Continue);
+ noAccessTime = true;
RegCloseKey(key);
}
#endif
-#if defined(Q_OS_WINRT)
- QEXPECT_FAIL("", "WinRT does not allow timestamp handling change in the filesystem due to sandboxing", Continue);
-#elif defined(Q_OS_QNX)
- QEXPECT_FAIL("", "QNX uses the noatime filesystem option", Continue);
-#elif defined(Q_OS_ANDROID)
- if (fileInfo.lastRead() <= beforeRead)
- QEXPECT_FAIL("", "Android may use relatime or noatime on mounts", Continue);
-#endif
- QVERIFY(fileInfo.lastRead() > beforeRead);
- QVERIFY(fileInfo.lastModified() > beforeWrite);
- QVERIFY(fileInfo.lastModified() < beforeRead);
+ if (noAccessTime)
+ return;
+
+ QVERIFY2(readTime > beforeRead, datePairString(readTime, beforeRead));
+ QVERIFY(writeTime < beforeRead);
}
void tst_QFileInfo::fileTimes_oldFile()
{
- // This is not supported on WinRT
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
- // All files are opened in share mode (both read and write).
- DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
-
- // All files on Windows can be read; there's no such thing as an
- // unreadable file. Add GENERIC_WRITE if WriteOnly is passed.
- int accessRights = GENERIC_READ | GENERIC_WRITE;
-
- SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
-
- // Regular file mode. In Unbuffered mode, pass the no-buffering flag.
- DWORD flagsAndAtts = FILE_ATTRIBUTE_NORMAL;
-
- // WriteOnly can create files, ReadOnly cannot.
- DWORD creationDisp = OPEN_ALWAYS;
-
- // Create the file handle.
- HANDLE fileHandle = CreateFile(L"oldfile.txt",
- accessRights,
- shareMode,
- &securityAtts,
- creationDisp,
- flagsAndAtts,
- NULL);
-
- // Set file times back to 1601.
- SYSTEMTIME stime;
- stime.wYear = 1601;
- stime.wMonth = 1;
- stime.wDayOfWeek = 1;
- stime.wDay = 1;
- stime.wHour = 1;
- stime.wMinute = 0;
- stime.wSecond = 0;
- stime.wMilliseconds = 0;
-
- FILETIME ctime;
- QVERIFY(SystemTimeToFileTime(&stime, &ctime));
- FILETIME atime = ctime;
- FILETIME mtime = atime;
- QVERIFY(fileHandle);
- QVERIFY(SetFileTime(fileHandle, &ctime, &atime, &mtime) != 0);
-
- CloseHandle(fileHandle);
-
- QFileInfo info("oldfile.txt");
- QCOMPARE(info.lastModified(), QDateTime(QDate(1601, 1, 1), QTime(1, 0), Qt::UTC).toLocalTime());
-#endif
+ // This is 2^{31} seconds before 1970-01-01 15:14:8,
+ // i.e. shortly after the start of time_t, in any time-zone:
+ const QDateTime early(QDate(1901, 12, 14), QTime(12, 0));
+ QFile file("ancientfile.txt");
+ file.open(QIODevice::WriteOnly);
+ file.write("\n", 1);
+ file.close();
+
+ /*
+ QFile's setFileTime calls QFSFileEngine::setFileTime() which fails unless
+ the file is open at the time. Of course, when writing, close() changes
+ modification time, so need to re-open for read in order to setFileTime().
+ */
+ file.open(QIODevice::ReadOnly);
+ bool ok = file.setFileTime(early, QFileDevice::FileModificationTime);
+ file.close();
+
+ if (ok) {
+ QFileInfo info(file.fileName());
+ QCOMPARE(info.lastModified(), early);
+ } else {
+ QSKIP("Unable to set file metadata to ancient values");
+ }
}
void tst_QFileInfo::isSymLink_data()
@@ -1927,6 +1908,8 @@ void tst_QFileInfo::invalidState()
info.setCaching(false);
info.created();
+ info.birthTime();
+ info.metadataChangeTime();
info.lastRead();
info.lastModified();
}
@@ -1939,6 +1922,8 @@ void tst_QFileInfo::invalidState()
info.setCaching(false);
info.created();
+ info.birthTime();
+ info.metadataChangeTime();
info.lastRead();
info.lastModified();
}
@@ -1951,6 +1936,8 @@ void tst_QFileInfo::invalidState()
info.setCaching(false);
info.created();
+ info.birthTime();
+ info.metadataChangeTime();
info.lastRead();
info.lastModified();
}
@@ -1963,6 +1950,8 @@ void tst_QFileInfo::nonExistingFileDates()
QFileInfo info("non-existing-file.foobar");
QVERIFY(!info.exists());
QVERIFY(!info.created().isValid());
+ QVERIFY(!info.birthTime().isValid());
+ QVERIFY(!info.metadataChangeTime().isValid());
QVERIFY(!info.lastRead().isValid());
QVERIFY(!info.lastModified().isValid());
}
diff --git a/tests/auto/corelib/io/qfilesystemmetadata/tst_qfilesystemmetadata.cpp b/tests/auto/corelib/io/qfilesystemmetadata/tst_qfilesystemmetadata.cpp
index 1c104688a5..ea4da39cd5 100644
--- a/tests/auto/corelib/io/qfilesystemmetadata/tst_qfilesystemmetadata.cpp
+++ b/tests/auto/corelib/io/qfilesystemmetadata/tst_qfilesystemmetadata.cpp
@@ -66,14 +66,16 @@ void tst_QFileSystemMetaData::timeSinceEpoch()
/* data.ftLastAccessTime = data.ftLastWriteTime = */
data.ftCreationTime = epochToFileTime(afterEpochUtc);
meta.fillFromFindData(data);
+ QCOMPARE(meta.birthTime().toUTC(),
+ QDateTime::fromMSecsSinceEpoch(afterEpochUtc * qint64(1000), Qt::UTC));
#else
QT_STATBUF data;
memset(&data, 0, sizeof(data));
data.st_ctime = afterEpochUtc;
meta.fillFromStatBuf(data);
-#endif
- QCOMPARE(meta.creationTime().toUTC(),
+ QCOMPARE(meta.metadataChangeTime().toUTC(),
QDateTime::fromMSecsSinceEpoch(afterEpochUtc * qint64(1000), Qt::UTC));
+#endif
}
#else // i.e. no Q_AUTOTEST_EXPORT
void tst_QFileSystemMetaData::timeSinceEpoch()
diff --git a/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp b/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp
index b0acb1c58d..b78fa29fb6 100644
--- a/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp
+++ b/tests/auto/corelib/io/qnodebug/tst_qnodebug.cpp
@@ -64,7 +64,7 @@ void tst_QNoDebug::noDebugOutput() const
void tst_QNoDebug::streaming() const
{
QDateTime dt(QDate(1,2,3),QTime(4,5,6));
- const QByteArray debugString = dt.toString(QStringLiteral("yyyy-MM-dd HH:mm:ss.zzz t")).toLatin1();
+ const QByteArray debugString = dt.toString(QStringViewLiteral("yyyy-MM-dd HH:mm:ss.zzz t")).toLatin1();
const QByteArray message = "QDateTime(" + debugString + " Qt::TimeSpec(LocalTime))";
QTest::ignoreMessage(QtWarningMsg, message.constData());
qWarning() << dt;
diff --git a/tests/auto/corelib/io/qprocess/testDetached/main.cpp b/tests/auto/corelib/io/qprocess/testDetached/main.cpp
index 702cabe873..c10e32d584 100644
--- a/tests/auto/corelib/io/qprocess/testDetached/main.cpp
+++ b/tests/auto/corelib/io/qprocess/testDetached/main.cpp
@@ -40,32 +40,89 @@
#include <windows.h>
#endif
+static void writeStuff(QFile &f)
+{
+ f.write(QDir::currentPath().toUtf8());
+ f.putChar('\n');
+#if defined(Q_OS_UNIX)
+ f.write(QByteArray::number(quint64(getpid())));
+#elif defined(Q_OS_WIN)
+ f.write(QByteArray::number(quint64(GetCurrentProcessId())));
+#endif
+ f.putChar('\n');
+ f.write(qgetenv("tst_QProcess"));
+ f.putChar('\n');
+}
+
+struct Args
+{
+ int exitCode = 0;
+ QByteArray errorMessage;
+ QString fileName;
+ FILE *channel = nullptr;
+ QByteArray channelName;
+};
+
+static Args parseArguments(const QStringList &args)
+{
+ Args result;
+ if (args.count() < 2) {
+ result.exitCode = 128;
+ result.errorMessage = "Usage: testDetached [--out-channel={stdout|stderr}] filename.txt\n";
+ return result;
+ }
+ for (const QString &arg : args) {
+ if (arg.startsWith("--")) {
+ if (!arg.startsWith("--out-channel=")) {
+ result.exitCode = 2;
+ result.errorMessage = "Unknown argument " + arg.toLocal8Bit();
+ return result;
+ }
+ result.channelName = arg.mid(14).toLocal8Bit();
+ if (result.channelName == "stdout") {
+ result.channel = stdout;
+ } else if (result.channelName == "stderr") {
+ result.channel = stderr;
+ } else {
+ result.exitCode = 3;
+ result.errorMessage = "Unknown channel " + result.channelName;
+ return result;
+ }
+ } else {
+ result.fileName = arg;
+ }
+ }
+ return result;
+}
+
int main(int argc, char **argv)
{
QCoreApplication app(argc, argv);
- QStringList args = app.arguments();
- if (args.count() != 2) {
- fprintf(stderr, "Usage: testDetached filename.txt\n");
- return 128;
+ const Args args = parseArguments(app.arguments());
+ if (args.exitCode) {
+ fprintf(stderr, "testDetached: %s\n", args.errorMessage.constData());
+ return args.exitCode;
}
- QFile f(args.at(1));
+ if (args.channel) {
+ QFile channel;
+ if (!channel.open(args.channel, QIODevice::WriteOnly | QIODevice::Text)) {
+ fprintf(stderr, "Cannot open channel %s for writing: %s\n",
+ qPrintable(args.channelName), qPrintable(channel.errorString()));
+ return 4;
+ }
+ writeStuff(channel);
+ }
+
+ QFile f(args.fileName);
if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
fprintf(stderr, "Cannot open %s for writing: %s\n",
qPrintable(f.fileName()), qPrintable(f.errorString()));
return 1;
}
- f.write(QDir::currentPath().toUtf8());
- f.putChar('\n');
-#if defined(Q_OS_UNIX)
- f.write(QByteArray::number(quint64(getpid())));
-#elif defined(Q_OS_WIN)
- f.write(QByteArray::number(quint64(GetCurrentProcessId())));
-#endif
- f.putChar('\n');
-
+ writeStuff(f);
f.close();
return 0;
diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
index f4d6d5cb40..de6eb28503 100644
--- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
+++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp
@@ -127,7 +127,8 @@ private slots:
void systemEnvironment();
void lockupsInStartDetached();
void waitForReadyReadForNonexistantProcess();
- void detachedWorkingDirectoryAndPid();
+ void detachedProcessParameters_data();
+ void detachedProcessParameters();
void startFinishStartFinish();
void invalidProgramString_data();
void invalidProgramString();
@@ -2072,21 +2073,54 @@ void tst_QProcess::fileWriterProcess()
} while (stopWatch.elapsed() < 3000);
}
-void tst_QProcess::detachedWorkingDirectoryAndPid()
+void tst_QProcess::detachedProcessParameters_data()
{
+ QTest::addColumn<QString>("outChannel");
+ QTest::newRow("none") << QString();
+ QTest::newRow("stdout") << QString("stdout");
+ QTest::newRow("stderr") << QString("stderr");
+}
+
+void tst_QProcess::detachedProcessParameters()
+{
+ QFETCH(QString, outChannel);
qint64 pid;
QFile infoFile(m_temporaryDir.path() + QLatin1String("/detachedinfo.txt"));
if (infoFile.exists())
QVERIFY(infoFile.remove());
+ QFile channelFile(m_temporaryDir.path() + QLatin1String("detachedinfo2.txt"));
+ if (channelFile.exists())
+ QVERIFY(channelFile.remove());
QString workingDir = QDir::currentPath() + "/testDetached";
QVERIFY(QFile::exists(workingDir));
- QStringList args;
- args << infoFile.fileName();
- QVERIFY(QProcess::startDetached(QDir::currentPath() + QLatin1String("/testDetached/testDetached"), args, workingDir, &pid));
+ QVERIFY(qgetenv("tst_QProcess").isEmpty());
+ QByteArray envVarValue("foobarbaz");
+ QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
+ environment.insert(QStringLiteral("tst_QProcess"), QString::fromUtf8(envVarValue));
+
+ QProcess process;
+ process.setProgram(QDir::currentPath() + QLatin1String("/testDetached/testDetached"));
+#ifdef Q_OS_WIN
+ int modifierCalls = 0;
+ process.setCreateProcessArgumentsModifier(
+ [&modifierCalls] (QProcess::CreateProcessArguments *) { modifierCalls++; });
+#endif
+ QStringList args(infoFile.fileName());
+ if (!outChannel.isEmpty()) {
+ args << QStringLiteral("--out-channel=") + outChannel;
+ if (outChannel == "stdout")
+ process.setStandardOutputFile(channelFile.fileName());
+ else if (outChannel == "stderr")
+ process.setStandardErrorFile(channelFile.fileName());
+ }
+ process.setArguments(args);
+ process.setWorkingDirectory(workingDir);
+ process.setProcessEnvironment(environment);
+ QVERIFY(process.startDetached(&pid));
QFileInfo fi(infoFile);
fi.setCaching(false);
@@ -2097,19 +2131,35 @@ void tst_QProcess::detachedWorkingDirectoryAndPid()
}
QVERIFY(infoFile.open(QIODevice::ReadOnly | QIODevice::Text));
- QString actualWorkingDir = QString::fromUtf8(infoFile.readLine());
- actualWorkingDir.chop(1); // strip off newline
- QByteArray processIdString = infoFile.readLine();
- processIdString.chop(1);
+ QString actualWorkingDir = QString::fromUtf8(infoFile.readLine()).trimmed();
+ QByteArray processIdString = infoFile.readLine().trimmed();
+ QByteArray actualEnvVarValue = infoFile.readLine().trimmed();
+ QByteArray infoFileContent;
+ if (!outChannel.isEmpty()) {
+ infoFile.seek(0);
+ infoFileContent = infoFile.readAll();
+ }
infoFile.close();
infoFile.remove();
+ if (!outChannel.isEmpty()) {
+ QVERIFY(channelFile.open(QIODevice::ReadOnly | QIODevice::Text));
+ QByteArray channelContent = channelFile.readAll();
+ channelFile.close();
+ channelFile.remove();
+ QCOMPARE(channelContent, infoFileContent);
+ }
+
bool ok = false;
qint64 actualPid = processIdString.toLongLong(&ok);
QVERIFY(ok);
QCOMPARE(actualWorkingDir, workingDir);
QCOMPARE(actualPid, pid);
+ QCOMPARE(actualEnvVarValue, envVarValue);
+#ifdef Q_OS_WIN
+ QCOMPARE(modifierCalls, 1);
+#endif
}
void tst_QProcess::switchReadChannels()
diff --git a/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp b/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp
index 9573f3078b..96970421d3 100644
--- a/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp
+++ b/tests/auto/corelib/io/qsavefile/tst_qsavefile.cpp
@@ -82,6 +82,11 @@ private slots:
void transactionalWriteErrorRenaming();
void symlink();
void directory();
+
+#ifdef Q_OS_WIN
+ void alternateDataStream_data();
+ void alternateDataStream();
+#endif
};
static inline QByteArray msgCannotOpen(const QFileDevice &f)
@@ -474,5 +479,60 @@ void tst_QSaveFile::directory()
#endif
}
+#ifdef Q_OS_WIN
+void tst_QSaveFile::alternateDataStream_data()
+{
+ QTest::addColumn<bool>("directWriteFallback");
+ QTest::addColumn<bool>("success");
+
+ QTest::newRow("default") << false << false;
+ QTest::newRow("directWriteFallback") << true << true;
+}
+
+void tst_QSaveFile::alternateDataStream()
+{
+ QFETCH(bool, directWriteFallback);
+ QFETCH(bool, success);
+ static const char newContent[] = "New content\r\n";
+
+ QTemporaryDir dir;
+ QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
+ QString baseName = dir.path() + QLatin1String("/base");
+ {
+ QFile baseFile(baseName);
+ QVERIFY2(baseFile.open(QIODevice::ReadWrite), qPrintable(baseFile.errorString()));
+ }
+
+ // First, create a file with old content
+ QString adsName = baseName + QLatin1String(":outfile");
+ {
+ QFile targetFile(adsName);
+ if (!targetFile.open(QIODevice::ReadWrite))
+ QSKIP("Failed to ceate ADS file (" + targetFile.errorString().toUtf8()
+ + "). Temp dir is FAT?");
+ targetFile.write("Old content\r\n");
+ }
+
+ // And write to it again using QSaveFile; only works if directWriteFallback is enabled
+ QSaveFile file(adsName);
+ file.setDirectWriteFallback(directWriteFallback);
+ QCOMPARE(file.directWriteFallback(), directWriteFallback);
+
+ if (success) {
+ QVERIFY2(file.open(QIODevice::WriteOnly), qPrintable(file.errorString()));
+ file.write(newContent);
+ QVERIFY2(file.commit(), qPrintable(file.errorString()));
+
+ // check the contents
+ QFile targetFile(adsName);
+ QVERIFY2(targetFile.open(QIODevice::ReadOnly), qPrintable(targetFile.errorString()));
+ QByteArray contents = targetFile.readAll();
+ QCOMPARE(contents, QByteArray(newContent));
+ } else {
+ QVERIFY(!file.open(QIODevice::WriteOnly));
+ }
+}
+#endif
+
QTEST_MAIN(tst_QSaveFile)
#include "tst_qsavefile.moc"
diff --git a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
index 332c2dcc01..012ce5f2f5 100644
--- a/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
+++ b/tests/auto/corelib/io/qsettings/tst_qsettings.cpp
@@ -118,6 +118,10 @@ private slots:
void remove();
void contains();
void sync();
+ void syncNonWriteableDir();
+#ifdef Q_OS_WIN
+ void syncAlternateDataStream();
+#endif
void setFallbacksEnabled();
void setFallbacksEnabled_data();
void fromFile_data();
@@ -1750,6 +1754,78 @@ void tst_QSettings::sync()
QCOMPARE(settings1.allKeys().count(), 11);
}
+void tst_QSettings::syncNonWriteableDir()
+{
+ QTemporaryDir tempDir;
+ QVERIFY2(tempDir.isValid(), qUtf8Printable(tempDir.errorString()));
+
+ // first, create a file
+ QString filename = tempDir.path() + "/config.ini";
+ {
+ QFile f(filename);
+ QVERIFY2(f.open(QIODevice::WriteOnly), qUtf8Printable(f.errorString()));
+ }
+
+ // second, make the dir unwriteable
+ QVERIFY(QFile::setPermissions(tempDir.path(), QFile::ReadUser | QFile::ExeUser));
+ struct UndoSetPermissions {
+ QString name;
+ UndoSetPermissions(const QString &name) : name(name) {}
+ ~UndoSetPermissions()
+ { QFile::setPermissions(name, QFile::ReadUser | QFile::WriteUser | QFile::ExeUser); }
+ };
+ UndoSetPermissions undo(tempDir.path()); // otherwise, QTemporaryDir will fail
+
+ {
+ QSettings settings(filename, QSettings::IniFormat);
+ QVERIFY(settings.isAtomicSyncRequired());
+ settings.setAtomicSyncRequired(false);
+ settings.setValue("alpha/beta", 1);
+ settings.sync();
+ QCOMPARE(settings.status(), QSettings::NoError);
+ }
+
+ QVERIFY(QFileInfo(filename).size() != 0);
+ QSettings settings(filename, QSettings::IniFormat);
+ QCOMPARE(settings.value("alpha/beta"), QVariant(1));
+}
+
+#ifdef Q_OS_WIN
+void tst_QSettings::syncAlternateDataStream()
+{
+ QTemporaryDir tempDir;
+ QVERIFY2(tempDir.isValid(), qUtf8Printable(tempDir.errorString()));
+
+ // first, create a file
+ QString filename = tempDir.path() + "/file";
+ {
+ QFile f(filename);
+ QVERIFY2(f.open(QIODevice::WriteOnly), qUtf8Printable(f.errorString()));
+ }
+
+ // then create an ADS
+ filename += ":config.ini";
+ {
+ QFile f(filename);
+ if (!f.open(QIODevice::WriteOnly))
+ QSKIP("Could not create ADS file (" + f.errorString().toUtf8() + ") - FAT drive?");
+ }
+
+ {
+ QSettings settings(filename, QSettings::IniFormat);
+ QVERIFY(settings.isAtomicSyncRequired());
+ settings.setAtomicSyncRequired(false);
+ settings.setValue("alpha/beta", 1);
+ settings.sync();
+ QCOMPARE(settings.status(), QSettings::NoError);
+ }
+
+ QVERIFY(QFileInfo(filename).size() != 0);
+ QSettings settings(filename, QSettings::IniFormat);
+ QCOMPARE(settings.value("alpha/beta"), QVariant(1));
+}
+#endif
+
void tst_QSettings::setFallbacksEnabled_data()
{
populateWithFormats();
diff --git a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
index 4bed8d0fd6..fcd9133099 100644
--- a/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
+++ b/tests/auto/corelib/io/qtemporarydir/tst_qtemporarydir.cpp
@@ -148,25 +148,24 @@ void tst_QTemporaryDir::fileTemplate_data()
{
QTest::addColumn<QString>("constructorTemplate");
QTest::addColumn<QString>("prefix");
+ QTest::addColumn<QString>("suffix");
+
+ QTest::newRow("default") << "" << "tst_qtemporarydir-" << "";
- QTest::newRow("constructor default") << "" << "tst_qtemporarydir-";
-
- QTest::newRow("constructor with xxx sufix") << "qt_XXXXXXxxx" << "qt_XXXXXXxxx";
- QTest::newRow("constructor with xXx sufix") << "qt_XXXXXXxXx" << "qt_XXXXXXxXx";
- QTest::newRow("constructor with no suffix") << "qt_XXXXXX" << "qt_";
- QTest::newRow("constructor with >6 X's, no suffix") << "qt_XXXXXXXXXX" << "qt_";
- // When more than 6 X are present at the end, linux and windows will only replace the last 6,
- // while Mac OS will actually replace all of them so we can only expect "qt_" (and check isValid).
- QTest::newRow("constructor with XXXX suffix") << "qt_XXXXXX_XXXX" << "qt_";
- QTest::newRow("constructor with XXXX prefix") << "qt_XXXX" << "qt_";
- QTest::newRow("constructor with XXXXX prefix") << "qt_XXXXX" << "qt_";
+ QTest::newRow("xxx-suffix") << "qt_XXXXXXxxx" << "qt_" << "xxx";
+ QTest::newRow("xXx-suffix") << "qt_XXXXXXxXx" << "qt_" << "xXx";
+ QTest::newRow("no-suffix") << "qt_XXXXXX" << "qt_" << "";
+ QTest::newRow("10X") << "qt_XXXXXXXXXX" << "qt_" << "";
+ QTest::newRow("4Xsuffix") << "qt_XXXXXX_XXXX" << "qt_" << "_XXXX";
+ QTest::newRow("4Xprefix") << "qt_XXXX" << "qt_XXXX" << "";
+ QTest::newRow("5Xprefix") << "qt_XXXXX" << "qt_XXXXX" << "";
if (canHandleUnicodeFileNames()) {
// Test Umlauts (contained in Latin1)
QString prefix = "qt_" + umlautTestText();
- QTest::newRow("Umlauts") << (prefix + "XXXXXX") << prefix;
- // Test Chinese
+ QTest::newRow("Umlauts") << (prefix + "XXXXXX") << prefix << "";
+ // test non-Latin1
prefix = "qt_" + hanTestText();
- QTest::newRow("Chinese characters") << (prefix + "XXXXXX") << prefix;
+ QTest::newRow("Chinese") << (prefix + "XXXXXX" + umlautTestText()) << prefix << umlautTestText();
}
}
@@ -174,14 +173,17 @@ void tst_QTemporaryDir::fileTemplate()
{
QFETCH(QString, constructorTemplate);
QFETCH(QString, prefix);
+ QFETCH(QString, suffix);
QTemporaryDir tempDir(constructorTemplate);
QVERIFY(tempDir.isValid());
QString dirName = QDir(tempDir.path()).dirName();
- if (prefix.length())
+ if (prefix.length()) {
QCOMPARE(dirName.left(prefix.length()), prefix);
+ QCOMPARE(dirName.right(suffix.length()), suffix);
+ }
}
diff --git a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
index 59cd3a8411..17bcde4992 100644
--- a/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
+++ b/tests/auto/corelib/io/qtemporaryfile/tst_qtemporaryfile.cpp
@@ -866,8 +866,6 @@ void tst_QTemporaryFile::guaranteeUnique()
// First pass. See which filename QTemporaryFile will try first.
{
- // Fix the random seed.
- qsrand(1135);
QTemporaryFile tmpFile("testFile1.XXXXXX");
tmpFile.open();
takenFileName = tmpFile.fileName();
@@ -881,8 +879,6 @@ void tst_QTemporaryFile::guaranteeUnique()
// Second pass, now we have blocked its first attempt with a directory.
{
- // Fix the random seed.
- qsrand(1135);
QTemporaryFile tmpFile("testFile1.XXXXXX");
QVERIFY(tmpFile.open());
QString uniqueFileName = tmpFile.fileName();
diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp
index c5647752fd..7eeaea564f 100644
--- a/tests/auto/corelib/io/qurl/tst_qurl.cpp
+++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp
@@ -1384,18 +1384,6 @@ void tst_QUrl::compat_constructor_01_data()
void tst_QUrl::compat_constructor_01()
{
- /* The following should work as expected:
- *
- * QUrlOperator op;
- * op.copy( QString( "Makefile" ),
- * QString("ftp://rms:grmpf12@nibbler/home/rms/tmp"),
- * false );
- *
- * as well as the following:
- *
- * QUrlOperator op;
- * op.copy(QString("ftp://ftp.qt-project.org/qt/INSTALL"), ".");
- */
QFETCH( QString, urlStr );
{
@@ -1425,11 +1413,6 @@ void tst_QUrl::compat_constructor_02_data()
void tst_QUrl::compat_constructor_02()
{
- /* The following should work as expected:
- *
- * QUrlOperator op( "ftp://ftp.qt-project.org/qt" );
- * op.copy(QString("INSTALL"), ".");
- */
QFETCH( QString, urlStr );
QFETCH( QString, fileName );
diff --git a/tests/auto/corelib/io/qwinoverlappedionotifier/qwinoverlappedionotifier.pro b/tests/auto/corelib/io/qwinoverlappedionotifier/qwinoverlappedionotifier.pro
deleted file mode 100644
index 4f0e9da3c2..0000000000
--- a/tests/auto/corelib/io/qwinoverlappedionotifier/qwinoverlappedionotifier.pro
+++ /dev/null
@@ -1,4 +0,0 @@
-CONFIG += testcase
-TARGET = tst_qwinoverlappedionotifier
-QT = core-private testlib
-SOURCES = tst_qwinoverlappedionotifier.cpp
diff --git a/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp b/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp
deleted file mode 100644
index 7034c2c9fd..0000000000
--- a/tests/auto/corelib/io/qwinoverlappedionotifier/tst_qwinoverlappedionotifier.cpp
+++ /dev/null
@@ -1,331 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL-EXCEPT$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 as published by the Free Software
-** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtTest/QtTest>
-#include <private/qwinoverlappedionotifier_p.h>
-#include <qbytearray.h>
-#include <qt_windows.h>
-
-#ifndef PIPE_REJECT_REMOTE_CLIENTS
-#define PIPE_REJECT_REMOTE_CLIENTS 0x08
-#endif
-
-class tst_QWinOverlappedIoNotifier : public QObject
-{
- Q_OBJECT
-
-private slots:
- void initTestCase();
- void readFile_data();
- void readFile();
- void waitForNotified_data();
- void waitForNotified();
- void waitForAnyNotified();
- void brokenPipe();
- void multipleOperations();
-
-private:
- QFileInfo sourceFileInfo;
- DWORD notifiedBytesRead;
- DWORD notifiedErrorCode;
-};
-
-class NotifierSink : public QObject
-{
- Q_OBJECT
-public:
- NotifierSink(QWinOverlappedIoNotifier *notifier)
- : QObject(notifier),
- threshold(1)
- {
- connect(notifier, &QWinOverlappedIoNotifier::notified, this, &NotifierSink::notified);
- }
-
-protected slots:
- void notified(DWORD bytesRead, DWORD errorCode, OVERLAPPED *overlapped)
- {
- IOResult ioResult;
- ioResult.bytes = bytesRead;
- ioResult.errorCode = errorCode;
- ioResult.overlapped = overlapped;
- notifications.append(ioResult);
- if (notifications.count() >= threshold)
- emit notificationReceived();
- }
-
-signals:
- void notificationReceived();
-
-public:
- int threshold;
-
- struct IOResult
- {
- IOResult()
- : bytes(0), errorCode(ERROR_SUCCESS), overlapped(0)
- {}
- DWORD bytes;
- DWORD errorCode;
- OVERLAPPED *overlapped;
- };
-
- QList<IOResult> notifications;
-};
-
-void tst_QWinOverlappedIoNotifier::initTestCase()
-{
- sourceFileInfo.setFile(QFINDTESTDATA("tst_qwinoverlappedionotifier.cpp"));
- QVERIFY2(sourceFileInfo.exists(), "File tst_qwinoverlappedionotifier.cpp not found.");
-}
-
-void tst_QWinOverlappedIoNotifier::readFile_data()
-{
- QTest::addColumn<QString>("fileName");
- QTest::addColumn<int>("readBufferSize");
- QTest::addColumn<DWORD>("expectedBytesRead");
-
- QString sourceFileName = QDir::toNativeSeparators(sourceFileInfo.absoluteFilePath());
- int sourceFileSize = sourceFileInfo.size();
-
- QTest::newRow("read file, less than available")
- << sourceFileName << sourceFileSize / 2 << DWORD(sourceFileSize / 2);
- QTest::newRow("read file, more than available")
- << sourceFileName << sourceFileSize * 2 << DWORD(sourceFileSize);
-}
-
-void tst_QWinOverlappedIoNotifier::readFile()
-{
- QFETCH(QString, fileName);
- QFETCH(int, readBufferSize);
- QFETCH(DWORD, expectedBytesRead);
-
- QWinOverlappedIoNotifier notifier;
- NotifierSink sink(&notifier);
- connect(&sink, &NotifierSink::notificationReceived, &QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
-
- HANDLE hFile = CreateFile(reinterpret_cast<const wchar_t*>(fileName.utf16()),
- GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- notifier.setHandle(hFile);
- notifier.setEnabled(true);
-
- OVERLAPPED overlapped;
- ZeroMemory(&overlapped, sizeof(OVERLAPPED));
- QByteArray buffer(readBufferSize, 0);
- BOOL readSuccess = ReadFile(hFile, buffer.data(), buffer.size(), NULL, &overlapped);
- QVERIFY(readSuccess || GetLastError() == ERROR_IO_PENDING);
-
- QTestEventLoop::instance().enterLoop(3);
- CloseHandle(hFile);
- QCOMPARE(sink.notifications.count(), 1);
- QCOMPARE(sink.notifications.last().bytes, expectedBytesRead);
- QCOMPARE(sink.notifications.last().errorCode, DWORD(ERROR_SUCCESS));
- QCOMPARE(sink.notifications.last().overlapped, &overlapped);
-}
-
-void tst_QWinOverlappedIoNotifier::waitForNotified_data()
-{
- readFile_data();
-}
-
-void tst_QWinOverlappedIoNotifier::waitForNotified()
-{
- QFETCH(QString, fileName);
- QFETCH(int, readBufferSize);
- QFETCH(DWORD, expectedBytesRead);
-
- QWinOverlappedIoNotifier notifier;
- NotifierSink sink(&notifier);
- HANDLE hFile = CreateFile(reinterpret_cast<const wchar_t*>(fileName.utf16()),
- GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- notifier.setHandle(hFile);
- notifier.setEnabled(true);
- QCOMPARE(notifier.waitForNotified(100, 0), false);
-
- OVERLAPPED overlapped;
- ZeroMemory(&overlapped, sizeof(OVERLAPPED));
- QByteArray buffer(readBufferSize, 0);
- BOOL readSuccess = ReadFile(hFile, buffer.data(), buffer.size(), NULL, &overlapped);
- QVERIFY(readSuccess || GetLastError() == ERROR_IO_PENDING);
-
- QCOMPARE(notifier.waitForNotified(3000, &overlapped), true);
- CloseHandle(hFile);
- QCOMPARE(sink.notifications.count(), 1);
- QCOMPARE(sink.notifications.last().bytes, expectedBytesRead);
- QCOMPARE(sink.notifications.last().errorCode, DWORD(ERROR_SUCCESS));
- QCOMPARE(sink.notifications.last().overlapped, &overlapped);
- QCOMPARE(notifier.waitForNotified(100, &overlapped), false);
-}
-
-void tst_QWinOverlappedIoNotifier::waitForAnyNotified()
-{
- const QString fileName = QDir::toNativeSeparators(sourceFileInfo.absoluteFilePath());
- const int readBufferSize = sourceFileInfo.size();
-
- QWinOverlappedIoNotifier notifier;
- HANDLE hFile = CreateFile(reinterpret_cast<const wchar_t*>(fileName.utf16()),
- GENERIC_READ, FILE_SHARE_READ,
- NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- notifier.setHandle(hFile);
- notifier.setEnabled(true);
- QVERIFY(!notifier.waitForAnyNotified(100));
-
- OVERLAPPED overlapped1;
- ZeroMemory(&overlapped1, sizeof(OVERLAPPED));
- QByteArray buffer1(readBufferSize, 0);
- BOOL readSuccess = ReadFile(hFile, buffer1.data(), buffer1.size(), NULL, &overlapped1);
- QVERIFY(readSuccess || GetLastError() == ERROR_IO_PENDING);
-
- OVERLAPPED overlapped2;
- ZeroMemory(&overlapped2, sizeof(OVERLAPPED));
- QByteArray buffer2(readBufferSize, 0);
- readSuccess = ReadFile(hFile, buffer2.data(), buffer2.size(), NULL, &overlapped2);
- QVERIFY(readSuccess || GetLastError() == ERROR_IO_PENDING);
-
- QSet<OVERLAPPED *> overlappedObjects;
- overlappedObjects << &overlapped1 << &overlapped2;
-
- for (int i = 1; i <= 2; ++i) {
- OVERLAPPED *notifiedOverlapped = notifier.waitForAnyNotified(3000);
- QVERIFY(overlappedObjects.contains(notifiedOverlapped));
- overlappedObjects.remove(notifiedOverlapped);
- }
-
- CloseHandle(hFile);
- QVERIFY(overlappedObjects.isEmpty());
- QVERIFY(!notifier.waitForAnyNotified(100));
-}
-
-void tst_QWinOverlappedIoNotifier::brokenPipe()
-{
- QWinOverlappedIoNotifier notifier;
- NotifierSink sink(&notifier);
- connect(&sink, &NotifierSink::notificationReceived, &QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
-
- wchar_t pipeName[] = L"\\\\.\\pipe\\tst_QWinOverlappedIoNotifier_brokenPipe";
- HANDLE hPipe = CreateNamedPipe(pipeName,
- PIPE_ACCESS_DUPLEX,
- PIPE_TYPE_BYTE | PIPE_NOWAIT | PIPE_REJECT_REMOTE_CLIENTS,
- 1, 0, 0, 0, NULL);
- QVERIFY(hPipe != INVALID_HANDLE_VALUE);
- HANDLE hReadEnd = CreateFile(pipeName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
- QVERIFY(hReadEnd != INVALID_HANDLE_VALUE);
- notifier.setHandle(hReadEnd);
- notifier.setEnabled(true);
-
- OVERLAPPED overlapped;
- ZeroMemory(&overlapped, sizeof(OVERLAPPED));
- QByteArray buffer(1024, 0);
- BOOL readSuccess = ReadFile(hReadEnd, buffer.data(), buffer.size(), NULL, &overlapped);
- QVERIFY(readSuccess || GetLastError() == ERROR_IO_PENDING);
-
- // close the write end of the pipe
- CloseHandle(hPipe);
-
- QTestEventLoop::instance().enterLoop(3);
- CloseHandle(hReadEnd);
- QCOMPARE(sink.notifications.count(), 1);
- QCOMPARE(sink.notifications.last().bytes, DWORD(0));
- QCOMPARE(sink.notifications.last().errorCode, DWORD(ERROR_BROKEN_PIPE));
- QCOMPARE(sink.notifications.last().overlapped, &overlapped);
-}
-
-void tst_QWinOverlappedIoNotifier::multipleOperations()
-{
- QWinOverlappedIoNotifier clientNotifier;
- NotifierSink sink(&clientNotifier);
- sink.threshold = 2;
- connect(&sink, &NotifierSink::notificationReceived,
- &QTestEventLoop::instance(), &QTestEventLoop::exitLoop);
-
- wchar_t pipeName[] = L"\\\\.\\pipe\\tst_QWinOverlappedIoNotifier_multipleOperations";
- HANDLE hServer = CreateNamedPipe(pipeName,
- PIPE_ACCESS_DUPLEX,
- PIPE_TYPE_BYTE | PIPE_NOWAIT | PIPE_REJECT_REMOTE_CLIENTS,
- 1, 0, 0, 0, NULL);
- QVERIFY(hServer != INVALID_HANDLE_VALUE);
- HANDLE hClient = CreateFile(pipeName, GENERIC_READ | GENERIC_WRITE, 0, NULL,
- OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
- QVERIFY(hClient != INVALID_HANDLE_VALUE);
- clientNotifier.setHandle(hClient);
- clientNotifier.setEnabled(true);
-
- // start async read on client
- QByteArray clientReadBuffer(377, Qt::Uninitialized);
- OVERLAPPED clientReadOverlapped;
- ZeroMemory(&clientReadOverlapped, sizeof(clientReadOverlapped));
- BOOL readSuccess = ReadFile(hClient, clientReadBuffer.data(), clientReadBuffer.size(),
- NULL, &clientReadOverlapped);
- QVERIFY(readSuccess || GetLastError() == ERROR_IO_PENDING);
-
- // start async write client -> server
- QByteArray clientDataToWrite(233, 'B');
- OVERLAPPED clientWriteOverlapped;
- ZeroMemory(&clientWriteOverlapped, sizeof(clientWriteOverlapped));
- BOOL writeSuccess = WriteFile(hClient, clientDataToWrite.data(), clientDataToWrite.size(),
- NULL, &clientWriteOverlapped);
- QVERIFY(writeSuccess || GetLastError() == ERROR_IO_PENDING);
-
- // start async write server -> client
- QByteArray serverDataToWrite(144, 'A');
- OVERLAPPED serverOverlapped;
- ZeroMemory(&serverOverlapped, sizeof(serverOverlapped));
- writeSuccess = WriteFile(hServer, serverDataToWrite.data(), serverDataToWrite.size(),
- NULL, &serverOverlapped);
- QVERIFY(writeSuccess || GetLastError() == ERROR_IO_PENDING);
-
- // read synchronously on server to complete the client -> server write
- QByteArray serverReadBuffer(610, Qt::Uninitialized);
- DWORD dwBytesRead = 0;
- readSuccess = ReadFile(hServer, serverReadBuffer.data(), serverReadBuffer.size(),
- &dwBytesRead, NULL);
- QVERIFY(readSuccess);
- QCOMPARE(int(dwBytesRead), clientDataToWrite.size());
- serverReadBuffer.resize(dwBytesRead);
- QCOMPARE(serverReadBuffer, clientDataToWrite);
-
- QTestEventLoop::instance().enterLoop(3);
- QTRY_COMPARE(sink.notifications.count(), 2);
- foreach (const NotifierSink::IOResult &r, sink.notifications) {
- QCOMPARE(r.errorCode, DWORD(ERROR_SUCCESS));
- if (r.bytes == DWORD(serverDataToWrite.count()))
- QCOMPARE(r.overlapped, &clientReadOverlapped);
- else if (r.bytes == DWORD(clientDataToWrite.count()))
- QCOMPARE(r.overlapped, &clientWriteOverlapped);
- else
- QVERIFY2(false, "Unexpected number of bytes received.");
- }
-
- CloseHandle(hClient);
- CloseHandle(hServer);
-}
-
-QTEST_MAIN(tst_QWinOverlappedIoNotifier)
-
-#include "tst_qwinoverlappedionotifier.moc"
diff --git a/tests/auto/corelib/itemmodels/itemmodels.pro b/tests/auto/corelib/itemmodels/itemmodels.pro
index c1d75cc2cb..a09f03a7b4 100644
--- a/tests/auto/corelib/itemmodels/itemmodels.pro
+++ b/tests/auto/corelib/itemmodels/itemmodels.pro
@@ -7,6 +7,7 @@ qtHaveModule(gui): SUBDIRS += \
qabstractproxymodel \
qidentityproxymodel \
qitemselectionmodel \
+ qsortfilterproxymodel_recursive \
qtHaveModule(widgets) {
SUBDIRS += \
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
index bc8f0c1c51..383bbbd3f8 100644
--- a/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
@@ -94,6 +94,7 @@ private slots:
void changeSourceDataKeepsStableSorting_qtbug1548();
void changeSourceDataForwardsRoles_qtbug35440();
void resortingDoesNotBreakTreeModels();
+ void dynamicFilterWithoutSort();
void sortFilterRole();
void selectionFilteredOut();
void match_data();
@@ -148,6 +149,9 @@ private slots:
void sourceLayoutChangeLeavesValidPersistentIndexes();
void rowMoveLeavesValidPersistentIndexes();
+ void emitLayoutChangedOnlyIfSortingChanged_data();
+ void emitLayoutChangedOnlyIfSortingChanged();
+
protected:
void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
void checkHierarchy(const QStringList &data, const QAbstractItemModel *model);
@@ -2057,8 +2061,6 @@ static void checkSortedTableModel(const QAbstractItemModel *model, const QString
void tst_QSortFilterProxyModel::changeSourceDataKeepsStableSorting_qtbug1548()
{
- QSKIP("This test will fail, see QTBUG-1548");
-
// Check that emitting dataChanged from the source model
// for a change of a role which is not the sorting role
// doesn't alter the sorting. In this case, we sort on the DisplayRole,
@@ -3568,6 +3570,13 @@ void tst_QSortFilterProxyModel::testParentLayoutChanged()
parentItem = item;
}
}
+ // item 0
+ // item 10
+ // - item 1
+ // - item 11
+ // - item 2
+ // - item 12
+ // ...
QSortFilterProxyModel proxy;
proxy.sort(0, Qt::AscendingOrder);
@@ -3609,11 +3618,12 @@ void tst_QSortFilterProxyModel::testParentLayoutChanged()
QVERIFY(proxy2ParentsChangedSpy.isValid());
QStandardItem *item = model.invisibleRootItem()->child(1)->child(1);
+ QCOMPARE(item->text(), QStringLiteral("item 11"));
// Ensure mapped:
proxy.mapFromSource(model.indexFromItem(item));
- item->setData("Changed");
+ item->setText("Changed");
QCOMPARE(dataChangedSpy.size(), 1);
QCOMPARE(layoutAboutToBeChangedSpy.size(), 1);
@@ -4026,7 +4036,7 @@ public:
}
- QModelIndex mapToSource(const QModelIndex &proxyIndex) const
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const override
{
Q_ASSERT(sourceModel());
return QSortFilterProxyModel::mapToSource(proxyIndex);
@@ -4353,5 +4363,152 @@ void tst_QSortFilterProxyModel::rowMoveLeavesValidPersistentIndexes()
QVERIFY(persistentIndex.parent().isValid());
}
+void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged_data()
+{
+ QTest::addColumn<int>("changedRow");
+ QTest::addColumn<Qt::ItemDataRole>("changedRole");
+ QTest::addColumn<QString>("newData");
+ QTest::addColumn<QString>("expectedSourceRowTexts");
+ QTest::addColumn<QString>("expectedProxyRowTexts");
+ QTest::addColumn<int>("expectedLayoutChanged");
+
+ // Starting point:
+ // a source model with 8,7,6,5,4,3,2,1
+ // a proxy model keeping only even rows and sorting them, therefore showing 2,4,6,8
+
+ // When setData changes ordering, layoutChanged should be emitted
+ QTest::newRow("ordering_change") << 0 << Qt::DisplayRole << "0" << "07654321" << "0246" << 1;
+
+ // When setData on visible row doesn't change ordering, layoutChanged should not be emitted
+ QTest::newRow("no_ordering_change") << 6 << Qt::DisplayRole << "0" << "87654301" << "0468" << 0;
+
+ // When setData happens on a filtered out row, layoutChanged should not be emitted
+ QTest::newRow("filtered_out") << 1 << Qt::DisplayRole << "9" << "89654321" << "2468" << 0;
+
+ // When setData makes a row visible, layoutChanged should not be emitted (rowsInserted is emitted instead)
+ QTest::newRow("make_row_visible") << 7 << Qt::DisplayRole << "0" << "87654320" << "02468" << 0;
+
+ // When setData makes a row hidden, layoutChanged should not be emitted (rowsRemoved is emitted instead)
+ QTest::newRow("make_row_hidden") << 4 << Qt::DisplayRole << "1" << "87651321" << "268" << 0;
+
+ // When setData happens on an unrelated role, layoutChanged should not be emitted
+ QTest::newRow("unrelated_role") << 0 << Qt::DecorationRole << "" << "87654321" << "2468" << 0;
+
+ // When many changes happen together... and trigger removal, insertion, and layoutChanged
+ QTest::newRow("many_changes") << -1 << Qt::DisplayRole << "3,4,2,5,6,0,7,9" << "34256079" << "0246" << 1;
+
+ // When many changes happen together... and trigger removal, insertion, but no change in ordering of visible rows => no layoutChanged
+ QTest::newRow("many_changes_no_layoutChanged") << -1 << Qt::DisplayRole << "7,5,4,3,2,1,0,8" << "75432108" << "0248" << 0;
+}
+
+void tst_QSortFilterProxyModel::emitLayoutChangedOnlyIfSortingChanged()
+{
+ QFETCH(int, changedRow);
+ QFETCH(QString, newData);
+ QFETCH(Qt::ItemDataRole, changedRole);
+ QFETCH(QString, expectedSourceRowTexts);
+ QFETCH(QString, expectedProxyRowTexts);
+ QFETCH(int, expectedLayoutChanged);
+
+ // Custom version of QStringListModel which supports emitting dataChanged for many rows at once
+ class CustomStringListModel : public QAbstractListModel
+ {
+ public:
+ bool setData(const QModelIndex &index, const QVariant &value, int role) override
+ {
+ if (index.row() >= 0 && index.row() < lst.size()
+ && (role == Qt::EditRole || role == Qt::DisplayRole)) {
+ lst.replace(index.row(), value.toString());
+ emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole});
+ return true;
+ }
+ return false;
+ }
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
+ {
+ if (role == Qt::DisplayRole || role == Qt::EditRole)
+ return lst.at(index.row());
+ return QVariant();
+ }
+ int rowCount(const QModelIndex & = QModelIndex()) const override
+ {
+ return lst.count();
+ }
+
+ void replaceData(const QStringList &newData)
+ {
+ lst = newData;
+ emit dataChanged(index(0, 0), index(rowCount()-1, 0), {Qt::DisplayRole, Qt::EditRole});
+ }
+
+ void emitDecorationChangedSignal()
+ {
+ const QModelIndex idx = index(0, 0);
+ emit dataChanged(idx, idx, {Qt::DecorationRole});
+ }
+ private:
+ QStringList lst;
+ };
+ CustomStringListModel model;
+ QStringList strings;
+ for (auto i = 8; i >= 1; --i)
+ strings.append(QString::number(i));
+ model.replaceData(strings);
+ QCOMPARE(rowTexts(&model), QStringLiteral("87654321"));
+
+ class FilterEvenRowsProxyModel : public QSortFilterProxyModel
+ {
+ public:
+ bool filterAcceptsRow(int srcRow, const QModelIndex& srcParent) const override
+ {
+ return sourceModel()->index(srcRow, 0, srcParent).data().toInt() % 2 == 0;
+ }
+ };
+
+ FilterEvenRowsProxyModel proxy;
+ proxy.sort(0);
+ proxy.setSourceModel(&model);
+ QCOMPARE(rowTexts(&proxy), QStringLiteral("2468"));
+
+ QSignalSpy modelDataChangedSpy(&model, &QAbstractItemModel::dataChanged);
+ QSignalSpy proxyLayoutChangedSpy(&proxy, &QAbstractItemModel::layoutChanged);
+
+ if (changedRole == Qt::DecorationRole)
+ model.emitDecorationChangedSignal();
+ else if (changedRow == -1)
+ model.replaceData(newData.split(QLatin1Char(',')));
+ else
+ model.setData(model.index(changedRow, 0), newData, changedRole);
+
+ QCOMPARE(rowTexts(&model), expectedSourceRowTexts);
+ QCOMPARE(rowTexts(&proxy), expectedProxyRowTexts);
+ QCOMPARE(modelDataChangedSpy.size(), 1);
+ QCOMPARE(proxyLayoutChangedSpy.size(), expectedLayoutChanged);
+}
+
+void tst_QSortFilterProxyModel::dynamicFilterWithoutSort()
+{
+ QStringListModel model;
+ const QStringList initial = QString("bravo charlie delta echo").split(QLatin1Char(' '));
+ model.setStringList(initial);
+ QSortFilterProxyModel proxy;
+ proxy.setDynamicSortFilter(true);
+ proxy.setSourceModel(&model);
+
+ QSignalSpy layoutChangeSpy(&proxy, &QAbstractItemModel::layoutChanged);
+ QSignalSpy resetSpy(&proxy, &QAbstractItemModel::modelReset);
+
+ QVERIFY(layoutChangeSpy.isValid());
+ QVERIFY(resetSpy.isValid());
+
+ model.setStringList(QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday");
+
+ QVERIFY(layoutChangeSpy.isEmpty());
+
+ QCOMPARE(model.stringList(), QStringList() << "Monday" << "Tuesday" << "Wednesday" << "Thursday" << "Friday");
+
+ QCOMPARE(resetSpy.count(), 1);
+}
+
QTEST_MAIN(tst_QSortFilterProxyModel)
#include "tst_qsortfilterproxymodel.moc"
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/.gitignore b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/.gitignore
new file mode 100644
index 0000000000..2007aaabbd
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/.gitignore
@@ -0,0 +1 @@
+tst_qsortfilterproxymodel_recursive
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/qsortfilterproxymodel_recursive.pro b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/qsortfilterproxymodel_recursive.pro
new file mode 100644
index 0000000000..a8b793dbc6
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/qsortfilterproxymodel_recursive.pro
@@ -0,0 +1,8 @@
+CONFIG += testcase
+CONFIG += parallel_test
+TARGET = tst_qsortfilterproxymodel_recursive
+
+QT += testlib
+
+SOURCES += tst_qsortfilterproxymodel_recursive.cpp
+DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0
diff --git a/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp
new file mode 100644
index 0000000000..54c79e0893
--- /dev/null
+++ b/tests/auto/corelib/itemmodels/qsortfilterproxymodel_recursive/tst_qsortfilterproxymodel_recursive.cpp
@@ -0,0 +1,727 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, authors Filipe Azevedo <filipe.azevedo@kdab.com> and David Faure <david.faure@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QTest>
+#include <QSignalSpy>
+
+#include <QtCore/QSortFilterProxyModel>
+#include <QtGui/QStandardItem>
+
+Q_DECLARE_METATYPE(QModelIndex)
+
+class ModelSignalSpy : public QObject {
+ Q_OBJECT
+public:
+ explicit ModelSignalSpy(QAbstractItemModel &model) {
+ connect(&model, &QAbstractItemModel::rowsInserted, this, &ModelSignalSpy::onRowsInserted);
+ connect(&model, &QAbstractItemModel::rowsRemoved, this, &ModelSignalSpy::onRowsRemoved);
+ connect(&model, &QAbstractItemModel::rowsAboutToBeInserted, this, &ModelSignalSpy::onRowsAboutToBeInserted);
+ connect(&model, &QAbstractItemModel::rowsAboutToBeRemoved, this, &ModelSignalSpy::onRowsAboutToBeRemoved);
+ connect(&model, &QAbstractItemModel::rowsMoved, this, &ModelSignalSpy::onRowsMoved);
+ connect(&model, &QAbstractItemModel::dataChanged, this, &ModelSignalSpy::onDataChanged);
+ connect(&model, &QAbstractItemModel::layoutChanged, this, &ModelSignalSpy::onLayoutChanged);
+ connect(&model, &QAbstractItemModel::modelReset, this, &ModelSignalSpy::onModelReset);
+ }
+
+ QStringList mSignals;
+
+private Q_SLOTS:
+ void onRowsInserted(QModelIndex p, int start, int end) {
+ mSignals << QLatin1String("rowsInserted(") + textForRowSpy(p, start, end) + ')';
+ }
+ void onRowsRemoved(QModelIndex p, int start, int end) {
+ mSignals << QLatin1String("rowsRemoved(") + textForRowSpy(p, start, end) + ')';
+ }
+ void onRowsAboutToBeInserted(QModelIndex p, int start, int end) {
+ mSignals << QLatin1String("rowsAboutToBeInserted(") + textForRowSpy(p, start, end) + ')';
+ }
+ void onRowsAboutToBeRemoved(QModelIndex p, int start, int end) {
+ mSignals << QLatin1String("rowsAboutToBeRemoved(") + textForRowSpy(p, start, end) + ')';
+ }
+ void onRowsMoved(QModelIndex,int,int,QModelIndex,int) {
+ mSignals << QStringLiteral("rowsMoved");
+ }
+ void onDataChanged(const QModelIndex &from, const QModelIndex& ) {
+ mSignals << QStringLiteral("dataChanged(%1)").arg(from.data().toString());
+ }
+ void onLayoutChanged() {
+ mSignals << QStringLiteral("layoutChanged");
+ }
+ void onModelReset() {
+ mSignals << QStringLiteral("modelReset");
+ }
+private:
+ QString textForRowSpy(const QModelIndex &parent, int start, int end)
+ {
+ QString txt = parent.data().toString();
+ if (!txt.isEmpty())
+ txt += QLatin1Char('.');
+ txt += QString::number(start+1);
+ if (start != end)
+ txt += QLatin1Char('-') + QString::number(end+1);
+ return txt;
+ }
+};
+
+class TestModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ TestModel(QAbstractItemModel *sourceModel)
+ : QSortFilterProxyModel()
+ {
+ setRecursiveFiltering(true);
+ setSourceModel(sourceModel);
+ }
+
+ virtual bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override
+ {
+ return sourceModel()->index(sourceRow, 0, sourceParent).data(Qt::UserRole +1).toBool()
+ && QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
+ }
+};
+
+// Represents this tree
+// - A
+// - - B
+// - - - C
+// - - - D
+// - - E
+// as a single string, englobing children in brackets, like this:
+// [A[B[C D] E]]
+// In addition, items that match the filtering (data(UserRole+1) == true) have a * after their value.
+static QString treeAsString(const QAbstractItemModel &model, const QModelIndex &parent = QModelIndex())
+{
+ QString ret;
+ const int rowCount = model.rowCount(parent);
+ if (rowCount > 0) {
+ ret += QLatin1Char('[');
+ for (int row = 0 ; row < rowCount; ++row) {
+ if (row > 0) {
+ ret += ' ';
+ }
+ const QModelIndex child = model.index(row, 0, parent);
+ ret += child.data().toString();
+ if (child.data(Qt::UserRole+1).toBool())
+ ret += QLatin1Char('*');
+ ret += treeAsString(model, child);
+ }
+ ret += QLatin1Char(']');
+ }
+ return ret;
+}
+
+// Fill a tree model based on a string representation (see treeAsString)
+static void fillModel(QStandardItemModel &model, const QString &str)
+{
+ QCOMPARE(str.count('['), str.count(']'));
+ QStandardItem *item = 0;
+ QString data;
+ for ( int i = 0 ; i < str.length() ; ++i ) {
+ const QChar ch = str.at(i);
+ if ((ch == '[' || ch == ']' || ch == ' ') && !data.isEmpty()) {
+ if (data.endsWith('*')) {
+ item->setData(true, Qt::UserRole + 1);
+ data.chop(1);
+ }
+ item->setText(data);
+ data.clear();
+ }
+ if (ch == '[') {
+ // Create new child
+ QStandardItem *child = new QStandardItem;
+ if (item)
+ item->appendRow(child);
+ else
+ model.appendRow(child);
+ item = child;
+ } else if (ch == ']') {
+ // Go up to parent
+ item = item->parent();
+ } else if (ch == ' ') {
+ // Create new sibling
+ QStandardItem *child = new QStandardItem;
+ QStandardItem *parent = item->parent();
+ if (parent)
+ parent->appendRow(child);
+ else
+ model.appendRow(child);
+ item = child;
+ } else {
+ data += ch;
+ }
+ }
+}
+
+class tst_QSortFilterProxyModel_Recursive : public QObject
+{
+ Q_OBJECT
+private:
+private Q_SLOTS:
+ void testInitialFiltering_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("proxyStr");
+
+ QTest::newRow("empty") << "[]" << "";
+ QTest::newRow("no") << "[1]" << "";
+ QTest::newRow("yes") << "[1*]" << "[1*]";
+ QTest::newRow("second") << "[1 2*]" << "[2*]";
+ QTest::newRow("child_yes") << "[1 2[2.1*]]" << "[2[2.1*]]";
+ QTest::newRow("grandchild_yes") << "[1 2[2.1[2.1.1*]]]" << "[2[2.1[2.1.1*]]]";
+ // 1, 3.1 and 4.2.1 match, so their parents are in the model
+ QTest::newRow("more") << "[1* 2[2.1] 3[3.1*] 4[4.1 4.2[4.2.1*]]]" << "[1* 3[3.1*] 4[4.2[4.2.1*]]]";
+ }
+
+ void testInitialFiltering()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, proxyStr);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), proxyStr);
+ }
+
+ // Test changing a role that is unrelated to the filtering.
+ void testUnrelatedDataChange()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1[1.1.1*]]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), sourceStr);
+
+ ModelSignalSpy spy(proxy);
+ QStandardItem *item_1_1_1 = model.item(0)->child(0)->child(0);
+
+ // When changing the text on the item
+ item_1_1_1->setText(QStringLiteral("ME"));
+
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[ME*]]]"));
+
+ QCOMPARE(spy.mSignals, QStringList()
+ << QStringLiteral("dataChanged(ME)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+ }
+
+ // Test changing a role that is unrelated to the filtering, in a hidden item.
+ void testHiddenDataChange()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1[1.1.1]]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), QString());
+
+ ModelSignalSpy spy(proxy);
+ QStandardItem *item_1_1_1 = model.item(0)->child(0)->child(0);
+
+ // When changing the text on a hidden item
+ item_1_1_1->setText(QStringLiteral("ME"));
+
+ QCOMPARE(treeAsString(proxy), QString());
+ QCOMPARE(spy.mSignals, QStringList());
+ }
+
+ // Test that we properly react to a data-changed signal in a descendant and include all required rows
+ void testDataChangeIn_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("initialProxyStr");
+ QTest::addColumn<QString>("add"); // set the flag on this item
+ QTest::addColumn<QString>("expectedProxyStr");
+ QTest::addColumn<QStringList>("expectedSignals");
+
+ QTest::newRow("toplevel") << "[1]" << "" << "1" << "[1*]"
+ << (QStringList() << QStringLiteral("rowsAboutToBeInserted(1)") << QStringLiteral("rowsInserted(1)"));
+ QTest::newRow("show_parents") << "[1[1.1[1.1.1]]]" << "" << "1.1.1" << "[1[1.1[1.1.1*]]]"
+ << (QStringList() << QStringLiteral("rowsAboutToBeInserted(1)") << QStringLiteral("rowsInserted(1)"));
+
+ const QStringList insert_1_1_1 = QStringList()
+ << QStringLiteral("rowsAboutToBeInserted(1.1.1)")
+ << QStringLiteral("rowsInserted(1.1.1)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)")
+ ;
+ QTest::newRow("parent_visible") << "[1[1.1*[1.1.1]]]" << "[1[1.1*]]" << "1.1.1" << "[1[1.1*[1.1.1*]]]"
+ << insert_1_1_1;
+
+ QTest::newRow("sibling_visible") << "[1[1.1[1.1.1 1.1.2*]]]" << "[1[1.1[1.1.2*]]]" << "1.1.1" << "[1[1.1[1.1.1* 1.1.2*]]]"
+ << insert_1_1_1;
+
+ QTest::newRow("visible_cousin") << "[1[1.1[1.1.1 1.1.2[1.1.2.1*]]]]" << "[1[1.1[1.1.2[1.1.2.1*]]]]" << "1.1.1" << "[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]"
+ << insert_1_1_1;
+
+ QTest::newRow("show_parent") << "[1[1.1[1.1.1 1.1.2] 1.2*]]" << "[1[1.2*]]" << "1.1.1" << "[1[1.1[1.1.1*] 1.2*]]"
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeInserted(1.1)")
+ << QStringLiteral("rowsInserted(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ QTest::newRow("with_children") << "[1[1.1[1.1.1[1.1.1.1*]]] 2*]" << "[1[1.1[1.1.1[1.1.1.1*]]] 2*]" << "1.1.1" << "[1[1.1[1.1.1*[1.1.1.1*]]] 2*]"
+ << (QStringList()
+ << QStringLiteral("dataChanged(1.1.1)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ }
+
+ void testDataChangeIn()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, initialProxyStr);
+ QFETCH(QString, add);
+ QFETCH(QString, expectedProxyStr);
+ QFETCH(QStringList, expectedSignals);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), initialProxyStr);
+
+ ModelSignalSpy spy(proxy);
+ // When changing the data on the designated item to show this row
+ QStandardItem *itemToChange = itemByText(model, add);
+ QVERIFY(!itemToChange->data().toBool());
+ itemToChange->setData(true);
+
+ // The proxy should update as expected
+ QCOMPARE(treeAsString(proxy), expectedProxyStr);
+
+ //qDebug() << spy.mSignals;
+ QCOMPARE(spy.mSignals, expectedSignals);
+ }
+
+ void testDataChangeOut_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("initialProxyStr");
+ QTest::addColumn<QString>("remove"); // unset the flag on this item
+ QTest::addColumn<QString>("expectedProxyStr");
+ QTest::addColumn<QStringList>("expectedSignals");
+
+ const QStringList remove1_1_1 = (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ QTest::newRow("toplevel") << "[1*]" << "[1*]" << "1" << ""
+ << (QStringList() << QStringLiteral("rowsAboutToBeRemoved(1)") << QStringLiteral("rowsRemoved(1)"));
+
+ QTest::newRow("hide_parent") << "[1[1.1[1.1.1*]]]" << "[1[1.1[1.1.1*]]]" << "1.1.1" << "" <<
+ (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1.1)")
+ << QStringLiteral("rowsRemoved(1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1)")
+ << QStringLiteral("rowsRemoved(1)"));
+
+ QTest::newRow("parent_visible") << "[1[1.1*[1.1.1*]]]" << "[1[1.1*[1.1.1*]]]" << "1.1.1" << "[1[1.1*]]"
+ << remove1_1_1;
+
+ QTest::newRow("visible") << "[1[1.1[1.1.1* 1.1.2*]]]" << "[1[1.1[1.1.1* 1.1.2*]]]" << "1.1.1" << "[1[1.1[1.1.2*]]]"
+ << remove1_1_1;
+ QTest::newRow("visible_cousin") << "[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]" << "[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]" << "1.1.1" << "[1[1.1[1.1.2[1.1.2.1*]]]]"
+ << remove1_1_1;
+
+ // The following tests trigger the removal of an ascendant.
+ QTest::newRow("remove_parent") << "[1[1.1[1.1.1* 1.1.2] 1.2*]]" << "[1[1.1[1.1.1*] 1.2*]]" << "1.1.1" << "[1[1.2*]]"
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1.1)")
+ << QStringLiteral("rowsRemoved(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ QTest::newRow("with_children") << "[1[1.1[1.1.1*[1.1.1.1*]]] 2*]" << "[1[1.1[1.1.1*[1.1.1.1*]]] 2*]" << "1.1.1" << "[1[1.1[1.1.1[1.1.1.1*]]] 2*]"
+ << (QStringList()
+ << QStringLiteral("dataChanged(1.1.1)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ QTest::newRow("last_visible") << "[1[1.1[1.1.1* 1.1.2]]]" << "[1[1.1[1.1.1*]]]" << "1.1.1" << ""
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1.1)")
+ << QStringLiteral("rowsRemoved(1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1)")
+ << QStringLiteral("rowsRemoved(1)"));
+
+ }
+
+ void testDataChangeOut()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, initialProxyStr);
+ QFETCH(QString, remove);
+ QFETCH(QString, expectedProxyStr);
+ QFETCH(QStringList, expectedSignals);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), initialProxyStr);
+
+ ModelSignalSpy spy(proxy);
+
+ // When changing the data on the designated item to exclude this row again
+ QStandardItem *itemToChange = itemByText(model, remove);
+ QVERIFY(itemToChange->data().toBool());
+ itemToChange->setData(false);
+
+ // The proxy should update as expected
+ QCOMPARE(treeAsString(proxy), expectedProxyStr);
+
+ //qDebug() << spy.mSignals;
+ QCOMPARE(spy.mSignals, expectedSignals);
+ }
+
+ void testInsert()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1[1.1.1]]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), QString());
+
+ ModelSignalSpy spy(proxy);
+ QStandardItem *item_1_1_1 = model.item(0)->child(0)->child(0);
+ QStandardItem *item_1_1_1_1 = new QStandardItem(QStringLiteral("1.1.1.1"));
+ item_1_1_1_1->setData(true);
+ item_1_1_1->appendRow(item_1_1_1_1);
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[1.1.1[1.1.1.1*]]]]"));
+
+ QCOMPARE(spy.mSignals, QStringList() << QStringLiteral("rowsAboutToBeInserted(1)")
+ << QStringLiteral("rowsInserted(1)"));
+ }
+
+ // Start from [1[1.1[1.1.1 1.1.2[1.1.2.1*]]]]
+ // where 1.1.1 is hidden but 1.1 is shown, we want to insert a shown child in 1.1.1.
+ // The proxy ensures dataChanged is called on 1.1,
+ // so that 1.1.1 and 1.1.1.1 are included in the model.
+ void testInsertCousin()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1[1.1.1 1.1.2[1.1.2.1*]]]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[1.1.2[1.1.2.1*]]]]"));
+
+ ModelSignalSpy spy(proxy);
+ {
+ QStandardItem *item_1_1_1_1 = new QStandardItem(QStringLiteral("1.1.1.1"));
+ item_1_1_1_1->setData(true);
+ QStandardItem *item_1_1_1 = model.item(0)->child(0)->child(0);
+ item_1_1_1->appendRow(item_1_1_1_1);
+ }
+
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[1.1.1[1.1.1.1*] 1.1.2[1.1.2.1*]]]]"));
+ //qDebug() << spy.mSignals;
+ QCOMPARE(spy.mSignals, QStringList()
+ << QStringLiteral("rowsAboutToBeInserted(1.1.1)")
+ << QStringLiteral("rowsInserted(1.1.1)")
+ << QStringLiteral("dataChanged(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+ }
+
+ void testInsertWithChildren()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), QString());
+
+ ModelSignalSpy spy(proxy);
+ {
+ QStandardItem *item_1_1_1 = new QStandardItem(QStringLiteral("1.1.1"));
+ QStandardItem *item_1_1_1_1 = new QStandardItem(QStringLiteral("1.1.1.1"));
+ item_1_1_1_1->setData(true);
+ item_1_1_1->appendRow(item_1_1_1_1);
+
+ QStandardItem *item_1_1 = model.item(0)->child(0);
+ item_1_1->appendRow(item_1_1_1);
+ }
+
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[1.1.1[1.1.1.1*]]]]"));
+ QCOMPARE(spy.mSignals, QStringList()
+ << QStringLiteral("rowsAboutToBeInserted(1)")
+ << QStringLiteral("rowsInserted(1)"));
+ }
+
+ void testInsertIntoVisibleWithChildren()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1[1.1.1*]]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), sourceStr);
+
+ ModelSignalSpy spy(proxy);
+ {
+ QStandardItem *item_1_1_2 = new QStandardItem(QStringLiteral("1.1.2"));
+ QStandardItem *item_1_1_2_1 = new QStandardItem(QStringLiteral("1.1.2.1"));
+ item_1_1_2_1->setData(true);
+ item_1_1_2->appendRow(item_1_1_2_1);
+
+ QStandardItem *item_1_1 = model.item(0)->child(0);
+ item_1_1->appendRow(item_1_1_2);
+ }
+
+ QCOMPARE(treeAsString(proxy), QStringLiteral("[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]"));
+ QCOMPARE(spy.mSignals, QStringList()
+ << QStringLiteral("rowsAboutToBeInserted(1.1.2)")
+ << QStringLiteral("rowsInserted(1.1.2)"));
+ }
+
+ void testInsertBefore()
+ {
+ QStandardItemModel model;
+ const QString sourceStr = "[1[1.1[1.1.2*]]]";
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), sourceStr);
+
+ ModelSignalSpy spy(proxy);
+ {
+ QStandardItem *item_1_1_1 = new QStandardItem("1.1.1");
+
+ QStandardItem *item_1_1 = model.item(0)->child(0);
+ item_1_1->insertRow(0, item_1_1_1);
+ }
+
+ QCOMPARE(treeAsString(proxy), QString("[1[1.1[1.1.2*]]]"));
+ QCOMPARE(spy.mSignals, QStringList());
+ }
+
+ void testInsertHidden() // inserting filtered-out rows shouldn't emit anything
+ {
+ QStandardItemModel model;
+ const QString sourceStr = QStringLiteral("[1[1.1]]");
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), QString());
+
+ ModelSignalSpy spy(proxy);
+ {
+ QStandardItem *item_1_1_1 = new QStandardItem(QStringLiteral("1.1.1"));
+ QStandardItem *item_1_1_1_1 = new QStandardItem(QStringLiteral("1.1.1.1"));
+ item_1_1_1->appendRow(item_1_1_1_1);
+
+ QStandardItem *item_1_1 = model.item(0)->child(0);
+ item_1_1->appendRow(item_1_1_1);
+ }
+
+ QCOMPARE(treeAsString(proxy), QString());
+ QCOMPARE(spy.mSignals, QStringList());
+ }
+
+ void testConsecutiveInserts_data()
+ {
+ testInitialFiltering_data();
+ }
+
+ void testConsecutiveInserts()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, proxyStr);
+
+ QStandardItemModel model;
+ TestModel proxy(&model); // this time the proxy listens to the model while we fill it
+
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+ QCOMPARE(treeAsString(proxy), proxyStr);
+ }
+
+ void testRemove_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("initialProxyStr");
+ QTest::addColumn<QString>("remove"); // remove this item
+ QTest::addColumn<QString>("expectedProxyStr");
+ QTest::addColumn<QStringList>("expectedSignals");
+
+ const QStringList remove1_1_1 = (QStringList() << QStringLiteral("rowsAboutToBeRemoved(1.1.1)") << QStringLiteral("rowsRemoved(1.1.1)"));
+
+ QTest::newRow("toplevel") << "[1* 2* 3*]" << "[1* 2* 3*]" << "1" << "[2* 3*]"
+ << (QStringList() << QStringLiteral("rowsAboutToBeRemoved(1)") << QStringLiteral("rowsRemoved(1)"));
+
+ QTest::newRow("remove_hidden") << "[1 2* 3*]" << "[2* 3*]" << "1" << "[2* 3*]" << QStringList();
+
+ QTest::newRow("parent_hidden") << "[1[1.1[1.1.1]]]" << "" << "1.1.1" << "" << QStringList();
+
+ QTest::newRow("child_hidden") << "[1[1.1*[1.1.1]]]" << "[1[1.1*]]" << "1.1.1" << "[1[1.1*]]" << QStringList();
+
+ QTest::newRow("parent_visible") << "[1[1.1*[1.1.1*]]]" << "[1[1.1*[1.1.1*]]]" << "1.1.1" << "[1[1.1*]]"
+ << remove1_1_1;
+
+ QTest::newRow("visible") << "[1[1.1[1.1.1* 1.1.2*]]]" << "[1[1.1[1.1.1* 1.1.2*]]]" << "1.1.1" << "[1[1.1[1.1.2*]]]"
+ << remove1_1_1;
+ QTest::newRow("visible_cousin") << "[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]" << "[1[1.1[1.1.1* 1.1.2[1.1.2.1*]]]]" << "1.1.1" << "[1[1.1[1.1.2[1.1.2.1*]]]]"
+ << remove1_1_1;
+
+ // The following tests trigger the removal of an ascendant.
+ // We could optimize the rows{AboutToBe,}Removed(1.1.1) away...
+
+ QTest::newRow("remove_parent") << "[1[1.1[1.1.1* 1.1.2] 1.2*]]" << "[1[1.1[1.1.1*] 1.2*]]" << "1.1.1" << "[1[1.2*]]"
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1.1)")
+ << QStringLiteral("rowsRemoved(1.1)")
+ << QStringLiteral("dataChanged(1)"));
+
+ QTest::newRow("with_children") << "[1[1.1[1.1.1[1.1.1.1*]]] 2*]" << "[1[1.1[1.1.1[1.1.1.1*]]] 2*]" << "1.1.1" << "[2*]"
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1)")
+ << QStringLiteral("rowsRemoved(1)"));
+
+ QTest::newRow("last_visible") << "[1[1.1[1.1.1* 1.1.2]]]" << "[1[1.1[1.1.1*]]]" << "1.1.1" << ""
+ << (QStringList()
+ << QStringLiteral("rowsAboutToBeRemoved(1.1.1)")
+ << QStringLiteral("rowsRemoved(1.1.1)")
+ << QStringLiteral("rowsAboutToBeRemoved(1)")
+ << QStringLiteral("rowsRemoved(1)"));
+
+
+ }
+
+ void testRemove()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, initialProxyStr);
+ QFETCH(QString, remove);
+ QFETCH(QString, expectedProxyStr);
+ QFETCH(QStringList, expectedSignals);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), initialProxyStr);
+
+ ModelSignalSpy spy(proxy);
+ QStandardItem *itemToRemove = itemByText(model, remove);
+ QVERIFY(itemToRemove);
+ if (itemToRemove->parent())
+ itemToRemove->parent()->removeRow(itemToRemove->row());
+ else
+ model.removeRow(itemToRemove->row());
+ QCOMPARE(treeAsString(proxy), expectedProxyStr);
+
+ //qDebug() << spy.mSignals;
+ QCOMPARE(spy.mSignals, expectedSignals);
+ }
+
+ void testStandardFiltering_data()
+ {
+ QTest::addColumn<QString>("sourceStr");
+ QTest::addColumn<QString>("initialProxyStr");
+ QTest::addColumn<QString>("filter");
+ QTest::addColumn<QString>("expectedProxyStr");
+
+ QTest::newRow("select_child") << "[1[1.1[1.1.1* 1.1.2*]]]" << "[1[1.1[1.1.1* 1.1.2*]]]"
+ << "1.1.2" << "[1[1.1[1.1.2*]]]";
+
+ QTest::newRow("filter_all_out") << "[1[1.1[1.1.1*]]]" << "[1[1.1[1.1.1*]]]"
+ << "test" << "";
+
+ QTest::newRow("select_parent") << "[1[1.1[1.1.1*[child*] 1.1.2*]]]" << "[1[1.1[1.1.1*[child*] 1.1.2*]]]"
+ << "1.1.1" << "[1[1.1[1.1.1*]]]";
+
+ }
+
+ void testStandardFiltering()
+ {
+ QFETCH(QString, sourceStr);
+ QFETCH(QString, initialProxyStr);
+ QFETCH(QString, filter);
+ QFETCH(QString, expectedProxyStr);
+
+ QStandardItemModel model;
+ fillModel(model, sourceStr);
+ QCOMPARE(treeAsString(model), sourceStr);
+
+ TestModel proxy(&model);
+ QCOMPARE(treeAsString(proxy), initialProxyStr);
+
+ ModelSignalSpy spy(proxy);
+
+ //qDebug() << "setFilterFixedString";
+ proxy.setFilterFixedString(filter);
+
+ QCOMPARE(treeAsString(proxy), expectedProxyStr);
+
+ }
+
+private:
+ QStandardItem *itemByText(const QStandardItemModel& model, const QString &text) const {
+ QModelIndexList list = model.match(model.index(0, 0), Qt::DisplayRole, text, 1, Qt::MatchRecursive);
+ return list.isEmpty() ? 0 : model.itemFromIndex(list.first());
+ }
+};
+
+QTEST_GUILESS_MAIN(tst_QSortFilterProxyModel_Recursive)
+#include "tst_qsortfilterproxymodel_recursive.moc"
diff --git a/tests/auto/corelib/json/tst_qtjson.cpp b/tests/auto/corelib/json/tst_qtjson.cpp
index b215364f0e..1e3604ac9e 100644
--- a/tests/auto/corelib/json/tst_qtjson.cpp
+++ b/tests/auto/corelib/json/tst_qtjson.cpp
@@ -80,7 +80,10 @@ private Q_SLOTS:
void undefinedValues();
+ void fromVariant_data();
void fromVariant();
+ void toVariant_data();
+ void toVariant();
void fromVariantMap();
void fromVariantHash();
void toVariantMap();
@@ -145,6 +148,9 @@ private Q_SLOTS:
void parseErrorOffset_data();
void parseErrorOffset();
+ void implicitValueType();
+ void implicitDocumentType();
+
private:
QString testDataDir;
};
@@ -1092,8 +1098,11 @@ void tst_QtJson::undefinedValues()
QCOMPARE(array.at(-1).type(), QJsonValue::Undefined);
}
-void tst_QtJson::fromVariant()
+void tst_QtJson::fromVariant_data()
{
+ QTest::addColumn<QVariant>("variant");
+ QTest::addColumn<QJsonValue>("jsonvalue");
+
bool boolValue = true;
int intValue = -1;
uint uintValue = 1;
@@ -1116,44 +1125,66 @@ void tst_QtJson::fromVariant()
variantList.append(doubleValue);
variantList.append(stringValue);
variantList.append(stringList);
- variantList.append(QVariant());
+ variantList.append(QVariant::fromValue(nullptr));
QJsonArray jsonArray_variant;
jsonArray_variant.append(boolValue);
jsonArray_variant.append(floatValue);
jsonArray_variant.append(doubleValue);
jsonArray_variant.append(stringValue);
jsonArray_variant.append(jsonArray_string);
- jsonArray_variant.append(QJsonValue());
+ jsonArray_variant.append(QJsonValue(QJsonValue::Null));
QVariantMap variantMap;
variantMap["bool"] = boolValue;
variantMap["float"] = floatValue;
variantMap["string"] = stringValue;
variantMap["array"] = variantList;
+ QVariantHash variantHash;
+ variantHash["bool"] = boolValue;
+ variantHash["float"] = floatValue;
+ variantHash["string"] = stringValue;
+ variantHash["array"] = variantList;
QJsonObject jsonObject;
jsonObject["bool"] = boolValue;
jsonObject["float"] = floatValue;
jsonObject["string"] = stringValue;
jsonObject["array"] = jsonArray_variant;
- QCOMPARE(QJsonValue::fromVariant(QVariant::fromValue(nullptr)), QJsonValue(QJsonValue::Null));
- QCOMPARE(QJsonValue::fromVariant(QVariant(boolValue)), QJsonValue(boolValue));
- QCOMPARE(QJsonValue::fromVariant(QVariant(intValue)), QJsonValue(intValue));
- QCOMPARE(QJsonValue::fromVariant(QVariant(uintValue)), QJsonValue(static_cast<double>(uintValue)));
- QCOMPARE(QJsonValue::fromVariant(QVariant(longlongValue)), QJsonValue(longlongValue));
- QCOMPARE(QJsonValue::fromVariant(QVariant(ulonglongValue)), QJsonValue(static_cast<double>(ulonglongValue)));
- QCOMPARE(QJsonValue::fromVariant(QVariant(floatValue)), QJsonValue(static_cast<double>(floatValue)));
- QCOMPARE(QJsonValue::fromVariant(QVariant(doubleValue)), QJsonValue(doubleValue));
- QCOMPARE(QJsonValue::fromVariant(QVariant(stringValue)), QJsonValue(stringValue));
- QCOMPARE(QJsonValue::fromVariant(QVariant(stringList)), QJsonValue(jsonArray_string));
- QCOMPARE(QJsonValue::fromVariant(QVariant(variantList)), QJsonValue(jsonArray_variant));
- QCOMPARE(QJsonValue::fromVariant(QVariant(variantMap)), QJsonValue(jsonObject));
-
- QVERIFY(QJsonValue::fromVariant(QVariant(QJsonValue(true))).isBool());
- QVERIFY(QJsonValue::fromVariant(QVariant(jsonArray_string)).isArray());
- QVERIFY(QJsonValue::fromVariant(QVariant(QJsonDocument(jsonArray_string))).isArray());
- QVERIFY(QJsonValue::fromVariant(QVariant(jsonObject)).isObject());
- QVERIFY(QJsonValue::fromVariant(QVariant(QJsonDocument(jsonObject))).isObject());
+ QTest::newRow("nullptr") << QVariant::fromValue(nullptr) << QJsonValue(QJsonValue::Null);
+ QTest::newRow("bool") << QVariant(boolValue) << QJsonValue(boolValue);
+ QTest::newRow("int") << QVariant(intValue) << QJsonValue(intValue);
+ QTest::newRow("uint") << QVariant(uintValue) << QJsonValue(static_cast<double>(uintValue));
+ QTest::newRow("longlong") << QVariant(longlongValue) << QJsonValue(longlongValue);
+ QTest::newRow("ulonglong") << QVariant(ulonglongValue) << QJsonValue(static_cast<double>(ulonglongValue));
+ QTest::newRow("float") << QVariant(floatValue) << QJsonValue(floatValue);
+ QTest::newRow("double") << QVariant(doubleValue) << QJsonValue(doubleValue);
+ QTest::newRow("string") << QVariant(stringValue) << QJsonValue(stringValue);
+ QTest::newRow("stringList") << QVariant(stringList) << QJsonValue(jsonArray_string);
+ QTest::newRow("variantList") << QVariant(variantList) << QJsonValue(jsonArray_variant);
+ QTest::newRow("variantMap") << QVariant(variantMap) << QJsonValue(jsonObject);
+ QTest::newRow("variantHash") << QVariant(variantHash) << QJsonValue(jsonObject);
+}
+
+void tst_QtJson::fromVariant()
+{
+ QFETCH( QVariant, variant );
+ QFETCH( QJsonValue, jsonvalue );
+
+ QCOMPARE(QJsonValue::fromVariant(variant), jsonvalue);
+ QCOMPARE(variant.toJsonValue(), jsonvalue);
+}
+
+void tst_QtJson::toVariant_data()
+{
+ fromVariant_data();
+}
+
+void tst_QtJson::toVariant()
+{
+ QFETCH( QVariant, variant );
+ QFETCH( QJsonValue, jsonvalue );
+
+ QCOMPARE(jsonvalue.toVariant(), variant);
}
void tst_QtJson::fromVariantMap()
@@ -2908,5 +2939,52 @@ void tst_QtJson::parseErrorOffset()
QCOMPARE(error.offset, errorOffset);
}
+void tst_QtJson::implicitValueType()
+{
+ QJsonObject rootObject{
+ {"object", QJsonObject{{"value", 42}}},
+ {"array", QJsonArray{665, 666, 667}}
+ };
+
+ QJsonValue objectValue = rootObject["object"];
+ QCOMPARE(objectValue["value"].toInt(), 42);
+ QCOMPARE(objectValue["missingValue"], QJsonValue(QJsonValue::Undefined));
+ QCOMPARE(objectValue[123], QJsonValue(QJsonValue::Undefined));
+ QCOMPARE(objectValue["missingValue"].toInt(123), 123);
+
+ QJsonValue arrayValue = rootObject["array"];
+ QCOMPARE(arrayValue[1].toInt(), 666);
+ QCOMPARE(arrayValue[-1], QJsonValue(QJsonValue::Undefined));
+ QCOMPARE(arrayValue["asObject"], QJsonValue(QJsonValue::Undefined));
+ QCOMPARE(arrayValue[-1].toInt(123), 123);
+
+ const QJsonObject constObject = rootObject;
+ QCOMPARE(constObject["object"]["value"].toInt(), 42);
+ QCOMPARE(constObject["array"][1].toInt(), 666);
+
+ QJsonValue objectAsValue(rootObject);
+ QCOMPARE(objectAsValue["object"]["value"].toInt(), 42);
+ QCOMPARE(objectAsValue["array"][1].toInt(), 666);
+}
+
+void tst_QtJson::implicitDocumentType()
+{
+ QJsonDocument emptyDocument;
+ QCOMPARE(emptyDocument["asObject"], QJsonValue(QJsonValue::Undefined));
+ QCOMPARE(emptyDocument[123], QJsonValue(QJsonValue::Undefined));
+
+ QJsonDocument objectDocument(QJsonObject{{"value", 42}});
+ QCOMPARE(objectDocument["value"].toInt(), 42);
+ QCOMPARE(objectDocument["missingValue"], QJsonValue(QJsonValue::Undefined));
+ QCOMPARE(objectDocument[123], QJsonValue(QJsonValue::Undefined));
+ QCOMPARE(objectDocument["missingValue"].toInt(123), 123);
+
+ QJsonDocument arrayDocument(QJsonArray{665, 666, 667});
+ QCOMPARE(arrayDocument[1].toInt(), 666);
+ QCOMPARE(arrayDocument[-1], QJsonValue(QJsonValue::Undefined));
+ QCOMPARE(arrayDocument["asObject"], QJsonValue(QJsonValue::Undefined));
+ QCOMPARE(arrayDocument[-1].toInt(123), 123);
+}
+
QTEST_MAIN(tst_QtJson)
#include "tst_qtjson.moc"
diff --git a/tests/auto/corelib/kernel/qmath/tst_qmath.cpp b/tests/auto/corelib/kernel/qmath/tst_qmath.cpp
index ad40b0140d..feb704e0aa 100644
--- a/tests/auto/corelib/kernel/qmath/tst_qmath.cpp
+++ b/tests/auto/corelib/kernel/qmath/tst_qmath.cpp
@@ -30,8 +30,6 @@
#include <QtTest/QtTest>
#include <qmath.h>
-static const double PI = 3.14159265358979323846264338327950288;
-
class tst_QMath : public QObject
{
Q_OBJECT
@@ -55,8 +53,9 @@ void tst_QMath::fastSinCos()
{
// Test evenly spaced angles from 0 to 2pi radians.
const int LOOP_COUNT = 100000;
+ const qreal loopAngle = 2 * M_PI / (LOOP_COUNT - 1);
for (int i = 0; i < LOOP_COUNT; ++i) {
- qreal angle = i * 2 * PI / (LOOP_COUNT - 1);
+ qreal angle = i * loopAngle;
QVERIFY(qAbs(qSin(angle) - qFastSin(angle)) < 1e-5);
QVERIFY(qAbs(qCos(angle) - qFastCos(angle)) < 1e-5);
}
@@ -69,18 +68,18 @@ void tst_QMath::degreesToRadians_data()
QTest::addColumn<double>("degreesDouble");
QTest::addColumn<double>("radiansDouble");
- QTest::newRow( "pi" ) << 180.0f << float(M_PI) << 180.0 << PI;
- QTest::newRow( "doublepi" ) << 360.0f << float(2*M_PI) << 360.0 << 2*PI;
- QTest::newRow( "halfpi" ) << 90.0f << float(M_PI_2) << 90.0 << PI/2;
+ QTest::newRow( "pi" ) << 180.0f << float(M_PI) << 180.0 << M_PI;
+ QTest::newRow( "doublepi" ) << 360.0f << float(2 * M_PI) << 360.0 << 2 * M_PI;
+ QTest::newRow( "halfpi" ) << 90.0f << float(M_PI_2) << 90.0 << M_PI_2;
QTest::newRow( "random" ) << 123.1234567f << 2.1489097058516724f << 123.123456789123456789 << 2.148909707407169856192285627;
QTest::newRow( "bigrandom" ) << 987654321.9876543f << 17237819.79023679f << 987654321987654321.987654321987654321 << 17237819790236794.0;
QTest::newRow( "zero" ) << 0.0f << 0.0f << 0.0 << 0.0;
- QTest::newRow( "minuspi" ) << -180.0f << float(-M_PI) << 180.0 << PI;
- QTest::newRow( "minusdoublepi" ) << -360.0f << float(-2*M_PI) << -360.0 << -2*PI;
- QTest::newRow( "minushalfpi" ) << -90.0f << float(-M_PI_2) << -90.0 << -PI/2;
+ QTest::newRow( "minuspi" ) << -180.0f << float(-M_PI) << 180.0 << M_PI;
+ QTest::newRow( "minusdoublepi" ) << -360.0f << float(-2 * M_PI) << -360.0 << -2 * M_PI;
+ QTest::newRow( "minushalfpi" ) << -90.0f << float(-M_PI_2) << -90.0 << -M_PI_2;
QTest::newRow( "minusrandom" ) << -123.1234567f << -2.1489097058516724f << -123.123456789123456789 << -2.148909707407169856192285627;
QTest::newRow( "minusbigrandom" ) << -987654321.9876543f << -17237819.79023679f << -987654321987654321.987654321987654321 << -17237819790236794.0;
@@ -104,18 +103,18 @@ void tst_QMath::radiansToDegrees_data()
QTest::addColumn<double>("radiansDouble");
QTest::addColumn<double>("degreesDouble");
- QTest::newRow( "pi" ) << float(M_PI) << 180.0f << PI << 180.0;
- QTest::newRow( "doublepi" ) << float(2*M_PI) << 360.0f << 2*PI << 360.0;
- QTest::newRow( "halfpi" ) << float(M_PI_2) << 90.0f<< PI/2 << 90.0;
+ QTest::newRow( "pi" ) << float(M_PI) << 180.0f << M_PI << 180.0;
+ QTest::newRow( "doublepi" ) << float(2 * M_PI) << 360.0f << 2 * M_PI << 360.0;
+ QTest::newRow( "halfpi" ) << float(M_PI_2) << 90.0f << M_PI_2 << 90.0;
QTest::newRow( "random" ) << 123.1234567f << 7054.454427971739f << 123.123456789123456789 << 7054.4544330781363896676339209079742431640625;
QTest::newRow( "bigrandom" ) << 987654321.9876543f << 56588424267.74745f << 987654321987654321.987654321987654321 << 56588424267747450880.0;
QTest::newRow( "zero" ) << 0.0f << 0.0f << 0.0 << 0.0;
- QTest::newRow( "minuspi" ) << float(-M_PI) << -180.0f << -PI << -180.0;
- QTest::newRow( "minusdoublepi" ) << float(-2*M_PI) << -360.0f << -2*PI << -360.0;
- QTest::newRow( "minushalfpi" ) << float(-M_PI_2) << -90.0f << -PI/2 << -90.0;
+ QTest::newRow( "minuspi" ) << float(-M_PI) << -180.0f << -M_PI << -180.0;
+ QTest::newRow( "minusdoublepi" ) << float(-2 * M_PI) << -360.0f << -2 * M_PI << -360.0;
+ QTest::newRow( "minushalfpi" ) << float(-M_PI_2) << -90.0f << -M_PI_2 << -90.0;
QTest::newRow( "minusrandom" ) << -123.1234567f << -7054.454427971739f << -123.123456789123456789 << -7054.4544330781363896676339209079742431640625;
QTest::newRow( "minusbigrandom" ) << -987654321.9876543f << -56588424267.74745f << -987654321987654321.987654321987654321 << -56588424267747450880.0;
diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
index e793d71fe2..35e14b7dbf 100644
--- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
+++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp
@@ -147,6 +147,77 @@ namespace MyNamespace {
{
Q_OBJECT
};
+
+ class ClassWithSetterGetterSignals : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ int value1() const { return m_value1; }
+ void setValue1(int v) {
+ if (v != m_value1) {
+ m_value1 = v;
+ Q_EMIT value1Changed();
+ }
+ }
+
+ int value2() const { return m_value2; }
+ void setValue2(int v) {
+ if (v != m_value2) {
+ m_value2 = v;
+ Q_EMIT value2Changed();
+ }
+ }
+
+ Q_SIGNALS:
+ void value1Changed();
+ void value2Changed();
+
+ private:
+ int m_value1 = 0;
+ int m_value2 = 0;
+ };
+
+ class ClassWithSetterGetterSignalsAddsProperties : public ClassWithSetterGetterSignals
+ {
+ Q_OBJECT
+ Q_PROPERTY(int value1 READ value1 WRITE setValue1 NOTIFY value1Changed)
+ Q_PROPERTY(int value2 READ value2 WRITE setValue2 NOTIFY value2Changed)
+ };
+
+ class ClassWithChangedSignal : public QObject
+ {
+ Q_OBJECT
+
+ public:
+ int value1() const { return m_value1; }
+ void setValue1(int v) {
+ if (v != m_value1) {
+ m_value1 = v;
+ Q_EMIT propertiesChanged();
+ }
+ }
+
+ void thisIsNotASignal() { }
+
+ Q_SIGNALS:
+ void propertiesChanged();
+
+ private:
+ int m_value1 = 0;
+ };
+
+ class ClassWithChangedSignalNewValue : public ClassWithChangedSignal
+ {
+ Q_OBJECT
+
+ Q_PROPERTY(int value2 MEMBER m_value2 NOTIFY propertiesChanged)
+ Q_PROPERTY(int value3 MEMBER m_value3 NOTIFY thisIsNotASignal)
+
+ private:
+ int m_value2 = 0;
+ int m_value3 = 0;
+ };
}
@@ -200,8 +271,11 @@ public:
private slots:
void connectSlotsByName();
void invokeMetaMember();
+ void invokePointer();
void invokeQueuedMetaMember();
+ void invokeQueuedPointer();
void invokeBlockingQueuedMetaMember();
+ void invokeBlockingQueuedPointer();
void invokeCustomTypes();
void invokeMetaConstructor();
void invokeTypedefTypes();
@@ -242,6 +316,8 @@ private slots:
void inherits_data();
void inherits();
+ void notifySignalsInParentClass();
+
signals:
void value6Changed();
void value7Changed(const QString &);
@@ -427,6 +503,10 @@ public slots:
+ QString::number(o6.size());
}
+public:
+ static void staticFunction0();
+ static qint64 staticFunction1();
+
signals:
void sig0();
QString sig1(QString s1);
@@ -440,8 +520,11 @@ private:
public:
QString slotResult;
+ static QString staticResult;
};
+QString QtTestObject::staticResult;
+
QtTestObject::QtTestObject()
{
connect(this, SIGNAL(sig0()), this, SLOT(sl0()));
@@ -500,6 +583,13 @@ void QtTestObject::testSender()
void QtTestObject::slotWithUnregisteredParameterType(MyUnregisteredType)
{ slotResult = "slotWithUnregisteredReturnType"; }
+void QtTestObject::staticFunction0()
+{
+ staticResult = "staticFunction0";
+}
+
+qint64 QtTestObject::staticFunction1()
+{ staticResult = "staticFunction1"; return Q_INT64_C(123456789)*123456789; }
void tst_QMetaObject::invokeMetaMember()
{
@@ -508,9 +598,18 @@ void tst_QMetaObject::invokeMetaMember()
QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5");
QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X");
- QVERIFY(!QMetaObject::invokeMethod(0, 0));
- QVERIFY(!QMetaObject::invokeMethod(0, "sl0"));
- QVERIFY(!QMetaObject::invokeMethod(&obj, 0));
+ // Test nullptr
+ char *nullCharArray = nullptr;
+ const char *nullConstCharArray = nullptr;
+ QVERIFY(!QMetaObject::invokeMethod(nullptr, nullCharArray));
+ QVERIFY(!QMetaObject::invokeMethod(nullptr, nullConstCharArray));
+ QVERIFY(!QMetaObject::invokeMethod(nullptr, "sl0"));
+ QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray));
+ QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray));
+ QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection));
+ QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection));
+ QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection, QGenericReturnArgument()));
+ QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection, QGenericReturnArgument()));
QVERIFY(QMetaObject::invokeMethod(&obj, "sl0"));
QCOMPARE(obj.slotResult, QString("sl0"));
@@ -639,6 +738,56 @@ void tst_QMetaObject::invokeMetaMember()
QCOMPARE(obj.slotResult, QString("sl1:hehe"));
}
+void testFunction(){}
+
+
+void tst_QMetaObject::invokePointer()
+{
+ QtTestObject obj;
+ QtTestObject *const nullTestObject = nullptr;
+
+ QString t1("1");
+
+ // Test member functions
+ QVERIFY(!QMetaObject::invokeMethod(nullTestObject, &QtTestObject::sl0));
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0));
+ QCOMPARE(obj.slotResult, QString("sl0"));
+
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::testSender));
+ QCOMPARE(obj.slotResult, QString("0x0"));
+
+ qint64 return64 = 0;
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl14, &return64));
+ QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
+ QCOMPARE(obj.slotResult, QString("sl14"));
+
+ // signals
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0));
+ QCOMPARE(obj.slotResult, QString("sl0"));
+
+ // Test function pointers
+ QVERIFY(!QMetaObject::invokeMethod(0, &testFunction));
+ QVERIFY(QMetaObject::invokeMethod(&obj, &testFunction));
+
+ QVERIFY(!QMetaObject::invokeMethod(0, &QtTestObject::staticFunction0));
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0));
+ QCOMPARE(QtTestObject::staticResult, QString("staticFunction0"));
+
+ return64 = 0;
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction1, &return64));
+ QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
+ QCOMPARE(QtTestObject::staticResult, QString("staticFunction1"));
+
+ // Test lambdas
+ QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.sl1(t1);}));
+ QCOMPARE(obj.slotResult, QString("sl1:1"));
+
+ QString exp;
+ QVERIFY(QMetaObject::invokeMethod(&obj, [&]()->QString{return obj.sl1("bubu");}, &exp));
+ QCOMPARE(exp, QString("yessir"));
+ QCOMPARE(obj.slotResult, QString("sl1:bubu"));
+}
+
void tst_QMetaObject::invokeQueuedMetaMember()
{
QtTestObject obj;
@@ -699,6 +848,44 @@ void tst_QMetaObject::invokeQueuedMetaMember()
}
}
+void tst_QMetaObject::invokeQueuedPointer()
+{
+ QtTestObject obj;
+
+ // Test member function
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0, Qt::QueuedConnection));
+ QVERIFY(obj.slotResult.isEmpty());
+ qApp->processEvents(QEventLoop::AllEvents);
+ QCOMPARE(obj.slotResult, QString("sl0"));
+
+ // signals
+ obj.slotResult.clear();
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0, Qt::QueuedConnection));
+ QVERIFY(obj.slotResult.isEmpty());
+ qApp->processEvents(QEventLoop::AllEvents);
+ QCOMPARE(obj.slotResult, QString("sl0"));
+
+ // Test function pointers
+ QtTestObject::staticResult.clear();
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0, Qt::QueuedConnection));
+ QVERIFY(QtTestObject::staticResult.isEmpty());
+ qApp->processEvents(QEventLoop::AllEvents);
+ QCOMPARE(QtTestObject::staticResult, QString("staticFunction0"));
+
+ // Test lambda
+ obj.slotResult.clear();
+ QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.sl0();}, Qt::QueuedConnection));
+ QVERIFY(obj.slotResult.isEmpty());
+ qApp->processEvents(QEventLoop::AllEvents);
+ QCOMPARE(obj.slotResult, QString("sl0"));
+
+ qint32 var = 0;
+ QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: Unable to invoke methods with return values in queued connections");
+ QVERIFY(!QMetaObject::invokeMethod(&obj, []()->qint32{return 1;}, Qt::QueuedConnection, &var));
+ QCOMPARE(var, 0);
+}
+
+
void tst_QMetaObject::invokeBlockingQueuedMetaMember()
{
QThread t;
@@ -832,6 +1019,62 @@ void tst_QMetaObject::invokeBlockingQueuedMetaMember()
}
+void tst_QMetaObject::invokeBlockingQueuedPointer()
+{
+ QtTestObject *const nullTestObject = nullptr;
+
+ QThread t;
+ t.start();
+ QtTestObject obj;
+ obj.moveToThread(&t);
+
+ QString t1("1");
+
+ // Test member functions
+ QVERIFY(!QMetaObject::invokeMethod(nullTestObject, &QtTestObject::sl0, Qt::BlockingQueuedConnection));
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0, Qt::BlockingQueuedConnection));
+ QCOMPARE(obj.slotResult, QString("sl0"));
+
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::testSender, Qt::BlockingQueuedConnection));
+ QCOMPARE(obj.slotResult, QString("0x0"));
+
+ // return qint64
+ qint64 return64 = 0;
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl14, Qt::BlockingQueuedConnection,
+ &return64));
+ QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
+ QCOMPARE(obj.slotResult, QString("sl14"));
+
+ //test signals
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0, Qt::BlockingQueuedConnection));
+ QCOMPARE(obj.slotResult, QString("sl0"));
+
+ // Test function pointers
+ QVERIFY(!QMetaObject::invokeMethod(0, &testFunction, Qt::BlockingQueuedConnection));
+ QVERIFY(QMetaObject::invokeMethod(&obj, &testFunction, Qt::BlockingQueuedConnection));
+
+ QVERIFY(!QMetaObject::invokeMethod(0, &QtTestObject::staticFunction0, Qt::BlockingQueuedConnection));
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0, Qt::BlockingQueuedConnection));
+ QCOMPARE(QtTestObject::staticResult, QString("staticFunction0"));
+
+ return64 = 0;
+ QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction1, Qt::BlockingQueuedConnection, &return64));
+ QCOMPARE(return64, Q_INT64_C(123456789)*123456789);
+ QCOMPARE(QtTestObject::staticResult, QString("staticFunction1"));
+
+ // Test lambdas
+ QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.sl1(t1);}, Qt::BlockingQueuedConnection));
+ QCOMPARE(obj.slotResult, QString("sl1:1"));
+
+ QString exp;
+ QVERIFY(QMetaObject::invokeMethod(&obj, [&]()->QString{return obj.sl1("bubu");}, Qt::BlockingQueuedConnection, &exp));
+ QCOMPARE(exp, QString("yessir"));
+ QCOMPARE(obj.slotResult, QString("sl1:bubu"));
+
+ QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.moveToThread(QThread::currentThread());}, Qt::BlockingQueuedConnection));
+ t.quit();
+ QVERIFY(t.wait());
+}
void tst_QMetaObject::qtMetaObjectInheritance()
@@ -1502,5 +1745,18 @@ void tst_QMetaObject::inherits()
QCOMPARE(derivedMetaObject->inherits(baseMetaObject), inheritsResult);
}
+void tst_QMetaObject::notifySignalsInParentClass()
+{
+ MyNamespace::ClassWithSetterGetterSignalsAddsProperties obj;
+ QCOMPARE(obj.metaObject()->property(obj.metaObject()->indexOfProperty("value1")).notifySignal().name(), QByteArray("value1Changed"));
+ QCOMPARE(obj.metaObject()->property(obj.metaObject()->indexOfProperty("value2")).notifySignal().name(), QByteArray("value2Changed"));
+
+ MyNamespace::ClassWithChangedSignalNewValue obj2;
+ QCOMPARE(obj2.metaObject()->property(obj2.metaObject()->indexOfProperty("value2")).notifySignal().name(), QByteArray("propertiesChanged"));
+
+ QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::notifySignal: cannot find the NOTIFY signal thisIsNotASignal in class MyNamespace::ClassWithChangedSignalNewValue for property 'value3'");
+ obj2.metaObject()->property(obj2.metaObject()->indexOfProperty("value3")).notifySignal();
+}
+
QTEST_MAIN(tst_QMetaObject)
#include "tst_qmetaobject.moc"
diff --git a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
index 9ae39449f8..6bb031e357 100644
--- a/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
+++ b/tests/auto/corelib/kernel/qmetaobjectbuilder/tst_qmetaobjectbuilder.cpp
@@ -806,6 +806,7 @@ void tst_QMetaObjectBuilder::enumerator()
QMetaEnumBuilder enum1 = builder.addEnumerator("foo");
QCOMPARE(enum1.name(), QByteArray("foo"));
QVERIFY(!enum1.isFlag());
+ QVERIFY(!enum1.isScoped());
QCOMPARE(enum1.keyCount(), 0);
QCOMPARE(enum1.index(), 0);
QCOMPARE(builder.enumeratorCount(), 1);
@@ -814,6 +815,7 @@ void tst_QMetaObjectBuilder::enumerator()
QMetaEnumBuilder enum2 = builder.addEnumerator("bar");
QCOMPARE(enum2.name(), QByteArray("bar"));
QVERIFY(!enum2.isFlag());
+ QVERIFY(!enum2.isScoped());
QCOMPARE(enum2.keyCount(), 0);
QCOMPARE(enum2.index(), 1);
QCOMPARE(builder.enumeratorCount(), 2);
@@ -827,6 +829,7 @@ void tst_QMetaObjectBuilder::enumerator()
// Modify the attributes on enum1.
enum1.setIsFlag(true);
+ enum1.setIsScoped(true);
QCOMPARE(enum1.addKey("ABC", 0), 0);
QCOMPARE(enum1.addKey("DEF", 1), 1);
QCOMPARE(enum1.addKey("GHI", -1), 2);
@@ -834,6 +837,7 @@ void tst_QMetaObjectBuilder::enumerator()
// Check that enum1 is changed, but enum2 is not.
QCOMPARE(enum1.name(), QByteArray("foo"));
QVERIFY(enum1.isFlag());
+ QVERIFY(enum1.isScoped());
QCOMPARE(enum1.keyCount(), 3);
QCOMPARE(enum1.index(), 0);
QCOMPARE(enum1.key(0), QByteArray("ABC"));
@@ -845,6 +849,7 @@ void tst_QMetaObjectBuilder::enumerator()
QCOMPARE(enum1.value(2), -1);
QCOMPARE(enum2.name(), QByteArray("bar"));
QVERIFY(!enum2.isFlag());
+ QVERIFY(!enum2.isScoped());
QCOMPARE(enum2.keyCount(), 0);
QCOMPARE(enum2.index(), 1);
@@ -856,6 +861,7 @@ void tst_QMetaObjectBuilder::enumerator()
// This time check that only method2 changed.
QCOMPARE(enum1.name(), QByteArray("foo"));
QVERIFY(enum1.isFlag());
+ QVERIFY(enum1.isScoped());
QCOMPARE(enum1.keyCount(), 3);
QCOMPARE(enum1.index(), 0);
QCOMPARE(enum1.key(0), QByteArray("ABC"));
@@ -867,6 +873,7 @@ void tst_QMetaObjectBuilder::enumerator()
QCOMPARE(enum1.value(2), -1);
QCOMPARE(enum2.name(), QByteArray("bar"));
QVERIFY(enum2.isFlag());
+ QVERIFY(!enum2.isScoped());
QCOMPARE(enum2.keyCount(), 2);
QCOMPARE(enum2.index(), 1);
QCOMPARE(enum2.key(0), QByteArray("XYZ"));
@@ -879,6 +886,7 @@ void tst_QMetaObjectBuilder::enumerator()
enum1.removeKey(2);
QCOMPARE(enum1.name(), QByteArray("foo"));
QVERIFY(enum1.isFlag());
+ QVERIFY(enum1.isScoped());
QCOMPARE(enum1.keyCount(), 2);
QCOMPARE(enum1.index(), 0);
QCOMPARE(enum1.key(0), QByteArray("ABC"));
@@ -889,6 +897,7 @@ void tst_QMetaObjectBuilder::enumerator()
QCOMPARE(enum1.value(2), -1);
QCOMPARE(enum2.name(), QByteArray("bar"));
QVERIFY(enum2.isFlag());
+ QVERIFY(!enum2.isScoped());
QCOMPARE(enum2.keyCount(), 2);
QCOMPARE(enum2.index(), 1);
QCOMPARE(enum2.key(0), QByteArray("XYZ"));
@@ -903,6 +912,7 @@ void tst_QMetaObjectBuilder::enumerator()
enum2 = builder.enumerator(0);
QCOMPARE(enum2.name(), QByteArray("bar"));
QVERIFY(enum2.isFlag());
+ QVERIFY(!enum2.isScoped());
QCOMPARE(enum2.keyCount(), 2);
QCOMPARE(enum2.index(), 0);
QCOMPARE(enum2.key(0), QByteArray("XYZ"));
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index f9ddd59aaa..076610a0c5 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -155,7 +155,9 @@ void tst_QMetaType::defined()
QCOMPARE(int(QMetaTypeId2<int*>::Defined), 0);
QCOMPARE(int(QMetaTypeId2<CustomQObject::CustomQEnum>::Defined), 1);
QCOMPARE(int(QMetaTypeId2<CustomGadget>::Defined), 1);
+ QCOMPARE(int(QMetaTypeId2<CustomGadget*>::Defined), 1);
QVERIFY(!QMetaTypeId2<GadgetDerived>::Defined);
+ QVERIFY(!QMetaTypeId2<GadgetDerived*>::Defined);
QVERIFY(int(QMetaTypeId2<CustomQObject*>::Defined));
QVERIFY(!QMetaTypeId2<CustomQObject>::Defined);
QVERIFY(!QMetaTypeId2<CustomNonQObject>::Defined);
@@ -397,6 +399,7 @@ void tst_QMetaType::typeName_data()
QTest::newRow("CustomQObject*") << ::qMetaTypeId<CustomQObject*>() << QString::fromLatin1("CustomQObject*");
QTest::newRow("CustomGadget") << ::qMetaTypeId<CustomGadget>() << QString::fromLatin1("CustomGadget");
+ QTest::newRow("CustomGadget*") << ::qMetaTypeId<CustomGadget*>() << QString::fromLatin1("CustomGadget*");
QTest::newRow("CustomQObject::CustomQEnum") << ::qMetaTypeId<CustomQObject::CustomQEnum>() << QString::fromLatin1("CustomQObject::CustomQEnum");
QTest::newRow("Qt::ArrowType") << ::qMetaTypeId<Qt::ArrowType>() << QString::fromLatin1("Qt::ArrowType");
}
@@ -1684,6 +1687,7 @@ public:
};
Q_DECLARE_METATYPE(MyGadget);
+Q_DECLARE_METATYPE(MyGadget*);
Q_DECLARE_METATYPE(const QMetaObject *);
Q_DECLARE_METATYPE(Qt::ScrollBarPolicy);
Q_DECLARE_METATYPE(MyGadget::MyEnum);
@@ -1693,16 +1697,18 @@ void tst_QMetaType::metaObject_data()
QTest::addColumn<int>("type");
QTest::addColumn<const QMetaObject*>("result");
QTest::addColumn<bool>("isGadget");
+ QTest::addColumn<bool>("isGadgetPtr");
QTest::addColumn<bool>("isQObjectPtr");
- QTest::newRow("QObject") << int(QMetaType::QObjectStar) << &QObject::staticMetaObject << false << true;
- QTest::newRow("QFile*") << ::qMetaTypeId<QFile*>() << &QFile::staticMetaObject << false << true;
- QTest::newRow("MyObject*") << ::qMetaTypeId<MyObject*>() << &MyObject::staticMetaObject << false << true;
- QTest::newRow("int") << int(QMetaType::Int) << static_cast<const QMetaObject *>(0) << false << false;
- QTest::newRow("QEasingCurve") << ::qMetaTypeId<QEasingCurve>() << &QEasingCurve::staticMetaObject << true << false;
- QTest::newRow("MyGadget") << ::qMetaTypeId<MyGadget>() << &MyGadget::staticMetaObject << true << false;
- QTest::newRow("MyEnum") << ::qMetaTypeId<MyGadget::MyEnum>() << &MyGadget::staticMetaObject << false << false;
- QTest::newRow("Qt::ScrollBarPolicy") << ::qMetaTypeId<Qt::ScrollBarPolicy>() << &QObject::staticQtMetaObject << false << false;
+ QTest::newRow("QObject") << int(QMetaType::QObjectStar) << &QObject::staticMetaObject << false << false << true;
+ QTest::newRow("QFile*") << ::qMetaTypeId<QFile*>() << &QFile::staticMetaObject << false << false << true;
+ QTest::newRow("MyObject*") << ::qMetaTypeId<MyObject*>() << &MyObject::staticMetaObject << false << false << true;
+ QTest::newRow("int") << int(QMetaType::Int) << static_cast<const QMetaObject *>(0) << false << false << false;
+ QTest::newRow("QEasingCurve") << ::qMetaTypeId<QEasingCurve>() << &QEasingCurve::staticMetaObject << true << false << false;
+ QTest::newRow("MyGadget") << ::qMetaTypeId<MyGadget>() << &MyGadget::staticMetaObject << true << false << false;
+ QTest::newRow("MyGadget*") << ::qMetaTypeId<MyGadget*>() << &MyGadget::staticMetaObject << false << true << false;
+ QTest::newRow("MyEnum") << ::qMetaTypeId<MyGadget::MyEnum>() << &MyGadget::staticMetaObject << false << false << false;
+ QTest::newRow("Qt::ScrollBarPolicy") << ::qMetaTypeId<Qt::ScrollBarPolicy>() << &QObject::staticQtMetaObject << false << false << false;
}
@@ -1711,12 +1717,14 @@ void tst_QMetaType::metaObject()
QFETCH(int, type);
QFETCH(const QMetaObject *, result);
QFETCH(bool, isGadget);
+ QFETCH(bool, isGadgetPtr);
QFETCH(bool, isQObjectPtr);
QCOMPARE(QMetaType::metaObjectForType(type), result);
QMetaType mt(type);
QCOMPARE(mt.metaObject(), result);
QCOMPARE(!!(mt.flags() & QMetaType::IsGadget), isGadget);
+ QCOMPARE(!!(mt.flags() & QMetaType::PointerToGadget), isGadgetPtr);
QCOMPARE(!!(mt.flags() & QMetaType::PointerToQObject), isQObjectPtr);
}
diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
index 642d48d721..3a52c684d0 100644
--- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
+++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp
@@ -140,6 +140,7 @@ private slots:
void connectFunctorWithContext();
void connectFunctorWithContextUnique();
void connectFunctorDeadlock();
+ void connectFunctorMoveOnly();
void connectStaticSlotWithObject();
void disconnectDoesNotLeakFunctor();
void contextDoesNotLeakFunctor();
@@ -6237,6 +6238,47 @@ void tst_QObject::connectFunctorDeadlock()
sender.emitSignal1();
}
+void tst_QObject::connectFunctorMoveOnly()
+{
+ struct MoveOnlyFunctor {
+ Q_DISABLE_COPY(MoveOnlyFunctor)
+ MoveOnlyFunctor(int *status) : status(status) {}
+ MoveOnlyFunctor(MoveOnlyFunctor &&o) : status(o.status) { o.status = nullptr; };
+ void operator()(int i) { *status = i; }
+ void operator()() { *status = -8; }
+ int *status;
+ };
+
+ int status = 1;
+ SenderObject obj;
+ QEventLoop e;
+
+ connect(&obj, &SenderObject::signal1, MoveOnlyFunctor(&status));
+ QCOMPARE(status, 1);
+ obj.signal1();
+ QCOMPARE(status, -8);
+
+ connect(&obj, &SenderObject::signal7, MoveOnlyFunctor(&status));
+ QCOMPARE(status, -8);
+ obj.signal7(7888, "Hello");
+ QCOMPARE(status, 7888);
+
+ // With a context
+ status = 1;
+ connect(&obj, &SenderObject::signal2, this, MoveOnlyFunctor(&status));
+ QCOMPARE(status, 1);
+ obj.signal2();
+ QCOMPARE(status, -8);
+
+ // QueuedConnection
+ status = 1;
+ connect(&obj, &SenderObject::signal3, this, MoveOnlyFunctor(&status), Qt::QueuedConnection);
+ obj.signal3();
+ QCOMPARE(status, 1);
+ QCoreApplication::processEvents();
+ QCOMPARE(status, -8);
+}
+
static int s_static_slot_checker = 1;
class StaticSlotChecker : public QObject
diff --git a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
index fd704f582d..e17d8ee38b 100644
--- a/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
+++ b/tests/auto/corelib/kernel/qtimer/tst_qtimer.cpp
@@ -836,7 +836,6 @@ void tst_QTimer::singleShotToFunctors()
QTest::qWait(800);
QCOMPARE(count, 2);
-#if defined(Q_COMPILER_LAMBDA)
QTimer::singleShot(0, [&count] { ++count; });
QCoreApplication::processEvents();
QCOMPARE(count, 3);
@@ -855,7 +854,15 @@ void tst_QTimer::singleShotToFunctors()
thread.quit();
thread.wait();
-#endif
+
+ struct MoveOnly : CountedStruct {
+ Q_DISABLE_COPY(MoveOnly);
+ MoveOnly(MoveOnly &&o) : CountedStruct(std::move(o)) {};
+ MoveOnly(int *c) : CountedStruct(c) {}
+ };
+ QTimer::singleShot(0, MoveOnly(&count));
+ QCoreApplication::processEvents();
+ QCOMPARE(count, 5);
_e.reset();
_t = Q_NULLPTR;
diff --git a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
index 66971af7b4..5bfe133966 100644
--- a/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
+++ b/tests/auto/corelib/kernel/qtranslator/tst_qtranslator.cpp
@@ -50,6 +50,7 @@ private slots:
void loadFromResource();
void loadDirectory();
void dependencies();
+ void translationInThreadWhileInstallingTranslator();
private:
int languageChangeEventCounter;
@@ -287,6 +288,52 @@ void tst_QTranslator::dependencies()
}
}
+struct TranslateThread : public QThread
+{
+ bool ok = false;
+ QAtomicInt terminate;
+ QMutex startupLock;
+ QWaitCondition runningCondition;
+
+ void run() {
+ bool startSignalled = false;
+
+ while (terminate.load() == 0) {
+ const QString result = QCoreApplication::translate("QPushButton", "Hello %n world(s)!", 0, 0);
+
+ if (!startSignalled) {
+ QMutexLocker startupLocker(&startupLock);
+ runningCondition.wakeAll();
+ startSignalled = true;
+ }
+
+ ok = (result == QLatin1String("Hallo 0 Welten!"))
+ || (result == QLatin1String("Hello 0 world(s)!"));
+ if (!ok)
+ break;
+ }
+ }
+};
+
+void tst_QTranslator::translationInThreadWhileInstallingTranslator()
+{
+ TranslateThread thread;
+
+ QMutexLocker startupLocker(&thread.startupLock);
+
+ thread.start();
+
+ thread.runningCondition.wait(&thread.startupLock);
+
+ QTranslator *tor = new QTranslator;
+ tor->load("hellotr_la");
+ QCoreApplication::installTranslator(tor);
+
+ ++thread.terminate;
+
+ QVERIFY(thread.wait());
+ QVERIFY(thread.ok);
+}
QTEST_MAIN(tst_QTranslator)
#include "tst_qtranslator.moc"
diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
index e43b7acfb8..0d45159d09 100644
--- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
+++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp
@@ -277,6 +277,8 @@ private slots:
void compareSanity();
void compareRich();
+ void nullConvert();
+
void accessSequentialContainerKey();
private:
@@ -369,6 +371,8 @@ void tst_QVariant::copy_constructor()
QVERIFY(var8.isNull());
}
+Q_DECLARE_METATYPE(int*)
+
void tst_QVariant::isNull()
{
QVariant var;
@@ -411,6 +415,18 @@ void tst_QVariant::isNull()
QVERIFY(var9.isNull());
var9 = QVariant::fromValue<QJsonValue>(QJsonValue(QJsonValue::Null));
QVERIFY(var9.isNull());
+
+ QVariant var10(QMetaType::VoidStar, nullptr);
+ QVERIFY(var10.isNull());
+ var10 = QVariant::fromValue<void*>(nullptr);
+ QVERIFY(var10.isNull());
+
+ QVariant var11(QMetaType::QObjectStar, nullptr);
+ QVERIFY(var11.isNull());
+ var11 = QVariant::fromValue<QObject*>(nullptr);
+ QVERIFY(var11.isNull());
+
+ QVERIFY(QVariant::fromValue<int*>(nullptr).isNull());
}
void tst_QVariant::swap()
@@ -1046,6 +1062,7 @@ void tst_QVariant::toByteArray_data()
QTest::newRow( "longlong" ) << QVariant( (qlonglong)34 ) << QByteArray( "34" );
QTest::newRow( "ulonglong" ) << QVariant( (qulonglong)34 ) << QByteArray( "34" );
+ QTest::newRow( "nullptr" ) << QVariant::fromValue(nullptr) << QByteArray();
}
void tst_QVariant::toByteArray()
@@ -1055,7 +1072,13 @@ void tst_QVariant::toByteArray()
QVERIFY( value.isValid() );
QVERIFY( value.canConvert( QVariant::ByteArray ) );
QByteArray ba = value.toByteArray();
+ QCOMPARE( ba.isNull(), result.isNull() );
QCOMPARE( ba, result );
+
+ QVERIFY( value.convert( QVariant::ByteArray ) );
+ QCOMPARE( value.isNull(), result.isNull() );
+ QCOMPARE( value.toByteArray().isNull(), result.isNull() );
+ QCOMPARE( value.toByteArray(), result );
}
void tst_QVariant::toString_data()
@@ -1082,6 +1105,7 @@ void tst_QVariant::toString_data()
QString( "123456789012" );
QTest::newRow("QJsonValue") << QVariant(QJsonValue(QString("hello"))) << QString("hello");
QTest::newRow("QJsonValue(Null)") << QVariant(QJsonValue(QJsonValue::Null)) << QString();
+ QTest::newRow("nullptr") << QVariant::fromValue(nullptr) << QString();
}
void tst_QVariant::toString()
@@ -1091,7 +1115,13 @@ void tst_QVariant::toString()
QVERIFY( value.isValid() );
QVERIFY( value.canConvert( QVariant::String ) );
QString str = value.toString();
+ QCOMPARE( str.isNull(), result.isNull() );
QCOMPARE( str, result );
+
+ QVERIFY( value.convert( QVariant::String ) );
+ QCOMPARE( value.isNull(), result.isNull() );
+ QCOMPARE( value.toString().isNull(), result.isNull() );
+ QCOMPARE( value.toString(), result );
}
void tst_QVariant::toDate_data()
@@ -2648,7 +2678,7 @@ void tst_QVariant::qvariant_cast_QObject_data()
QTest::newRow("null QObject") << QVariant::fromValue<QObject*>(0) << true << true;
QTest::newRow("null derived QObject") << QVariant::fromValue<CustomQObject*>(0) << true << true;
QTest::newRow("null custom object") << QVariant::fromValue<CustomNonQObject*>(0) << false << true;
- QTest::newRow("null int") << QVariant::fromValue<int>(0) << false << true;
+ QTest::newRow("zero int") << QVariant::fromValue<int>(0) << false << false;
}
void tst_QVariant::qvariant_cast_QObject()
@@ -2666,12 +2696,14 @@ void tst_QVariant::qvariant_cast_QObject()
QVERIFY(data.canConvert(QMetaType::QObjectStar));
QVERIFY(data.canConvert(::qMetaTypeId<QObject*>()));
QCOMPARE(data.value<QObject*>() == 0, isNull);
+ QCOMPARE(data.isNull(), isNull);
QVERIFY(data.convert(QMetaType::QObjectStar));
QCOMPARE(data.userType(), int(QMetaType::QObjectStar));
} else {
QVERIFY(!data.canConvert<QObject*>());
QVERIFY(!data.canConvert(QMetaType::QObjectStar));
QVERIFY(!data.canConvert(::qMetaTypeId<QObject*>()));
+ QCOMPARE(data.isNull(), isNull);
QVERIFY(!data.value<QObject*>());
QVERIFY(!data.convert(QMetaType::QObjectStar));
QVERIFY(data.userType() != QMetaType::QObjectStar);
@@ -3403,21 +3435,6 @@ void tst_QVariant::toIntFromDouble() const
QCOMPARE(result, 2147483630);
}
-void tst_QVariant::setValue()
-{
- QJsonDocument t; //we just take a value so that we're sure that it will be shared
- QVariant v1 = QVariant::fromValue(t);
- QVERIFY( v1.isDetached() );
- QVariant v2 = v1;
- QVERIFY( !v1.isDetached() );
- QVERIFY( !v2.isDetached() );
-
- v2.setValue(3); //set an integer value
-
- QVERIFY( v1.isDetached() );
- QVERIFY( v2.isDetached() );
-}
-
void tst_QVariant::fpStringRoundtrip_data() const
{
QTest::addColumn<QVariant>("number");
@@ -3649,6 +3666,20 @@ Q_DECLARE_METATYPE(MyMovable *)
Q_DECLARE_METATYPE(MyNotMovable *)
Q_DECLARE_METATYPE(QSharedDataPointer<MyShared>)
+void tst_QVariant::setValue()
+{
+ MyNotMovable t; //we just take a value so that we're sure that it will be shared
+ QVariant v1 = QVariant::fromValue(t);
+ QVERIFY( v1.isDetached() );
+ QVariant v2 = v1;
+ QVERIFY( !v1.isDetached() );
+ QVERIFY( !v2.isDetached() );
+
+ v2.setValue(3); //set an integer value
+
+ QVERIFY( v1.isDetached() );
+ QVERIFY( v2.isDetached() );
+}
void tst_QVariant::moreCustomTypes()
{
@@ -3751,7 +3782,7 @@ void tst_QVariant::moreCustomTypes()
{
int i = 5;
PLAY_WITH_VARIANT((void *)(&i), false, QString(), 0, false);
- PLAY_WITH_VARIANT((void *)(0), false, QString(), 0, false);
+ PLAY_WITH_VARIANT((void *)(0), true, QString(), 0, false);
}
{
@@ -4862,6 +4893,33 @@ void tst_QVariant::compareRich()
<< QStringLiteral("d"));
}
+void tst_QVariant::nullConvert()
+{
+ // Test quirks with QVariants different types of null states.
+
+ // null variant with no initialized value
+ QVariant nullVar(QVariant::String);
+ QVERIFY(nullVar.isValid());
+ QVERIFY(nullVar.isNull());
+ // We can not convert a variant with no value
+ QVERIFY(!nullVar.convert(QVariant::Url));
+ QCOMPARE(nullVar.type(), QVariant::Url);
+ QVERIFY(nullVar.isNull());
+
+ // variant initialized with null value
+ QVariant nullStr = QVariant::fromValue(QString());
+ QVERIFY(nullStr.isValid());
+ QVERIFY(nullStr.isNull());
+ // We can convert an initialized null value however
+ QVERIFY(nullStr.convert(QVariant::Url));
+ QCOMPARE(nullStr.type(), QVariant::Url);
+ QVERIFY(nullStr.isValid());
+ // QUrl does not have an isNull method
+ QVERIFY(!nullStr.isNull());
+ // The URL is not valid however
+ QVERIFY(!nullStr.toUrl().isValid());
+}
+
void tst_QVariant::accessSequentialContainerKey()
{
QString nameResult;
@@ -4886,6 +4944,5 @@ void tst_QVariant::accessSequentialContainerKey()
QCOMPARE(nameResult, QStringLiteral("Seven"));
}
-
QTEST_MAIN(tst_QVariant)
#include "tst_qvariant.moc"
diff --git a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
index 3221587300..304f6121a5 100644
--- a/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
+++ b/tests/auto/corelib/kernel/qwineventnotifier/tst_qwineventnotifier.cpp
@@ -31,6 +31,8 @@
#include <qtimer.h>
#include <qt_windows.h>
+#include <memory>
+
class tst_QWinEventNotifier : public QObject
{
Q_OBJECT
@@ -40,6 +42,7 @@ protected slots:
void simple_timerSet();
private slots:
void simple();
+ void manyNotifiers();
private:
HANDLE simpleHEvent;
@@ -87,6 +90,91 @@ void tst_QWinEventNotifier::simple()
QVERIFY(simpleActivated);
}
+class EventWithNotifier : public QObject
+{
+ Q_OBJECT
+public:
+ EventWithNotifier()
+ {
+ connect(&notifier, &QWinEventNotifier::activated,
+ this, &EventWithNotifier::onNotifierActivated);
+ notifier.setHandle(CreateEvent(0, TRUE, FALSE, 0));
+ notifier.setEnabled(true);
+
+ static int nextIndex = 0;
+ idx = nextIndex++;
+ }
+
+ ~EventWithNotifier()
+ {
+ notifier.setEnabled(false);
+ CloseHandle(notifier.handle());
+ }
+
+ HANDLE eventHandle() const { return notifier.handle(); }
+ int numberOfTimesActivated() const { return activatedCount; }
+
+signals:
+ void activated();
+
+public slots:
+ void onNotifierActivated()
+ {
+ ResetEvent(notifier.handle());
+ activatedCount++;
+ emit activated();
+ }
+
+private:
+ QWinEventNotifier notifier;
+ int activatedCount = 0;
+ int idx = 0;
+};
+
+void tst_QWinEventNotifier::manyNotifiers()
+{
+ const size_t maxEvents = 100;
+ const size_t middleEvenEvent = maxEvents / 2;
+ Q_ASSERT(middleEvenEvent % 2 == 0);
+ using EventWithNotifierPtr = std::unique_ptr<EventWithNotifier>;
+ std::vector<EventWithNotifierPtr> events(maxEvents);
+ std::generate(events.begin(), events.end(), [] () {
+ return EventWithNotifierPtr(new EventWithNotifier);
+ });
+
+ QTestEventLoop loop;
+ auto connection = connect(events.at(8).get(), &EventWithNotifier::activated, &loop, &QTestEventLoop::exitLoop);
+ for (const auto &ewn : events) {
+ connect(ewn.get(), &EventWithNotifier::activated, [&events, &loop] () {
+ if (std::all_of(events.cbegin(), events.cend(),
+ [] (const EventWithNotifierPtr &ewn) {
+ return ewn->numberOfTimesActivated() > 0; })) {
+ loop.exitLoop();
+ }
+ });
+ }
+
+ // Activate all even events before running the event loop.
+ for (size_t i = 0; i < events.size(); i += 2)
+ SetEvent(events.at(i)->eventHandle());
+
+ // Wait until event notifier with index 8 has been activated.
+ loop.enterLoop(30);
+ QObject::disconnect(connection);
+
+ // Activate all odd events after the event loop has run for a bit.
+ for (size_t i = 1; i < events.size(); i += 2)
+ SetEvent(events.at(i)->eventHandle());
+
+ // Wait until all event notifiers have fired.
+ loop.enterLoop(30);
+
+ // All notifiers must have been activated exactly once.
+ QVERIFY(std::all_of(events.cbegin(), events.cend(), [] (const EventWithNotifierPtr &ewn) {
+ return ewn->numberOfTimesActivated() == 1;
+ }));
+}
+
QTEST_MAIN(tst_QWinEventNotifier)
#include "tst_qwineventnotifier.moc"
diff --git a/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp b/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp
index d93603f641..c74bce3b5b 100644
--- a/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp
+++ b/tests/auto/corelib/mimetypes/qmimetype/tst_qmimetype.cpp
@@ -46,6 +46,7 @@ private slots:
void genericIconName();
void iconName();
void suffixes();
+ void gadget();
};
// ------------------------------------------------------------------------------------------------
@@ -201,5 +202,44 @@ void tst_qmimetype::suffixes()
// ------------------------------------------------------------------------------------------------
+void tst_qmimetype::gadget()
+{
+ QMimeType instantiatedQMimeType (
+ buildQMimeType (
+ qMimeTypeName(),
+ qMimeTypeGenericIconName(),
+ qMimeTypeIconName(),
+ qMimeTypeGlobPatterns()
+ )
+ );
+
+ const QMetaObject *metaObject = &instantiatedQMimeType.staticMetaObject;
+
+ QCOMPARE(metaObject->className(), "QMimeType");
+ QVariantMap properties;
+ for (int i = metaObject->propertyOffset(); i < metaObject->propertyCount(); i++) {
+ QMetaProperty property = metaObject->property(i);
+ properties[property.name()] = property.readOnGadget(&instantiatedQMimeType);
+ }
+
+ QCOMPARE(properties["valid"].toBool(), instantiatedQMimeType.isValid());
+ QCOMPARE(properties["isDefault"].toBool(), instantiatedQMimeType.isDefault());
+ QCOMPARE(properties["name"].toString(), instantiatedQMimeType.name());
+ QCOMPARE(properties["comment"].toString(), instantiatedQMimeType.comment());
+ QCOMPARE(properties["genericIconName"].toString(), instantiatedQMimeType.genericIconName());
+ QCOMPARE(properties["iconName"].toString(), instantiatedQMimeType.iconName());
+ QCOMPARE(properties["globPatterns"].toStringList(), instantiatedQMimeType.globPatterns());
+ QCOMPARE(properties["parentMimeTypes"].toStringList(), instantiatedQMimeType.parentMimeTypes());
+ QCOMPARE(properties["allAncestors"].toStringList(), instantiatedQMimeType.allAncestors());
+ QCOMPARE(properties["aliases"].toStringList(), instantiatedQMimeType.aliases());
+ QCOMPARE(properties["suffixes"].toStringList(), instantiatedQMimeType.suffixes());
+ QCOMPARE(properties["preferredSuffix"].toString(), instantiatedQMimeType.preferredSuffix());
+ QCOMPARE(properties["filterString"].toString(), instantiatedQMimeType.filterString());
+
+ QVERIFY(metaObject->indexOfMethod("inherits(QString)") >= 0);
+}
+
+// ------------------------------------------------------------------------------------------------
+
QTEST_GUILESS_MAIN(tst_qmimetype)
#include "tst_qmimetype.moc"
diff --git a/tests/auto/corelib/plugin/quuid/tst_quuid.cpp b/tests/auto/corelib/plugin/quuid/tst_quuid.cpp
index d3102c7ee5..9e3edc96ec 100644
--- a/tests/auto/corelib/plugin/quuid/tst_quuid.cpp
+++ b/tests/auto/corelib/plugin/quuid/tst_quuid.cpp
@@ -41,6 +41,7 @@ private slots:
void fromChar();
void toString();
+ void fromString_data();
void fromString();
void toByteArray();
void fromByteArray();
@@ -127,15 +128,58 @@ void tst_QUuid::toString()
QCOMPARE(uuidB.toString(), QString("{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}"));
}
+void tst_QUuid::fromString_data()
+{
+ QTest::addColumn<QUuid>("expected");
+ QTest::addColumn<QString>("input");
+
+ QUuid invalid = {};
+
+#define ROW(which, string) \
+ QTest::addRow("%-38s -> %s", string, #which) << which << string
+ ROW(uuidA, "{fc69b59e-cc34-4436-a43c-ee95d128b8c5}");
+ ROW(uuidA, "fc69b59e-cc34-4436-a43c-ee95d128b8c5}");
+ ROW(uuidA, "{fc69b59e-cc34-4436-a43c-ee95d128b8c5" );
+ ROW(uuidA, "fc69b59e-cc34-4436-a43c-ee95d128b8c5" );
+
+ ROW(uuidA, "{fc69b59e-cc34-4436-a43c-ee95d128b8c56"); // too long (not an error!)
+ ROW(invalid, "{fc69b59e-cc34-4436-a43c-ee95d128b8c" ); // premature end (within length limits)
+ ROW(invalid, " fc69b59e-cc34-4436-a43c-ee95d128b8c5}"); // leading space
+ ROW(uuidA, "{fc69b59e-cc34-4436-a43c-ee95d128b8c5 "); // trailing space (not an error!)
+ ROW(invalid, "{gc69b59e-cc34-4436-a43c-ee95d128b8c5}"); // non-hex digit in 1st group
+ ROW(invalid, "{fc69b59e-cp34-4436-a43c-ee95d128b8c5}"); // non-hex digit in 2nd group
+ ROW(invalid, "{fc69b59e-cc34-44r6-a43c-ee95d128b8c5}"); // non-hex digit in 3rd group
+ ROW(invalid, "{fc69b59e-cc34-4436-a4yc-ee95d128b8c5}"); // non-hex digit in 4th group
+ ROW(invalid, "{fc69b59e-cc34-4436-a43c-ee95d128j8c5}"); // non-hex digit in last group
+ ROW(invalid, "(fc69b59e-cc34-4436-a43c-ee95d128b8c5}"); // wrong initial character
+ ROW(invalid, "{fc69b59e+cc34-4436-a43c-ee95d128b8c5}"); // wrong 1st separator
+ ROW(invalid, "{fc69b59e-cc34*4436-a43c-ee95d128b8c5}"); // wrong 2nd separator
+ ROW(invalid, "{fc69b59e-cc34-44366a43c-ee95d128b8c5}"); // wrong 3rd separator
+ ROW(invalid, "{fc69b59e-cc34-4436-a43c\303\244ee95d128b8c5}"); // wrong 4th separator (&auml;)
+ ROW(uuidA, "{fc69b59e-cc34-4436-a43c-ee95d128b8c5)"); // wrong final character (not an error!)
+
+ ROW(uuidB, "{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}");
+#undef ROW
+}
+
void tst_QUuid::fromString()
{
- QCOMPARE(uuidA, QUuid(QString("{fc69b59e-cc34-4436-a43c-ee95d128b8c5}")));
- QCOMPARE(uuidA, QUuid(QString("fc69b59e-cc34-4436-a43c-ee95d128b8c5}")));
- QCOMPARE(uuidA, QUuid(QString("{fc69b59e-cc34-4436-a43c-ee95d128b8c5")));
- QCOMPARE(uuidA, QUuid(QString("fc69b59e-cc34-4436-a43c-ee95d128b8c5")));
- QCOMPARE(QUuid(), QUuid(QString("{fc69b59e-cc34-4436-a43c-ee95d128b8c")));
+ QFETCH(const QUuid, expected);
+ QFETCH(const QString, input);
- QCOMPARE(uuidB, QUuid(QString("{1ab6e93a-b1cb-4a87-ba47-ec7e99039a7b}")));
+ const auto inputL1 = input.toLatin1();
+ const auto inputU8 = input.toUtf8();
+
+ QCOMPARE(expected, QUuid(input));
+ QCOMPARE(expected, QUuid(inputU8));
+ QCOMPARE(expected, QUuid(inputL1));
+
+ QCOMPARE(expected, QUuid::fromString(input));
+
+ // for QLatin1String, construct one whose data() is not NUL-terminated:
+ const auto longerInputL1 = inputL1 + '5'; // the '5' makes the premature end check incorrectly succeed
+ const auto inputL1S = QLatin1String(longerInputL1.data(), inputL1.size());
+ QCOMPARE(expected, QUuid::fromString(inputL1S));
}
void tst_QUuid::toByteArray()
diff --git a/tests/auto/corelib/plugin/quuid/tst_quuid_darwin.mm b/tests/auto/corelib/plugin/quuid/tst_quuid_darwin.mm
index d90bff65b3..41ccece115 100644
--- a/tests/auto/corelib/plugin/quuid/tst_quuid_darwin.mm
+++ b/tests/auto/corelib/plugin/quuid/tst_quuid_darwin.mm
@@ -36,7 +36,7 @@ void tst_QUuid_darwinTypes()
{
// QUuid <-> CFUUID
{
- QUuid qtUuid(QByteArrayLiteral("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
+ const auto qtUuid = QUuid::fromString(QLatin1String("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
const CFUUIDRef cfuuid = qtUuid.toCFUUID();
QCOMPARE(QUuid::fromCFUUID(cfuuid), qtUuid);
CFStringRef cfstring = CFUUIDCreateString(0, cfuuid);
@@ -45,10 +45,10 @@ void tst_QUuid_darwinTypes()
CFRelease(cfuuid);
}
{
- QUuid qtUuid(QByteArrayLiteral("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
+ auto qtUuid = QUuid::fromString(QLatin1String("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
const CFUUIDRef cfuuid = qtUuid.toCFUUID();
QUuid qtUuidCopy(qtUuid);
- qtUuid = QUuid(QByteArrayLiteral("93eec131-13c5-4d13-aaea-e456b4c57efa")); // modify
+ qtUuid = QUuid::fromString(QLatin1String("93eec131-13c5-4d13-aaea-e456b4c57efa")); // modify
QCOMPARE(QUuid::fromCFUUID(cfuuid), qtUuidCopy);
CFStringRef cfstring = CFUUIDCreateString(0, cfuuid);
QCOMPARE(QString::fromCFString(cfstring), qtUuidCopy.toString().mid(1, 36).toUpper());
@@ -59,7 +59,7 @@ void tst_QUuid_darwinTypes()
{
QMacAutoReleasePool pool;
- QUuid qtUuid(QByteArrayLiteral("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
+ const auto qtUuid = QUuid::fromString(QLatin1String("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
const NSUUID *nsuuid = qtUuid.toNSUUID();
QCOMPARE(QUuid::fromNSUUID(nsuuid), qtUuid);
QCOMPARE(QString::fromNSString([nsuuid UUIDString]), qtUuid.toString().mid(1, 36).toUpper());
@@ -67,10 +67,10 @@ void tst_QUuid_darwinTypes()
{
QMacAutoReleasePool pool;
- QUuid qtUuid(QByteArrayLiteral("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
+ auto qtUuid = QUuid::fromString(QLatin1String("0f7169cc-5711-4af9-99d9-fecb2329fdef"));
const NSUUID *nsuuid = qtUuid.toNSUUID();
QUuid qtUuidCopy(qtUuid);
- qtUuid = QUuid(QByteArrayLiteral("93eec131-13c5-4d13-aaea-e456b4c57efa")); // modify
+ qtUuid = QUuid::fromString(QLatin1String("93eec131-13c5-4d13-aaea-e456b4c57efa")); // modify
QCOMPARE(QUuid::fromNSUUID(nsuuid), qtUuidCopy);
QCOMPARE(QString::fromNSString([nsuuid UUIDString]), qtUuidCopy.toString().mid(1, 36).toUpper());
}
diff --git a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
index a546cad225..37b052bf1d 100644
--- a/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
+++ b/tests/auto/corelib/thread/qfuture/tst_qfuture.cpp
@@ -1205,8 +1205,6 @@ void tst_QFuture::pause()
Interface.reportFinished();
}
-const int resultCount = 1000;
-
class ResultObject : public QObject
{
Q_OBJECT
diff --git a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
index 2970b2e118..ba470a77c9 100644
--- a/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
+++ b/tests/auto/corelib/thread/qsemaphore/tst_qsemaphore.cpp
@@ -42,6 +42,7 @@ private slots:
void tryAcquireWithTimeout();
void tryAcquireWithTimeoutStarvation();
void producerConsumer();
+ void raii();
};
static QSemaphore *semaphore = 0;
@@ -417,5 +418,54 @@ void tst_QSemaphore::producerConsumer()
consumer.wait();
}
+void tst_QSemaphore::raii()
+{
+ QSemaphore sem;
+
+ QCOMPARE(sem.available(), 0);
+
+ // basic operation:
+ {
+ QSemaphoreReleaser r0;
+ const QSemaphoreReleaser r1(sem);
+ const QSemaphoreReleaser r2(sem, 2);
+
+ QCOMPARE(r0.semaphore(), nullptr);
+ QCOMPARE(r1.semaphore(), &sem);
+ QCOMPARE(r2.semaphore(), &sem);
+ }
+
+ QCOMPARE(sem.available(), 3);
+
+ // cancel:
+ {
+ const QSemaphoreReleaser r1(sem);
+ QSemaphoreReleaser r2(sem, 2);
+
+ QCOMPARE(r2.cancel(), &sem);
+ QCOMPARE(r2.semaphore(), nullptr);
+ }
+
+ QCOMPARE(sem.available(), 4);
+
+ // move-assignment:
+ {
+ const QSemaphoreReleaser r1(sem);
+ QSemaphoreReleaser r2(sem, 2);
+
+ QCOMPARE(sem.available(), 4);
+
+ r2 = QSemaphoreReleaser();
+
+ QCOMPARE(sem.available(), 6);
+
+ r2 = QSemaphoreReleaser(sem, 42);
+
+ QCOMPARE(sem.available(), 6);
+ }
+
+ QCOMPARE(sem.available(), 49);
+}
+
QTEST_MAIN(tst_QSemaphore)
#include "tst_qsemaphore.moc"
diff --git a/tests/auto/corelib/thread/qthread/qthread.pro b/tests/auto/corelib/thread/qthread/qthread.pro
index e0ef506d2c..37552f1fca 100644
--- a/tests/auto/corelib/thread/qthread/qthread.pro
+++ b/tests/auto/corelib/thread/qthread/qthread.pro
@@ -2,6 +2,8 @@ CONFIG += testcase
TARGET = tst_qthread
QT = core testlib
SOURCES = tst_qthread.cpp
+qtConfig(c++14):CONFIG += c++14
+qtConfig(c++1z):CONFIG += c++1z
INCLUDEPATH += ../../../../shared/
HEADERS += ../../../../shared/emulationdetector.h
diff --git a/tests/auto/corelib/thread/qthread/tst_qthread.cpp b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
index 5c8522a313..27a617ec85 100644
--- a/tests/auto/corelib/thread/qthread/tst_qthread.cpp
+++ b/tests/auto/corelib/thread/qthread/tst_qthread.cpp
@@ -47,6 +47,10 @@
#endif
#endif
+#ifndef QT_NO_EXCEPTIONS
+#include <exception>
+#endif
+
#include "emulationdetector.h"
class tst_QThread : public QObject
@@ -100,6 +104,8 @@ private slots:
void stressTest();
void quitLock();
+
+ void create();
};
enum { one_minute = 60 * 1000, five_minutes = 5 * one_minute };
@@ -1330,6 +1336,259 @@ void tst_QThread::quitLock()
QVERIFY(exitThreadCalled);
}
+void tst_QThread::create()
+{
+#ifndef QTHREAD_HAS_CREATE
+ QSKIP("This test requires QThread::create");
+#else
+ {
+ const auto &function = [](){};
+ QScopedPointer<QThread> thread(QThread::create(function));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ thread->start();
+ QVERIFY(thread->wait());
+ }
+
+ {
+ // no side effects before starting
+ int i = 0;
+ const auto &function = [&i]() { i = 42; };
+ QScopedPointer<QThread> thread(QThread::create(function));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ QCOMPARE(i, 0);
+ thread->start();
+ QVERIFY(thread->wait());
+ QCOMPARE(i, 42);
+ }
+
+ {
+ // control thread progress
+ QSemaphore semaphore1;
+ QSemaphore semaphore2;
+
+ const auto &function = [&semaphore1, &semaphore2]() -> void
+ {
+ semaphore1.acquire();
+ semaphore2.release();
+ };
+
+ QScopedPointer<QThread> thread(QThread::create(function));
+
+ QVERIFY(thread);
+ thread->start();
+ QTRY_VERIFY(thread->isRunning());
+ semaphore1.release();
+ semaphore2.acquire();
+ QVERIFY(thread->wait());
+ QVERIFY(!thread->isRunning());
+ }
+
+ {
+ // ignore return values
+ const auto &function = []() { return 42; };
+ QScopedPointer<QThread> thread(QThread::create(function));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ thread->start();
+ QVERIFY(thread->wait());
+ }
+
+ {
+ // return value of create
+ QScopedPointer<QThread> thread;
+ QSemaphore s;
+ const auto &function = [&thread, &s]() -> void
+ {
+ s.acquire();
+ QCOMPARE(thread.data(), QThread::currentThread());
+ };
+
+ thread.reset(QThread::create(function));
+ QVERIFY(thread);
+ thread->start();
+ QTRY_VERIFY(thread->isRunning());
+ s.release();
+ QVERIFY(thread->wait());
+ }
+
+ {
+ // move-only parameters
+ struct MoveOnlyValue {
+ explicit MoveOnlyValue(int v) : v(v) {}
+ ~MoveOnlyValue() = default;
+ MoveOnlyValue(const MoveOnlyValue &) = delete;
+ MoveOnlyValue(MoveOnlyValue &&) = default;
+ MoveOnlyValue &operator=(const MoveOnlyValue &) = delete;
+ MoveOnlyValue &operator=(MoveOnlyValue &&) = default;
+ int v;
+ };
+
+ struct MoveOnlyFunctor {
+ explicit MoveOnlyFunctor(int *i) : i(i) {}
+ ~MoveOnlyFunctor() = default;
+ MoveOnlyFunctor(const MoveOnlyFunctor &) = delete;
+ MoveOnlyFunctor(MoveOnlyFunctor &&) = default;
+ MoveOnlyFunctor &operator=(const MoveOnlyFunctor &) = delete;
+ MoveOnlyFunctor &operator=(MoveOnlyFunctor &&) = default;
+ int operator()() { return (*i = 42); }
+ int *i;
+ };
+
+ {
+ int i = 0;
+ MoveOnlyFunctor f(&i);
+ QScopedPointer<QThread> thread(QThread::create(std::move(f)));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ thread->start();
+ QVERIFY(thread->wait());
+ QCOMPARE(i, 42);
+ }
+
+#if defined(__cpp_init_captures) && __cpp_init_captures >= 201304
+ {
+ int i = 0;
+ MoveOnlyValue mo(123);
+ auto moveOnlyFunction = [&i, mo = std::move(mo)]() { i = mo.v; };
+ QScopedPointer<QThread> thread(QThread::create(std::move(moveOnlyFunction)));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ thread->start();
+ QVERIFY(thread->wait());
+ QCOMPARE(i, 123);
+ }
+#endif // __cpp_init_captures
+
+#ifdef QTHREAD_HAS_VARIADIC_CREATE
+ {
+ int i = 0;
+ const auto &function = [&i](MoveOnlyValue &&mo) { i = mo.v; };
+ QScopedPointer<QThread> thread(QThread::create(function, MoveOnlyValue(123)));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ thread->start();
+ QVERIFY(thread->wait());
+ QCOMPARE(i, 123);
+ }
+
+ {
+ int i = 0;
+ const auto &function = [&i](MoveOnlyValue &&mo) { i = mo.v; };
+ MoveOnlyValue mo(-1);
+ QScopedPointer<QThread> thread(QThread::create(function, std::move(mo)));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ thread->start();
+ QVERIFY(thread->wait());
+ QCOMPARE(i, -1);
+ }
+#endif // QTHREAD_HAS_VARIADIC_CREATE
+ }
+
+#ifdef QTHREAD_HAS_VARIADIC_CREATE
+ {
+ // simple parameter passing
+ int i = 0;
+ const auto &function = [&i](int j, int k) { i = j * k; };
+ QScopedPointer<QThread> thread(QThread::create(function, 3, 4));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ QCOMPARE(i, 0);
+ thread->start();
+ QVERIFY(thread->wait());
+ QCOMPARE(i, 12);
+ }
+
+ {
+ // ignore return values (with parameters)
+ const auto &function = [](double d) { return d * 2.0; };
+ QScopedPointer<QThread> thread(QThread::create(function, 3.14));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ thread->start();
+ QVERIFY(thread->wait());
+ }
+
+ {
+ // handling of pointers to member functions, std::ref, etc.
+ struct S {
+ S() : v(0) {}
+ void doSomething() { ++v; }
+ int v;
+ };
+
+ S object;
+
+ QCOMPARE(object.v, 0);
+
+ QScopedPointer<QThread> thread;
+ thread.reset(QThread::create(&S::doSomething, object));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ thread->start();
+ QVERIFY(thread->wait());
+
+ QCOMPARE(object.v, 0); // a copy was passed, this should still be 0
+
+ thread.reset(QThread::create(&S::doSomething, std::ref(object)));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ thread->start();
+ QVERIFY(thread->wait());
+
+ QCOMPARE(object.v, 1);
+
+ thread.reset(QThread::create(&S::doSomething, &object));
+ QVERIFY(thread);
+ QVERIFY(!thread->isRunning());
+ thread->start();
+ QVERIFY(thread->wait());
+
+ QCOMPARE(object.v, 2);
+ }
+
+ {
+ // std::ref into ordinary reference
+ int i = 42;
+ const auto &function = [](int &i) { i *= 2; };
+ QScopedPointer<QThread> thread(QThread::create(function, std::ref(i)));
+ QVERIFY(thread);
+ thread->start();
+ QVERIFY(thread->wait());
+ QCOMPARE(i, 84);
+ }
+
+#ifndef QT_NO_EXCEPTIONS
+ {
+ // exceptions when copying/decaying the arguments are thrown at build side and won't terminate
+ class ThreadException : public std::exception
+ {
+ };
+
+ struct ThrowWhenCopying
+ {
+ ThrowWhenCopying() = default;
+ ThrowWhenCopying(const ThrowWhenCopying &)
+ {
+ throw ThreadException();
+ }
+ ~ThrowWhenCopying() = default;
+ ThrowWhenCopying &operator=(const ThrowWhenCopying &) = default;
+ };
+
+ const auto &function = [](const ThrowWhenCopying &){};
+ QScopedPointer<QThread> thread;
+ ThrowWhenCopying t;
+ QVERIFY_EXCEPTION_THROWN(thread.reset(QThread::create(function, t)), ThreadException);
+ QVERIFY(!thread);
+ }
+#endif // QT_NO_EXCEPTIONS
+#endif // QTHREAD_HAS_VARIADIC_CREATE
+#endif // QTHREAD_HAS_CREATE
+}
+
class StopableJob : public QObject
{
Q_OBJECT
diff --git a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
index fdc4ecb5c8..782eed03e8 100644
--- a/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
+++ b/tests/auto/corelib/thread/qthreadpool/tst_qthreadpool.cpp
@@ -92,6 +92,7 @@ private slots:
void tryTake();
void waitForDoneTimeout();
void destroyingWaitsForTasksToFinish();
+ void stackSize();
void stressTest();
private:
@@ -961,21 +962,6 @@ void tst_QThreadPool::cancel()
QSemaphore sem(0);
QSemaphore startedThreads(0);
- class SemaphoreReleaser
- {
- QSemaphore &sem;
- int n;
- Q_DISABLE_COPY(SemaphoreReleaser)
- public:
- explicit SemaphoreReleaser(QSemaphore &sem, int n)
- : sem(sem), n(n) {}
-
- ~SemaphoreReleaser()
- {
- sem.release(n);
- }
- };
-
class BlockingRunnable : public QRunnable
{
public:
@@ -1014,7 +1000,7 @@ void tst_QThreadPool::cancel()
// ensure that the QThreadPool doesn't deadlock if any of the checks fail
// and cause an early return:
- const SemaphoreReleaser semReleaser(sem, runs);
+ const QSemaphoreReleaser semReleaser(sem, runs);
count.store(0);
QAtomicInt dtorCounter = 0;
@@ -1048,21 +1034,6 @@ void tst_QThreadPool::tryTake()
QSemaphore sem(0);
QSemaphore startedThreads(0);
- class SemaphoreReleaser
- {
- QSemaphore &sem;
- int n;
- Q_DISABLE_COPY(SemaphoreReleaser)
- public:
- explicit SemaphoreReleaser(QSemaphore &sem, int n)
- : sem(sem), n(n) {}
-
- ~SemaphoreReleaser()
- {
- sem.release(n);
- }
- };
-
class BlockingRunnable : public QRunnable
{
public:
@@ -1101,7 +1072,7 @@ void tst_QThreadPool::tryTake()
// ensure that the QThreadPool doesn't deadlock if any of the checks fail
// and cause an early return:
- const SemaphoreReleaser semReleaser(sem, Runs);
+ const QSemaphoreReleaser semReleaser(sem, Runs);
count.store(0);
QAtomicInt dtorCounter = 0;
@@ -1166,6 +1137,39 @@ void tst_QThreadPool::destroyingWaitsForTasksToFinish()
}
}
+// Verify that QThreadPool::stackSize is used when creating
+// new threads. Note that this tests the Qt property only
+// since QThread::stackSize() does not reflect the actual
+// stack size used by the native thread.
+void tst_QThreadPool::stackSize()
+{
+ uint targetStackSize = 512 * 1024;
+ uint threadStackSize = 1; // impossible value
+
+ class StackSizeChecker : public QRunnable
+ {
+ public:
+ uint *stackSize;
+
+ StackSizeChecker(uint *stackSize)
+ :stackSize(stackSize)
+ {
+
+ }
+
+ void run()
+ {
+ *stackSize = QThread::currentThread()->stackSize();
+ }
+ };
+
+ QThreadPool threadPool;
+ threadPool.setStackSize(targetStackSize);
+ threadPool.start(new StackSizeChecker(&threadStackSize));
+ QVERIFY(threadPool.waitForDone(30000)); // 30s timeout
+ QCOMPARE(threadStackSize, targetStackSize);
+}
+
void tst_QThreadPool::stressTest()
{
class Task : public QRunnable
diff --git a/tests/auto/corelib/tools/containerapisymmetry/.gitignore b/tests/auto/corelib/tools/containerapisymmetry/.gitignore
new file mode 100644
index 0000000000..172ca970f2
--- /dev/null
+++ b/tests/auto/corelib/tools/containerapisymmetry/.gitignore
@@ -0,0 +1 @@
+tst_containerapisymmetry
diff --git a/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro b/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro
new file mode 100644
index 0000000000..30dc8026ef
--- /dev/null
+++ b/tests/auto/corelib/tools/containerapisymmetry/containerapisymmetry.pro
@@ -0,0 +1,7 @@
+CONFIG += testcase
+TARGET = tst_containerapisymmetry
+SOURCES += tst_containerapisymmetry.cpp
+QT = core testlib
+
+# This test does not work with strict iterators
+DEFINES -= QT_STRICT_ITERATORS
diff --git a/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
new file mode 100644
index 0000000000..3b8111f1a3
--- /dev/null
+++ b/tests/auto/corelib/tools/containerapisymmetry/tst_containerapisymmetry.cpp
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+
+#include "qbytearray.h"
+#include "qlinkedlist.h"
+#include "qlist.h"
+#include "qstring.h"
+#include "qvarlengtharray.h"
+#include "qvector.h"
+
+#include <vector> // for reference
+
+class tst_ContainerApiSymmetry : public QObject
+{
+ Q_OBJECT
+
+private:
+ template <typename Container>
+ void front_back_impl() const;
+
+private Q_SLOTS:
+ void front_back_std_vector() { front_back_impl<std::vector<int>>(); }
+ void front_back_QVector() { front_back_impl<QVector<int>>(); }
+ void front_back_QList() { front_back_impl<QList<qintptr>>(); }
+ void front_back_QLinkedList() { front_back_impl<QLinkedList<int>>(); }
+ void front_back_QVarLengthArray() { front_back_impl<QVarLengthArray<int>>(); }
+ void front_back_QString() { front_back_impl<QString>(); }
+ void front_back_QStringRef() { front_back_impl<QStringRef>(); }
+ void front_back_QStringView() { front_back_impl<QStringView>(); }
+ void front_back_QLatin1String() { front_back_impl<QLatin1String>(); }
+ void front_back_QByteArray() { front_back_impl<QByteArray>(); }
+};
+
+template <typename Container>
+Container make(int size)
+{
+ Container c;
+ int i = 1;
+ while (size--)
+ c.push_back(typename Container::value_type(i++));
+ return c;
+}
+
+static QString s_string = QStringLiteral("\1\2\3\4\5\6\7");
+
+template <> QStringRef make(int size) { return s_string.leftRef(size); }
+template <> QStringView make(int size) { return QStringView(s_string).left(size); }
+template <> QLatin1String make(int size) { return QLatin1String("\1\2\3\4\5\6\7", size); }
+
+template <typename T> T clean(T &&t) { return std::forward<T>(t); }
+inline QChar clean(QCharRef ch) { return ch; }
+inline char clean(QByteRef ch) { return ch; }
+inline char clean(QLatin1Char ch) { return ch.toLatin1(); }
+
+template <typename Container>
+void tst_ContainerApiSymmetry::front_back_impl() const
+{
+ using V = typename Container::value_type;
+ auto c1 = make<Container>(1);
+ QCOMPARE(clean(c1.front()), V(1));
+ QCOMPARE(clean(c1.back()), V(1));
+ QCOMPARE(clean(qAsConst(c1).front()), V(1));
+ QCOMPARE(clean(qAsConst(c1).back()), V(1));
+
+ auto c2 = make<Container>(2);
+ QCOMPARE(clean(c2.front()), V(1));
+ QCOMPARE(clean(c2.back()), V(2));
+ QCOMPARE(clean(qAsConst(c2).front()), V(1));
+ QCOMPARE(clean(qAsConst(c2).back()), V(2));
+}
+
+QTEST_APPLESS_MAIN(tst_ContainerApiSymmetry)
+#include "tst_containerapisymmetry.moc"
diff --git a/tests/auto/corelib/tools/qchar/tst_qchar.cpp b/tests/auto/corelib/tools/qchar/tst_qchar.cpp
index e5a6e953d3..cf4f6d21e2 100644
--- a/tests/auto/corelib/tools/qchar/tst_qchar.cpp
+++ b/tests/auto/corelib/tools/qchar/tst_qchar.cpp
@@ -36,6 +36,8 @@ class tst_QChar : public QObject
{
Q_OBJECT
private slots:
+ void fromChar16_t();
+ void fromWchar_t();
void operator_eqeq_null();
void operators_data();
void operators();
@@ -72,6 +74,33 @@ private slots:
void unicodeVersion();
};
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+
+void tst_QChar::fromChar16_t()
+{
+#if defined(Q_COMPILER_UNICODE_STRINGS)
+ QChar aUmlaut = u'\u00E4'; // German small letter a-umlaut
+ QCOMPARE(aUmlaut, QChar(0xE4));
+ QChar replacementCharacter = u'\uFFFD';
+ QCOMPARE(replacementCharacter, QChar(QChar::ReplacementCharacter));
+#else
+ QSKIP("This test requires C++11 char16_t support enabled in the compiler.");
+#endif
+}
+
+void tst_QChar::fromWchar_t()
+{
+#if defined(Q_OS_WIN)
+ QChar aUmlaut = L'\u00E4'; // German small letter a-umlaut
+ QCOMPARE(aUmlaut, QChar(0xE4));
+ QChar replacementCharacter = L'\uFFFD';
+ QCOMPARE(replacementCharacter, QChar(QChar::ReplacementCharacter));
+#else
+ QSKIP("This is a Windows-only test.");
+#endif
+}
+
void tst_QChar::operator_eqeq_null()
{
{
diff --git a/tests/auto/corelib/tools/qdate/tst_qdate.cpp b/tests/auto/corelib/tools/qdate/tst_qdate.cpp
index f88eac1a9f..ff31f01d7c 100644
--- a/tests/auto/corelib/tools/qdate/tst_qdate.cpp
+++ b/tests/auto/corelib/tools/qdate/tst_qdate.cpp
@@ -1490,7 +1490,7 @@ void tst_QDate::roundtrip() const
void tst_QDate::qdebug() const
{
- QTest::ignoreMessage(QtDebugMsg, "QDate(\"\")");
+ QTest::ignoreMessage(QtDebugMsg, "QDate(Invalid)");
qDebug() << QDate();
QTest::ignoreMessage(QtDebugMsg, "QDate(\"1983-08-07\")");
qDebug() << QDate(1983, 8, 7);
diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
index 28ad2d193c..c0ed88e154 100644
--- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp
@@ -131,6 +131,8 @@ private slots:
void setOffsetFromUtc();
void toOffsetFromUtc();
+ void zoneAtTime_data();
+ void zoneAtTime();
void timeZoneAbbreviation();
void getDate();
@@ -1378,11 +1380,13 @@ void tst_QDateTime::toTimeSpec()
QCOMPARE(utcToLocal.date(), fromLocal.date());
QCOMPARE(utcToLocal.time(), fromLocal.time());
QCOMPARE(utcToLocal.timeSpec(), Qt::LocalTime);
+ QCOMPARE(utcToLocal.toTimeSpec(Qt::UTC), fromUtc);
QCOMPARE(localToUtc, fromUtc);
QCOMPARE(localToUtc.date(), fromUtc.date());
QCOMPARE(localToUtc.time(), fromUtc.time());
QCOMPARE(localToUtc.timeSpec(), Qt::UTC);
+ QCOMPARE(localToUtc.toTimeSpec(Qt::LocalTime), fromLocal);
QCOMPARE(utcToUtc, localToUtc);
QCOMPARE(utcToUtc.date(), localToUtc.date());
@@ -1399,11 +1403,13 @@ void tst_QDateTime::toTimeSpec()
QCOMPARE(utcToOffset.date(), fromUtc.date());
QCOMPARE(utcToOffset.time(), fromUtc.time());
QCOMPARE(utcToOffset.timeSpec(), Qt::UTC);
+ QCOMPARE(utcToOffset.toTimeSpec(Qt::UTC), fromUtc);
QCOMPARE(localToOffset, fromUtc);
QCOMPARE(localToOffset.date(), fromUtc.date());
QCOMPARE(localToOffset.time(), fromUtc.time());
QCOMPARE(localToOffset.timeSpec(), Qt::UTC);
+ QCOMPARE(localToOffset.toTimeSpec(Qt::LocalTime), fromLocal);
} else {
QSKIP("Not tested with timezone other than Central European (CET/CEST)");
}
@@ -2277,6 +2283,9 @@ void tst_QDateTime::fromStringDateFormat_data()
QTest::newRow("ISO .99999 of a minute (comma)") << QString::fromLatin1("2012-01-01T08:00,99999")
<< Qt::ISODate << QDateTime(QDate(2012, 1, 1), QTime(8, 0, 59, 999), Qt::LocalTime);
QTest::newRow("ISO empty") << QString::fromLatin1("") << Qt::ISODate << invalidDateTime();
+ QTest::newRow("ISO short") << QString::fromLatin1("2017-07-01T") << Qt::ISODate << invalidDateTime();
+ QTest::newRow("ISO zoned date") << QString::fromLatin1("2017-07-01Z") << Qt::ISODate << invalidDateTime();
+ QTest::newRow("ISO zoned empty time") << QString::fromLatin1("2017-07-01TZ") << Qt::ISODate << invalidDateTime();
// Test Qt::RFC2822Date format (RFC 2822).
QTest::newRow("RFC 2822 +0100") << QString::fromLatin1("13 Feb 1987 13:24:51 +0100")
@@ -2476,21 +2485,19 @@ void tst_QDateTime::fromStringToStringLocale()
QLocale def;
QLocale::setDefault(QLocale(QLocale::French, QLocale::France));
+#define ROUNDTRIP(format) \
+ QCOMPARE(QDateTime::fromString(dateTime.toString(format), format), dateTime)
- QCOMPARE(QDateTime::fromString(dateTime.toString(Qt::DefaultLocaleShortDate), Qt::DefaultLocaleShortDate), dateTime);
- QCOMPARE(QDateTime::fromString(dateTime.toString(Qt::SystemLocaleShortDate), Qt::SystemLocaleShortDate), dateTime);
+ ROUNDTRIP(Qt::DefaultLocaleShortDate);
+ ROUNDTRIP(Qt::SystemLocaleShortDate);
// obsolete
- QCOMPARE(QDateTime::fromString(dateTime.toString(Qt::SystemLocaleDate), Qt::SystemLocaleDate), dateTime);
- QCOMPARE(QDateTime::fromString(dateTime.toString(Qt::LocaleDate), Qt::LocaleDate), dateTime);
-
- QEXPECT_FAIL("data0", "This format is apparently failing because of a bug in the datetime parser. (QTBUG-22833)", Continue);
- QCOMPARE(QDateTime::fromString(dateTime.toString(Qt::DefaultLocaleLongDate), Qt::DefaultLocaleLongDate), dateTime);
-#ifndef Q_OS_WIN
- QEXPECT_FAIL("data0", "This format is apparently failing because of a bug in the datetime parser. (QTBUG-22833)", Continue);
-#endif
- QCOMPARE(QDateTime::fromString(dateTime.toString(Qt::SystemLocaleLongDate), Qt::SystemLocaleLongDate), dateTime);
+ ROUNDTRIP(Qt::SystemLocaleDate);
+ ROUNDTRIP(Qt::LocaleDate);
+ ROUNDTRIP(Qt::DefaultLocaleLongDate);
+ ROUNDTRIP(Qt::SystemLocaleLongDate);
+#undef ROUNDTRIP
QLocale::setDefault(def);
}
@@ -2625,6 +2632,71 @@ void tst_QDateTime::toOffsetFromUtc()
QCOMPARE(dt2.time(), QTime(0, 0, 0));
}
+void tst_QDateTime::zoneAtTime_data()
+{
+ QTest::addColumn<QByteArray>("ianaID");
+ QTest::addColumn<QDate>("date");
+ QTest::addColumn<int>("offset");
+#define ADDROW(name, zone, date, offset) \
+ QTest::newRow(name) << QByteArray(zone) << (date) << (offset)
+
+ // Check DST handling around epoch:
+ {
+ QDate epoch(1970, 1, 1);
+ ADDROW("epoch:UTC", "UTC", epoch, 0);
+ // Paris and Berlin skipped DST around 1970; but Rome used it.
+ ADDROW("epoch:CET", "Europe/Rome", epoch, 3600);
+ ADDROW("epoch:PST", "America/Vancouver", epoch, -8 * 3600);
+ ADDROW("epoch:EST", "America/New_York", epoch, -5 * 3600);
+ }
+ {
+ // QDateTime deliberately ignores DST before the epoch.
+ QDate summer69(1969, 8, 15); // Woodstock started
+ ADDROW("summer69:UTC", "UTC", summer69, 0);
+ ADDROW("summer69:CET", "Europe/Rome", summer69, 3600);
+ ADDROW("summer69:PST", "America/Vancouver", summer69, -8 * 3600);
+ ADDROW("summer69:EST", "America/New_York", summer69, -5 * 3600);
+ }
+ {
+ // ... but takes it into account after:
+ QDate summer70(1970, 8, 26); // Isle of Wight festival
+ ADDROW("summer70:UTC", "UTC", summer70, 0);
+ ADDROW("summer70:CET", "Europe/Rome", summer70, 2 * 3600);
+ ADDROW("summer70:PST", "America/Vancouver", summer70, -7 * 3600);
+ ADDROW("summer70:EST", "America/New_York", summer70, -4 * 3600);
+ }
+
+#ifndef Q_OS_WIN
+ // Bracket a few noteworthy transitions:
+ ADDROW("before:ACWST", "Australia/Eucla", QDate(1974, 10, 26), 31500); // 8:45
+ ADDROW("after:ACWST", "Australia/Eucla", QDate(1974, 10, 27), 35100); // 9:45
+ ADDROW("before:NPT", "Asia/Kathmandu", QDate(1985, 12, 31), 19800); // 5:30
+ ADDROW("after:NPT", "Asia/Kathmandu", QDate(1986, 1, 1), 20700); // 5:45
+ // The two that have skipped a day (each):
+ ADDROW("before:LINT", "Pacific/Kiritimati", QDate(1994, 12, 31), -36000);
+ ADDROW("after:LINT", "Pacific/Kiritimati", QDate(1995, 2, 1), 14 * 3600);
+ ADDROW("after:WST", "Pacific/Apia", QDate(2011, 12, 31), 14 * 3600);
+#endif // MS lacks ACWST, NPT; doesn't grok date-line crossings; and Windows 7 lacks LINT.
+ ADDROW("before:WST", "Pacific/Apia", QDate(2011, 12, 29), -36000);
+#undef ADDROW
+}
+
+void tst_QDateTime::zoneAtTime()
+{
+ QFETCH(QByteArray, ianaID);
+ QFETCH(QDate, date);
+ QFETCH(int, offset);
+ const QTime noon(12, 0);
+
+ QTimeZone zone(ianaID);
+ QVERIFY(zone.isValid());
+ QCOMPARE(QDateTime(date, noon, zone).offsetFromUtc(), offset);
+ if (date.year() < 1970)
+ QCOMPARE(zone.standardTimeOffset(QDateTime(date, noon, zone)), offset);
+ else // zone.offsetFromUtc *does* include DST, even before epoch
+ QCOMPARE(zone.offsetFromUtc(QDateTime(date, noon, zone)), offset);
+}
+
void tst_QDateTime::timeZoneAbbreviation()
{
QDateTime dt1(QDate(2013, 1, 1), QTime(1, 0, 0), Qt::OffsetFromUTC, 60 * 60);
diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
index 943b4316ff..0015efacfa 100644
--- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp
+++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
@@ -60,6 +60,7 @@ private slots:
void compare2();
void iterators(); // sligthly modified from tst_QMap
void keyIterator();
+ void keyValueIterator();
void keys_values_uniqueKeys(); // slightly modified from tst_QMap
void noNeedlessRehashes();
@@ -1124,6 +1125,60 @@ void tst_QHash::keyIterator()
Q_STATIC_ASSERT(std::is_default_constructible<keyIterator>::value);
}
+void tst_QHash::keyValueIterator()
+{
+ QHash<int, int> hash;
+ typedef QHash<int, int>::const_key_value_iterator::value_type entry_type;
+
+ for (int i = 0; i < 100; ++i)
+ hash.insert(i, i * 100);
+
+ auto key_value_it = hash.constKeyValueBegin();
+ auto it = hash.cbegin();
+
+
+ for (int i = 0; i < hash.size(); ++i) {
+ QVERIFY(key_value_it != hash.constKeyValueEnd());
+ QVERIFY(it != hash.cend());
+
+ entry_type pair(it.key(), it.value());
+ QCOMPARE(*key_value_it, pair);
+ ++key_value_it;
+ ++it;
+ }
+
+ QVERIFY(key_value_it == hash.constKeyValueEnd());
+ QVERIFY(it == hash.cend());
+
+ int key = 50;
+ int value = 50 * 100;
+ entry_type pair(key, value);
+ key_value_it = std::find(hash.constKeyValueBegin(), hash.constKeyValueEnd(), pair);
+ it = std::find(hash.cbegin(), hash.cend(), value);
+
+ QVERIFY(key_value_it != hash.constKeyValueEnd());
+ QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
+
+ ++it;
+ ++key_value_it;
+ QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
+
+ --it;
+ --key_value_it;
+ QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
+
+ ++it;
+ ++key_value_it;
+ QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
+
+ --it;
+ --key_value_it;
+ QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
+ key = 99;
+ value = 99 * 100;
+ QCOMPARE(std::count(hash.constKeyValueBegin(), hash.constKeyValueEnd(), entry_type(key, value)), 1);
+}
+
void tst_QHash::rehash_isnt_quadratic()
{
// this test should be incredibly slow if rehash() is quadratic
diff --git a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
index 4a81adf9fe..124e3cdf00 100644
--- a/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
+++ b/tests/auto/corelib/tools/qhashfunctions/tst_qhashfunctions.cpp
@@ -49,6 +49,7 @@ public slots:
void init();
private Q_SLOTS:
+ void consistent();
void qhash();
void qhash_of_empty_and_null_qstring();
void qhash_of_empty_and_null_qbytearray();
@@ -61,6 +62,17 @@ private Q_SLOTS:
void setGlobalQHashSeed();
};
+void tst_QHashFunctions::consistent()
+{
+ // QString-like
+ {
+ const QString s = QStringLiteral("abcdefghijklmnopqrstuvxyz").repeated(16);
+
+ QCOMPARE(qHash(s), qHash(QStringRef(&s)));
+ QCOMPARE(qHash(s), qHash(QStringView(s)));
+ }
+}
+
void tst_QHashFunctions::initTestCase()
{
Q_STATIC_ASSERT(int(RandomSeed) > 0);
@@ -160,6 +172,14 @@ void tst_QHashFunctions::qhash_of_empty_and_null_qstring()
QString null, empty("");
QCOMPARE(null, empty);
QCOMPARE(qHash(null, seed), qHash(empty, seed));
+
+ QStringRef nullRef, emptyRef(&empty);
+ QCOMPARE(nullRef, emptyRef);
+ QCOMPARE(qHash(nullRef, seed), qHash(emptyRef, seed));
+
+ QStringView nullView, emptyView(empty);
+ QCOMPARE(nullView, emptyView);
+ QCOMPARE(qHash(nullView, seed), qHash(emptyView, seed));
}
void tst_QHashFunctions::qhash_of_empty_and_null_qbytearray()
@@ -264,17 +284,17 @@ void tst_QHashFunctions::rangeCommutative()
void tst_QHashFunctions::setGlobalQHashSeed()
{
// Setter works as advertised
- qSetGlobalQHashSeed(0x10101010);
- QCOMPARE(qGlobalQHashSeed(), 0x10101010);
+ qSetGlobalQHashSeed(0);
+ QCOMPARE(qGlobalQHashSeed(), 0);
// Creating a new QHash doesn't reset the seed
QHash<QString, int> someHash;
someHash.insert("foo", 42);
- QCOMPARE(qGlobalQHashSeed(), 0x10101010);
+ QCOMPARE(qGlobalQHashSeed(), 0);
// Reset works as advertised
qSetGlobalQHashSeed(-1);
- QVERIFY(qGlobalQHashSeed() != -1);
+ QVERIFY(qGlobalQHashSeed() > 0);
}
QTEST_APPLESS_MAIN(tst_QHashFunctions)
diff --git a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp b/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
index a68671d899..c8373b6ae9 100644
--- a/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
+++ b/tests/auto/corelib/tools/qlatin1string/tst_qlatin1string.cpp
@@ -48,6 +48,7 @@ private Q_SLOTS:
void midLeftRight();
void nullString();
void emptyString();
+ void iterators();
void relationalOperators_data();
void relationalOperators();
};
@@ -155,6 +156,22 @@ void tst_QLatin1String::emptyString()
}
}
+void tst_QLatin1String::iterators()
+{
+ QLatin1String hello("hello");
+ QLatin1String olleh("olleh");
+
+ QVERIFY(std::equal(hello.begin(), hello.end(),
+ olleh.rbegin()));
+ QVERIFY(std::equal(hello.rbegin(), hello.rend(),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(olleh.begin(), olleh.size())));
+
+ QVERIFY(std::equal(hello.cbegin(), hello.cend(),
+ olleh.rbegin()));
+ QVERIFY(std::equal(hello.crbegin(), hello.crend(),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(olleh.begin(), olleh.size())));
+}
+
void tst_QLatin1String::relationalOperators_data()
{
QTest::addColumn<QLatin1StringContainer>("lhs");
diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
index 10d78b1f2f..d424e6086d 100644
--- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp
@@ -137,6 +137,8 @@ private slots:
void textDirection_data();
void textDirection();
+ void formattedDataSize_data();
+ void formattedDataSize();
void bcp47Name();
private:
@@ -1221,6 +1223,9 @@ void tst_QLocale::dayOfWeek()
QCOMPARE(QLocale::c().toString(date, "ddd"), shortName);
QCOMPARE(QLocale::c().toString(date, "dddd"), longName);
+
+ QCOMPARE(QLocale::c().toString(date, QStringViewLiteral("ddd")), shortName);
+ QCOMPARE(QLocale::c().toString(date, QStringViewLiteral("dddd")), longName);
}
void tst_QLocale::formatDate_data()
@@ -1263,6 +1268,7 @@ void tst_QLocale::formatDate()
QLocale l(QLocale::C);
QCOMPARE(l.toString(date, format), result);
+ QCOMPARE(l.toString(date, QStringView(format)), result);
}
@@ -1319,6 +1325,7 @@ void tst_QLocale::formatTime()
QLocale l(QLocale::C);
QCOMPARE(l.toString(time, format), result);
+ QCOMPARE(l.toString(time, QStringView(format)), result);
}
@@ -1480,6 +1487,7 @@ void tst_QLocale::formatDateTime()
QLocale l(localeName);
QCOMPARE(l.toString(dateTime, format), result);
+ QCOMPARE(l.toString(dateTime, QStringView(format)), result);
}
void tst_QLocale::formatTimeZone()
@@ -2203,9 +2211,9 @@ void tst_QLocale::timeFormat()
QCOMPARE(c.timeFormat(QLocale::NarrowFormat), c.timeFormat(QLocale::ShortFormat));
const QLocale no("no_NO");
- QCOMPARE(no.timeFormat(QLocale::NarrowFormat), QLatin1String("HH.mm"));
- QCOMPARE(no.timeFormat(QLocale::ShortFormat), QLatin1String("HH.mm"));
- QCOMPARE(no.timeFormat(QLocale::LongFormat), QLatin1String("HH.mm.ss t"));
+ QCOMPARE(no.timeFormat(QLocale::NarrowFormat), QLatin1String("HH:mm"));
+ QCOMPARE(no.timeFormat(QLocale::ShortFormat), QLatin1String("HH:mm"));
+ QCOMPARE(no.timeFormat(QLocale::LongFormat), QLatin1String("HH:mm:ss t"));
const QLocale id("id_ID");
QCOMPARE(id.timeFormat(QLocale::ShortFormat), QLatin1String("HH.mm"));
@@ -2227,9 +2235,9 @@ void tst_QLocale::dateTimeFormat()
QCOMPARE(c.dateTimeFormat(QLocale::NarrowFormat), c.dateTimeFormat(QLocale::ShortFormat));
const QLocale no("no_NO");
- QCOMPARE(no.dateTimeFormat(QLocale::NarrowFormat), QLatin1String("dd.MM.yyyy HH.mm"));
- QCOMPARE(no.dateTimeFormat(QLocale::ShortFormat), QLatin1String("dd.MM.yyyy HH.mm"));
- QCOMPARE(no.dateTimeFormat(QLocale::LongFormat), QLatin1String("dddd d. MMMM yyyy HH.mm.ss t"));
+ QCOMPARE(no.dateTimeFormat(QLocale::NarrowFormat), QLatin1String("dd.MM.yyyy HH:mm"));
+ QCOMPARE(no.dateTimeFormat(QLocale::ShortFormat), QLatin1String("dd.MM.yyyy HH:mm"));
+ QCOMPARE(no.dateTimeFormat(QLocale::LongFormat), QLatin1String("dddd d. MMMM yyyy HH:mm:ss t"));
}
void tst_QLocale::monthName()
@@ -2510,8 +2518,8 @@ void tst_QLocale::textDirection_data()
default:
break;
}
- QString testName = QLocalePrivate::languageToCode(QLocale::Language(language));
- QTest::newRow(testName.toLatin1().constData()) << language << int(QLocale::AnyScript) << rightToLeft;
+ const QLatin1String testName = QLocalePrivate::languageToCode(QLocale::Language(language));
+ QTest::newRow(qPrintable(testName)) << language << int(QLocale::AnyScript) << rightToLeft;
}
QTest::newRow("pa_Arab") << int(QLocale::Punjabi) << int(QLocale::ArabicScript) << true;
QTest::newRow("uz_Arab") << int(QLocale::Uzbek) << int(QLocale::ArabicScript) << true;
@@ -2527,6 +2535,81 @@ void tst_QLocale::textDirection()
QCOMPARE(locale.textDirection() == Qt::RightToLeft, rightToLeft);
}
+void tst_QLocale::formattedDataSize_data()
+{
+ QTest::addColumn<QLocale::Language>("language");
+ QTest::addColumn<int>("decimalPlaces");
+ QTest::addColumn<QLocale::DataSizeFormats>("units");
+ QTest::addColumn<int>("bytes");
+ QTest::addColumn<QString>("output");
+
+ struct {
+ const char *name;
+ QLocale::Language lang;
+ const char *bytes;
+ const char abbrev;
+ const char sep; // decimal separator
+ } data[] = {
+ { "English", QLocale::English, "bytes", 'B', '.' },
+ { "French", QLocale::French, "octets", 'o', ',' },
+ { "C", QLocale::C, "bytes", 'B', '.' }
+ };
+
+ for (const auto row : data) {
+#define ROWB(id, deci, num, text) \
+ QTest::addRow("%s-%s", row.name, id) \
+ << row.lang << deci << format \
+ << num << (QString(text) + QChar(' ') + QString(row.bytes))
+#define ROWQ(id, deci, num, head, tail) \
+ QTest::addRow("%s-%s", row.name, id) \
+ << row.lang << deci << format \
+ << num << (QString(head) + QChar(row.sep) + QString(tail) + QChar(row.abbrev))
+
+ // Metatype system fails to handle raw enum members as format; needs variable
+ {
+ const QLocale::DataSizeFormats format = QLocale::DataSizeIecFormat;
+ ROWB("IEC-0", 2, 0, "0");
+ ROWB("IEC-10", 2, 10, "10");
+ ROWQ("IEC-12Ki", 2, 12345, "12", "06 Ki");
+ ROWQ("IEC-16Ki", 2, 16384, "16", "00 Ki");
+ ROWQ("IEC-1235k", 2, 1234567, "1", "18 Mi");
+ ROWQ("IEC-1374k", 2, 1374744, "1", "31 Mi");
+ ROWQ("IEC-1234M", 2, 1234567890, "1", "15 Gi");
+ }
+ {
+ const QLocale::DataSizeFormats format = QLocale::DataSizeTraditionalFormat;
+ ROWB("Trad-0", 2, 0, "0");
+ ROWB("Trad-10", 2, 10, "10");
+ ROWQ("Trad-12Ki", 2, 12345, "12", "06 k");
+ ROWQ("Trad-16Ki", 2, 16384, "16", "00 k");
+ ROWQ("Trad-1235k", 2, 1234567, "1", "18 M");
+ ROWQ("Trad-1374k", 2, 1374744, "1", "31 M");
+ ROWQ("Trad-1234M", 2, 1234567890, "1", "15 G");
+ }
+ {
+ const QLocale::DataSizeFormats format = QLocale::DataSizeSIFormat;
+ ROWB("Decimal-0", 2, 0, "0");
+ ROWB("Decimal-10", 2, 10, "10");
+ ROWQ("Decimal-16Ki", 2, 16384, "16", "38 k");
+ ROWQ("Decimal-1234k", 2, 1234567, "1", "23 M");
+ ROWQ("Decimal-1374k", 2, 1374744, "1", "37 M");
+ ROWQ("Decimal-1234M", 2, 1234567890, "1", "23 G");
+ }
+#undef ROWQ
+#undef ROWB
+ }
+}
+
+void tst_QLocale::formattedDataSize()
+{
+ QFETCH(QLocale::Language, language);
+ QFETCH(int, decimalPlaces);
+ QFETCH(QLocale::DataSizeFormats, units);
+ QFETCH(int, bytes);
+ QFETCH(QString, output);
+ QCOMPARE(QLocale(language).formattedDataSize(bytes, decimalPlaces, units), output);
+}
+
void tst_QLocale::bcp47Name()
{
QCOMPARE(QLocale("C").bcp47Name(), QStringLiteral("en"));
diff --git a/tests/auto/corelib/tools/qmap/tst_qmap.cpp b/tests/auto/corelib/tools/qmap/tst_qmap.cpp
index f42ffc0471..b39444e76f 100644
--- a/tests/auto/corelib/tools/qmap/tst_qmap.cpp
+++ b/tests/auto/corelib/tools/qmap/tst_qmap.cpp
@@ -61,6 +61,7 @@ private slots:
void iterators();
void keyIterator();
+ void keyValueIterator();
void keys_values_uniqueKeys();
void qmultimap_specific();
@@ -863,6 +864,59 @@ void tst_QMap::keyIterator()
Q_STATIC_ASSERT(std::is_default_constructible<keyIterator>::value);
}
+void tst_QMap::keyValueIterator()
+{
+ QMap<int, int> map;
+ typedef QMap<int, int>::const_key_value_iterator::value_type entry_type;
+
+ for (int i = 0; i < 100; ++i)
+ map.insert(i, i * 100);
+
+ auto key_value_it = map.constKeyValueBegin();
+ auto it = map.cbegin();
+
+ for (int i = 0; i < map.size(); ++i) {
+ QVERIFY(key_value_it != map.constKeyValueEnd());
+ QVERIFY(it != map.cend());
+
+ entry_type pair(it.key(), it.value());
+ QCOMPARE(*key_value_it, pair);
+ ++key_value_it;
+ ++it;
+ }
+
+ QVERIFY(key_value_it == map.constKeyValueEnd());
+ QVERIFY(it == map.cend());
+
+ int key = 50;
+ int value = 50 * 100;
+ entry_type pair(key, value);
+ key_value_it = std::find(map.constKeyValueBegin(), map.constKeyValueEnd(), pair);
+ it = std::find(map.cbegin(), map.cend(), value);
+
+ QVERIFY(key_value_it != map.constKeyValueEnd());
+ QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
+
+ ++it;
+ ++key_value_it;
+ QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
+
+ --it;
+ --key_value_it;
+ QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
+
+ ++it;
+ ++key_value_it;
+ QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
+
+ --it;
+ --key_value_it;
+ QCOMPARE(*key_value_it, entry_type(it.key(), it.value()));
+ key = 99;
+ value = 99 * 100;
+ QCOMPARE(std::count(map.constKeyValueBegin(), map.constKeyValueEnd(), entry_type(key, value)), 1);
+}
+
void tst_QMap::keys_values_uniqueKeys()
{
QMap<QString, int> map;
diff --git a/tests/auto/corelib/tools/qrect/tst_qrect.cpp b/tests/auto/corelib/tools/qrect/tst_qrect.cpp
index d3c6412b0d..1c2221ec29 100644
--- a/tests/auto/corelib/tools/qrect/tst_qrect.cpp
+++ b/tests/auto/corelib/tools/qrect/tst_qrect.cpp
@@ -171,6 +171,7 @@ private slots:
void containsPointF_data();
void containsPointF();
void smallRects() const;
+ void toRect();
};
// Used to work around some floating point precision problems.
@@ -4331,5 +4332,36 @@ void tst_QRect::smallRects() const
QVERIFY(r1 != r2);
}
+void tst_QRect::toRect()
+{
+ for (qreal x = 1.0; x < 2.0; x += 0.25) {
+ for (qreal y = 1.0; y < 2.0; y += 0.25) {
+ for (qreal w = 1.0; w < 2.0; w += 0.25) {
+ for (qreal h = 1.0; h < 2.0; h += 0.25) {
+ const QRectF rectf(x, y, w, h);
+ const QRectF rect = rectf.toRect();
+ QVERIFY(qAbs(rect.x() - rectf.x()) < 1.0);
+ QVERIFY(qAbs(rect.y() - rectf.y()) < 1.0);
+ QVERIFY(qAbs(rect.width() - rectf.width()) < 1.0);
+ QVERIFY(qAbs(rect.height() - rectf.height()) < 1.0);
+ QVERIFY(qAbs(rect.right() - rectf.right()) < 1.0);
+ QVERIFY(qAbs(rect.bottom() - rectf.bottom()) < 1.0);
+
+ const QRectF arect = rectf.toAlignedRect();
+ QVERIFY(qAbs(arect.x() - rectf.x()) < 1.0);
+ QVERIFY(qAbs(arect.y() - rectf.y()) < 1.0);
+ QVERIFY(qAbs(arect.width() - rectf.width()) < 2.0);
+ QVERIFY(qAbs(arect.height() - rectf.height()) < 2.0);
+ QVERIFY(qAbs(arect.right() - rectf.right()) < 1.0);
+ QVERIFY(qAbs(arect.bottom() - rectf.bottom()) < 1.0);
+
+ QVERIFY(arect.contains(rectf));
+ QVERIFY(arect.contains(rect));
+ }
+ }
+ }
+ }
+}
+
QTEST_MAIN(tst_QRect)
#include "tst_qrect.moc"
diff --git a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
index 2a93250ba5..c828551e44 100644
--- a/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
+++ b/tests/auto/corelib/tools/qregularexpression/tst_qregularexpression.cpp
@@ -169,6 +169,7 @@ void consistencyCheck(const QRegularExpressionMatch &match)
int length = match.capturedLength(i);
QString captured = match.captured(i);
QStringRef capturedRef = match.capturedRef(i);
+ QStringView capturedView = match.capturedView(i);
if (!captured.isNull()) {
QVERIFY(startPos >= 0);
@@ -177,11 +178,13 @@ void consistencyCheck(const QRegularExpressionMatch &match)
QVERIFY(endPos >= startPos);
QVERIFY((endPos - startPos) == length);
QVERIFY(captured == capturedRef);
+ QVERIFY(captured == capturedView);
} else {
QVERIFY(startPos == -1);
QVERIFY(endPos == -1);
QVERIFY((endPos - startPos) == length);
QVERIFY(capturedRef.isNull());
+ QVERIFY(capturedView.isNull());
}
}
}
diff --git a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
index 21efaede00..a4b06d1b3b 100644
--- a/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
+++ b/tests/auto/corelib/tools/qscopedpointer/tst_qscopedpointer.cpp
@@ -88,7 +88,7 @@ class MySubClass : public MyClass
void tst_QScopedPointer::useSubClassInConstructor()
{
/* Use a syntax which users typically would do. */
- QScopedPointer<MyClass> p(new MyClass());
+ QScopedPointer<MyClass> p(new MySubClass());
}
void tst_QScopedPointer::dataOnValue()
diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
index 24f16b9911..70ccc72630 100644
--- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp
@@ -4726,8 +4726,8 @@ void tst_QString::arg()
QString s14( "%1%2%3" );
QCOMPARE( s4.arg("foo"), QLatin1String("[foo]") );
- QCOMPARE( s5.arg("foo"), QLatin1String("[foo]") );
- QCOMPARE( s6.arg("foo"), QLatin1String("[foo]") );
+ QCOMPARE( s5.arg(QLatin1String("foo")), QLatin1String("[foo]") );
+ QCOMPARE( s6.arg(QStringViewLiteral("foo")), QLatin1String("[foo]") );
QCOMPARE( s7.arg("foo"), QLatin1String("[foo]") );
QCOMPARE( s8.arg("foo"), QLatin1String("[foo %1]") );
QCOMPARE( s8.arg("foo").arg("bar"), QLatin1String("[foo bar]") );
@@ -4788,11 +4788,11 @@ void tst_QString::arg()
QCOMPARE( QString("%%%1%%%2").arg("foo").arg("bar"), QLatin1String("%%foo%%bar") );
QCOMPARE( QString("%1").arg("hello", -10), QLatin1String("hello ") );
- QCOMPARE( QString("%1").arg("hello", -5), QLatin1String("hello") );
- QCOMPARE( QString("%1").arg("hello", -2), QLatin1String("hello") );
+ QCOMPARE( QString("%1").arg(QLatin1String("hello"), -5), QLatin1String("hello") );
+ QCOMPARE( QString("%1").arg(QStringViewLiteral("hello"), -2), QLatin1String("hello") );
QCOMPARE( QString("%1").arg("hello", 0), QLatin1String("hello") );
- QCOMPARE( QString("%1").arg("hello", 2), QLatin1String("hello") );
- QCOMPARE( QString("%1").arg("hello", 5), QLatin1String("hello") );
+ QCOMPARE( QString("%1").arg(QLatin1String("hello"), 2), QLatin1String("hello") );
+ QCOMPARE( QString("%1").arg(QStringViewLiteral("hello"), 5), QLatin1String("hello") );
QCOMPARE( QString("%1").arg("hello", 10), QLatin1String(" hello") );
QCOMPARE( QString("%1%1").arg("hello"), QLatin1String("hellohello") );
QCOMPARE( QString("%2%1").arg("hello"), QLatin1String("%2hello") );
@@ -6067,14 +6067,6 @@ void tst_QString::compare_data()
lower += QChar(QChar::lowSurrogate(0x10428));
QTest::newRow("data8") << upper << lower << -1 << 0;
- QTest::newRow("vectorized-boundaries-7") << QString("1234567") << QString("abcdefg") << -1 << -1;
- QTest::newRow("vectorized-boundaries-8") << QString("12345678") << QString("abcdefgh") << -1 << -1;
- QTest::newRow("vectorized-boundaries-9") << QString("123456789") << QString("abcdefghi") << -1 << -1;
-
- QTest::newRow("vectorized-boundaries-15") << QString("123456789012345") << QString("abcdefghiklmnop") << -1 << -1;
- QTest::newRow("vectorized-boundaries-16") << QString("1234567890123456") << QString("abcdefghiklmnopq") << -1 << -1;
- QTest::newRow("vectorized-boundaries-17") << QString("12345678901234567") << QString("abcdefghiklmnopqr") << -1 << -1;
-
// embedded nulls
// These don't work as of now. It's OK that these don't work since \0 is not a valid unicode
/*QTest::newRow("data10") << QString(QByteArray("\0", 1)) << QString(QByteArray("\0", 1)) << 0 << 0;
@@ -6083,6 +6075,44 @@ void tst_QString::compare_data()
QTest::newRow("data13") << QString("ab\0c") << QString(QByteArray("ab\0c", 4)) << 0 << 0;
QTest::newRow("data14") << QString(QByteArray("ab\0c", 4)) << QString("abc") << -1 << -1;
QTest::newRow("data15") << QString("abc") << QString(QByteArray("ab\0c", 4)) << 1 << 1;*/
+
+ // All tests below (generated by the 3 for-loops) are meant to excercise the vectorized versions
+ // of ucstrncmp.
+
+ QString in1, in2;
+ for (int i = 0; i < 70; ++i) {
+ in1 += QString::number(i % 10);
+ in2 += QString::number((70 - i + 1) % 10);
+ }
+ Q_ASSERT(in1.length() == in2.length());
+ Q_ASSERT(in1 != in2);
+ Q_ASSERT(in1.at(0) < in2.at(0));
+ for (int i = 0; i < in1.length(); ++i) {
+ Q_ASSERT(in1.at(i) != in2.at(i));
+ }
+
+ for (int i = 1; i <= 65; ++i) {
+ QString inp1 = in1.left(i);
+ QString inp2 = in2.left(i);
+ QTest::addRow("all-different-%d", i) << inp1 << inp2 << -1 << -1;
+ }
+
+ for (int i = 1; i <= 65; ++i) {
+ QString start(i - 1, 'a');
+
+ QString in = start + QLatin1Char('a');
+ QTest::addRow("all-same-%d", i) << in << in << 0 << 0;
+
+ QString in2 = start + QLatin1Char('b');
+ QTest::addRow("last-different-%d", i) << in << in2 << -1 << -1;
+ }
+
+ for (int i = 0; i < 16; ++i) {
+ QString in1(16, 'a');
+ QString in2 = in1;
+ in2[i] = 'b';
+ QTest::addRow("all-same-except-char-%d", i) << in1 << in2 << -1 << -1;
+ }
}
static bool isLatin(const QString &s)
diff --git a/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro b/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro
index bc38b17949..a4e91e38bd 100644
--- a/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro
+++ b/tests/auto/corelib/tools/qstringapisymmetry/qstringapisymmetry.pro
@@ -3,3 +3,4 @@ TARGET = tst_qstringapisymmetry
QT = core testlib
SOURCES = tst_qstringapisymmetry.cpp
qtConfig(c++14): CONFIG += c++14
+qtConfig(c++1z): CONFIG += c++1z
diff --git a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp
index 9d9b47b61e..e482b409a5 100644
--- a/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp
+++ b/tests/auto/corelib/tools/qstringapisymmetry/tst_qstringapisymmetry.cpp
@@ -31,6 +31,7 @@
#undef QT_ASCII_CAST_WARNINGS
#include <QString>
+#include <QStringView>
#include <QChar>
#include <QStringRef>
#include <QLatin1String>
@@ -44,6 +45,7 @@ Q_DECLARE_METATYPE(QStringRef)
template <typename T>
QString toQString(const T &t) { return QString(t); }
QString toQString(const QStringRef &ref) { return ref.toString(); }
+QString toQString(QStringView view) { return view.toString(); }
// FIXME: these are missing at the time of writing, add them, then remove the dummies here:
#define MAKE_RELOP(op, A1, A2) \
@@ -81,13 +83,15 @@ class tst_QStringApiSymmetry : public QObject
void compare_impl() const;
private Q_SLOTS:
- // test all combinations of {QChar, QStringRef, QString, QLatin1String, QByteArray, const char*}
+ // test all combinations of {QChar, QStringRef, QString, QStringView, QLatin1String, QByteArray, const char*}
void compare_QChar_QChar_data() { compare_data(false); }
void compare_QChar_QChar() { compare_impl<QChar, QChar>(); }
void compare_QChar_QStringRef_data() { compare_data(false); }
void compare_QChar_QStringRef() { compare_impl<QChar, QStringRef>(); }
void compare_QChar_QString_data() { compare_data(false); }
void compare_QChar_QString() { compare_impl<QChar, QString>(); }
+ void compare_QChar_QStringView_data() { compare_data(false); }
+ void compare_QChar_QStringView() { compare_impl<QChar, QStringView>(); }
void compare_QChar_QLatin1String_data() { compare_data(false); }
void compare_QChar_QLatin1String() { compare_impl<QChar, QLatin1String>(); }
void compare_QChar_QByteArray_data() { compare_data(false); }
@@ -101,6 +105,8 @@ private Q_SLOTS:
void compare_QStringRef_QStringRef() { compare_impl<QStringRef, QStringRef>(); }
void compare_QStringRef_QString_data() { compare_data(); }
void compare_QStringRef_QString() { compare_impl<QStringRef, QString>(); }
+ void compare_QStringRef_QStringView_data() { compare_data(); }
+ void compare_QStringRef_QStringView() { compare_impl<QStringRef, QStringView>(); }
void compare_QStringRef_QLatin1String_data() { compare_data(); }
void compare_QStringRef_QLatin1String() { compare_impl<QStringRef, QLatin1String>(); }
void compare_QStringRef_QByteArray_data() { compare_data(); }
@@ -114,6 +120,8 @@ private Q_SLOTS:
void compare_QString_QStringRef() { compare_impl<QString, QStringRef>(); }
void compare_QString_QString_data() { compare_data(); }
void compare_QString_QString() { compare_impl<QString, QString>(); }
+ void compare_QString_QStringView_data() { compare_data(); }
+ void compare_QString_QStringView() { compare_impl<QString, QStringView>(); }
void compare_QString_QLatin1String_data() { compare_data(); }
void compare_QString_QLatin1String() { compare_impl<QString, QLatin1String>(); }
void compare_QString_QByteArray_data() { compare_data(); }
@@ -121,12 +129,25 @@ private Q_SLOTS:
void compare_QString_const_char_star_data() { compare_data(); }
void compare_QString_const_char_star() { compare_impl<QString, const char *>(); }
+ void compare_QStringView_QChar_data() { compare_data(false); }
+ void compare_QStringView_QChar() { compare_impl<QStringView, QChar>(); }
+ void compare_QStringView_QStringRef_data() { compare_data(); }
+ void compare_QStringView_QStringRef() { compare_impl<QStringView, QStringRef>(); }
+ void compare_QStringView_QString_data() { compare_data(); }
+ void compare_QStringView_QString() { compare_impl<QStringView, QString>(); }
+ void compare_QStringView_QStringView_data() { compare_data(); }
+ void compare_QStringView_QStringView() { compare_impl<QStringView, QStringView>(); }
+ void compare_QStringView_QLatin1String_data() { compare_data(); }
+ void compare_QStringView_QLatin1String() { compare_impl<QStringView, QLatin1String>(); }
+
void compare_QLatin1String_QChar_data() { compare_data(false); }
void compare_QLatin1String_QChar() { compare_impl<QLatin1String, QChar>(); }
void compare_QLatin1String_QStringRef_data() { compare_data(); }
void compare_QLatin1String_QStringRef() { compare_impl<QLatin1String, QStringRef>(); }
void compare_QLatin1String_QString_data() { compare_data(); }
void compare_QLatin1String_QString() { compare_impl<QLatin1String, QString>(); }
+ void compare_QLatin1String_QStringView_data() { compare_data(); }
+ void compare_QLatin1String_QStringView() { compare_impl<QLatin1String, QStringView>(); }
void compare_QLatin1String_QLatin1String_data() { compare_data(); }
void compare_QLatin1String_QLatin1String() { compare_impl<QLatin1String, QLatin1String>(); }
void compare_QLatin1String_QByteArray_data() { compare_data(); }
@@ -160,6 +181,181 @@ private Q_SLOTS:
//void compare_const_char_star_const_char_star_data() { compare_data(); }
//void compare_const_char_star_const_char_star() { compare_impl<const char *, const char *>(); }
+private:
+ void startsWith_data(bool rhsIsQChar = false);
+ template <typename Haystack, typename Needle> void startsWith_impl() const;
+
+ void endsWith_data(bool rhsIsQChar = false);
+ template <typename Haystack, typename Needle> void endsWith_impl() const;
+
+private Q_SLOTS:
+ // test all combinations of {QString, QStringRef, QStringView, QLatin1String} x {QString, QStringRef, QStringView, QLatin1String, QChar}:
+ void startsWith_QString_QString_data() { startsWith_data(); }
+ void startsWith_QString_QString() { startsWith_impl<QString, QString>(); }
+ void startsWith_QString_QStringRef_data() { startsWith_data(); }
+ void startsWith_QString_QStringRef() { startsWith_impl<QString, QStringRef>(); }
+ void startsWith_QString_QStringView_data() { startsWith_data(); }
+ void startsWith_QString_QStringView() { startsWith_impl<QString, QStringView>(); }
+ void startsWith_QString_QLatin1String_data() { startsWith_data(); }
+ void startsWith_QString_QLatin1String() { startsWith_impl<QString, QLatin1String>(); }
+ void startsWith_QString_QChar_data() { startsWith_data(false); }
+ void startsWith_QString_QChar() { startsWith_impl<QString, QChar>(); }
+
+ void startsWith_QStringRef_QString_data() { startsWith_data(); }
+ void startsWith_QStringRef_QString() { startsWith_impl<QStringRef, QString>(); }
+ void startsWith_QStringRef_QStringRef_data() { startsWith_data(); }
+ void startsWith_QStringRef_QStringRef() { startsWith_impl<QStringRef, QStringRef>(); }
+ void startsWith_QStringRef_QStringView_data() { startsWith_data(); }
+ void startsWith_QStringRef_QStringView() { startsWith_impl<QStringRef, QStringView>(); }
+ void startsWith_QStringRef_QLatin1String_data() { startsWith_data(); }
+ void startsWith_QStringRef_QLatin1String() { startsWith_impl<QStringRef, QLatin1String>(); }
+ void startsWith_QStringRef_QChar_data() { startsWith_data(false); }
+ void startsWith_QStringRef_QChar() { startsWith_impl<QStringRef, QChar>(); }
+
+ void startsWith_QStringView_QString_data() { startsWith_data(); }
+ void startsWith_QStringView_QString() { startsWith_impl<QStringView, QString>(); }
+ void startsWith_QStringView_QStringRef_data() { startsWith_data(); }
+ void startsWith_QStringView_QStringRef() { startsWith_impl<QStringView, QStringRef>(); }
+ void startsWith_QStringView_QStringView_data() { startsWith_data(); }
+ void startsWith_QStringView_QStringView() { startsWith_impl<QStringView, QStringView>(); }
+ void startsWith_QStringView_QLatin1String_data() { startsWith_data(); }
+ void startsWith_QStringView_QLatin1String() { startsWith_impl<QStringView, QLatin1String>(); }
+ void startsWith_QStringView_QChar_data() { startsWith_data(false); }
+ void startsWith_QStringView_QChar() { startsWith_impl<QStringView, QChar>(); }
+
+ void startsWith_QLatin1String_QString_data() { startsWith_data(); }
+ void startsWith_QLatin1String_QString() { startsWith_impl<QLatin1String, QString>(); }
+ void startsWith_QLatin1String_QStringRef_data() { startsWith_data(); }
+ void startsWith_QLatin1String_QStringRef() { startsWith_impl<QLatin1String, QStringRef>(); }
+ void startsWith_QLatin1String_QStringView_data() { startsWith_data(); }
+ void startsWith_QLatin1String_QStringView() { startsWith_impl<QLatin1String, QStringView>(); }
+ void startsWith_QLatin1String_QLatin1String_data() { startsWith_data(); }
+ void startsWith_QLatin1String_QLatin1String() { startsWith_impl<QLatin1String, QLatin1String>(); }
+ void startsWith_QLatin1String_QChar_data() { startsWith_data(false); }
+ void startsWith_QLatin1String_QChar() { startsWith_impl<QLatin1String, QChar>(); }
+
+ void endsWith_QString_QString_data() { endsWith_data(); }
+ void endsWith_QString_QString() { endsWith_impl<QString, QString>(); }
+ void endsWith_QString_QStringRef_data() { endsWith_data(); }
+ void endsWith_QString_QStringRef() { endsWith_impl<QString, QStringRef>(); }
+ void endsWith_QString_QStringView_data() { endsWith_data(); }
+ void endsWith_QString_QStringView() { endsWith_impl<QString, QStringView>(); }
+ void endsWith_QString_QLatin1String_data() { endsWith_data(); }
+ void endsWith_QString_QLatin1String() { endsWith_impl<QString, QLatin1String>(); }
+ void endsWith_QString_QChar_data() { endsWith_data(false); }
+ void endsWith_QString_QChar() { endsWith_impl<QString, QChar>(); }
+
+ void endsWith_QStringRef_QString_data() { endsWith_data(); }
+ void endsWith_QStringRef_QString() { endsWith_impl<QStringRef, QString>(); }
+ void endsWith_QStringRef_QStringRef_data() { endsWith_data(); }
+ void endsWith_QStringRef_QStringRef() { endsWith_impl<QStringRef, QStringRef>(); }
+ void endsWith_QStringRef_QStringView_data() { endsWith_data(); }
+ void endsWith_QStringRef_QStringView() { endsWith_impl<QStringRef, QStringView>(); }
+ void endsWith_QStringRef_QLatin1String_data() { endsWith_data(); }
+ void endsWith_QStringRef_QLatin1String() { endsWith_impl<QStringRef, QLatin1String>(); }
+ void endsWith_QStringRef_QChar_data() { endsWith_data(false); }
+ void endsWith_QStringRef_QChar() { endsWith_impl<QStringRef, QChar>(); }
+
+ void endsWith_QStringView_QString_data() { endsWith_data(); }
+ void endsWith_QStringView_QString() { endsWith_impl<QStringView, QString>(); }
+ void endsWith_QStringView_QStringRef_data() { endsWith_data(); }
+ void endsWith_QStringView_QStringRef() { endsWith_impl<QStringView, QStringRef>(); }
+ void endsWith_QStringView_QStringView_data() { endsWith_data(); }
+ void endsWith_QStringView_QStringView() { endsWith_impl<QStringView, QStringView>(); }
+ void endsWith_QStringView_QLatin1String_data() { endsWith_data(); }
+ void endsWith_QStringView_QLatin1String() { endsWith_impl<QStringView, QLatin1String>(); }
+ void endsWith_QStringView_QChar_data() { endsWith_data(false); }
+ void endsWith_QStringView_QChar() { endsWith_impl<QStringView, QChar>(); }
+
+ void endsWith_QLatin1String_QString_data() { endsWith_data(); }
+ void endsWith_QLatin1String_QString() { endsWith_impl<QLatin1String, QString>(); }
+ void endsWith_QLatin1String_QStringRef_data() { endsWith_data(); }
+ void endsWith_QLatin1String_QStringRef() { endsWith_impl<QLatin1String, QStringRef>(); }
+ void endsWith_QLatin1String_QStringView_data() { endsWith_data(); }
+ void endsWith_QLatin1String_QStringView() { endsWith_impl<QLatin1String, QStringView>(); }
+ void endsWith_QLatin1String_QLatin1String_data() { endsWith_data(); }
+ void endsWith_QLatin1String_QLatin1String() { endsWith_impl<QLatin1String, QLatin1String>(); }
+ void endsWith_QLatin1String_QChar_data() { endsWith_data(false); }
+ void endsWith_QLatin1String_QChar() { endsWith_impl<QLatin1String, QChar>(); }
+
+private:
+ void mid_data();
+ template <typename String> void mid_impl();
+
+ void left_data();
+ template <typename String> void left_impl();
+
+ void right_data();
+ template <typename String> void right_impl();
+
+ void chop_data();
+ template <typename String> void chop_impl();
+
+ void truncate_data() { left_data(); }
+ template <typename String> void truncate_impl();
+
+private Q_SLOTS:
+
+ void mid_QString_data() { mid_data(); }
+ void mid_QString() { mid_impl<QString>(); }
+ void mid_QStringRef_data() { mid_data(); }
+ void mid_QStringRef() { mid_impl<QStringRef>(); }
+ void mid_QStringView_data() { mid_data(); }
+ void mid_QStringView() { mid_impl<QStringView>(); }
+ void mid_QLatin1String_data() { mid_data(); }
+ void mid_QLatin1String() { mid_impl<QLatin1String>(); }
+ void mid_QByteArray_data() { mid_data(); }
+ void mid_QByteArray() { mid_impl<QByteArray>(); }
+
+ void left_truncate_QString_data() { left_data(); }
+ void left_truncate_QString() { left_impl<QString>(); }
+ void left_truncate_QStringRef_data() { left_data(); }
+ void left_truncate_QStringRef() { left_impl<QStringRef>(); }
+ void left_truncate_QStringView_data() { left_data(); }
+ void left_truncate_QStringView() { left_impl<QStringView>(); }
+ void left_truncate_QLatin1String_data() { left_data(); }
+ void left_truncate_QLatin1String() { left_impl<QLatin1String>(); }
+ void left_truncate_QByteArray_data() { left_data(); }
+ void left_truncate_QByteArray() { left_impl<QByteArray>(); }
+
+ void right_QString_data() { right_data(); }
+ void right_QString() { right_impl<QString>(); }
+ void right_QStringRef_data() { right_data(); }
+ void right_QStringRef() { right_impl<QStringRef>(); }
+ void right_QStringView_data() { right_data(); }
+ void right_QStringView() { right_impl<QStringView>(); }
+ void right_QLatin1String_data() { right_data(); }
+ void right_QLatin1String() { right_impl<QLatin1String>(); }
+ void right_QByteArray_data() { right_data(); }
+ void right_QByteArray() { right_impl<QByteArray>(); }
+
+ void chop_QString_data() { chop_data(); }
+ void chop_QString() { chop_impl<QString>(); }
+ void chop_QStringRef_data() { chop_data(); }
+ void chop_QStringRef() { chop_impl<QStringRef>(); }
+ void chop_QStringView_data() { chop_data(); }
+ void chop_QStringView() { chop_impl<QStringView>(); }
+ void chop_QLatin1String_data() { chop_data(); }
+ void chop_QLatin1String() { chop_impl<QLatin1String>(); }
+ void chop_QByteArray_data() { chop_data(); }
+ void chop_QByteArray() { chop_impl<QByteArray>(); }
+
+private:
+ void trimmed_data();
+ template <typename String> void trimmed_impl();
+
+private Q_SLOTS:
+ void trim_trimmed_QString_data() { trimmed_data(); }
+ void trim_trimmed_QString() { trimmed_impl<QString>(); }
+ void trim_trimmed_QStringRef_data() { trimmed_data(); }
+ void trim_trimmed_QStringRef() { trimmed_impl<QStringRef>(); }
+ void trim_trimmed_QStringView_data() { trimmed_data(); }
+ void trim_trimmed_QStringView() { trimmed_impl<QStringView>(); }
+ void trim_trimmed_QLatin1String_data() { trimmed_data(); }
+ void trim_trimmed_QLatin1String() { trimmed_impl<QLatin1String>(); }
+ void trim_trimmed_QByteArray_data() { trimmed_data(); }
+ void trim_trimmed_QByteArray() { trimmed_impl<QByteArray>(); }
+
//
// UTF-16-only checks:
//
@@ -183,21 +379,29 @@ private Q_SLOTS:
void toLocal8Bit_QString() { toLocal8Bit_impl<QString>(); }
void toLocal8Bit_QStringRef_data() { toLocal8Bit_data(); }
void toLocal8Bit_QStringRef() { toLocal8Bit_impl<QStringRef>(); }
+ void toLocal8Bit_QStringView_data() { toLocal8Bit_data(); }
+ void toLocal8Bit_QStringView() { toLocal8Bit_impl<QStringView>(); }
void toLatin1_QString_data() { toLatin1_data(); }
void toLatin1_QString() { toLatin1_impl<QString>(); }
void toLatin1_QStringRef_data() { toLatin1_data(); }
void toLatin1_QStringRef() { toLatin1_impl<QStringRef>(); }
+ void toLatin1_QStringView_data() { toLatin1_data(); }
+ void toLatin1_QStringView() { toLatin1_impl<QStringView>(); }
void toUtf8_QString_data() { toUtf8_data(); }
void toUtf8_QString() { toUtf8_impl<QString>(); }
void toUtf8_QStringRef_data() { toUtf8_data(); }
void toUtf8_QStringRef() { toUtf8_impl<QStringRef>(); }
+ void toUtf8_QStringView_data() { toUtf8_data(); }
+ void toUtf8_QStringView() { toUtf8_impl<QStringView>(); }
void toUcs4_QString_data() { toUcs4_data(); }
void toUcs4_QString() { toUcs4_impl<QString>(); }
void toUcs4_QStringRef_data() { toUcs4_data(); }
void toUcs4_QStringRef() { toUcs4_impl<QStringRef>(); }
+ void toUcs4_QStringView_data() { toUcs4_data(); }
+ void toUcs4_QStringView() { toUcs4_impl<QStringView>(); }
};
void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
@@ -217,6 +421,9 @@ void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
QTest::newRow("null <> empty") << QStringRef() << QLatin1String()
<< QStringRef(&empty) << QLatin1String("")
<< 0 << 0;
+ QTest::newRow("empty <> null") << QStringRef(&empty) << QLatin1String("")
+ << QStringRef() << QLatin1String()
+ << 0 << 0;
}
#define ROW(lhs, rhs) \
@@ -239,10 +446,20 @@ void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
#undef ROW
}
+template <typename String> String detached(String s)
+{
+ if (!s.isNull()) { // detaching loses nullness, but we need to preserve it
+ auto d = s.data();
+ Q_UNUSED(d);
+ }
+ return s;
+}
+
template <class Str> Str make(const QStringRef &sf, QLatin1String l1, const QByteArray &u8);
template <> QChar make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.isEmpty() ? QChar() : sf.at(0); }
template <> QStringRef make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf; }
template <> QString make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.toString(); }
+template <> QStringView make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf; }
template <> QLatin1String make(const QStringRef &, QLatin1String l1, const QByteArray &) { return l1; }
template <> QByteArray make(const QStringRef &, QLatin1String, const QByteArray &u8) { return u8; }
template <> const char * make(const QStringRef &, QLatin1String, const QByteArray &u8) { return u8.data(); }
@@ -260,6 +477,38 @@ struct has_nothrow_compare {
};
template <typename LHS, typename RHS>
+struct has_qCompareStrings {
+ enum { value = !std::is_same<LHS, QChar>::value && !std::is_same<RHS, QChar>::value &&
+ !is_utf8_encoded<LHS>::value && !is_utf8_encoded<RHS>::value };
+};
+
+template <typename LHS, typename RHS>
+using if_has_qCompareStrings = typename std::enable_if<has_qCompareStrings<LHS, RHS>::value, bool>::type;
+
+template <typename LHS, typename RHS>
+using if_lacks_qCompareStrings = typename std::enable_if<!has_qCompareStrings<LHS, RHS>::value, bool>::type;
+
+static inline Q_DECL_CONSTEXPR int sign(int x) Q_DECL_NOTHROW
+{
+ return x < 0 ? -1 :
+ x > 0 ? +1 :
+ /*else*/ 0 ;
+}
+
+template <typename LHS, typename RHS, if_has_qCompareStrings<LHS, RHS> = true>
+int qCompareStringsWrapper(const LHS &lhs, const RHS &rhs, Qt::CaseSensitivity cs, int)
+ Q_DECL_NOEXCEPT_EXPR(noexcept(qCompareStrings(lhs, rhs, cs)))
+{
+ return qCompareStrings(lhs, rhs, cs);
+}
+
+template <typename LHS, typename RHS, if_lacks_qCompareStrings<LHS, RHS> = true>
+int qCompareStringsWrapper(const LHS &, const RHS &, Qt::CaseSensitivity, int result)
+{
+ return result;
+}
+
+template <typename LHS, typename RHS>
void tst_QStringApiSymmetry::compare_impl() const
{
QFETCH(QStringRef, lhsUnicode);
@@ -267,6 +516,7 @@ void tst_QStringApiSymmetry::compare_impl() const
QFETCH(QStringRef, rhsUnicode);
QFETCH(QLatin1String, rhsLatin1);
QFETCH(int, caseSensitiveCompareResult);
+ QFETCH(const int, caseInsensitiveCompareResult);
const auto lhsU8 = lhsUnicode.toUtf8();
const auto rhsU8 = rhsUnicode.toUtf8();
@@ -283,6 +533,10 @@ void tst_QStringApiSymmetry::compare_impl() const
# define QVERIFY_NOEXCEPT(expr)
#endif
+ QCOMPARE(sign(qCompareStringsWrapper(lhs, rhs, Qt::CaseSensitive, caseSensitiveCompareResult)),
+ sign(caseSensitiveCompareResult));
+ QCOMPARE(sign(qCompareStringsWrapper(lhs, rhs, Qt::CaseInsensitive, caseInsensitiveCompareResult)),
+ sign(caseInsensitiveCompareResult));
#define CHECK(op) \
QVERIFY_NOEXCEPT(lhs op rhs); \
do { if (caseSensitiveCompareResult op 0) { \
@@ -300,6 +554,529 @@ void tst_QStringApiSymmetry::compare_impl() const
#undef CHECK
}
+static QString empty = QLatin1String("");
+// the tests below rely on the fact that these objects' names match their contents:
+static QString a = QStringLiteral("a");
+static QString A = QStringLiteral("A");
+static QString b = QStringLiteral("b");
+static QString B = QStringLiteral("B");
+static QString c = QStringLiteral("c");
+static QString C = QStringLiteral("C");
+static QString ab = QStringLiteral("ab");
+static QString aB = QStringLiteral("aB");
+static QString Ab = QStringLiteral("Ab");
+static QString AB = QStringLiteral("AB");
+static QString bc = QStringLiteral("bc");
+static QString bC = QStringLiteral("bC");
+static QString Bc = QStringLiteral("Bc");
+static QString BC = QStringLiteral("BC");
+static QString abc = QStringLiteral("abc");
+static QString abC = QStringLiteral("abC");
+static QString aBc = QStringLiteral("aBc");
+static QString aBC = QStringLiteral("aBC");
+static QString Abc = QStringLiteral("Abc");
+static QString AbC = QStringLiteral("AbC");
+static QString ABc = QStringLiteral("ABc");
+static QString ABC = QStringLiteral("ABC");
+
+void tst_QStringApiSymmetry::startsWith_data(bool rhsHasVariableLength)
+{
+ QTest::addColumn<QStringRef>("haystackU16");
+ QTest::addColumn<QLatin1String>("haystackL1");
+ QTest::addColumn<QStringRef>("needleU16");
+ QTest::addColumn<QLatin1String>("needleL1");
+ QTest::addColumn<bool>("resultCS");
+ QTest::addColumn<bool>("resultCIS");
+
+ if (rhsHasVariableLength) {
+ QTest::addRow("null ~= ^null") << QStringRef() << QLatin1String()
+ << QStringRef() << QLatin1String() << true << true;
+ QTest::addRow("empty ~= ^null") << QStringRef(&empty) << QLatin1String("")
+ << QStringRef() << QLatin1String() << true << true;
+ QTest::addRow("a ~= ^null") << QStringRef(&a) << QLatin1String("a")
+ << QStringRef() << QLatin1String() << true << true;
+ QTest::addRow("null ~= ^empty") << QStringRef() << QLatin1String()
+ << QStringRef(&empty) << QLatin1String("") << false << false;
+ QTest::addRow("a ~= ^empty") << QStringRef(&a) << QLatin1String("a")
+ << QStringRef(&empty) << QLatin1String("") << true << true;
+ QTest::addRow("empty ~= ^empty") << QStringRef(&empty) << QLatin1String("")
+ << QStringRef(&empty) << QLatin1String("") << true << true;
+ }
+ QTest::addRow("null ~= ^a") << QStringRef() << QLatin1String()
+ << QStringRef(&a) << QLatin1String("a") << false << false;
+ QTest::addRow("empty ~= ^a") << QStringRef(&empty) << QLatin1String("")
+ << QStringRef(&a) << QLatin1String("a") << false << false;
+
+#define ROW(h, n, cs, cis) \
+ QTest::addRow("%s ~= ^%s", #h, #n) << QStringRef(&h) << QLatin1String(#h) \
+ << QStringRef(&n) << QLatin1String(#n) \
+ << bool(cs) << bool(cis)
+ ROW(a, a, 1, 1);
+ ROW(a, A, 0, 1);
+ ROW(a, b, 0, 0);
+
+ if (rhsHasVariableLength)
+ ROW(a, aB, 0, 0);
+
+ ROW(ab, a, 1, 1);
+ if (rhsHasVariableLength) {
+ ROW(ab, ab, 1, 1);
+ ROW(ab, aB, 0, 1);
+ ROW(ab, Ab, 0, 1);
+ }
+ ROW(ab, c, 0, 0);
+
+ if (rhsHasVariableLength)
+ ROW(ab, abc, 0, 0);
+
+ ROW(Abc, c, 0, 0);
+ if (rhsHasVariableLength) {
+ ROW(Abc, ab, 0, 1);
+ ROW(Abc, aB, 0, 1);
+ ROW(Abc, Ab, 1, 1);
+ ROW(Abc, AB, 0, 1);
+ ROW(aBC, ab, 0, 1);
+ ROW(aBC, aB, 1, 1);
+ ROW(aBC, Ab, 0, 1);
+ ROW(aBC, AB, 0, 1);
+ }
+ ROW(ABC, b, 0, 0);
+ ROW(ABC, a, 0, 1);
+#undef ROW
+}
+
+template <typename Haystack, typename Needle>
+void tst_QStringApiSymmetry::startsWith_impl() const
+{
+ QFETCH(const QStringRef, haystackU16);
+ QFETCH(const QLatin1String, haystackL1);
+ QFETCH(const QStringRef, needleU16);
+ QFETCH(const QLatin1String, needleL1);
+ QFETCH(const bool, resultCS);
+ QFETCH(const bool, resultCIS);
+
+ const auto haystackU8 = haystackU16.toUtf8();
+ const auto needleU8 = needleU16.toUtf8();
+
+ const auto haystack = make<Haystack>(haystackU16, haystackL1, haystackU8);
+ const auto needle = make<Needle>(needleU16, needleL1, needleU8);
+
+ QCOMPARE(haystack.startsWith(needle), resultCS);
+ QCOMPARE(haystack.startsWith(needle, Qt::CaseSensitive), resultCS);
+ QCOMPARE(haystack.startsWith(needle, Qt::CaseInsensitive), resultCIS);
+}
+
+void tst_QStringApiSymmetry::endsWith_data(bool rhsHasVariableLength)
+{
+ QTest::addColumn<QStringRef>("haystackU16");
+ QTest::addColumn<QLatin1String>("haystackL1");
+ QTest::addColumn<QStringRef>("needleU16");
+ QTest::addColumn<QLatin1String>("needleL1");
+ QTest::addColumn<bool>("resultCS");
+ QTest::addColumn<bool>("resultCIS");
+
+ if (rhsHasVariableLength) {
+ QTest::addRow("null ~= null$") << QStringRef() << QLatin1String()
+ << QStringRef() << QLatin1String() << true << true;
+ QTest::addRow("empty ~= null$") << QStringRef(&empty) << QLatin1String("")
+ << QStringRef() << QLatin1String() << true << true;
+ QTest::addRow("a ~= null$") << QStringRef(&a) << QLatin1String("a")
+ << QStringRef() << QLatin1String() << true << true;
+ QTest::addRow("null ~= empty$") << QStringRef() << QLatin1String()
+ << QStringRef(&empty) << QLatin1String("") << false << false;
+ QTest::addRow("a ~= empty$") << QStringRef(&a) << QLatin1String("a")
+ << QStringRef(&empty) << QLatin1String("") << true << true;
+ QTest::addRow("empty ~= empty$") << QStringRef(&empty) << QLatin1String("")
+ << QStringRef(&empty) << QLatin1String("") << true << true;
+ }
+ QTest::addRow("null ~= a$") << QStringRef() << QLatin1String()
+ << QStringRef(&a) << QLatin1String("a") << false << false;
+ QTest::addRow("empty ~= a$") << QStringRef(&empty) << QLatin1String("")
+ << QStringRef(&a) << QLatin1String("a") << false << false;
+
+#define ROW(h, n, cs, cis) \
+ QTest::addRow("%s ~= %s$", #h, #n) << QStringRef(&h) << QLatin1String(#h) \
+ << QStringRef(&n) << QLatin1String(#n) \
+ << bool(cs) << bool(cis)
+ ROW(a, a, 1, 1);
+ ROW(a, A, 0, 1);
+ ROW(a, b, 0, 0);
+
+ if (rhsHasVariableLength)
+ ROW(b, ab, 0, 0);
+
+ ROW(ab, b, 1, 1);
+ if (rhsHasVariableLength) {
+ ROW(ab, ab, 1, 1);
+ ROW(ab, aB, 0, 1);
+ ROW(ab, Ab, 0, 1);
+ }
+ ROW(ab, c, 0, 0);
+
+ if (rhsHasVariableLength)
+ ROW(bc, abc, 0, 0);
+
+ ROW(Abc, c, 1, 1);
+ if (rhsHasVariableLength) {
+ ROW(Abc, bc, 1, 1);
+ ROW(Abc, bC, 0, 1);
+ ROW(Abc, Bc, 0, 1);
+ ROW(Abc, BC, 0, 1);
+ ROW(aBC, bc, 0, 1);
+ ROW(aBC, bC, 0, 1);
+ ROW(aBC, Bc, 0, 1);
+ ROW(aBC, BC, 1, 1);
+ }
+ ROW(ABC, b, 0, 0);
+ ROW(ABC, a, 0, 0);
+#undef ROW
+}
+
+template <typename Haystack, typename Needle>
+void tst_QStringApiSymmetry::endsWith_impl() const
+{
+ QFETCH(const QStringRef, haystackU16);
+ QFETCH(const QLatin1String, haystackL1);
+ QFETCH(const QStringRef, needleU16);
+ QFETCH(const QLatin1String, needleL1);
+ QFETCH(const bool, resultCS);
+ QFETCH(const bool, resultCIS);
+
+ const auto haystackU8 = haystackU16.toUtf8();
+ const auto needleU8 = needleU16.toUtf8();
+
+ const auto haystack = make<Haystack>(haystackU16, haystackL1, haystackU8);
+ const auto needle = make<Needle>(needleU16, needleL1, needleU8);
+
+ QCOMPARE(haystack.endsWith(needle), resultCS);
+ QCOMPARE(haystack.endsWith(needle, Qt::CaseSensitive), resultCS);
+ QCOMPARE(haystack.endsWith(needle, Qt::CaseInsensitive), resultCIS);
+}
+
+void tst_QStringApiSymmetry::mid_data()
+{
+ QTest::addColumn<QStringRef>("unicode");
+ QTest::addColumn<QLatin1String>("latin1");
+ QTest::addColumn<int>("pos");
+ QTest::addColumn<int>("n");
+ QTest::addColumn<QStringRef>("result");
+ QTest::addColumn<QStringRef>("result2");
+
+ QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << 0 << QStringRef() << QStringRef();
+ QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << 0 << QStringRef(&empty) << QStringRef(&empty);
+
+ // Some classes' mid() implementations have a wide contract, others a narrow one
+ // so only test valid arguents here:
+#define ROW(base, p, n, r1, r2) \
+ QTest::addRow("%s%d%d", #base, p, n) << QStringRef(&base) << QLatin1String(#base) << p << n << QStringRef(&r1) << QStringRef(&r2)
+
+ ROW(a, 0, 0, a, empty);
+ ROW(a, 0, 1, a, a);
+ ROW(a, 1, 0, empty, empty);
+
+ ROW(ab, 0, 0, ab, empty);
+ ROW(ab, 0, 1, ab, a);
+ ROW(ab, 0, 2, ab, ab);
+ ROW(ab, 1, 0, b, empty);
+ ROW(ab, 1, 1, b, b);
+ ROW(ab, 2, 0, empty, empty);
+
+ ROW(abc, 0, 0, abc, empty);
+ ROW(abc, 0, 1, abc, a);
+ ROW(abc, 0, 2, abc, ab);
+ ROW(abc, 0, 3, abc, abc);
+ ROW(abc, 1, 0, bc, empty);
+ ROW(abc, 1, 1, bc, b);
+ ROW(abc, 1, 2, bc, bc);
+ ROW(abc, 2, 0, c, empty);
+ ROW(abc, 2, 1, c, c);
+ ROW(abc, 3, 0, empty, empty);
+#undef ROW
+}
+
+template <typename String>
+void tst_QStringApiSymmetry::mid_impl()
+{
+ QFETCH(const QStringRef, unicode);
+ QFETCH(const QLatin1String, latin1);
+ QFETCH(const int, pos);
+ QFETCH(const int, n);
+ QFETCH(const QStringRef, result);
+ QFETCH(const QStringRef, result2);
+
+ const auto utf8 = unicode.toUtf8();
+
+ const auto s = make<String>(unicode, latin1, utf8);
+
+ {
+ const auto mid = s.mid(pos);
+ const auto mid2 = s.mid(pos, n);
+
+ QCOMPARE(mid, result);
+ QCOMPARE(mid.isNull(), result.isNull());
+ QCOMPARE(mid.isEmpty(), result.isEmpty());
+
+ QCOMPARE(mid2, result2);
+ QCOMPARE(mid2.isNull(), result2.isNull());
+ QCOMPARE(mid2.isEmpty(), result2.isEmpty());
+ }
+ {
+ const auto mid = detached(s).mid(pos);
+ const auto mid2 = detached(s).mid(pos, n);
+
+ QCOMPARE(mid, result);
+ QCOMPARE(mid.isNull(), result.isNull());
+ QCOMPARE(mid.isEmpty(), result.isEmpty());
+
+ QCOMPARE(mid2, result2);
+ QCOMPARE(mid2.isNull(), result2.isNull());
+ QCOMPARE(mid2.isEmpty(), result2.isEmpty());
+ }
+}
+
+void tst_QStringApiSymmetry::left_data()
+{
+ QTest::addColumn<QStringRef>("unicode");
+ QTest::addColumn<QLatin1String>("latin1");
+ QTest::addColumn<int>("n");
+ QTest::addColumn<QStringRef>("result");
+
+ QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << QStringRef();
+ QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << QStringRef(&empty);
+
+ // Some classes' left() implementations have a wide contract, others a narrow one
+ // so only test valid arguents here:
+#define ROW(base, n, res) \
+ QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res);
+
+ ROW(a, 0, empty);
+ ROW(a, 1, a);
+
+ ROW(ab, 0, empty);
+ ROW(ab, 1, a);
+ ROW(ab, 2, ab);
+
+ ROW(abc, 0, empty);
+ ROW(abc, 1, a);
+ ROW(abc, 2, ab);
+ ROW(abc, 3, abc);
+#undef ROW
+}
+
+template <typename String>
+void tst_QStringApiSymmetry::left_impl()
+{
+ QFETCH(const QStringRef, unicode);
+ QFETCH(const QLatin1String, latin1);
+ QFETCH(const int, n);
+ QFETCH(const QStringRef, result);
+
+ const auto utf8 = unicode.toUtf8();
+
+ const auto s = make<String>(unicode, latin1, utf8);
+
+ {
+ const auto left = s.left(n);
+
+ QCOMPARE(left, result);
+ QCOMPARE(left.isNull(), result.isNull());
+ QCOMPARE(left.isEmpty(), result.isEmpty());
+ }
+ {
+ const auto left = detached(s).left(n);
+
+ QCOMPARE(left, result);
+ QCOMPARE(left.isNull(), result.isNull());
+ QCOMPARE(left.isEmpty(), result.isEmpty());
+ }
+ {
+ auto left = s;
+ left.truncate(n);
+
+ QCOMPARE(left, result);
+ QCOMPARE(left.isNull(), result.isNull());
+ QCOMPARE(left.isEmpty(), result.isEmpty());
+ }
+}
+
+void tst_QStringApiSymmetry::right_data()
+{
+ QTest::addColumn<QStringRef>("unicode");
+ QTest::addColumn<QLatin1String>("latin1");
+ QTest::addColumn<int>("n");
+ QTest::addColumn<QStringRef>("result");
+
+ QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << QStringRef();
+ QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << QStringRef(&empty);
+
+ // Some classes' right() implementations have a wide contract, others a narrow one
+ // so only test valid arguents here:
+#define ROW(base, n, res) \
+ QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res);
+
+ ROW(a, 0, empty);
+ ROW(a, 1, a);
+
+ ROW(ab, 0, empty);
+ ROW(ab, 1, b);
+ ROW(ab, 2, ab);
+
+ ROW(abc, 0, empty);
+ ROW(abc, 1, c);
+ ROW(abc, 2, bc);
+ ROW(abc, 3, abc);
+#undef ROW
+}
+
+template <typename String>
+void tst_QStringApiSymmetry::right_impl()
+{
+ QFETCH(const QStringRef, unicode);
+ QFETCH(const QLatin1String, latin1);
+ QFETCH(const int, n);
+ QFETCH(const QStringRef, result);
+
+ const auto utf8 = unicode.toUtf8();
+
+ const auto s = make<String>(unicode, latin1, utf8);
+
+ {
+ const auto right = s.right(n);
+
+ QCOMPARE(right, result);
+ QCOMPARE(right.isNull(), result.isNull());
+ QCOMPARE(right.isEmpty(), result.isEmpty());
+ }
+ {
+ const auto right = detached(s).right(n);
+
+ QCOMPARE(right, result);
+ QCOMPARE(right.isNull(), result.isNull());
+ QCOMPARE(right.isEmpty(), result.isEmpty());
+ }
+}
+
+void tst_QStringApiSymmetry::chop_data()
+{
+ QTest::addColumn<QStringRef>("unicode");
+ QTest::addColumn<QLatin1String>("latin1");
+ QTest::addColumn<int>("n");
+ QTest::addColumn<QStringRef>("result");
+
+ QTest::addRow("null") << QStringRef() << QLatin1String() << 0 << QStringRef();
+ QTest::addRow("empty") << QStringRef(&empty) << QLatin1String("") << 0 << QStringRef(&empty);
+
+ // Some classes' truncate() implementations have a wide contract, others a narrow one
+ // so only test valid arguents here:
+#define ROW(base, n, res) \
+ QTest::addRow("%s%d", #base, n) << QStringRef(&base) << QLatin1String(#base) << n << QStringRef(&res);
+
+ ROW(a, 0, a);
+ ROW(a, 1, empty);
+
+ ROW(ab, 0, ab);
+ ROW(ab, 1, a);
+ ROW(ab, 2, empty);
+
+ ROW(abc, 0, abc);
+ ROW(abc, 1, ab);
+ ROW(abc, 2, a);
+ ROW(abc, 3, empty);
+#undef ROW
+}
+
+template <typename String>
+void tst_QStringApiSymmetry::chop_impl()
+{
+ QFETCH(const QStringRef, unicode);
+ QFETCH(const QLatin1String, latin1);
+ QFETCH(const int, n);
+ QFETCH(const QStringRef, result);
+
+ const auto utf8 = unicode.toUtf8();
+
+ const auto s = make<String>(unicode, latin1, utf8);
+
+ {
+ const auto chopped = s.chopped(n);
+
+ QCOMPARE(chopped, result);
+ QCOMPARE(chopped.isNull(), result.isNull());
+ QCOMPARE(chopped.isEmpty(), result.isEmpty());
+ }
+ {
+ const auto chopped = detached(s).chopped(n);
+
+ QCOMPARE(chopped, result);
+ QCOMPARE(chopped.isNull(), result.isNull());
+ QCOMPARE(chopped.isEmpty(), result.isEmpty());
+ }
+ {
+ auto chopped = s;
+ chopped.chop(n);
+
+ QCOMPARE(chopped, result);
+ QCOMPARE(chopped.isNull(), result.isNull());
+ QCOMPARE(chopped.isEmpty(), result.isEmpty());
+ }
+}
+
+void tst_QStringApiSymmetry::trimmed_data()
+{
+ QTest::addColumn<QString>("unicode");
+ QTest::addColumn<QStringRef>("result");
+
+ const auto latin1Whitespace = QLatin1String(" \r\n\t\f\v");
+
+ QTest::addRow("null") << QString() << QStringRef();
+
+ auto add = [latin1Whitespace](const QString &str) {
+ // run through all substrings of latin1Whitespace
+ for (int len = 0; len < latin1Whitespace.size(); ++len) {
+ for (int pos = 0; pos < latin1Whitespace.size() - len; ++pos) {
+ const QString unicode = latin1Whitespace.mid(pos, len) + str + latin1Whitespace.mid(pos, len);
+ const QScopedPointer<const char> escaped(QTest::toString(unicode));
+ QTest::addRow("%s", escaped.data()) << unicode << QStringRef(&str);
+ }
+ }
+ };
+
+ add(empty);
+ add(a);
+ add(ab);
+}
+
+template <typename String>
+void tst_QStringApiSymmetry::trimmed_impl()
+{
+ QFETCH(const QString, unicode);
+ QFETCH(const QStringRef, result);
+
+ const auto utf8 = unicode.toUtf8();
+ const auto l1s = unicode.toLatin1();
+ const auto l1 = l1s.isNull() ? QLatin1String() : QLatin1String(l1s);
+
+ const auto ref = unicode.isNull() ? QStringRef() : QStringRef(&unicode);
+ const auto s = make<String>(ref, l1, utf8);
+
+ QCOMPARE(s.isNull(), unicode.isNull());
+
+ {
+ const auto trimmed = s.trimmed();
+
+ QCOMPARE(trimmed, result);
+ QCOMPARE(trimmed.isNull(), result.isNull());
+ QCOMPARE(trimmed.isEmpty(), result.isEmpty());
+ }
+ {
+ const auto trimmed = detached(s).trimmed();
+
+ QCOMPARE(trimmed, result);
+ QCOMPARE(trimmed.isNull(), result.isNull());
+ QCOMPARE(trimmed.isEmpty(), result.isEmpty());
+ }
+}
+
//
//
// UTF-16-only checks:
@@ -309,6 +1086,7 @@ void tst_QStringApiSymmetry::compare_impl() const
template <class Str> Str make(const QString &s);
template <> QStringRef make(const QString &s) { return QStringRef(&s); }
template <> QString make(const QString &s) { return s; }
+template <> QStringView make(const QString &s) { return s; }
#define REPEAT_16X(X) X X X X X X X X X X X X X X X X
#define LONG_STRING_256 REPEAT_16X("0123456789abcdef")
diff --git a/tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp b/tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp
index 319f772516..7d5504c22c 100644
--- a/tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp
+++ b/tests/auto/corelib/tools/qstringiterator/tst_qstringiterator.cpp
@@ -326,22 +326,22 @@ void tst_QStringIterator::position()
QLatin1Char('p')
// codeunit count: 35
};
+ static const int stringDataSize = sizeof(stringData) / sizeof(stringData[0]);
- const QString string(stringData, sizeof(stringData) / sizeof(stringData[0]));
- QStringIterator i(string);
+ QStringIterator i(QStringView(stringData, stringDataSize));
- QCOMPARE(i.position(), string.constBegin());
+ QCOMPARE(i.position(), stringData);
QVERIFY(i.hasNext());
QVERIFY(!i.hasPrevious());
- i.setPosition(string.constEnd());
- QCOMPARE(i.position(), string.constEnd());
+ i.setPosition(stringData + stringDataSize);
+ QCOMPARE(i.position(), stringData + stringDataSize);
QVERIFY(!i.hasNext());
QVERIFY(i.hasPrevious());
#define QCHAR_UNICODE_VALUE(x) ((uint)(QChar(x).unicode()))
- const QString::const_iterator begin = string.constBegin();
+ const QChar *begin = stringData;
i.setPosition(begin);
QCOMPARE(i.position(), begin);
QCOMPARE(i.peekNext(), QCHAR_UNICODE_VALUE(QLatin1Char('a')));
diff --git a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
index 2385aa992c..9f054190e5 100644
--- a/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
+++ b/tests/auto/corelib/tools/qstringlist/tst_qstringlist.cpp
@@ -264,6 +264,15 @@ void tst_QStringList::contains()
QVERIFY(list.contains("ARTHUR", Qt::CaseInsensitive));
QVERIFY(list.contains("dent", Qt::CaseInsensitive));
QVERIFY(!list.contains("hans", Qt::CaseInsensitive));
+
+ QVERIFY(list.contains(QLatin1String("arthur")));
+ QVERIFY(!list.contains(QLatin1String("ArthuR")));
+ QVERIFY(!list.contains(QLatin1String("Hans")));
+ QVERIFY(list.contains(QLatin1String("arthur"), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QLatin1String("ArthuR"), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QLatin1String("ARTHUR"), Qt::CaseInsensitive));
+ QVERIFY(list.contains(QLatin1String("dent"), Qt::CaseInsensitive));
+ QVERIFY(!list.contains(QLatin1String("hans"), Qt::CaseInsensitive));
}
void tst_QStringList::removeDuplicates_data()
diff --git a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp b/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp
index d2374fe0ae..473f563f9b 100644
--- a/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp
+++ b/tests/auto/corelib/tools/qstringref/tst_qstringref.cpp
@@ -1862,7 +1862,9 @@ void tst_QStringRef::double_conversion()
void tst_QStringRef::trimmed()
{
- QString a;
+ QVERIFY(QStringRef().trimmed().isNull());
+ QString a = "";
+ QVERIFY(!QStringRef(&a).trimmed().isNull());
QStringRef b;
a = "Text";
b = a.leftRef(-1);
diff --git a/tests/auto/corelib/tools/qstringview/.gitignore b/tests/auto/corelib/tools/qstringview/.gitignore
new file mode 100644
index 0000000000..5f757d448a
--- /dev/null
+++ b/tests/auto/corelib/tools/qstringview/.gitignore
@@ -0,0 +1 @@
+tst_qstringview
diff --git a/tests/auto/corelib/tools/qstringview/qstringview.pro b/tests/auto/corelib/tools/qstringview/qstringview.pro
new file mode 100644
index 0000000000..e0e9973c91
--- /dev/null
+++ b/tests/auto/corelib/tools/qstringview/qstringview.pro
@@ -0,0 +1,6 @@
+CONFIG += testcase
+TARGET = tst_qstringview
+QT = core testlib
+contains(QT_CONFIG, c++14):CONFIG *= c++14
+contains(QT_CONFIG, c++1z):CONFIG *= c++1z
+SOURCES += tst_qstringview.cpp
diff --git a/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
new file mode 100644
index 0000000000..9617afb651
--- /dev/null
+++ b/tests/auto/corelib/tools/qstringview/tst_qstringview.cpp
@@ -0,0 +1,555 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Marc Mutz <marc.mutz@kdab.com>
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QStringView>
+#include <QString>
+#include <QChar>
+#include <QStringRef>
+
+#include <QTest>
+
+#include <string>
+
+template <typename T>
+using CanConvert = std::is_convertible<T, QStringView>;
+
+Q_STATIC_ASSERT(!CanConvert<QLatin1String>::value);
+Q_STATIC_ASSERT(!CanConvert<const char*>::value);
+Q_STATIC_ASSERT(!CanConvert<QByteArray>::value);
+
+// QStringView qchar_does_not_compile() { return QStringView(QChar('a')); }
+// QStringView qlatin1string_does_not_compile() { return QStringView(QLatin1String("a")); }
+// QStringView const_char_star_does_not_compile() { return QStringView("a"); }
+// QStringView qbytearray_does_not_compile() { return QStringView(QByteArray("a")); }
+
+//
+// QChar
+//
+
+Q_STATIC_ASSERT(!CanConvert<QChar>::value);
+
+Q_STATIC_ASSERT(CanConvert<QChar[123]>::value);
+
+Q_STATIC_ASSERT(CanConvert< QString >::value);
+Q_STATIC_ASSERT(CanConvert<const QString >::value);
+Q_STATIC_ASSERT(CanConvert< QString&>::value);
+Q_STATIC_ASSERT(CanConvert<const QString&>::value);
+
+Q_STATIC_ASSERT(CanConvert< QStringRef >::value);
+Q_STATIC_ASSERT(CanConvert<const QStringRef >::value);
+Q_STATIC_ASSERT(CanConvert< QStringRef&>::value);
+Q_STATIC_ASSERT(CanConvert<const QStringRef&>::value);
+
+
+//
+// ushort
+//
+
+Q_STATIC_ASSERT(!CanConvert<ushort>::value);
+
+Q_STATIC_ASSERT(CanConvert<ushort[123]>::value);
+
+Q_STATIC_ASSERT(CanConvert< ushort*>::value);
+Q_STATIC_ASSERT(CanConvert<const ushort*>::value);
+
+
+//
+// char16_t
+//
+
+#if defined(Q_COMPILER_UNICODE_STRINGS)
+
+Q_STATIC_ASSERT(!CanConvert<char16_t>::value);
+
+Q_STATIC_ASSERT(CanConvert< char16_t*>::value);
+Q_STATIC_ASSERT(CanConvert<const char16_t*>::value);
+
+#endif
+
+#if defined(Q_STDLIB_UNICODE_STRINGS)
+
+Q_STATIC_ASSERT(CanConvert< std::u16string >::value);
+Q_STATIC_ASSERT(CanConvert<const std::u16string >::value);
+Q_STATIC_ASSERT(CanConvert< std::u16string&>::value);
+Q_STATIC_ASSERT(CanConvert<const std::u16string&>::value);
+
+#endif
+
+
+//
+// wchar_t
+//
+
+Q_CONSTEXPR bool CanConvertFromWCharT =
+#ifdef Q_OS_WIN
+ true
+#else
+ false
+#endif
+ ;
+
+Q_STATIC_ASSERT(!CanConvert<wchar_t>::value);
+
+Q_STATIC_ASSERT(CanConvert< wchar_t*>::value == CanConvertFromWCharT);
+Q_STATIC_ASSERT(CanConvert<const wchar_t*>::value == CanConvertFromWCharT);
+
+Q_STATIC_ASSERT(CanConvert< std::wstring >::value == CanConvertFromWCharT);
+Q_STATIC_ASSERT(CanConvert<const std::wstring >::value == CanConvertFromWCharT);
+Q_STATIC_ASSERT(CanConvert< std::wstring&>::value == CanConvertFromWCharT);
+Q_STATIC_ASSERT(CanConvert<const std::wstring&>::value == CanConvertFromWCharT);
+
+
+class tst_QStringView : public QObject
+{
+ Q_OBJECT
+
+private Q_SLOTS:
+ void constExpr() const;
+ void basics() const;
+ void at() const;
+
+ void fromQString() const;
+ void fromQStringRef() const;
+
+ void fromQCharStar() const
+ {
+ const QChar str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ fromLiteral(str);
+ }
+
+ void fromUShortStar() const
+ {
+ const ushort str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ fromLiteral(str);
+ }
+
+ void fromChar16TStar() const
+ {
+#if defined(Q_COMPILER_UNICODE_STRINGS)
+ fromLiteral(u"Hello, World!");
+#else
+ QSKIP("This test requires C++11 char16_t support enabled in the compiler");
+#endif
+ }
+
+ void fromWCharTStar() const
+ {
+#ifdef Q_OS_WIN
+ fromLiteral(L"Hello, World!");
+#else
+ QSKIP("This is a Windows-only test");
+#endif
+ }
+
+ void fromQCharRange() const
+ {
+ const QChar str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+ fromRange(std::begin(str), std::end(str));
+ }
+
+ void fromUShortRange() const
+ {
+ const ushort str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+ fromRange(std::begin(str), std::end(str));
+ }
+
+ void fromChar16TRange() const
+ {
+#if defined(Q_COMPILER_UNICODE_STRINGS)
+ const char16_t str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+ fromRange(std::begin(str), std::end(str));
+#else
+ QSKIP("This test requires C++11 char16_t support enabled in the compiler");
+#endif
+ }
+
+ void fromWCharTRange() const
+ {
+#ifdef Q_OS_WIN
+ const wchar_t str[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+ fromRange(std::begin(str), std::end(str));
+#else
+ QSKIP("This is a Windows-only test");
+#endif
+ }
+
+ // std::basic_string
+ void fromStdStringWCharT() const
+ {
+#ifdef Q_OS_WIN
+ fromStdString<wchar_t>();
+#else
+ QSKIP("This is a Windows-only test");
+#endif
+ }
+ void fromStdStringChar16T() const
+ {
+#ifdef Q_STDLIB_UNICODE_STRINGS
+ fromStdString<char16_t>();
+#else
+ QSKIP("This test requires C++11 char16_t support enabled in compiler & stdlib");
+#endif
+ }
+
+private:
+ template <typename String>
+ void conversion_tests(String arg) const;
+ template <typename Char>
+ void fromLiteral(const Char *arg) const;
+ template <typename Char>
+ void fromRange(const Char *first, const Char *last) const;
+ template <typename Char, typename Container>
+ void fromContainer() const;
+ template <typename Char>
+ void fromStdString() const { fromContainer<Char, std::basic_string<Char> >(); }
+};
+
+void tst_QStringView::constExpr() const
+{
+ // compile-time checks
+#ifdef Q_COMPILER_CONSTEXPR
+ {
+ constexpr QStringView sv;
+ Q_STATIC_ASSERT(sv.size() == 0);
+ Q_STATIC_ASSERT(sv.isNull());
+ Q_STATIC_ASSERT(sv.empty());
+ Q_STATIC_ASSERT(sv.isEmpty());
+ Q_STATIC_ASSERT(sv.utf16() == nullptr);
+
+ constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
+ Q_STATIC_ASSERT(sv2.isNull());
+ Q_STATIC_ASSERT(sv2.empty());
+ }
+ {
+ constexpr QStringView sv = QStringViewLiteral("");
+ Q_STATIC_ASSERT(sv.size() == 0);
+ Q_STATIC_ASSERT(!sv.isNull());
+ Q_STATIC_ASSERT(sv.empty());
+ Q_STATIC_ASSERT(sv.isEmpty());
+ Q_STATIC_ASSERT(sv.utf16() != nullptr);
+
+ constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
+ Q_STATIC_ASSERT(!sv2.isNull());
+ Q_STATIC_ASSERT(sv2.empty());
+ }
+ {
+ constexpr QStringView sv = QStringViewLiteral("Hello");
+ Q_STATIC_ASSERT(sv.size() == 5);
+ Q_STATIC_ASSERT(!sv.empty());
+ Q_STATIC_ASSERT(!sv.isEmpty());
+ Q_STATIC_ASSERT(!sv.isNull());
+ Q_STATIC_ASSERT(*sv.utf16() == 'H');
+ Q_STATIC_ASSERT(sv[0] == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.at(0) == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.front() == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.first() == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv[4] == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.back() == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.last() == QLatin1Char('o'));
+
+ constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
+ Q_STATIC_ASSERT(!sv2.isNull());
+ Q_STATIC_ASSERT(!sv2.empty());
+ Q_STATIC_ASSERT(sv2.size() == 5);
+ }
+#if !defined(Q_OS_WIN) || defined(Q_COMPILER_UNICODE_STRINGS)
+ {
+ Q_STATIC_ASSERT(QStringView(u"Hello").size() == 5);
+ constexpr QStringView sv = u"Hello";
+ Q_STATIC_ASSERT(sv.size() == 5);
+ Q_STATIC_ASSERT(!sv.empty());
+ Q_STATIC_ASSERT(!sv.isEmpty());
+ Q_STATIC_ASSERT(!sv.isNull());
+ Q_STATIC_ASSERT(*sv.utf16() == 'H');
+ Q_STATIC_ASSERT(sv[0] == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.at(0) == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.front() == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.first() == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv[4] == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.back() == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.last() == QLatin1Char('o'));
+
+ constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
+ Q_STATIC_ASSERT(!sv2.isNull());
+ Q_STATIC_ASSERT(!sv2.empty());
+ Q_STATIC_ASSERT(sv2.size() == 5);
+ }
+#else // storage_type is wchar_t
+ {
+ Q_STATIC_ASSERT(QStringView(L"Hello").size() == 5);
+ constexpr QStringView sv = L"Hello";
+ Q_STATIC_ASSERT(sv.size() == 5);
+ Q_STATIC_ASSERT(!sv.empty());
+ Q_STATIC_ASSERT(!sv.isEmpty());
+ Q_STATIC_ASSERT(!sv.isNull());
+ Q_STATIC_ASSERT(*sv.utf16() == 'H');
+ Q_STATIC_ASSERT(sv[0] == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.at(0) == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.front() == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv.first() == QLatin1Char('H'));
+ Q_STATIC_ASSERT(sv[4] == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.at(4) == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.back() == QLatin1Char('o'));
+ Q_STATIC_ASSERT(sv.last() == QLatin1Char('o'));
+
+ constexpr QStringView sv2(sv.utf16(), sv.utf16() + sv.size());
+ Q_STATIC_ASSERT(!sv2.isNull());
+ Q_STATIC_ASSERT(!sv2.empty());
+ Q_STATIC_ASSERT(sv2.size() == 5);
+ }
+#endif
+#endif
+}
+
+void tst_QStringView::basics() const
+{
+ QStringView sv1;
+
+ // a default-constructed QStringView is null:
+ QVERIFY(sv1.isNull());
+ // which implies it's empty();
+ QVERIFY(sv1.isEmpty());
+
+ QStringView sv2;
+
+ QVERIFY(sv2 == sv1);
+ QVERIFY(!(sv2 != sv1));
+}
+
+void tst_QStringView::at() const
+{
+ QString hello("Hello");
+ QStringView sv(hello);
+ QCOMPARE(sv.at(0), QChar('H')); QCOMPARE(sv[0], QChar('H'));
+ QCOMPARE(sv.at(1), QChar('e')); QCOMPARE(sv[1], QChar('e'));
+ QCOMPARE(sv.at(2), QChar('l')); QCOMPARE(sv[2], QChar('l'));
+ QCOMPARE(sv.at(3), QChar('l')); QCOMPARE(sv[3], QChar('l'));
+ QCOMPARE(sv.at(4), QChar('o')); QCOMPARE(sv[4], QChar('o'));
+}
+
+void tst_QStringView::fromQString() const
+{
+ QString null;
+ QString empty = "";
+
+ QVERIFY( QStringView(null).isNull());
+ QVERIFY( QStringView(null).isEmpty());
+ QVERIFY( QStringView(empty).isEmpty());
+ QVERIFY(!QStringView(empty).isNull());
+
+ conversion_tests(QString("Hello World!"));
+}
+
+void tst_QStringView::fromQStringRef() const
+{
+ QStringRef null;
+ QString emptyS = "";
+ QStringRef empty(&emptyS);
+
+ QVERIFY( QStringView(null).isNull());
+ QVERIFY( QStringView(null).isEmpty());
+ QVERIFY( QStringView(empty).isEmpty());
+ QVERIFY(!QStringView(empty).isNull());
+
+ conversion_tests(QString("Hello World!").midRef(6));
+}
+
+template <typename Char>
+void tst_QStringView::fromLiteral(const Char *arg) const
+{
+ const Char *null = nullptr;
+ const Char empty[] = { 0 };
+
+ QCOMPARE(QStringView(null).size(), qssize_t(0));
+ QCOMPARE(QStringView(null).data(), nullptr);
+ QCOMPARE(QStringView(empty).size(), qssize_t(0));
+ QCOMPARE(static_cast<const void*>(QStringView(empty).data()),
+ static_cast<const void*>(empty));
+
+ QVERIFY( QStringView(null).isNull());
+ QVERIFY( QStringView(null).isEmpty());
+ QVERIFY( QStringView(empty).isEmpty());
+ QVERIFY(!QStringView(empty).isNull());
+
+ conversion_tests(arg);
+}
+
+template <typename Char>
+void tst_QStringView::fromRange(const Char *first, const Char *last) const
+{
+ const Char *null = nullptr;
+ QCOMPARE(QStringView(null, null).size(), 0);
+ QCOMPARE(QStringView(null, null).data(), nullptr);
+ QCOMPARE(QStringView(first, first).size(), 0);
+ QCOMPARE(static_cast<const void*>(QStringView(first, first).data()),
+ static_cast<const void*>(first));
+
+ const auto sv = QStringView(first, last);
+ QCOMPARE(sv.size(), last - first);
+ QCOMPARE(static_cast<const void*>(sv.data()),
+ static_cast<const void*>(first));
+
+ // can't call conversion_tests() here, as it requires a single object
+}
+
+template <typename Char, typename Container>
+void tst_QStringView::fromContainer() const
+{
+ const QString s = "Hello World!";
+
+ Container c;
+ // unspecified whether empty containers make null QStringViews
+ QVERIFY(QStringView(c).isEmpty());
+
+ QCOMPARE(sizeof(Char), sizeof(QChar));
+
+ const auto *data = reinterpret_cast<const Char *>(s.utf16());
+ std::copy(data, data + s.size(), std::back_inserter(c));
+ conversion_tests(std::move(c));
+}
+
+namespace help {
+template <typename T>
+size_t size(const T &t) { return size_t(t.size()); }
+template <typename T>
+size_t size(const T *t)
+{
+ size_t result = 0;
+ if (t) {
+ while (*t++)
+ ++result;
+ }
+ return result;
+}
+size_t size(const QChar *t)
+{
+ size_t result = 0;
+ if (t) {
+ while (!t++->isNull())
+ ++result;
+ }
+ return result;
+}
+
+template <typename T>
+typename T::const_iterator cbegin(const T &t) { return t.cbegin(); }
+template <typename T>
+const T * cbegin(const T *t) { return t; }
+
+template <typename T>
+typename T::const_iterator cend(const T &t) { return t.cend(); }
+template <typename T>
+const T * cend(const T *t) { return t + size(t); }
+
+template <typename T>
+typename T::const_reverse_iterator crbegin(const T &t) { return t.crbegin(); }
+template <typename T>
+std::reverse_iterator<const T*> crbegin(const T *t) { return std::reverse_iterator<const T*>(cend(t)); }
+
+template <typename T>
+typename T::const_reverse_iterator crend(const T &t) { return t.crend(); }
+template <typename T>
+std::reverse_iterator<const T*> crend(const T *t) { return std::reverse_iterator<const T*>(cbegin(t)); }
+
+} // namespace help
+
+template <typename String>
+void tst_QStringView::conversion_tests(String string) const
+{
+ // copy-construct:
+ {
+ QStringView sv = string;
+
+ QCOMPARE(help::size(sv), help::size(string));
+
+ // check iterators:
+
+ QVERIFY(std::equal(help::cbegin(string), help::cend(string),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv.cbegin(), sv.size())));
+ QVERIFY(std::equal(help::cbegin(string), help::cend(string),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(sv.begin(), sv.size())));
+ QVERIFY(std::equal(help::crbegin(string), help::crend(string),
+ sv.crbegin()));
+ QVERIFY(std::equal(help::crbegin(string), help::crend(string),
+ sv.rbegin()));
+
+ QCOMPARE(sv, string);
+ }
+
+ QStringView sv;
+
+ // copy-assign:
+ {
+ sv = string;
+
+ QCOMPARE(help::size(sv), help::size(string));
+
+ // check relational operators:
+
+ QCOMPARE(sv, string);
+ QCOMPARE(string, sv);
+
+ QVERIFY(!(sv != string));
+ QVERIFY(!(string != sv));
+
+ QVERIFY(!(sv < string));
+ QVERIFY(sv <= string);
+ QVERIFY(!(sv > string));
+ QVERIFY(sv >= string);
+
+ QVERIFY(!(string < sv));
+ QVERIFY(string <= sv);
+ QVERIFY(!(string > sv));
+ QVERIFY(string >= sv);
+ }
+
+ // copy-construct from rvalue (QStringView never assumes ownership):
+ {
+ QStringView sv2 = std::move(string);
+ QCOMPARE(sv2, sv);
+ QCOMPARE(sv2, string);
+ }
+
+ // copy-assign from rvalue (QStringView never assumes ownership):
+ {
+ QStringView sv2;
+ sv2 = std::move(string);
+ QCOMPARE(sv2, sv);
+ QCOMPARE(sv2, string);
+ }
+}
+
+QTEST_APPLESS_MAIN(tst_QStringView)
+#include "tst_qstringview.moc"
diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
index e75ed5cc67..9f22c3d51d 100644
--- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
+++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
@@ -62,7 +62,9 @@ private slots:
private:
void printTimeZone(const QTimeZone &tz);
#ifdef QT_BUILD_INTERNAL
+ // Generic tests of privates, called by implementation-specific private tests:
void testCetPrivate(const QTimeZonePrivate &tzp);
+ void testEpochTranPrivate(const QTimeZonePrivate &tzp);
#endif // QT_BUILD_INTERNAL
const bool debug;
};
@@ -167,11 +169,11 @@ void tst_QTimeZone::createTest()
QDateTime jun = QDateTime(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::UTC);
QDateTime janPrev = QDateTime(QDate(2011, 1, 1), QTime(0, 0, 0), Qt::UTC);
- QCOMPARE(tz.offsetFromUtc(jan), 46800);
- QCOMPARE(tz.offsetFromUtc(jun), 43200);
+ QCOMPARE(tz.offsetFromUtc(jan), 13 * 3600);
+ QCOMPARE(tz.offsetFromUtc(jun), 12 * 3600);
- QCOMPARE(tz.standardTimeOffset(jan), 43200);
- QCOMPARE(tz.standardTimeOffset(jun), 43200);
+ QCOMPARE(tz.standardTimeOffset(jan), 12 * 3600);
+ QCOMPARE(tz.standardTimeOffset(jun), 12 * 3600);
QCOMPARE(tz.daylightTimeOffset(jan), 3600);
QCOMPARE(tz.daylightTimeOffset(jun), 0);
@@ -183,38 +185,46 @@ void tst_QTimeZone::createTest()
// Only test transitions if host system supports them
if (tz.hasTransitions()) {
QTimeZone::OffsetData tran = tz.nextTransition(jan);
- QCOMPARE(tran.atUtc.toMSecsSinceEpoch(), (qint64)1333202400000);
- QCOMPARE(tran.offsetFromUtc, 43200);
- QCOMPARE(tran.standardTimeOffset, 43200);
+ // 2012-04-01 03:00 NZDT, +13 -> +12
+ QCOMPARE(tran.atUtc,
+ QDateTime(QDate(2012, 4, 1), QTime(3, 0), Qt::OffsetFromUTC, 13 * 3600));
+ QCOMPARE(tran.offsetFromUtc, 12 * 3600);
+ QCOMPARE(tran.standardTimeOffset, 12 * 3600);
QCOMPARE(tran.daylightTimeOffset, 0);
tran = tz.nextTransition(jun);
- QCOMPARE(tran.atUtc.toMSecsSinceEpoch(), (qint64)1348927200000);
- QCOMPARE(tran.offsetFromUtc, 46800);
- QCOMPARE(tran.standardTimeOffset, 43200);
+ // 2012-09-30 02:00 NZST, +12 -> +13
+ QCOMPARE(tran.atUtc,
+ QDateTime(QDate(2012, 9, 30), QTime(2, 0), Qt::OffsetFromUTC, 12 * 3600));
+ QCOMPARE(tran.offsetFromUtc, 13 * 3600);
+ QCOMPARE(tran.standardTimeOffset, 12 * 3600);
QCOMPARE(tran.daylightTimeOffset, 3600);
tran = tz.previousTransition(jan);
- QCOMPARE(tran.atUtc.toMSecsSinceEpoch(), (qint64)1316872800000);
- QCOMPARE(tran.offsetFromUtc, 46800);
- QCOMPARE(tran.standardTimeOffset, 43200);
+ // 2011-09-25 02:00 NZST, +12 -> +13
+ QCOMPARE(tran.atUtc,
+ QDateTime(QDate(2011, 9, 25), QTime(2, 0), Qt::OffsetFromUTC, 12 * 3600));
+ QCOMPARE(tran.offsetFromUtc, 13 * 3600);
+ QCOMPARE(tran.standardTimeOffset, 12 * 3600);
QCOMPARE(tran.daylightTimeOffset, 3600);
tran = tz.previousTransition(jun);
- QCOMPARE(tran.atUtc.toMSecsSinceEpoch(), (qint64)1333202400000);
- QCOMPARE(tran.offsetFromUtc, 43200);
- QCOMPARE(tran.standardTimeOffset, 43200);
+ // 2012-04-01 03:00 NZDT, +13 -> +12 (again)
+ QCOMPARE(tran.atUtc,
+ QDateTime(QDate(2012, 4, 1), QTime(3, 0), Qt::OffsetFromUTC, 13 * 3600));
+ QCOMPARE(tran.offsetFromUtc, 12 * 3600);
+ QCOMPARE(tran.standardTimeOffset, 12 * 3600);
QCOMPARE(tran.daylightTimeOffset, 0);
QTimeZone::OffsetDataList expected;
- tran.atUtc = QDateTime::fromMSecsSinceEpoch(1301752800000, Qt::UTC);
- tran.offsetFromUtc = 46800;
- tran.standardTimeOffset = 43200;
+ tran.atUtc = QDateTime(QDate(2011, 4, 3), QTime(2, 0), Qt::OffsetFromUTC, 13 * 3600);
+ tran.offsetFromUtc = 13 * 3600;
+ tran.standardTimeOffset = 12 * 3600;
tran.daylightTimeOffset = 3600;
expected << tran;
- tran.atUtc = QDateTime::fromMSecsSinceEpoch(1316872800000, Qt::UTC);
- tran.offsetFromUtc = 43200;
- tran.standardTimeOffset = 43200;
+ tran.atUtc = QDateTime(QDate(2011, 9, 25), QTime(2, 0), Qt::OffsetFromUTC, 12 * 3600);
+ tran.offsetFromUtc = 12 * 3600;
+ tran.standardTimeOffset = 12 * 3600;
tran.daylightTimeOffset = 0;
expected << tran;
QTimeZone::OffsetDataList result = tz.transitions(janPrev, jan);
@@ -749,12 +759,13 @@ void tst_QTimeZone::icuTest()
}
testCetPrivate(tzp);
+ testEpochTranPrivate(QIcuTimeZonePrivate("America/Toronto"));
#endif // QT_USE_ICU
}
void tst_QTimeZone::tzTest()
{
-#if defined QT_BUILD_INTERNAL && defined Q_OS_UNIX && !defined Q_OS_MAC
+#if defined QT_BUILD_INTERNAL && defined Q_OS_UNIX && !defined Q_OS_DARWIN
// Known datetimes
qint64 std = QDateTime(QDate(2012, 1, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
qint64 dst = QDateTime(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
@@ -822,6 +833,7 @@ void tst_QTimeZone::tzTest()
}
testCetPrivate(tzp);
+ testEpochTranPrivate(QTzTimeZonePrivate("America/Toronto"));
// Test first and last transition rule
// Warning: This could vary depending on age of TZ file!
@@ -845,7 +857,8 @@ void tst_QTimeZone::tzTest()
}
dat = tzp.nextTransition(-9999999999999);
- QCOMPARE(dat.atMSecsSinceEpoch, (qint64)-2422054408000);
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(dat.atMSecsSinceEpoch, Qt::OffsetFromUTC, 3600),
+ QDateTime(QDate(1893, 4, 1), QTime(0, 6, 32), Qt::OffsetFromUTC, 3600));
QCOMPARE(dat.standardTimeOffset, 3600);
QCOMPARE(dat.daylightTimeOffset, 0);
@@ -855,37 +868,41 @@ void tst_QTimeZone::tzTest()
// Tets high dates use the POSIX rule
dat = tzp.data(stdHi);
- QCOMPARE(dat.atMSecsSinceEpoch, (qint64)stdHi);
+ QCOMPARE(dat.atMSecsSinceEpoch - stdHi, (qint64)0);
QCOMPARE(dat.offsetFromUtc, 3600);
QCOMPARE(dat.standardTimeOffset, 3600);
QCOMPARE(dat.daylightTimeOffset, 0);
dat = tzp.data(dstHi);
- QCOMPARE(dat.atMSecsSinceEpoch, (qint64)dstHi);
+ QCOMPARE(dat.atMSecsSinceEpoch - dstHi, (qint64)0);
QCOMPARE(dat.offsetFromUtc, 7200);
QCOMPARE(dat.standardTimeOffset, 3600);
QCOMPARE(dat.daylightTimeOffset, 3600);
dat = tzp.previousTransition(stdHi);
- QCOMPARE(dat.atMSecsSinceEpoch, (qint64)4096659600000);
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(dat.atMSecsSinceEpoch, Qt::OffsetFromUTC, 3600),
+ QDateTime(QDate(2099, 10, 26), QTime(2, 0), Qt::OffsetFromUTC, 3600));
QCOMPARE(dat.offsetFromUtc, 3600);
QCOMPARE(dat.standardTimeOffset, 3600);
QCOMPARE(dat.daylightTimeOffset, 0);
dat = tzp.previousTransition(dstHi);
- QCOMPARE(dat.atMSecsSinceEpoch, (qint64)4109965200000);
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(dat.atMSecsSinceEpoch, Qt::OffsetFromUTC, 3600),
+ QDateTime(QDate(2100, 3, 29), QTime(2, 0), Qt::OffsetFromUTC, 3600));
QCOMPARE(dat.offsetFromUtc, 7200);
QCOMPARE(dat.standardTimeOffset, 3600);
QCOMPARE(dat.daylightTimeOffset, 3600);
dat = tzp.nextTransition(stdHi);
- QCOMPARE(dat.atMSecsSinceEpoch, (qint64)4109965200000);
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(dat.atMSecsSinceEpoch, Qt::OffsetFromUTC, 3600),
+ QDateTime(QDate(2100, 3, 29), QTime(2, 0), Qt::OffsetFromUTC, 3600));
QCOMPARE(dat.offsetFromUtc, 7200);
QCOMPARE(dat.standardTimeOffset, 3600);
QCOMPARE(dat.daylightTimeOffset, 3600);
dat = tzp.nextTransition(dstHi);
- QCOMPARE(dat.atMSecsSinceEpoch, (qint64)4128109200000);
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(dat.atMSecsSinceEpoch, Qt::OffsetFromUTC, 3600),
+ QDateTime(QDate(2100, 10, 25), QTime(2, 0), Qt::OffsetFromUTC, 3600));
QCOMPARE(dat.offsetFromUtc, 3600);
QCOMPARE(dat.standardTimeOffset, 3600);
QCOMPARE(dat.daylightTimeOffset, 0);
@@ -917,12 +934,12 @@ void tst_QTimeZone::tzTest()
QDateTime dt(QDate(2016, 3, 28), QTime(0, 0, 0), Qt::UTC);
QCOMPARE(tzBarnaul.data(dt.toMSecsSinceEpoch()).abbreviation, QString("+07"));
}
-#endif // Q_OS_UNIX
+#endif // QT_BUILD_INTERNAL && Q_OS_UNIX && !Q_OS_DARWIN
}
void tst_QTimeZone::macTest()
{
-#if defined(QT_BUILD_INTERNAL) && defined (Q_OS_MAC)
+#if defined(QT_BUILD_INTERNAL) && defined(Q_OS_DARWIN)
// Known datetimes
qint64 std = QDateTime(QDate(2012, 1, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
qint64 dst = QDateTime(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::UTC).toMSecsSinceEpoch();
@@ -969,7 +986,8 @@ void tst_QTimeZone::macTest()
}
testCetPrivate(tzp);
-#endif // Q_OS_MAC
+ testEpochTranPrivate(QMacTimeZonePrivate("America/Toronto"));
+#endif // QT_BUILD_INTERNAL && Q_OS_DARWIN
}
void tst_QTimeZone::darwinTypes()
@@ -1034,6 +1052,7 @@ void tst_QTimeZone::winTest()
}
testCetPrivate(tzp);
+ testEpochTranPrivate(QWinTimeZonePrivate("America/Toronto"));
#endif // Q_OS_WIN
}
@@ -1076,50 +1095,103 @@ void tst_QTimeZone::testCetPrivate(const QTimeZonePrivate &tzp)
// Only test transitions if host system supports them
if (tzp.hasTransitions()) {
QTimeZonePrivate::Data tran = tzp.nextTransition(std);
- QCOMPARE(tran.atMSecsSinceEpoch, (qint64)1332637200000);
+ // 2012-03-25 02:00 CET, +1 -> +2
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(tran.atMSecsSinceEpoch, Qt::UTC),
+ QDateTime(QDate(2012, 3, 25), QTime(2, 0), Qt::OffsetFromUTC, 3600));
QCOMPARE(tran.offsetFromUtc, 7200);
QCOMPARE(tran.standardTimeOffset, 3600);
QCOMPARE(tran.daylightTimeOffset, 3600);
tran = tzp.nextTransition(dst);
- QCOMPARE(tran.atMSecsSinceEpoch, (qint64)1351386000000);
+ // 2012-10-28 03:00 CEST, +2 -> +1
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(tran.atMSecsSinceEpoch, Qt::UTC),
+ QDateTime(QDate(2012, 10, 28), QTime(3, 0), Qt::OffsetFromUTC, 2 * 3600));
QCOMPARE(tran.offsetFromUtc, 3600);
QCOMPARE(tran.standardTimeOffset, 3600);
QCOMPARE(tran.daylightTimeOffset, 0);
tran = tzp.previousTransition(std);
- QCOMPARE(tran.atMSecsSinceEpoch, (qint64)1319936400000);
+ // 2011-10-30 03:00 CEST, +2 -> +1
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(tran.atMSecsSinceEpoch, Qt::UTC),
+ QDateTime(QDate(2011, 10, 30), QTime(3, 0), Qt::OffsetFromUTC, 2 * 3600));
QCOMPARE(tran.offsetFromUtc, 3600);
QCOMPARE(tran.standardTimeOffset, 3600);
QCOMPARE(tran.daylightTimeOffset, 0);
tran = tzp.previousTransition(dst);
- QCOMPARE(tran.atMSecsSinceEpoch, (qint64)1332637200000);
+ // 2012-03-25 02:00 CET, +1 -> +2 (again)
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(tran.atMSecsSinceEpoch, Qt::UTC),
+ QDateTime(QDate(2012, 3, 25), QTime(2, 0), Qt::OffsetFromUTC, 3600));
QCOMPARE(tran.offsetFromUtc, 7200);
QCOMPARE(tran.standardTimeOffset, 3600);
QCOMPARE(tran.daylightTimeOffset, 3600);
QTimeZonePrivate::DataList expected;
- tran.atMSecsSinceEpoch = (qint64)1301752800000;
+ // 2011-03-27 02:00 CET, +1 -> +2
+ tran.atMSecsSinceEpoch = QDateTime(QDate(2011, 3, 27), QTime(2, 0),
+ Qt::OffsetFromUTC, 3600).toMSecsSinceEpoch();
tran.offsetFromUtc = 7200;
tran.standardTimeOffset = 3600;
tran.daylightTimeOffset = 3600;
expected << tran;
- tran.atMSecsSinceEpoch = (qint64)1316872800000;
+ // 2011-10-30 03:00 CEST, +2 -> +1
+ tran.atMSecsSinceEpoch = QDateTime(QDate(2011, 10, 30), QTime(3, 0),
+ Qt::OffsetFromUTC, 2 * 3600).toMSecsSinceEpoch();
tran.offsetFromUtc = 3600;
tran.standardTimeOffset = 3600;
tran.daylightTimeOffset = 0;
expected << tran;
QTimeZonePrivate::DataList result = tzp.transitions(prev, std);
QCOMPARE(result.count(), expected.count());
- for (int i = 0; i > expected.count(); ++i) {
- QCOMPARE(result.at(i).atMSecsSinceEpoch, expected.at(i).atMSecsSinceEpoch);
+ for (int i = 0; i < expected.count(); ++i) {
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(result.at(i).atMSecsSinceEpoch,
+ Qt::OffsetFromUTC, 3600),
+ QDateTime::fromMSecsSinceEpoch(expected.at(i).atMSecsSinceEpoch,
+ Qt::OffsetFromUTC, 3600));
QCOMPARE(result.at(i).offsetFromUtc, expected.at(i).offsetFromUtc);
QCOMPARE(result.at(i).standardTimeOffset, expected.at(i).standardTimeOffset);
QCOMPARE(result.at(i).daylightTimeOffset, expected.at(i).daylightTimeOffset);
}
}
}
+
+// Needs a zone with DST around the epoch; currently America/Toronto (EST5EDT)
+void tst_QTimeZone::testEpochTranPrivate(const QTimeZonePrivate &tzp)
+{
+ if (!tzp.hasTransitions())
+ return; // test only viable for transitions
+
+ QTimeZonePrivate::Data tran = tzp.nextTransition(0); // i.e. first after epoch
+ // 1970-04-26 02:00 EST, -5 -> -4
+ const QDateTime after = QDateTime(QDate(1970, 4, 26), QTime(2, 0), Qt::OffsetFromUTC, -5 * 3600);
+ const QDateTime found = QDateTime::fromMSecsSinceEpoch(tran.atMSecsSinceEpoch, Qt::UTC);
+#ifdef Q_OS_WIN // MS gets the date wrong: 5th April instead of 26th.
+ QCOMPARE(found.toOffsetFromUtc(-5 * 3600).time(), after.time());
+#else
+ QCOMPARE(found, after);
+#endif
+ QCOMPARE(tran.offsetFromUtc, -4 * 3600);
+ QCOMPARE(tran.standardTimeOffset, -5 * 3600);
+ QCOMPARE(tran.daylightTimeOffset, 3600);
+
+ // Pre-epoch time-zones might not be supported at all:
+ tran = tzp.nextTransition(QDateTime(QDate(1601, 1, 1), QTime(0, 0),
+ Qt::UTC).toMSecsSinceEpoch());
+ if (tran.atMSecsSinceEpoch != QTimeZonePrivate::invalidSeconds()
+ && tran.atMSecsSinceEpoch < 0) {
+ // ... but, if they are, we should be able to search back to them:
+ tran = tzp.previousTransition(0); // i.e. last before epoch
+ // 1969-10-26 02:00 EDT, -4 -> -5
+ QCOMPARE(QDateTime::fromMSecsSinceEpoch(tran.atMSecsSinceEpoch, Qt::UTC),
+ QDateTime(QDate(1969, 10, 26), QTime(2, 0), Qt::OffsetFromUTC, -4 * 3600));
+ QCOMPARE(tran.offsetFromUtc, -5 * 3600);
+ QCOMPARE(tran.standardTimeOffset, -5 * 3600);
+ QCOMPARE(tran.daylightTimeOffset, 0);
+ } else {
+ // Do not use QSKIP(): that would discard the rest of this sub-test's caller.
+ qDebug() << "No support for pre-epoch time-zone transitions";
+ }
+}
#endif // QT_BUILD_INTERNAL
QTEST_APPLESS_MAIN(tst_QTimeZone)
diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
index 0806ad1318..3971353cbb 100644
--- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
+++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp
@@ -30,8 +30,6 @@
#include <qvarlengtharray.h>
#include <qvariant.h>
-const int N = 1;
-
class tst_QVarLengthArray : public QObject
{
Q_OBJECT
diff --git a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
index 2e34e82388..9812d93a50 100644
--- a/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
+++ b/tests/auto/corelib/tools/qversionnumber/tst_qversionnumber.cpp
@@ -513,6 +513,14 @@ void tst_QVersionNumber::fromString()
QCOMPARE(QVersionNumber::fromString(constructionString), expectedVersion);
QCOMPARE(QVersionNumber::fromString(constructionString, &index), expectedVersion);
QCOMPARE(index, suffixIndex);
+
+ QCOMPARE(QVersionNumber::fromString(QStringView(constructionString)), expectedVersion);
+ QCOMPARE(QVersionNumber::fromString(QStringView(constructionString), &index), expectedVersion);
+ QCOMPARE(index, suffixIndex);
+
+ QCOMPARE(QVersionNumber::fromString(QLatin1String(constructionString.toLatin1())), expectedVersion);
+ QCOMPARE(QVersionNumber::fromString(QLatin1String(constructionString.toLatin1()), &index), expectedVersion);
+ QCOMPARE(index, suffixIndex);
}
void tst_QVersionNumber::toString_data()
diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro
index e45771a704..6720307d59 100644
--- a/tests/auto/corelib/tools/tools.pro
+++ b/tests/auto/corelib/tools/tools.pro
@@ -1,6 +1,7 @@
TEMPLATE=subdirs
SUBDIRS=\
collections \
+ containerapisymmetry \
qalgorithms \
qarraydata \
qarraydata_strictiterators \
@@ -56,6 +57,7 @@ SUBDIRS=\
qstringlist \
qstringmatcher \
qstringref \
+ qstringview \
qtextboundaryfinder \
qtime \
qtimezone \
diff --git a/tests/auto/gui/gui.pro b/tests/auto/gui/gui.pro
index 2fd3024afe..d7cda11513 100644
--- a/tests/auto/gui/gui.pro
+++ b/tests/auto/gui/gui.pro
@@ -9,8 +9,11 @@ SUBDIRS = \
painting \
qopenglconfig \
qopengl \
+ qvulkan \
text \
util \
itemmodels \
!qtConfig(opengl): SUBDIRS -= qopengl qopenglconfig
+
+!qtConfig(vulkan): SUBDIRS -= qvulkan
diff --git a/tests/auto/gui/image/qicon/tst_qicon.cpp b/tests/auto/gui/image/qicon/tst_qicon.cpp
index 175179699d..bf8f7ade9e 100644
--- a/tests/auto/gui/image/qicon/tst_qicon.cpp
+++ b/tests/auto/gui/image/qicon/tst_qicon.cpp
@@ -530,16 +530,6 @@ void tst_QIcon::streamAvailableSizes()
}
}
-
-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;
-}
-
#ifndef QT_NO_WIDGETS
void tst_QIcon::task184901_badCache()
{
diff --git a/tests/auto/gui/image/qiconhighdpi/icons/misc/button.9.png b/tests/auto/gui/image/qiconhighdpi/icons/misc/button.9.png
new file mode 100644
index 0000000000..1a560a1d74
--- /dev/null
+++ b/tests/auto/gui/image/qiconhighdpi/icons/misc/button.9.png
Binary files differ
diff --git a/tests/auto/gui/image/qiconhighdpi/icons/misc/button@2x.9.png b/tests/auto/gui/image/qiconhighdpi/icons/misc/button@2x.9.png
new file mode 100644
index 0000000000..f010dc55c7
--- /dev/null
+++ b/tests/auto/gui/image/qiconhighdpi/icons/misc/button@2x.9.png
Binary files differ
diff --git a/tests/auto/gui/image/qiconhighdpi/tst_qiconhighdpi.cpp b/tests/auto/gui/image/qiconhighdpi/tst_qiconhighdpi.cpp
index ce7f68a0a6..51892cca04 100644
--- a/tests/auto/gui/image/qiconhighdpi/tst_qiconhighdpi.cpp
+++ b/tests/auto/gui/image/qiconhighdpi/tst_qiconhighdpi.cpp
@@ -39,6 +39,7 @@ private slots:
void initTestCase();
void fromTheme_data();
void fromTheme();
+ void ninePatch();
};
tst_QIconHighDpi::tst_QIconHighDpi()
@@ -182,6 +183,24 @@ void tst_QIconHighDpi::fromTheme()
QCOMPARE(pixmap.devicePixelRatio(), expectedDpr);
}
+void tst_QIconHighDpi::ninePatch()
+{
+ const QIcon icon(":/icons/misc/button.9.png");
+ const int dpr = qCeil(qApp->devicePixelRatio());
+
+ switch (dpr) {
+ case 1:
+ QCOMPARE(icon.availableSizes().size(), 1);
+ QCOMPARE(icon.availableSizes().at(0), QSize(42, 42));
+ break;
+ case 2:
+ QCOMPARE(icon.availableSizes().size(), 2);
+ QCOMPARE(icon.availableSizes().at(0), QSize(42, 42));
+ QCOMPARE(icon.availableSizes().at(1), QSize(82, 82));
+ break;
+ }
+}
+
int main(int argc, char *argv[])
{
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
diff --git a/tests/auto/gui/image/qiconhighdpi/tst_qiconhighdpi.qrc b/tests/auto/gui/image/qiconhighdpi/tst_qiconhighdpi.qrc
index 80b5e38ee6..5cc1c6d9b1 100644
--- a/tests/auto/gui/image/qiconhighdpi/tst_qiconhighdpi.qrc
+++ b/tests/auto/gui/image/qiconhighdpi/tst_qiconhighdpi.qrc
@@ -4,5 +4,7 @@
<file>icons/testtheme/22x22/actions/appointment-new.png</file>
<file>icons/testtheme/index.theme</file>
<file>icons/testtheme/22x22@2/actions/appointment-new.png</file>
+ <file>icons/misc/button.9.png</file>
+ <file>icons/misc/button@2x.9.png</file>
</qresource>
</RCC>
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index fac785ac86..0e65f6a23d 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -218,69 +218,71 @@ private slots:
void toCGImage();
#endif
+ void hugeQImage();
+
private:
const QString m_prefix;
};
-static QString formatToString(QImage::Format format)
+static QLatin1String formatToString(QImage::Format format)
{
switch (format) {
case QImage::Format_Invalid:
- return QStringLiteral("Invalid");
+ return QLatin1String("Invalid");
case QImage::Format_Mono:
- return QStringLiteral("Mono");
+ return QLatin1String("Mono");
case QImage::Format_MonoLSB:
- return QStringLiteral("MonoLSB");
+ return QLatin1String("MonoLSB");
case QImage::Format_Indexed8:
- return QStringLiteral("Indexed8");
+ return QLatin1String("Indexed8");
case QImage::Format_RGB32:
- return QStringLiteral("RGB32");
+ return QLatin1String("RGB32");
case QImage::Format_ARGB32:
- return QStringLiteral("ARGB32");
+ return QLatin1String("ARGB32");
case QImage::Format_ARGB32_Premultiplied:
- return QStringLiteral("ARGB32pm");
+ return QLatin1String("ARGB32pm");
case QImage::Format_RGB16:
- return QStringLiteral("RGB16");
+ return QLatin1String("RGB16");
case QImage::Format_ARGB8565_Premultiplied:
- return QStringLiteral("ARGB8565pm");
+ return QLatin1String("ARGB8565pm");
case QImage::Format_RGB666:
- return QStringLiteral("RGB666");
+ return QLatin1String("RGB666");
case QImage::Format_ARGB6666_Premultiplied:
- return QStringLiteral("ARGB6666pm");
+ return QLatin1String("ARGB6666pm");
case QImage::Format_RGB555:
- return QStringLiteral("RGB555");
+ return QLatin1String("RGB555");
case QImage::Format_ARGB8555_Premultiplied:
- return QStringLiteral("ARGB8555pm");
+ return QLatin1String("ARGB8555pm");
case QImage::Format_RGB888:
- return QStringLiteral("RGB888");
+ return QLatin1String("RGB888");
case QImage::Format_RGB444:
- return QStringLiteral("RGB444");
+ return QLatin1String("RGB444");
case QImage::Format_ARGB4444_Premultiplied:
- return QStringLiteral("ARGB4444pm");
+ return QLatin1String("ARGB4444pm");
case QImage::Format_RGBX8888:
- return QStringLiteral("RGBx88888");
+ return QLatin1String("RGBx88888");
case QImage::Format_RGBA8888:
- return QStringLiteral("RGBA88888");
+ return QLatin1String("RGBA88888");
case QImage::Format_RGBA8888_Premultiplied:
- return QStringLiteral("RGBA88888pm");
+ return QLatin1String("RGBA88888pm");
case QImage::Format_BGR30:
- return QStringLiteral("BGR30");
+ return QLatin1String("BGR30");
case QImage::Format_A2BGR30_Premultiplied:
- return QStringLiteral("A2BGR30pm");
+ return QLatin1String("A2BGR30pm");
case QImage::Format_RGB30:
- return QStringLiteral("RGB30");
+ return QLatin1String("RGB30");
case QImage::Format_A2RGB30_Premultiplied:
- return QStringLiteral("A2RGB30pm");
+ return QLatin1String("A2RGB30pm");
case QImage::Format_Alpha8:
- return QStringLiteral("Alpha8");
+ return QLatin1String("Alpha8");
case QImage::Format_Grayscale8:
- return QStringLiteral("Grayscale8");
+ return QLatin1String("Grayscale8");
default:
break;
};
Q_UNREACHABLE();
qWarning("Unhandled image format");
- return QStringLiteral("unknown");
+ return QLatin1String("unknown");
}
tst_QImage::tst_QImage()
@@ -314,8 +316,7 @@ void tst_QImage::create()
{
bool cr = true;
QT_TRY {
- //QImage image(7000000, 7000000, 8, 256, QImage::IgnoreEndian);
- QImage image(7000000, 7000000, QImage::Format_Indexed8);
+ QImage image(700000000, 70000000, QImage::Format_Indexed8);
image.setColorCount(256);
cr = !image.isNull();
} QT_CATCH (...) {
@@ -2321,7 +2322,7 @@ void tst_QImage::rgbSwapped_data()
QTest::addColumn<QImage::Format>("format");
for (int i = QImage::Format_Indexed8; i < QImage::Format_Alpha8; ++i) {
- QTest::newRow(qPrintable(formatToString(QImage::Format(i)))) << QImage::Format(i);
+ QTest::addRow("%s", formatToString(QImage::Format(i)).data()) << QImage::Format(i);
}
}
@@ -2366,7 +2367,7 @@ void tst_QImage::rgbSwapped()
QCOMPARE(image, imageSwappedTwice);
- QCOMPARE(memcmp(image.constBits(), imageSwappedTwice.constBits(), image.byteCount()), 0);
+ QCOMPARE(memcmp(image.constBits(), imageSwappedTwice.constBits(), image.sizeInBytes()), 0);
}
void tst_QImage::mirrored_data()
@@ -2478,7 +2479,7 @@ void tst_QImage::mirrored()
QCOMPARE(image, imageMirroredTwice);
if (format != QImage::Format_Mono && format != QImage::Format_MonoLSB)
- QCOMPARE(memcmp(image.constBits(), imageMirroredTwice.constBits(), image.byteCount()), 0);
+ QCOMPARE(memcmp(image.constBits(), imageMirroredTwice.constBits(), image.sizeInBytes()), 0);
else {
for (int i = 0; i < image.height(); ++i)
for (int j = 0; j < image.width(); ++j)
@@ -2540,8 +2541,8 @@ void tst_QImage::inplaceRgbSwapped()
QImage dataSwapped;
{
QVERIFY(!orig.isNull());
- volatileData = new uchar[orig.byteCount()];
- memcpy(volatileData, orig.constBits(), orig.byteCount());
+ volatileData = new uchar[orig.sizeInBytes()];
+ memcpy(volatileData, orig.constBits(), orig.sizeInBytes());
QImage dataImage;
if (rw)
@@ -2576,11 +2577,12 @@ void tst_QImage::inplaceMirrored_data()
continue;
if (i == QImage::Format_RGB444 || i == QImage::Format_ARGB4444_Premultiplied)
continue;
- QTest::newRow(qPrintable(formatToString(QImage::Format(i)) + QStringLiteral(", vertical")))
+ const auto fmt = formatToString(QImage::Format(i));
+ QTest::addRow("%s, vertical", fmt.data())
<< QImage::Format(i) << true << false;
- QTest::newRow(qPrintable(formatToString(QImage::Format(i)) + QStringLiteral(", horizontal")))
+ QTest::addRow("%s, horizontal", fmt.data())
<< QImage::Format(i) << false << true;
- QTest::newRow(qPrintable(formatToString(QImage::Format(i)) + QStringLiteral(", horizontal+vertical")))
+ QTest::addRow("%s, horizontal+vertical", fmt.data())
<< QImage::Format(i) << true << true;
}
}
@@ -2651,8 +2653,8 @@ void tst_QImage::inplaceMirrored()
QImage dataSwapped;
{
QVERIFY(!orig.isNull());
- volatileData = new uchar[orig.byteCount()];
- memcpy(volatileData, orig.constBits(), orig.byteCount());
+ volatileData = new uchar[orig.sizeInBytes()];
+ memcpy(volatileData, orig.constBits(), orig.sizeInBytes());
QImage dataImage;
if (rw)
@@ -2744,12 +2746,12 @@ void tst_QImage::genericRgbConversion_data()
QTest::addColumn<QImage::Format>("dest_format");
for (int i = QImage::Format_RGB32; i < QImage::Format_Alpha8; ++i) {
- const QString formatI = formatToString(QImage::Format(i));
+ const QLatin1String formatI = formatToString(QImage::Format(i));
for (int j = QImage::Format_RGB32; j < QImage::Format_Alpha8; ++j) {
if (i == j)
continue;
- const QString test = formatI + QLatin1String(" -> ") + formatToString(QImage::Format(j));
- QTest::newRow(qPrintable(test)) << QImage::Format(i) << QImage::Format(j);
+ QTest::addRow("%s -> %s", formatI.data(), formatToString(QImage::Format(j)).data())
+ << QImage::Format(i) << QImage::Format(j);
}
}
}
@@ -2786,8 +2788,8 @@ void tst_QImage::inplaceRgbConversion_data()
for (int j = QImage::Format_RGB32; j < QImage::Format_Alpha8; ++j) {
if (i == j)
continue;
- QString test = QString::fromLatin1("%1 -> %2").arg(formatToString(QImage::Format(i))).arg(formatToString(QImage::Format(j)));
- QTest::newRow(qPrintable(test)) << QImage::Format(i) << QImage::Format(j);
+ QTest::addRow("%s -> %s", formatToString(QImage::Format(i)).data(), formatToString(QImage::Format(j)).data())
+ << QImage::Format(i) << QImage::Format(j);
}
}
}
@@ -2953,7 +2955,7 @@ void tst_QImage::invertPixelsRGB_data()
QTest::addColumn<QImage::Format>("image_format");
for (int i = QImage::Format_RGB32; i < QImage::Format_Alpha8; ++i) {
- QTest::newRow(qPrintable(formatToString(QImage::Format(i)))) << QImage::Format(i);
+ QTest::addRow("%s", formatToString(QImage::Format(i)).data()) << QImage::Format(i);
}
}
@@ -3130,10 +3132,10 @@ void tst_QImage::rgb30Repremul_data()
{
QTest::addColumn<uint>("color");
for (int i = 255; i > 0; i -= 15) {
- QTest::newRow(qPrintable(QStringLiteral("100% red=") + QString::number(i))) << qRgba(i, 0, 0, 0xff);
- QTest::newRow(qPrintable(QStringLiteral("75% red=") + QString::number(i))) << qRgba(i, 0, 0, 0xc0);
- QTest::newRow(qPrintable(QStringLiteral("50% red=") + QString::number(i))) << qRgba(i, 0, 0, 0x80);
- QTest::newRow(qPrintable(QStringLiteral("37.5% red=") + QString::number(i))) << qRgba(i, 0, 0, 0x60);
+ QTest::addRow("100%% red=%d", i) << qRgba(i, 0, 0, 0xff);
+ QTest::addRow("75%% red=%d", i) << qRgba(i, 0, 0, 0xc0);
+ QTest::addRow("50%% red=%d", i) << qRgba(i, 0, 0, 0x80);
+ QTest::addRow("37.5%% red=%d", i) << qRgba(i, 0, 0, 0x60);
}
}
@@ -3393,7 +3395,7 @@ void tst_QImage::toCGImage_data()
QImage::Format_RGBA8888, QImage::Format_RGBX8888, QImage::Format_ARGB32_Premultiplied };
for (int i = QImage::Format_Invalid; i < QImage::Format_Grayscale8; ++i) {
- QTest::newRow(qPrintable(formatToString(QImage::Format(i))))
+ QTest::addRow("%s", formatToString(QImage::Format(i)).data())
<< QImage::Format(i) << supported.contains(QImage::Format(i));
}
}
@@ -3415,6 +3417,32 @@ void tst_QImage::toCGImage()
#endif
+void tst_QImage::hugeQImage()
+{
+#if Q_PROCESSOR_WORDSIZE < 8
+ QSKIP("Test only makes sense on 64-bit machines");
+#else
+ QImage image(25000, 25000, QImage::Format_RGB32);
+
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.height(), 25000);
+ QCOMPARE(image.width(), 25000);
+ QCOMPARE(image.sizeInBytes(), qssize_t(25000)*25000*4);
+ QCOMPARE(image.bytesPerLine(), 25000 * 4);
+
+ QCOMPARE(image.constScanLine(24990), image.constBits() + qssize_t(25000)*24990*4);
+
+ image.setPixel(20000, 24990, 0xffaabbcc);
+ QCOMPARE(image.pixel(20000, 24990), 0xffaabbcc);
+ QCOMPARE((reinterpret_cast<const unsigned int *>(image.constScanLine(24990)))[20000], 0xffaabbcc);
+
+ QImage canvas(100, 100, QImage::Format_RGB32);
+ QPainter painter(&canvas);
+ painter.drawImage(0,0, image, 19950, 24900, 100, 100);
+ painter.end();
+ QCOMPARE(reinterpret_cast<const unsigned int *>(canvas.constScanLine(90))[50], 0xffaabbcc);
+#endif
+}
QTEST_GUILESS_MAIN(tst_QImage)
#include "tst_qimage.moc"
diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
index d5c624833c..a53c2ddb5b 100644
--- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
+++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp
@@ -77,6 +77,9 @@ private slots:
void saveWithNoFormat();
void saveToTemporaryFile();
+
+ void writeEmpty();
+
private:
QTemporaryDir m_temporaryDir;
QString prefix;
@@ -463,7 +466,7 @@ void tst_QImageWriter::saveWithNoFormat()
SKIP_IF_UNSUPPORTED(format);
QImage niceImage(64, 64, QImage::Format_ARGB32);
- memset(niceImage.bits(), 0, niceImage.byteCount());
+ memset(niceImage.bits(), 0, niceImage.sizeInBytes());
QImageWriter writer(fileName /* , 0 - no format! */);
if (error != 0) {
@@ -529,5 +532,18 @@ void tst_QImageWriter::saveToTemporaryFile()
}
}
+void tst_QImageWriter::writeEmpty()
+{
+ // check writing a null QImage errors gracefully
+ QTemporaryDir dir;
+ QVERIFY2(dir.isValid(), qPrintable(dir.errorString()));
+ QString fileName(dir.path() + QLatin1String("/testimage.bmp"));
+ QVERIFY(!QFileInfo(fileName).exists());
+ QImageWriter writer(fileName);
+ QVERIFY(!writer.write(QImage()));
+ QCOMPARE(writer.error(), QImageWriter::InvalidImageError);
+ QVERIFY(!QFileInfo(fileName).exists());
+}
+
QTEST_MAIN(tst_QImageWriter)
#include "tst_qimagewriter.moc"
diff --git a/tests/auto/gui/kernel/kernel.pro b/tests/auto/gui/kernel/kernel.pro
index 559395a9ae..46786262c0 100644
--- a/tests/auto/gui/kernel/kernel.pro
+++ b/tests/auto/gui/kernel/kernel.pro
@@ -2,6 +2,7 @@ TEMPLATE=subdirs
SUBDIRS=\
qbackingstore \
qclipboard \
+ qcursor \
qdrag \
qevent \
qfileopenevent \
diff --git a/tests/auto/gui/kernel/qcursor/qcursor.pro b/tests/auto/gui/kernel/qcursor/qcursor.pro
new file mode 100644
index 0000000000..16e7d7c41c
--- /dev/null
+++ b/tests/auto/gui/kernel/qcursor/qcursor.pro
@@ -0,0 +1,6 @@
+QT += testlib
+TARGET = tst_qcursor
+CONFIG += testcase
+CONFIG -= app_bundle
+
+SOURCES += tst_qcursor.cpp
diff --git a/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp b/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp
new file mode 100644
index 0000000000..d505f5a655
--- /dev/null
+++ b/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QTest>
+#include <qcursor.h>
+#include <qpixmap.h>
+#include <qbitmap.h>
+
+class tst_QCursor : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void equality();
+};
+
+#define VERIFY_EQUAL(lhs, rhs) \
+ QVERIFY(lhs == rhs); \
+ QVERIFY(rhs == lhs); \
+ QVERIFY(!(rhs != lhs)); \
+ QVERIFY(!(lhs != rhs))
+
+#define VERIFY_DIFFERENT(lhs, rhs) \
+ QVERIFY(lhs != rhs); \
+ QVERIFY(rhs != lhs); \
+ QVERIFY(!(rhs == lhs)); \
+ QVERIFY(!(lhs == rhs))
+
+void tst_QCursor::equality()
+{
+ VERIFY_EQUAL(QCursor(), QCursor());
+ VERIFY_EQUAL(QCursor(Qt::CrossCursor), QCursor(Qt::CrossCursor));
+ VERIFY_DIFFERENT(QCursor(Qt::CrossCursor), QCursor());
+
+ // Shape
+ QCursor shapeCursor(Qt::WaitCursor);
+ VERIFY_EQUAL(shapeCursor, shapeCursor);
+ QCursor shapeCursorCopy(shapeCursor);
+ VERIFY_EQUAL(shapeCursor, shapeCursorCopy);
+ shapeCursorCopy.setShape(Qt::DragMoveCursor);
+ VERIFY_DIFFERENT(shapeCursor, shapeCursorCopy);
+ shapeCursorCopy.setShape(shapeCursor.shape());
+ VERIFY_EQUAL(shapeCursor, shapeCursorCopy);
+
+ // Pixmap
+ QPixmap pixmap(16, 16);
+ QCursor pixmapCursor(pixmap);
+ VERIFY_EQUAL(pixmapCursor, pixmapCursor);
+ VERIFY_EQUAL(pixmapCursor, QCursor(pixmapCursor));
+ VERIFY_EQUAL(pixmapCursor, QCursor(pixmap));
+ VERIFY_DIFFERENT(pixmapCursor, QCursor());
+ VERIFY_DIFFERENT(pixmapCursor, QCursor(pixmap, 5, 5));
+ VERIFY_DIFFERENT(pixmapCursor, QCursor(QPixmap(16, 16)));
+ VERIFY_DIFFERENT(pixmapCursor, shapeCursor);
+
+ // Bitmap & mask
+ QBitmap bitmap(16, 16);
+ QBitmap mask(16, 16);
+ QCursor bitmapCursor(bitmap, mask);
+ VERIFY_EQUAL(bitmapCursor, bitmapCursor);
+ VERIFY_EQUAL(bitmapCursor, QCursor(bitmapCursor));
+ VERIFY_EQUAL(bitmapCursor, QCursor(bitmap, mask));
+ VERIFY_DIFFERENT(bitmapCursor, QCursor());
+ VERIFY_DIFFERENT(bitmapCursor, QCursor(bitmap, mask, 5, 5));
+ VERIFY_DIFFERENT(bitmapCursor, QCursor(bitmap, QBitmap(16, 16)));
+ VERIFY_DIFFERENT(bitmapCursor, QCursor(QBitmap(16, 16), mask));
+ VERIFY_DIFFERENT(bitmapCursor, shapeCursor);
+ VERIFY_DIFFERENT(bitmapCursor, pixmapCursor);
+
+ // Empty pixmap
+ QPixmap emptyPixmap;
+ QCursor emptyPixmapCursor(emptyPixmap);
+ QCOMPARE(emptyPixmapCursor.shape(), Qt::ArrowCursor);
+ VERIFY_EQUAL(emptyPixmapCursor, QCursor());
+ VERIFY_EQUAL(emptyPixmapCursor, QCursor(emptyPixmap, 5, 5));
+ VERIFY_DIFFERENT(emptyPixmapCursor, shapeCursor);
+ VERIFY_DIFFERENT(emptyPixmapCursor, pixmapCursor);
+ VERIFY_DIFFERENT(emptyPixmapCursor, bitmapCursor);
+
+ // Empty bitmap & mask
+ QBitmap emptyBitmap;
+ QCursor emptyBitmapCursor(emptyBitmap, emptyBitmap);
+ QCOMPARE(emptyBitmapCursor.shape(), Qt::ArrowCursor);
+ VERIFY_EQUAL(emptyBitmapCursor, QCursor());
+ VERIFY_EQUAL(emptyBitmapCursor, QCursor(emptyBitmap, emptyBitmap, 5, 5));
+ VERIFY_EQUAL(emptyBitmapCursor, QCursor(emptyBitmap, mask));
+ VERIFY_EQUAL(emptyBitmapCursor, QCursor(bitmap, emptyBitmap));
+ VERIFY_EQUAL(emptyBitmapCursor, emptyPixmapCursor);
+ VERIFY_DIFFERENT(emptyBitmapCursor, shapeCursor);
+ VERIFY_DIFFERENT(emptyBitmapCursor, pixmapCursor);
+ VERIFY_DIFFERENT(emptyBitmapCursor, bitmapCursor);
+}
+
+#undef VERIFY_EQUAL
+#undef VERIFY_DIFFERENT
+
+QTEST_MAIN(tst_QCursor)
+#include "tst_qcursor.moc"
diff --git a/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp b/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
index 6394a956bd..f8b6bf064a 100644
--- a/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
+++ b/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp
@@ -36,14 +36,18 @@
#include <QLibraryInfo>
#ifdef Q_OS_MAC
-#ifdef Q_OS_OSX
-#include <Carbon/Carbon.h>
-#endif
struct MacSpecialKey {
int key;
ushort macSymbol;
};
+// Unicode code points for the glyphs associated with these keys
+// Defined by Carbon headers but not anywhere in Cocoa
+static const int kShiftUnicode = 0x21E7;
+static const int kControlUnicode = 0x2303;
+static const int kOptionUnicode = 0x2325;
+static const int kCommandUnicode = 0x2318;
+
static const int NumEntries = 21;
static const MacSpecialKey entries[NumEntries] = {
{ Qt::Key_Escape, 0x238B },
@@ -61,12 +65,10 @@ static const MacSpecialKey entries[NumEntries] = {
{ Qt::Key_Down, 0x2193 },
{ Qt::Key_PageUp, 0x21DE },
{ Qt::Key_PageDown, 0x21DF },
-#ifdef Q_OS_OSX
{ Qt::Key_Shift, kShiftUnicode },
{ Qt::Key_Control, kCommandUnicode },
{ Qt::Key_Meta, kControlUnicode },
{ Qt::Key_Alt, kOptionUnicode },
-#endif
{ Qt::Key_CapsLock, 0x21EA },
};
diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST
index 1443359377..9ffcf73d64 100644
--- a/tests/auto/gui/kernel/qwindow/BLACKLIST
+++ b/tests/auto/gui/kernel/qwindow/BLACKLIST
@@ -19,3 +19,7 @@ ubuntu-16.04
osx
[modalWindowModallity]
osx
+[visibility]
+osx-10.11 ci
+osx-10.12 ci
+
diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
index 92f7182249..ff8ee3d168 100644
--- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
+++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp
@@ -268,12 +268,21 @@ class Window : public QWindow
{
public:
Window(const Qt::WindowFlags flags = Qt::Window | Qt::WindowTitleHint | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint)
+ : QWindow(), lastReceivedWindowState(windowState())
{
reset();
setFlags(flags);
#if defined(Q_OS_QNX)
setSurfaceType(QSurface::OpenGLSurface);
#endif
+
+#if !defined(Q_OS_MACOS)
+ // FIXME: All platforms should send window-state change events, regardless
+ // of the sync/async nature of the the underlying platform, but they don't.
+ connect(this, &QWindow::windowStateChanged, [=]() {
+ lastReceivedWindowState = windowState();
+ });
+#endif
}
void reset()
@@ -298,6 +307,10 @@ public:
case QEvent::Move:
m_framePositionsOnMove << framePosition();
break;
+
+ case QEvent::WindowStateChange:
+ lastReceivedWindowState = windowState();
+
default:
break;
}
@@ -326,6 +339,8 @@ public:
}
QVector<QPoint> m_framePositionsOnMove;
+ Qt::WindowStates lastReceivedWindowState;
+
private:
QHash<QEvent::Type, int> m_received;
QVector<QEvent::Type> m_order;
@@ -482,17 +497,15 @@ void tst_QWindow::positioning()
window.reset();
window.setWindowState(Qt::WindowFullScreen);
- QCoreApplication::processEvents();
+ QTRY_COMPARE(window.lastReceivedWindowState, Qt::WindowFullScreen);
QTRY_VERIFY(window.received(QEvent::Resize) > 0);
- QTest::qWait(2000);
window.reset();
window.setWindowState(Qt::WindowNoState);
- QCoreApplication::processEvents();
+ QTRY_COMPARE(window.lastReceivedWindowState, Qt::WindowNoState);
QTRY_VERIFY(window.received(QEvent::Resize) > 0);
- QTest::qWait(2000);
QTRY_COMPARE(originalPos, window.position());
QTRY_COMPARE(originalFramePos, window.framePosition());
@@ -1748,7 +1761,7 @@ void tst_QWindow::visibility()
{
qRegisterMetaType<Qt::WindowModality>("QWindow::Visibility");
- QWindow window;
+ Window window;
QSignalSpy spy(&window, SIGNAL(visibilityChanged(QWindow::Visibility)));
window.setVisibility(QWindow::AutomaticVisibility);
@@ -1769,11 +1782,13 @@ void tst_QWindow::visibility()
QCOMPARE(window.windowState(), Qt::WindowFullScreen);
QCOMPARE(window.visibility(), QWindow::FullScreen);
QCOMPARE(spy.count(), 1);
+ QTRY_COMPARE(window.lastReceivedWindowState, Qt::WindowFullScreen);
spy.clear();
window.setWindowState(Qt::WindowNoState);
QCOMPARE(window.visibility(), QWindow::Windowed);
QCOMPARE(spy.count(), 1);
+ QTRY_COMPARE(window.lastReceivedWindowState, Qt::WindowNoState);
spy.clear();
window.setVisible(false);
@@ -1786,16 +1801,27 @@ void tst_QWindow::mask()
{
QRegion mask = QRect(10, 10, 800 - 20, 600 - 20);
- QWindow window;
- window.resize(800, 600);
- window.setMask(mask);
+ {
+ QWindow window;
+ window.resize(800, 600);
+ QCOMPARE(window.mask(), QRegion());
- QCOMPARE(window.mask(), QRegion());
+ window.create();
+ window.setMask(mask);
+ QCOMPARE(window.mask(), mask);
+ }
- window.create();
- window.setMask(mask);
+ {
+ QWindow window;
+ window.resize(800, 600);
+ QCOMPARE(window.mask(), QRegion());
+
+ window.setMask(mask);
+ QCOMPARE(window.mask(), mask);
+ window.create();
+ QCOMPARE(window.mask(), mask);
+ }
- QCOMPARE(window.mask(), mask);
}
void tst_QWindow::initialSize()
@@ -1840,6 +1866,9 @@ void tst_QWindow::modalDialog()
if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive))
QSKIP("Wayland: This fails. Figure out why.");
+ if (QGuiApplication::platformName() == QLatin1String("cocoa"))
+ QSKIP("Test fails due to QTBUG-61965, and is slow due to QTBUG-61964");
+
QWindow normalWindow;
normalWindow.setFramePosition(m_availableTopLeft + QPoint(80, 80));
normalWindow.resize(m_testWindowSize);
diff --git a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
index c2c04b69c5..96d983c8f7 100644
--- a/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
+++ b/tests/auto/gui/math3d/qmatrixnxn/tst_qmatrixnxn.cpp
@@ -2278,8 +2278,8 @@ void tst_QMatrixNxN::rotate4x4_data()
float y = 2.0f;
float z = -6.0f;
float angle = -45.0f;
- float c = std::cos(angle * M_PI / 180.0f);
- float s = std::sin(angle * M_PI / 180.0f);
+ float c = std::cos(qDegreesToRadians(angle));
+ float s = std::sin(qDegreesToRadians(angle));
float len = std::sqrt(x * x + y * y + z * z);
float xu = x / len;
float yu = y / len;
diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
index 53af65e010..097dd111d3 100644
--- a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
+++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp
@@ -815,7 +815,7 @@ void tst_QQuaternion::fromAxisAndAngle()
// 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();
- const float a = (angle * M_PI / 180.0) / 2.0;
+ const float a = qDegreesToRadians(angle) / 2.0;
const float sin_a = std::sin(a);
const float cos_a = std::cos(a);
QQuaternion result(cos_a,
diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
index 1ce7e797fc..6809aea086 100644
--- a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
+++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp
@@ -545,19 +545,32 @@ void tst_QColor::setNamedColor_data()
QColor bySetNamedColor; \
bySetNamedColor.setNamedColor(expr); \
auto byCtor = QColor(expr); \
- QTest::newRow(e.name + QByteArrayLiteral(#expr)) \
+ QTest::addRow("%s: %s", e.name, #expr) \
<< byCtor << bySetNamedColor << expected; \
} while (0) \
/*end*/
- ROW(QLatin1String(e.name));
- ROW(QString(QLatin1String(e.name)));
+ const auto l1 = QLatin1String(e.name);
+ const auto l1UpperBA = QByteArray(e.name).toUpper();
+ const auto l1Upper = QLatin1String(l1UpperBA);
+ const auto l1SpaceBA = QByteArray(e.name).insert(1, ' ');
+ const auto l1Space = QLatin1String(l1SpaceBA);
+
+ const auto u16 = QString(l1);
+ const auto u16Upper = u16.toUpper();
+ const auto u16Space = QString(u16).insert(1, ' ');
+
+ ROW(l1);
+ ROW(u16);
+ ROW(QStringView(u16));
// name should be case insensitive
- ROW(QLatin1String(QByteArray(e.name).toUpper()));
- ROW(QString(e.name).toUpper());
+ ROW(l1Upper);
+ ROW(u16Upper);
+ ROW(QStringView(u16Upper));
// spaces should be ignored
- ROW(QLatin1String(QByteArray(e.name).insert(1, ' ')));
- ROW(QString(e.name).insert(1, ' '));
+ ROW(l1Space);
+ ROW(u16Space);
+ ROW(QStringView(u16Space));
#undef ROW
}
}
diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
index 6b6869c2ba..779783d5ec 100644
--- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp
@@ -399,51 +399,6 @@ void tst_QPainter::cleanupTestCase()
QFile::remove(QLatin1String("foo.png"));
}
-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"};
-
-
#ifndef QT_NO_WIDGETS
void tst_QPainter::drawPixmap_comp_data()
{
@@ -3559,11 +3514,9 @@ void tst_QPainter::drawImage_data()
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
+ QTest::addRow("srcFormat %d, dstFormat %d, odd x: %d, odd width: %d",
+ srcFormat, dstFormat, odd_x, odd_width)
+ << (10 + odd_x) << 10 << (20 + odd_width) << 20
<< QImage::Format(srcFormat)
<< QImage::Format(dstFormat);
}
diff --git a/tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp b/tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp
index 13b6e28f5f..bf3e5dfb52 100644
--- a/tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp
+++ b/tests/auto/gui/painting/qpolygon/tst_qpolygon.cpp
@@ -49,6 +49,8 @@ private slots:
void boundingRectF();
void makeEllipse();
void swap();
+ void intersections_data();
+ void intersections();
};
tst_QPolygon::tst_QPolygon()
@@ -159,5 +161,45 @@ void tst_QPolygon::swap()
QCOMPARE(p2.count(),3);
}
+void tst_QPolygon::intersections_data()
+{
+ QTest::addColumn<QPolygon>("poly1");
+ QTest::addColumn<QPolygon>("poly2");
+ QTest::addColumn<bool>("result");
+
+ QTest::newRow("empty intersects nothing")
+ << QPolygon()
+ << QPolygon(QVector<QPoint>() << QPoint(0,0) << QPoint(10,10) << QPoint(-10,10))
+ << false;
+ QTest::newRow("identical triangles")
+ << QPolygon(QVector<QPoint>() << QPoint(0,0) << QPoint(10,10) << QPoint(-10,10))
+ << QPolygon(QVector<QPoint>() << QPoint(0,0) << QPoint(10,10) << QPoint(-10,10))
+ << true;
+ QTest::newRow("not intersecting")
+ << QPolygon(QVector<QPoint>() << QPoint(0,0) << QPoint(10,10) << QPoint(-10,10))
+ << QPolygon(QVector<QPoint>() << QPoint(0,20) << QPoint(10,12) << QPoint(-10,12))
+ << false;
+ QTest::newRow("clean intersection of squares")
+ << QPolygon(QVector<QPoint>() << QPoint(0,0) << QPoint(0,10) << QPoint(10,10) << QPoint(10,0))
+ << QPolygon(QVector<QPoint>() << QPoint(5,5) << QPoint(5,15) << QPoint(15,15) << QPoint(15,5))
+ << true;
+ QTest::newRow("clean contains of squares")
+ << QPolygon(QVector<QPoint>() << QPoint(0,0) << QPoint(0,10) << QPoint(10,10) << QPoint(10,0))
+ << QPolygon(QVector<QPoint>() << QPoint(5,5) << QPoint(5,8) << QPoint(8,8) << QPoint(8,5))
+ << true;
+}
+
+void tst_QPolygon::intersections()
+{
+ QFETCH(QPolygon, poly1);
+ QFETCH(QPolygon, poly2);
+ QFETCH(bool, result);
+
+ QCOMPARE(poly2.intersects(poly1), poly1.intersects(poly2));
+ QCOMPARE(poly2.intersected(poly1).isEmpty(), poly1.intersected(poly2).isEmpty());
+ QCOMPARE(!poly1.intersected(poly2).isEmpty(), poly1.intersects(poly2));
+ QCOMPARE(poly1.intersects(poly2), result);
+}
+
QTEST_APPLESS_MAIN(tst_QPolygon)
#include "tst_qpolygon.moc"
diff --git a/tests/auto/gui/painting/qtransform/tst_qtransform.cpp b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp
index 0c089cdaa3..0a6a95daca 100644
--- a/tests/auto/gui/painting/qtransform/tst_qtransform.cpp
+++ b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp
@@ -29,7 +29,6 @@
#include <QtTest/QtTest>
#include "qtransform.h"
-#include <math.h>
#include <qpolygon.h>
#include <qdebug.h>
@@ -67,10 +66,6 @@ private:
Q_DECLARE_METATYPE(QTransform)
-#if defined(Q_OS_WIN) && !defined(M_PI)
-#define M_PI 3.14159265897932384626433832795f
-#endif
-
void tst_QTransform::mapRect_data()
{
mapping_data();
diff --git a/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp b/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp
index a79526c434..da88a868f3 100644
--- a/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp
+++ b/tests/auto/gui/painting/qwmatrix/tst_qwmatrix.cpp
@@ -114,131 +114,96 @@ void tst_QWMatrix::mapping_data()
<< QRect( 0, 0, 30, 40 )
<< QPolygon( QRect( -300, -400, 300, 400 ) );
-#if defined(Q_OS_WIN) && !defined(M_PI)
-#define M_PI 3.14159265897932384626433832795f
-#endif
+ const auto rotate = [](qreal degrees) {
+ const qreal rad = qDegreesToRadians(degrees);
+ return QMatrix(std::cos(rad), -std::sin(rad),
+ std::sin(rad), std::cos(rad), 0, 0);
+ };
// rotations
- float deg = 0.;
- QTest::newRow( "rot 0 a" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ),
- std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot 0 a" ) << rotate(0.)
<< QRect( 0, 0, 30, 40 )
<< QPolygon ( QRect( 0, 0, 30, 40 ) );
- deg = 0.00001f;
- QTest::newRow( "rot 0 b" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ),
- std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot 0 b" ) << rotate(0.00001f)
<< QRect( 0, 0, 30, 40 )
<< QPolygon ( QRect( 0, 0, 30, 40 ) );
- deg = 0.;
- QTest::newRow( "rot 0 c" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ),
- std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot 0 c" ) << rotate(0.)
<< QRect( 10, 20, 30, 40 )
<< QPolygon ( QRect( 10, 20, 30, 40 ) );
- deg = 0.00001f;
- QTest::newRow( "rot 0 d" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ),
- std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot 0 d" ) << rotate(0.00001f)
<< QRect( 10, 20, 30, 40 )
<< QPolygon ( QRect( 10, 20, 30, 40 ) );
#if 0
- // rotations
- deg = 90.;
- QTest::newRow( "rotscale 90 a" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ const auto rotScale = [](qreal degrees, qreal scale) {
+ const qreal rad = qDegreesToRadians(degrees);
+ return QMatrix(scale * std::cos(rad), -scale * std::sin(rad),
+ scale * std::sin(rad), scale * std::cos(rad), 0, 0);
+ };
+ // rotations with scaling
+ QTest::newRow( "rotscale 90 a" ) << rotScale(90., 10)
<< QRect( 0, 0, 30, 40 )
<< QPolygon( QRect( 0, -299, 400, 300 ) );
- deg = 90.00001;
- QTest::newRow( "rotscale 90 b" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 90 b" ) << rotScale(90.00001, 10)
<< QRect( 0, 0, 30, 40 )
<< QPolygon( QRect( 0, -299, 400, 300 ) );
- deg = 90.;
- QTest::newRow( "rotscale 90 c" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 90 c" ) << rotScale(90., 10)
<< QRect( 10, 20, 30, 40 )
<< QPolygon( QRect( 200, -399, 400, 300 ) );
- deg = 90.00001;
- QTest::newRow( "rotscale 90 d" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 90 d" ) << rotScale(90.00001, 10)
<< QRect( 10, 20, 30, 40 )
<< QPolygon( QRect( 200, -399, 400, 300 ) );
- deg = 180.;
- QTest::newRow( "rotscale 180 a" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 180 a" ) << rotScale(180., 10)
<< QRect( 0, 0, 30, 40 )
<< QPolygon( QRect( -299, -399, 300, 400 ) );
- deg = 180.000001;
- QTest::newRow( "rotscale 180 b" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 180 b" ) << rotScale(180.000001, 10)
<< QRect( 0, 0, 30, 40 )
<< QPolygon( QRect( -299, -399, 300, 400 ) );
- deg = 180.;
- QTest::newRow( "rotscale 180 c" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 180 c" ) << rotScale(180., 10)
<< QRect( 10, 20, 30, 40 )
<< QPolygon( QRect( -399, -599, 300, 400 ) );
- deg = 180.000001;
- QTest::newRow( "rotscale 180 d" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 180 d" ) << rotScale(180.000001, 10)
<< QRect( 10, 20, 30, 40 )
<< QPolygon( QRect( -399, -599, 300, 400 ) );
- deg = 270.;
- QTest::newRow( "rotscale 270 a" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 270 a" ) << rotScale(270., 10)
<< QRect( 0, 0, 30, 40 )
<< QPolygon( QRect( -399, 00, 400, 300 ) );
- deg = 270.0000001;
- QTest::newRow( "rotscale 270 b" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 270 b" ) << rotScale(270.0000001, 10)
<< QRect( 0, 0, 30, 40 )
<< QPolygon( QRect( -399, 00, 400, 300 ) );
- deg = 270.;
- QTest::newRow( "rotscale 270 c" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 270 c" ) << rotScale(270., 10)
<< QRect( 10, 20, 30, 40 )
<< QPolygon( QRect( -599, 100, 400, 300 ) );
- deg = 270.000001;
- QTest::newRow( "rotscale 270 d" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rotscale 270 d" ) << rotScale(270.000001, 10)
<< 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( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ),
- std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot 45 a" ) << rotate(45)
<< QRect( 0, 0, 10, 10 )
<< QPolygon( QRect( 0, -7, 14, 14 ) );
- QTest::newRow( "rot 45 b" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ),
- std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot 45 b" ) << rotate(45)
<< QRect( 10, 20, 30, 40 )
<< QPolygon( QRect( 21, -14, 49, 49 ) );
- QTest::newRow( "rot 45 c" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot 45 c" ) << rotScale(45, 10)
<< QRect( 0, 0, 10, 10 )
<< QPolygon( QRect( 0, -70, 141, 141 ) );
- QTest::newRow( "rot 45 d" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot 45 d" ) << rotScale(45, 10)
<< QRect( 10, 20, 30, 40 )
<< QPolygon( QRect( 212, -141, 495, 495 ) );
- deg = -45;
- QTest::newRow( "rot -45 a" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ),
- std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot -45 a" ) << rotate(-45)
<< QRect( 0, 0, 10, 10 )
<< QPolygon( QRect( -7, 0, 14, 14 ) );
- QTest::newRow( "rot -45 b" ) << QMatrix( std::cos( M_PI*deg/180. ), -std::sin( M_PI*deg/180. ),
- std::sin( M_PI*deg/180. ), std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot -45 b" ) << rotate(-45)
<< QRect( 10, 20, 30, 40 )
<< QPolygon( QRect( -35, 21, 49, 49 ) );
- QTest::newRow( "rot -45 c" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot -45 c" ) << rotScale(-45, 10)
<< QRect( 0, 0, 10, 10 )
<< QPolygon( QRect( -70, 0, 141, 141 ) );
- QTest::newRow( "rot -45 d" ) << QMatrix( 10*std::cos( M_PI*deg/180. ), -10*std::sin( M_PI*deg/180. ),
- 10*std::sin( M_PI*deg/180. ), 10*std::cos( M_PI*deg/180. ), 0, 0 )
+ QTest::newRow( "rot -45 d" ) << rotScale(-45, 10)
<< QRect( 10, 20, 30, 40 )
<< QPolygon( QRect( -353, 212, 495, 495 ) );
#endif
diff --git a/tests/auto/gui/qvulkan/qvulkan.pro b/tests/auto/gui/qvulkan/qvulkan.pro
new file mode 100644
index 0000000000..0db990a2d6
--- /dev/null
+++ b/tests/auto/gui/qvulkan/qvulkan.pro
@@ -0,0 +1,9 @@
+############################################################
+# Project file for autotest for gui/vulkan functionality
+############################################################
+
+CONFIG += testcase
+TARGET = tst_qvulkan
+QT += gui-private core-private testlib
+
+SOURCES += tst_qvulkan.cpp
diff --git a/tests/auto/gui/qvulkan/tst_qvulkan.cpp b/tests/auto/gui/qvulkan/tst_qvulkan.cpp
new file mode 100644
index 0000000000..8027935003
--- /dev/null
+++ b/tests/auto/gui/qvulkan/tst_qvulkan.cpp
@@ -0,0 +1,435 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtGui/QVulkanInstance>
+#include <QtGui/QVulkanFunctions>
+#include <QtGui/QVulkanWindow>
+
+#include <QtTest/QtTest>
+
+#include <QSignalSpy>
+
+class tst_QVulkan : public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void vulkanInstance();
+ void vulkanCheckSupported();
+ void vulkanPlainWindow();
+ void vulkanVersionRequest();
+ void vulkanWindow();
+ void vulkanWindowRenderer();
+ void vulkanWindowGrab();
+};
+
+void tst_QVulkan::vulkanInstance()
+{
+ QVulkanInstance inst;
+ if (!inst.create())
+ QSKIP("Vulkan init failed; skip");
+
+ QVERIFY(inst.isValid());
+ QVERIFY(inst.vkInstance() != VK_NULL_HANDLE);
+ QVERIFY(inst.functions());
+ QVERIFY(!inst.flags().testFlag(QVulkanInstance::NoDebugOutputRedirect));
+
+ inst.destroy();
+
+ QVERIFY(!inst.isValid());
+ QVERIFY(inst.handle() == nullptr);
+
+ inst.setFlags(QVulkanInstance::NoDebugOutputRedirect);
+ // pass a bogus layer and extension
+ inst.setExtensions(QByteArrayList() << "abcdefg" << "notanextension");
+ inst.setLayers(QByteArrayList() << "notalayer");
+ QVERIFY(inst.create());
+
+ QVERIFY(inst.isValid());
+ QVERIFY(inst.vkInstance() != VK_NULL_HANDLE);
+ QVERIFY(inst.handle() != nullptr);
+ QVERIFY(inst.functions());
+ QVERIFY(inst.flags().testFlag(QVulkanInstance::NoDebugOutputRedirect));
+ QVERIFY(!inst.extensions().contains("abcdefg"));
+ QVERIFY(!inst.extensions().contains("notanextension"));
+ QVERIFY(!inst.extensions().contains("notalayer"));
+ // at least the surface extensions should be there however
+ QVERIFY(inst.extensions().contains("VK_KHR_surface"));
+
+ QVERIFY(inst.getInstanceProcAddr("vkGetDeviceQueue"));
+}
+
+void tst_QVulkan::vulkanCheckSupported()
+{
+ // Test the early calls to supportedLayers/extensions that need the library
+ // and some basics, but do not initialize the instance.
+ QVulkanInstance inst;
+ QVERIFY(!inst.isValid());
+
+ QVulkanInfoVector<QVulkanLayer> vl = inst.supportedLayers();
+ qDebug() << vl;
+ QVERIFY(!inst.isValid());
+
+ QVulkanInfoVector<QVulkanExtension> ve = inst.supportedExtensions();
+ qDebug() << ve;
+ QVERIFY(!inst.isValid());
+
+ if (inst.create()) { // skip the rest when Vulkan is not supported at all
+ QVERIFY(!ve.isEmpty());
+ QVERIFY(ve == inst.supportedExtensions());
+ }
+}
+
+void tst_QVulkan::vulkanPlainWindow()
+{
+ QVulkanInstance inst;
+ if (!inst.create())
+ QSKIP("Vulkan init failed; skip");
+
+ QWindow w;
+ w.setSurfaceType(QSurface::VulkanSurface);
+ w.setVulkanInstance(&inst);
+ w.resize(1024, 768);
+ w.show();
+ QTest::qWaitForWindowExposed(&w);
+
+ QCOMPARE(w.vulkanInstance(), &inst);
+
+ VkSurfaceKHR surface = QVulkanInstance::surfaceForWindow(&w);
+ QVERIFY(surface != VK_NULL_HANDLE);
+
+ // exercise supportsPresent (and QVulkanFunctions) a bit
+ QVulkanFunctions *f = inst.functions();
+ VkPhysicalDevice physDev;
+ uint32_t count = 1;
+ VkResult err = f->vkEnumeratePhysicalDevices(inst.vkInstance(), &count, &physDev);
+ if (err != VK_SUCCESS)
+ QSKIP("No physical devices; skip");
+
+ VkPhysicalDeviceProperties physDevProps;
+ f->vkGetPhysicalDeviceProperties(physDev, &physDevProps);
+ qDebug("Device name: %s Driver version: %d.%d.%d", physDevProps.deviceName,
+ VK_VERSION_MAJOR(physDevProps.driverVersion), VK_VERSION_MINOR(physDevProps.driverVersion),
+ VK_VERSION_PATCH(physDevProps.driverVersion));
+
+ bool supports = inst.supportsPresent(physDev, 0, &w);
+ qDebug("queue family 0 supports presenting to window = %d", supports);
+}
+
+void tst_QVulkan::vulkanVersionRequest()
+{
+ QVulkanInstance inst;
+ if (!inst.create())
+ QSKIP("Vulkan init failed; skip");
+
+ // Now that we know Vulkan is functional, check the requested apiVersion is
+ // passed to vkCreateInstance as expected.
+
+ inst.destroy();
+
+ inst.setApiVersion(QVersionNumber(10, 0, 0));
+ QVERIFY(!inst.create());
+ QCOMPARE(inst.errorCode(), VK_ERROR_INCOMPATIBLE_DRIVER);
+}
+
+static void waitForUnexposed(QWindow *w)
+{
+ QElapsedTimer timer;
+ timer.start();
+ while (w->isExposed()) {
+ int remaining = 5000 - int(timer.elapsed());
+ if (remaining <= 0)
+ break;
+ QCoreApplication::processEvents(QEventLoop::AllEvents, remaining);
+ QCoreApplication::sendPostedEvents(Q_NULLPTR, QEvent::DeferredDelete);
+ QTest::qSleep(10);
+ }
+}
+
+void tst_QVulkan::vulkanWindow()
+{
+ QVulkanInstance inst;
+ if (!inst.create())
+ QSKIP("Vulkan init failed; skip");
+
+ // First let's forget to set the instance.
+ QVulkanWindow w;
+ QVERIFY(!w.isValid());
+ w.resize(1024, 768);
+ w.show();
+ QTest::qWaitForWindowExposed(&w);
+ QVERIFY(!w.isValid());
+
+ // Now set it. A simple hide - show should be enough to correct, this, no
+ // need for a full destroy - create.
+ w.hide();
+ waitForUnexposed(&w);
+ w.setVulkanInstance(&inst);
+ QVector<VkPhysicalDeviceProperties> pdevs = w.availablePhysicalDevices();
+ if (pdevs.isEmpty())
+ QSKIP("No Vulkan physical devices; skip");
+ w.show();
+ QTest::qWaitForWindowExposed(&w);
+ QVERIFY(w.isValid());
+ QCOMPARE(w.vulkanInstance(), &inst);
+ QVulkanInfoVector<QVulkanExtension> exts = w.supportedDeviceExtensions();
+
+ // Now destroy and recreate.
+ w.destroy();
+ waitForUnexposed(&w);
+ QVERIFY(!w.isValid());
+ // check that flags can be set between a destroy() - show()
+ w.setFlags(QVulkanWindow::PersistentResources);
+ // supported lists can be queried before expose too
+ QVERIFY(w.supportedDeviceExtensions() == exts);
+ w.show();
+ QTest::qWaitForWindowExposed(&w);
+ QVERIFY(w.isValid());
+ QVERIFY(w.flags().testFlag(QVulkanWindow::PersistentResources));
+
+ QVERIFY(w.physicalDevice() != VK_NULL_HANDLE);
+ QVERIFY(w.physicalDeviceProperties() != nullptr);
+ QVERIFY(w.device() != VK_NULL_HANDLE);
+ QVERIFY(w.graphicsQueue() != VK_NULL_HANDLE);
+ QVERIFY(w.graphicsCommandPool() != VK_NULL_HANDLE);
+ QVERIFY(w.defaultRenderPass() != VK_NULL_HANDLE);
+
+ QVERIFY(w.concurrentFrameCount() > 0);
+ QVERIFY(w.concurrentFrameCount() <= QVulkanWindow::MAX_CONCURRENT_FRAME_COUNT);
+}
+
+class TestVulkanRenderer;
+
+class TestVulkanWindow : public QVulkanWindow
+{
+public:
+ QVulkanWindowRenderer *createRenderer() override;
+
+private:
+ TestVulkanRenderer *m_renderer = nullptr;
+};
+
+struct TestVulkan {
+ int preInitResCount = 0;
+ int initResCount = 0;
+ int initSwcResCount = 0;
+ int releaseResCount = 0;
+ int releaseSwcResCount = 0;
+ int startNextFrameCount = 0;
+} testVulkan;
+
+class TestVulkanRenderer : public QVulkanWindowRenderer
+{
+public:
+ TestVulkanRenderer(QVulkanWindow *w) : m_window(w) { }
+
+ void preInitResources() override;
+ void initResources() override;
+ void initSwapChainResources() override;
+ void releaseSwapChainResources() override;
+ void releaseResources() override;
+
+ void startNextFrame() override;
+
+private:
+ QVulkanWindow *m_window;
+ QVulkanDeviceFunctions *m_devFuncs;
+};
+
+void TestVulkanRenderer::preInitResources()
+{
+ if (testVulkan.initResCount) {
+ qWarning("initResources called before preInitResources?!");
+ testVulkan.preInitResCount = -1;
+ return;
+ }
+
+ // Ensure the physical device and the surface are available at this stage.
+ VkPhysicalDevice physDev = m_window->physicalDevice();
+ if (physDev == VK_NULL_HANDLE) {
+ qWarning("No physical device in preInitResources");
+ testVulkan.preInitResCount = -1;
+ return;
+ }
+ VkSurfaceKHR surface = m_window->vulkanInstance()->surfaceForWindow(m_window);
+ if (surface == VK_NULL_HANDLE) {
+ qWarning("No surface in preInitResources");
+ testVulkan.preInitResCount = -1;
+ return;
+ }
+
+ ++testVulkan.preInitResCount;
+}
+
+void TestVulkanRenderer::initResources()
+{
+ m_devFuncs = m_window->vulkanInstance()->deviceFunctions(m_window->device());
+ ++testVulkan.initResCount;
+}
+
+void TestVulkanRenderer::initSwapChainResources()
+{
+ ++testVulkan.initSwcResCount;
+}
+
+void TestVulkanRenderer::releaseSwapChainResources()
+{
+ ++testVulkan.releaseSwcResCount;
+}
+
+void TestVulkanRenderer::releaseResources()
+{
+ ++testVulkan.releaseResCount;
+}
+
+void TestVulkanRenderer::startNextFrame()
+{
+ ++testVulkan.startNextFrameCount;
+
+ VkClearColorValue clearColor = { 0, 1, 0, 1 };
+ VkClearDepthStencilValue clearDS = { 1, 0 };
+ VkClearValue clearValues[2];
+ memset(clearValues, 0, sizeof(clearValues));
+ clearValues[0].color = clearColor;
+ clearValues[1].depthStencil = clearDS;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_window->defaultRenderPass();
+ rpBeginInfo.framebuffer = m_window->currentFramebuffer();
+ const QSize sz = m_window->swapChainImageSize();
+ rpBeginInfo.renderArea.extent.width = sz.width();
+ rpBeginInfo.renderArea.extent.height = sz.height();
+ rpBeginInfo.clearValueCount = 2;
+ rpBeginInfo.pClearValues = clearValues;
+ VkCommandBuffer cmdBuf = m_window->currentCommandBuffer();
+ m_devFuncs->vkCmdBeginRenderPass(cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ m_devFuncs->vkCmdEndRenderPass(cmdBuf);
+
+ m_window->frameReady();
+}
+
+QVulkanWindowRenderer *TestVulkanWindow::createRenderer()
+{
+ Q_ASSERT(!m_renderer);
+ m_renderer = new TestVulkanRenderer(this);
+ return m_renderer;
+}
+
+void tst_QVulkan::vulkanWindowRenderer()
+{
+ QVulkanInstance inst;
+ if (!inst.create())
+ QSKIP("Vulkan init failed; skip");
+
+ testVulkan = TestVulkan();
+
+ TestVulkanWindow w;
+ w.setVulkanInstance(&inst);
+ w.resize(1024, 768);
+ w.show();
+ QTest::qWaitForWindowExposed(&w);
+
+ if (w.availablePhysicalDevices().isEmpty())
+ QSKIP("No Vulkan physical devices; skip");
+
+ QVERIFY(testVulkan.preInitResCount == 1);
+ QVERIFY(testVulkan.initResCount == 1);
+ QVERIFY(testVulkan.initSwcResCount == 1);
+ // this has to be QTRY due to the async update in QVulkanWindowPrivate::ensureStarted()
+ QTRY_VERIFY(testVulkan.startNextFrameCount >= 1);
+
+ QVERIFY(!w.swapChainImageSize().isEmpty());
+ QVERIFY(w.colorFormat() != VK_FORMAT_UNDEFINED);
+ QVERIFY(w.depthStencilFormat() != VK_FORMAT_UNDEFINED);
+
+ w.destroy();
+ waitForUnexposed(&w);
+ QVERIFY(testVulkan.releaseSwcResCount == 1);
+ QVERIFY(testVulkan.releaseResCount == 1);
+}
+
+void tst_QVulkan::vulkanWindowGrab()
+{
+ QVulkanInstance inst;
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+ if (!inst.create())
+ QSKIP("Vulkan init failed; skip");
+
+ testVulkan = TestVulkan();
+
+ TestVulkanWindow w;
+ w.setVulkanInstance(&inst);
+ w.resize(1024, 768);
+ w.show();
+ QTest::qWaitForWindowExposed(&w);
+
+ if (w.availablePhysicalDevices().isEmpty())
+ QSKIP("No Vulkan physical devices; skip");
+
+ if (!w.supportsGrab())
+ QSKIP("No grab support; skip");
+
+ QVERIFY(!w.swapChainImageSize().isEmpty());
+
+ QImage img1 = w.grab();
+ QImage img2 = w.grab();
+ QImage img3 = w.grab();
+
+ QVERIFY(!img1.isNull());
+ QVERIFY(!img2.isNull());
+ QVERIFY(!img3.isNull());
+
+ QCOMPARE(img1.size(), w.swapChainImageSize());
+ QCOMPARE(img2.size(), w.swapChainImageSize());
+ QCOMPARE(img3.size(), w.swapChainImageSize());
+
+ QRgb a = img1.pixel(10, 20);
+ QRgb b = img2.pixel(5, 5);
+ QRgb c = img3.pixel(50, 30);
+
+ QCOMPARE(a, b);
+ QCOMPARE(b, c);
+ QRgb refPixel = qRgb(0, 255, 0);
+
+ int redFuzz = qAbs(qRed(a) - qRed(refPixel));
+ int greenFuzz = qAbs(qGreen(a) - qGreen(refPixel));
+ int blueFuzz = qAbs(qBlue(a) - qBlue(refPixel));
+
+ QVERIFY(redFuzz <= 1);
+ QVERIFY(blueFuzz <= 1);
+ QVERIFY(greenFuzz <= 1);
+
+ w.destroy();
+}
+
+QTEST_MAIN(tst_QVulkan)
+
+#include "tst_qvulkan.moc"
diff --git a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp
index 8667caa1ef..0a422fca17 100644
--- a/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp
+++ b/tests/auto/gui/text/qfontmetrics/tst_qfontmetrics.cpp
@@ -47,7 +47,11 @@ private slots:
void elidedText();
void veryNarrowElidedText();
void averageCharWidth();
+
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void bypassShaping();
+#endif
+
void elidedMultiLength();
void elidedMultiLengthF();
void inFontUcs4();
@@ -187,6 +191,7 @@ void tst_QFontMetrics::averageCharWidth()
QVERIFY(fmf.averageCharWidth() != 0);
}
+#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
void tst_QFontMetrics::bypassShaping()
{
QFont f;
@@ -201,6 +206,7 @@ void tst_QFontMetrics::bypassShaping()
// This assertion is needed in Qt WebKit's WebCore::Font::offsetForPositionForSimpleText
QCOMPARE(textWidth, charsWidth);
}
+#endif
template<class FontMetrics, typename PrimitiveType> void elidedMultiLength_helper()
{
diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
index 764b99646b..2f3da2c196 100644
--- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
+++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp
@@ -187,6 +187,7 @@ private slots:
void cssInheritance();
void lineHeightType();
+ void cssLineHeightMultiplier();
private:
void backgroundImage_checkExpectedHtml(const QTextDocument &doc);
void buildRegExpData();
@@ -3398,6 +3399,33 @@ void tst_QTextDocument::lineHeightType()
{
QTextDocument td;
+ td.setHtml("<html><head><style type=\"text/css\">body { -qt-line-height-type: fixed; line-height: 10; -qt-line-height-type: fixed; }</style></head><body>Foobar</body></html>");
+ QTextBlock block = td.begin();
+ QTextBlockFormat format = block.blockFormat();
+ QCOMPARE(int(format.lineHeightType()), int(QTextBlockFormat::FixedHeight));
+ QCOMPARE(format.lineHeight(), 10.0);
+ }
+
+ {
+ QTextDocument td;
+ td.setHtml("<html><head><style type=\"text/css\">body { -qt-line-height-type: proportional; line-height: 3; }</style></head><body>Foobar</body></html>");
+ QTextBlock block = td.begin();
+ QTextBlockFormat format = block.blockFormat();
+ QCOMPARE(int(format.lineHeightType()), int(QTextBlockFormat::ProportionalHeight));
+ QCOMPARE(format.lineHeight(), 3.0);
+ }
+
+ {
+ QTextDocument td;
+ td.setHtml("<html><head><style type=\"text/css\">body { line-height: 2.5; -qt-line-height-type: proportional; }</style></head><body>Foobar</body></html>");
+ QTextBlock block = td.begin();
+ QTextBlockFormat format = block.blockFormat();
+ QCOMPARE(int(format.lineHeightType()), int(QTextBlockFormat::ProportionalHeight));
+ QCOMPARE(format.lineHeight(), 2.5);
+ }
+
+ {
+ QTextDocument td;
td.setHtml("<html><head><style type=\"text/css\">body { line-height: 33; -qt-line-height-type: minimum; }</style></head><body>Foobar</body></html>");
QTextBlock block = td.begin();
QTextBlockFormat format = block.blockFormat();
@@ -3424,5 +3452,26 @@ void tst_QTextDocument::lineHeightType()
}
}
+void tst_QTextDocument::cssLineHeightMultiplier()
+{
+ {
+ QTextDocument td;
+ td.setHtml("<html><head><style type=\"text/css\">body { line-height: 10; }</style></head><body>Foobar</body></html>");
+ QTextBlock block = td.begin();
+ QTextBlockFormat format = block.blockFormat();
+ QCOMPARE(int(format.lineHeightType()), int(QTextBlockFormat::ProportionalHeight));
+ QCOMPARE(format.lineHeight(), 1000.0);
+ }
+
+ {
+ QTextDocument td;
+ td.setHtml("<html><head><style type=\"text/css\">body {line-height: 1.38; }</style></head><body>Foobar</body></html>");
+ QTextBlock block = td.begin();
+ QTextBlockFormat format = block.blockFormat();
+ QCOMPARE(int(format.lineHeightType()), int(QTextBlockFormat::ProportionalHeight));
+ QCOMPARE(format.lineHeight(), 138.0);
+ }
+}
+
QTEST_MAIN(tst_QTextDocument)
#include "tst_qtextdocument.moc"
diff --git a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
index b8af5271ea..b68a014bff 100644
--- a/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
+++ b/tests/auto/gui/text/qtextlayout/tst_qtextlayout.cpp
@@ -1312,7 +1312,7 @@ void tst_QTextLayout::testDefaultTabs()
QCOMPARE(line.cursorToX(31), 480.);
QTextOption option = layout.textOption();
- option.setTabStop(90);
+ option.setTabStopDistance(90);
layout.setTextOption(option);
layout.beginLayout();
line = layout.createLine();
@@ -1351,7 +1351,7 @@ void tst_QTextLayout::testTabs()
layout.setCacheEnabled(true);
QTextOption option = layout.textOption();
- option.setTabStop(150);
+ option.setTabStopDistance(150);
layout.setTextOption(option);
layout.beginLayout();
diff --git a/tests/auto/gui/text/qtextscriptengine/BLACKLIST b/tests/auto/gui/text/qtextscriptengine/BLACKLIST
new file mode 100644
index 0000000000..52eb9086a9
--- /dev/null
+++ b/tests/auto/gui/text/qtextscriptengine/BLACKLIST
@@ -0,0 +1,2 @@
+[thaiWithZWJ]
+rhel-7.2
diff --git a/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp
index ee50b98733..0371f51961 100644
--- a/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp
+++ b/tests/auto/gui/text/qtextscriptengine/tst_qtextscriptengine.cpp
@@ -78,6 +78,9 @@ private slots:
void thaiIsolatedSaraAm();
void thaiWithZWJ();
void thaiMultipleVowels();
+
+ void shapingDisabledDevanagari();
+ void shapingDisabledLatin();
private:
bool haveTestFonts;
};
@@ -1280,5 +1283,62 @@ void tst_QTextScriptEngine::thaiMultipleVowels()
// If we haven't crashed at this point, then the test has passed.
}
+void tst_QTextScriptEngine::shapingDisabledLatin()
+{
+ QString s("fi");
+
+ QFont font("Calibri");
+ font.setStyleStrategy(QFont::PreferNoShaping);
+
+ QTextLayout layout(s);
+ layout.setFont(font);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ QList<QGlyphRun> runs = layout.glyphRuns();
+
+ QCOMPARE(runs.size(), 1);
+ QCOMPARE(runs.first().glyphIndexes().size(), 2);
+}
+
+void tst_QTextScriptEngine::shapingDisabledDevanagari()
+{
+ QString s;
+ s += QChar(0x0915); // KA
+ s += QChar(0x094D); // VIRAMA
+ s += QChar(0x0915); // KA
+
+
+ QList<QGlyphRun> normalRuns;
+ {
+ QTextLayout layout(s);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ normalRuns = layout.glyphRuns();
+ }
+
+ QFont font;
+ font.setStyleStrategy(QFont::PreferNoShaping);
+
+ QList<QGlyphRun> noShapingRuns;
+ {
+ QTextLayout layout(s);
+ layout.setFont(font);
+ layout.beginLayout();
+ layout.createLine();
+ layout.endLayout();
+
+ noShapingRuns = layout.glyphRuns();
+ }
+
+ // Even though shaping is disabled, Devanagari requires it, so the flag should be ignored.
+ QCOMPARE(normalRuns.size(), 1);
+ QCOMPARE(noShapingRuns.size(), 1);
+ QCOMPARE(noShapingRuns.first().glyphIndexes().size(), normalRuns.first().glyphIndexes().size());
+}
+
QTEST_MAIN(tst_QTextScriptEngine)
#include "tst_qtextscriptengine.moc"
diff --git a/tests/auto/gui/util/qshadergenerator/qshadergenerator.pro b/tests/auto/gui/util/qshadergenerator/qshadergenerator.pro
new file mode 100644
index 0000000000..c1f610e029
--- /dev/null
+++ b/tests/auto/gui/util/qshadergenerator/qshadergenerator.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+QT += testlib gui-private
+
+SOURCES += tst_qshadergenerator.cpp
+TARGET = tst_qshadergenerator
diff --git a/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp
new file mode 100644
index 0000000000..d0a0225055
--- /dev/null
+++ b/tests/auto/gui/util/qshadergenerator/tst_qshadergenerator.cpp
@@ -0,0 +1,895 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QtCore/qmetaobject.h>
+#include <QtGui/private/qshadergenerator_p.h>
+#include <QtGui/private/qshaderlanguage_p.h>
+
+namespace
+{
+ QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion)
+ {
+ auto format = QShaderFormat();
+ format.setApi(api);
+ format.setVersion(QVersionNumber(majorVersion, minorVersion));
+ return format;
+ }
+
+ QShaderNodePort createPort(QShaderNodePort::Direction portDirection, const QString &portName)
+ {
+ auto port = QShaderNodePort();
+ port.direction = portDirection;
+ port.name = portName;
+ return port;
+ }
+
+ QShaderNode createNode(const QVector<QShaderNodePort> &ports, const QStringList &layers = QStringList())
+ {
+ auto node = QShaderNode();
+ node.setUuid(QUuid::createUuid());
+ node.setLayers(layers);
+ for (const auto &port : ports)
+ node.addPort(port);
+ return node;
+ }
+
+ QShaderGraph::Edge createEdge(const QUuid &sourceUuid, const QString &sourceName,
+ const QUuid &targetUuid, const QString &targetName,
+ const QStringList &layers = QStringList())
+ {
+ auto edge = QShaderGraph::Edge();
+ edge.sourceNodeUuid = sourceUuid;
+ edge.sourcePortName = sourceName;
+ edge.targetNodeUuid = targetUuid;
+ edge.targetPortName = targetName;
+ edge.layers = layers;
+ return edge;
+ }
+
+ QShaderGraph createGraph()
+ {
+ const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
+ const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
+
+ auto graph = QShaderGraph();
+
+ auto worldPosition = createNode({
+ createPort(QShaderNodePort::Output, "value")
+ });
+ worldPosition.setParameter("name", "worldPosition");
+ worldPosition.addRule(openGLES2, QShaderNode::Rule("highp vec3 $value = $name;",
+ QByteArrayList() << "varying highp vec3 $name;"));
+ worldPosition.addRule(openGL3, QShaderNode::Rule("vec3 $value = $name;",
+ QByteArrayList() << "in vec3 $name;"));
+
+ auto texture = createNode({
+ createPort(QShaderNodePort::Output, "texture")
+ });
+ texture.addRule(openGLES2, QShaderNode::Rule("sampler2D $texture = texture;",
+ QByteArrayList() << "uniform sampler2D texture;"));
+ texture.addRule(openGL3, QShaderNode::Rule("sampler2D $texture = texture;",
+ QByteArrayList() << "uniform sampler2D texture;"));
+
+ auto texCoord = createNode({
+ createPort(QShaderNodePort::Output, "texCoord")
+ });
+ texCoord.addRule(openGLES2, QShaderNode::Rule("highp vec2 $texCoord = texCoord;",
+ QByteArrayList() << "varying highp vec2 texCoord;"));
+ texCoord.addRule(openGL3, QShaderNode::Rule("vec2 $texCoord = texCoord;",
+ QByteArrayList() << "in vec2 texCoord;"));
+
+ auto lightIntensity = createNode({
+ createPort(QShaderNodePort::Output, "lightIntensity")
+ });
+ lightIntensity.addRule(openGLES2, QShaderNode::Rule("highp float $lightIntensity = lightIntensity;",
+ QByteArrayList() << "uniform highp float lightIntensity;"));
+ lightIntensity.addRule(openGL3, QShaderNode::Rule("float $lightIntensity = lightIntensity;",
+ QByteArrayList() << "uniform float lightIntensity;"));
+
+ auto exposure = createNode({
+ createPort(QShaderNodePort::Output, "exposure")
+ });
+ exposure.addRule(openGLES2, QShaderNode::Rule("highp float $exposure = exposure;",
+ QByteArrayList() << "uniform highp float exposure;"));
+ exposure.addRule(openGL3, QShaderNode::Rule("float $exposure = exposure;",
+ QByteArrayList() << "uniform float exposure;"));
+
+ auto fragColor = createNode({
+ createPort(QShaderNodePort::Input, "fragColor")
+ });
+ fragColor.addRule(openGLES2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
+ fragColor.addRule(openGL3, QShaderNode::Rule("fragColor = $fragColor;",
+ QByteArrayList() << "out vec4 fragColor;"));
+
+ auto sampleTexture = createNode({
+ createPort(QShaderNodePort::Input, "sampler"),
+ createPort(QShaderNodePort::Input, "coord"),
+ createPort(QShaderNodePort::Output, "color")
+ });
+ sampleTexture.addRule(openGLES2, QShaderNode::Rule("highp vec4 $color = texture2D($sampler, $coord);"));
+ sampleTexture.addRule(openGL3, QShaderNode::Rule("vec4 $color = texture2D($sampler, $coord);"));
+
+ auto lightFunction = createNode({
+ createPort(QShaderNodePort::Input, "baseColor"),
+ createPort(QShaderNodePort::Input, "position"),
+ createPort(QShaderNodePort::Input, "lightIntensity"),
+ createPort(QShaderNodePort::Output, "outputColor")
+ });
+ lightFunction.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);",
+ QByteArrayList() << "#pragma include es2/lightmodel.frag.inc"));
+ lightFunction.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);",
+ QByteArrayList() << "#pragma include gl3/lightmodel.frag.inc"));
+
+ auto exposureFunction = createNode({
+ createPort(QShaderNodePort::Input, "inputColor"),
+ createPort(QShaderNodePort::Input, "exposure"),
+ createPort(QShaderNodePort::Output, "outputColor")
+ });
+ exposureFunction.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = $inputColor * pow(2.0, $exposure);"));
+ exposureFunction.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = $inputColor * pow(2.0, $exposure);"));
+
+ graph.addNode(worldPosition);
+ graph.addNode(texture);
+ graph.addNode(texCoord);
+ graph.addNode(lightIntensity);
+ graph.addNode(exposure);
+ graph.addNode(fragColor);
+ graph.addNode(sampleTexture);
+ graph.addNode(lightFunction);
+ graph.addNode(exposureFunction);
+
+ graph.addEdge(createEdge(texture.uuid(), "texture", sampleTexture.uuid(), "sampler"));
+ graph.addEdge(createEdge(texCoord.uuid(), "texCoord", sampleTexture.uuid(), "coord"));
+
+ graph.addEdge(createEdge(worldPosition.uuid(), "value", lightFunction.uuid(), "position"));
+ graph.addEdge(createEdge(sampleTexture.uuid(), "color", lightFunction.uuid(), "baseColor"));
+ graph.addEdge(createEdge(lightIntensity.uuid(), "lightIntensity", lightFunction.uuid(), "lightIntensity"));
+
+ graph.addEdge(createEdge(lightFunction.uuid(), "outputColor", exposureFunction.uuid(), "inputColor"));
+ graph.addEdge(createEdge(exposure.uuid(), "exposure", exposureFunction.uuid(), "exposure"));
+
+ graph.addEdge(createEdge(exposureFunction.uuid(), "outputColor", fragColor.uuid(), "fragColor"));
+
+ return graph;
+ }
+}
+
+class tst_QShaderGenerator : public QObject
+{
+ Q_OBJECT
+private slots:
+ void shouldHaveDefaultState();
+ void shouldGenerateShaderCode_data();
+ void shouldGenerateShaderCode();
+ void shouldGenerateVersionCommands_data();
+ void shouldGenerateVersionCommands();
+ void shouldProcessLanguageQualifierAndTypeEnums_data();
+ void shouldProcessLanguageQualifierAndTypeEnums();
+ void shouldGenerateDifferentCodeDependingOnActiveLayers();
+};
+
+void tst_QShaderGenerator::shouldHaveDefaultState()
+{
+ // GIVEN
+ auto generator = QShaderGenerator();
+
+ // THEN
+ QVERIFY(generator.graph.nodes().isEmpty());
+ QVERIFY(generator.graph.edges().isEmpty());
+ QVERIFY(!generator.format.isValid());
+}
+
+void tst_QShaderGenerator::shouldGenerateShaderCode_data()
+{
+ QTest::addColumn<QShaderGraph>("graph");
+ QTest::addColumn<QShaderFormat>("format");
+ QTest::addColumn<QByteArray>("expectedCode");
+
+ const auto graph = createGraph();
+
+ const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
+ const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
+ const auto openGL32 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 2);
+ const auto openGL4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
+
+ const auto versionGLES2 = QByteArrayList() << "#version 100" << "";
+ const auto versionGL3 = QByteArrayList() << "#version 130" << "";
+ const auto versionGL32 = QByteArrayList() << "#version 150 core" << "";
+ const auto versionGL4 = QByteArrayList() << "#version 400 core" << "";
+
+ const auto es2Code = QByteArrayList() << "varying highp vec3 worldPosition;"
+ << "uniform sampler2D texture;"
+ << "varying highp vec2 texCoord;"
+ << "uniform highp float lightIntensity;"
+ << "uniform highp float exposure;"
+ << "#pragma include es2/lightmodel.frag.inc"
+ << ""
+ << "void main()"
+ << "{"
+ << " highp vec2 v2 = texCoord;"
+ << " sampler2D v1 = texture;"
+ << " highp float v3 = lightIntensity;"
+ << " highp vec4 v5 = texture2D(v1, v2);"
+ << " highp vec3 v0 = worldPosition;"
+ << " highp float v4 = exposure;"
+ << " highp vec4 v6 = lightModel(v5, v0, v3);"
+ << " highp vec4 v7 = v6 * pow(2.0, v4);"
+ << " gl_fragColor = v7;"
+ << "}"
+ << "";
+
+ const auto gl3Code = QByteArrayList() << "in vec3 worldPosition;"
+ << "uniform sampler2D texture;"
+ << "in vec2 texCoord;"
+ << "uniform float lightIntensity;"
+ << "uniform float exposure;"
+ << "out vec4 fragColor;"
+ << "#pragma include gl3/lightmodel.frag.inc"
+ << ""
+ << "void main()"
+ << "{"
+ << " vec2 v2 = texCoord;"
+ << " sampler2D v1 = texture;"
+ << " float v3 = lightIntensity;"
+ << " vec4 v5 = texture2D(v1, v2);"
+ << " vec3 v0 = worldPosition;"
+ << " float v4 = exposure;"
+ << " vec4 v6 = lightModel(v5, v0, v3);"
+ << " vec4 v7 = v6 * pow(2.0, v4);"
+ << " fragColor = v7;"
+ << "}"
+ << "";
+
+ QTest::newRow("EmptyGraphAndFormat") << QShaderGraph() << QShaderFormat() << QByteArrayLiteral("\nvoid main()\n{\n}\n");
+ QTest::newRow("LightExposureGraphAndES2") << graph << openGLES2 << (versionGLES2 + es2Code).join('\n');
+ QTest::newRow("LightExposureGraphAndGL3") << graph << openGL3 << (versionGL3 + gl3Code).join('\n');
+ QTest::newRow("LightExposureGraphAndGL32") << graph << openGL32 << (versionGL32 + gl3Code).join('\n');
+ QTest::newRow("LightExposureGraphAndGL4") << graph << openGL4 << (versionGL4 + gl3Code).join('\n');
+}
+
+void tst_QShaderGenerator::shouldGenerateShaderCode()
+{
+ // GIVEN
+ QFETCH(QShaderGraph, graph);
+ QFETCH(QShaderFormat, format);
+
+ auto generator = QShaderGenerator();
+ generator.graph = graph;
+ generator.format = format;
+
+ // WHEN
+ const auto code = generator.createShaderCode();
+
+ // THEN
+ QFETCH(QByteArray, expectedCode);
+ QCOMPARE(code, expectedCode);
+}
+
+void tst_QShaderGenerator::shouldGenerateVersionCommands_data()
+{
+ QTest::addColumn<QShaderFormat>("format");
+ QTest::addColumn<QByteArray>("version");
+
+ QTest::newRow("GLES2") << createFormat(QShaderFormat::OpenGLES, 2, 0) << QByteArrayLiteral("#version 100");
+ QTest::newRow("GLES3") << createFormat(QShaderFormat::OpenGLES, 3, 0) << QByteArrayLiteral("#version 300 es");
+
+ QTest::newRow("GL20") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0) << QByteArrayLiteral("#version 110");
+ QTest::newRow("GL21") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 1) << QByteArrayLiteral("#version 120");
+ QTest::newRow("GL30") << createFormat(QShaderFormat::OpenGLNoProfile, 3, 0) << QByteArrayLiteral("#version 130");
+ QTest::newRow("GL31") << createFormat(QShaderFormat::OpenGLNoProfile, 3, 1) << QByteArrayLiteral("#version 140");
+ QTest::newRow("GL32") << createFormat(QShaderFormat::OpenGLNoProfile, 3, 2) << QByteArrayLiteral("#version 150");
+ QTest::newRow("GL33") << createFormat(QShaderFormat::OpenGLNoProfile, 3, 3) << QByteArrayLiteral("#version 330");
+ QTest::newRow("GL40") << createFormat(QShaderFormat::OpenGLNoProfile, 4, 0) << QByteArrayLiteral("#version 400");
+ QTest::newRow("GL41") << createFormat(QShaderFormat::OpenGLNoProfile, 4, 1) << QByteArrayLiteral("#version 410");
+ QTest::newRow("GL42") << createFormat(QShaderFormat::OpenGLNoProfile, 4, 2) << QByteArrayLiteral("#version 420");
+ QTest::newRow("GL43") << createFormat(QShaderFormat::OpenGLNoProfile, 4, 3) << QByteArrayLiteral("#version 430");
+
+ QTest::newRow("GL20core") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0) << QByteArrayLiteral("#version 110");
+ QTest::newRow("GL21core") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 1) << QByteArrayLiteral("#version 120");
+ QTest::newRow("GL30core") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0) << QByteArrayLiteral("#version 130");
+ QTest::newRow("GL31core") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 1) << QByteArrayLiteral("#version 140");
+ QTest::newRow("GL32core") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 2) << QByteArrayLiteral("#version 150 core");
+ QTest::newRow("GL33core") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 3) << QByteArrayLiteral("#version 330 core");
+ QTest::newRow("GL40core") << createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0) << QByteArrayLiteral("#version 400 core");
+ QTest::newRow("GL41core") << createFormat(QShaderFormat::OpenGLCoreProfile, 4, 1) << QByteArrayLiteral("#version 410 core");
+ QTest::newRow("GL42core") << createFormat(QShaderFormat::OpenGLCoreProfile, 4, 2) << QByteArrayLiteral("#version 420 core");
+ QTest::newRow("GL43core") << createFormat(QShaderFormat::OpenGLCoreProfile, 4, 3) << QByteArrayLiteral("#version 430 core");
+
+ QTest::newRow("GL20compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0) << QByteArrayLiteral("#version 110");
+ QTest::newRow("GL21compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 1) << QByteArrayLiteral("#version 120");
+ QTest::newRow("GL30compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 3, 0) << QByteArrayLiteral("#version 130");
+ QTest::newRow("GL31compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 3, 1) << QByteArrayLiteral("#version 140");
+ QTest::newRow("GL32compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 3, 2) << QByteArrayLiteral("#version 150 compatibility");
+ QTest::newRow("GL33compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 3, 3) << QByteArrayLiteral("#version 330 compatibility");
+ QTest::newRow("GL40compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 4, 0) << QByteArrayLiteral("#version 400 compatibility");
+ QTest::newRow("GL41compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 4, 1) << QByteArrayLiteral("#version 410 compatibility");
+ QTest::newRow("GL42compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 4, 2) << QByteArrayLiteral("#version 420 compatibility");
+ QTest::newRow("GL43compatibility") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 4, 3) << QByteArrayLiteral("#version 430 compatibility");
+}
+
+void tst_QShaderGenerator::shouldGenerateVersionCommands()
+{
+ // GIVEN
+ QFETCH(QShaderFormat, format);
+
+ auto generator = QShaderGenerator();
+ generator.format = format;
+
+ // WHEN
+ const auto code = generator.createShaderCode();
+
+ // THEN
+ QFETCH(QByteArray, version);
+ const auto expectedCode = (QByteArrayList() << version
+ << ""
+ << ""
+ << "void main()"
+ << "{"
+ << "}"
+ << "").join('\n');
+ QCOMPARE(code, expectedCode);
+}
+
+
+namespace {
+ QString toGlsl(QShaderLanguage::StorageQualifier qualifier, const QShaderFormat &format)
+ {
+ if (format.version().majorVersion() <= 2) {
+ // Note we're assuming fragment shader only here, it'd be different
+ // values for vertex shader, will need to be fixed properly at some
+ // point but isn't necessary yet (this problem already exists in past
+ // commits anyway)
+ switch (qualifier) {
+ case QShaderLanguage::Const:
+ return "const";
+ case QShaderLanguage::Input:
+ return "varying";
+ case QShaderLanguage::Output:
+ return ""; // Although fragment shaders for <=2 only have fixed outputs
+ case QShaderLanguage::Uniform:
+ return "uniform";
+ }
+ } else {
+ switch (qualifier) {
+ case QShaderLanguage::Const:
+ return "const";
+ case QShaderLanguage::Input:
+ return "in";
+ case QShaderLanguage::Output:
+ return "out";
+ case QShaderLanguage::Uniform:
+ return "uniform";
+ }
+ }
+
+ Q_UNREACHABLE();
+ }
+
+ QString toGlsl(QShaderLanguage::VariableType type)
+ {
+ switch (type) {
+ case QShaderLanguage::Bool:
+ return "bool";
+ case QShaderLanguage::Int:
+ return "int";
+ case QShaderLanguage::Uint:
+ return "uint";
+ case QShaderLanguage::Float:
+ return "float";
+ case QShaderLanguage::Double:
+ return "double";
+ case QShaderLanguage::Vec2:
+ return "vec2";
+ case QShaderLanguage::Vec3:
+ return "vec3";
+ case QShaderLanguage::Vec4:
+ return "vec4";
+ case QShaderLanguage::DVec2:
+ return "dvec2";
+ case QShaderLanguage::DVec3:
+ return "dvec3";
+ case QShaderLanguage::DVec4:
+ return "dvec4";
+ case QShaderLanguage::BVec2:
+ return "bvec2";
+ case QShaderLanguage::BVec3:
+ return "bvec3";
+ case QShaderLanguage::BVec4:
+ return "bvec4";
+ case QShaderLanguage::IVec2:
+ return "ivec2";
+ case QShaderLanguage::IVec3:
+ return "ivec3";
+ case QShaderLanguage::IVec4:
+ return "ivec4";
+ case QShaderLanguage::UVec2:
+ return "uvec2";
+ case QShaderLanguage::UVec3:
+ return "uvec3";
+ case QShaderLanguage::UVec4:
+ return "uvec4";
+ case QShaderLanguage::Mat2:
+ return "mat2";
+ case QShaderLanguage::Mat3:
+ return "mat3";
+ case QShaderLanguage::Mat4:
+ return "mat4";
+ case QShaderLanguage::Mat2x2:
+ return "mat2x2";
+ case QShaderLanguage::Mat2x3:
+ return "mat2x3";
+ case QShaderLanguage::Mat2x4:
+ return "mat2x4";
+ case QShaderLanguage::Mat3x2:
+ return "mat3x2";
+ case QShaderLanguage::Mat3x3:
+ return "mat3x3";
+ case QShaderLanguage::Mat3x4:
+ return "mat3x4";
+ case QShaderLanguage::Mat4x2:
+ return "mat4x2";
+ case QShaderLanguage::Mat4x3:
+ return "mat4x3";
+ case QShaderLanguage::Mat4x4:
+ return "mat4x4";
+ case QShaderLanguage::DMat2:
+ return "dmat2";
+ case QShaderLanguage::DMat3:
+ return "dmat3";
+ case QShaderLanguage::DMat4:
+ return "dmat4";
+ case QShaderLanguage::DMat2x2:
+ return "dmat2x2";
+ case QShaderLanguage::DMat2x3:
+ return "dmat2x3";
+ case QShaderLanguage::DMat2x4:
+ return "dmat2x4";
+ case QShaderLanguage::DMat3x2:
+ return "dmat3x2";
+ case QShaderLanguage::DMat3x3:
+ return "dmat3x3";
+ case QShaderLanguage::DMat3x4:
+ return "dmat3x4";
+ case QShaderLanguage::DMat4x2:
+ return "dmat4x2";
+ case QShaderLanguage::DMat4x3:
+ return "dmat4x3";
+ case QShaderLanguage::DMat4x4:
+ return "dmat4x4";
+ case QShaderLanguage::Sampler1D:
+ return "sampler1D";
+ case QShaderLanguage::Sampler2D:
+ return "sampler2D";
+ case QShaderLanguage::Sampler3D:
+ return "sampler3D";
+ case QShaderLanguage::SamplerCube:
+ return "samplerCube";
+ case QShaderLanguage::Sampler2DRect:
+ return "sampler2DRect";
+ case QShaderLanguage::Sampler2DMs:
+ return "sampler2DMS";
+ case QShaderLanguage::SamplerBuffer:
+ return "samplerBuffer";
+ case QShaderLanguage::Sampler1DArray:
+ return "sampler1DArray";
+ case QShaderLanguage::Sampler2DArray:
+ return "sampler2DArray";
+ case QShaderLanguage::Sampler2DMsArray:
+ return "sampler2DMSArray";
+ case QShaderLanguage::SamplerCubeArray:
+ return "samplerCubeArray";
+ case QShaderLanguage::Sampler1DShadow:
+ return "sampler1DShadow";
+ case QShaderLanguage::Sampler2DShadow:
+ return "sampler2DShadow";
+ case QShaderLanguage::Sampler2DRectShadow:
+ return "sampler2DRectShadow";
+ case QShaderLanguage::Sampler1DArrayShadow:
+ return "sampler1DArrayShadow";
+ case QShaderLanguage::Sampler2DArrayShadow:
+ return "sample2DArrayShadow";
+ case QShaderLanguage::SamplerCubeShadow:
+ return "samplerCubeShadow";
+ case QShaderLanguage::SamplerCubeArrayShadow:
+ return "samplerCubeArrayShadow";
+ case QShaderLanguage::ISampler1D:
+ return "isampler1D";
+ case QShaderLanguage::ISampler2D:
+ return "isampler2D";
+ case QShaderLanguage::ISampler3D:
+ return "isampler3D";
+ case QShaderLanguage::ISamplerCube:
+ return "isamplerCube";
+ case QShaderLanguage::ISampler2DRect:
+ return "isampler2DRect";
+ case QShaderLanguage::ISampler2DMs:
+ return "isampler2DMS";
+ case QShaderLanguage::ISamplerBuffer:
+ return "isamplerBuffer";
+ case QShaderLanguage::ISampler1DArray:
+ return "isampler1DArray";
+ case QShaderLanguage::ISampler2DArray:
+ return "isampler2DArray";
+ case QShaderLanguage::ISampler2DMsArray:
+ return "isampler2DMSArray";
+ case QShaderLanguage::ISamplerCubeArray:
+ return "isamplerCubeArray";
+ case QShaderLanguage::USampler1D:
+ return "usampler1D";
+ case QShaderLanguage::USampler2D:
+ return "usampler2D";
+ case QShaderLanguage::USampler3D:
+ return "usampler3D";
+ case QShaderLanguage::USamplerCube:
+ return "usamplerCube";
+ case QShaderLanguage::USampler2DRect:
+ return "usampler2DRect";
+ case QShaderLanguage::USampler2DMs:
+ return "usampler2DMS";
+ case QShaderLanguage::USamplerBuffer:
+ return "usamplerBuffer";
+ case QShaderLanguage::USampler1DArray:
+ return "usampler1DArray";
+ case QShaderLanguage::USampler2DArray:
+ return "usampler2DArray";
+ case QShaderLanguage::USampler2DMsArray:
+ return "usampler2DMSArray";
+ case QShaderLanguage::USamplerCubeArray:
+ return "usamplerCubeArray";
+ }
+
+ Q_UNREACHABLE();
+ }
+}
+
+void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums_data()
+{
+ QTest::addColumn<QShaderGraph>("graph");
+ QTest::addColumn<QShaderFormat>("format");
+ QTest::addColumn<QByteArray>("expectedCode");
+
+ const auto es2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
+ const auto es3 = createFormat(QShaderFormat::OpenGLES, 3, 0);
+ const auto gl2 = createFormat(QShaderFormat::OpenGLNoProfile, 2, 0);
+ const auto gl3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
+ const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
+
+ const auto qualifierEnum = QMetaEnum::fromType<QShaderLanguage::StorageQualifier>();
+ const auto typeEnum = QMetaEnum::fromType<QShaderLanguage::VariableType>();
+
+ for (int qualifierIndex = 0; qualifierIndex < qualifierEnum.keyCount(); qualifierIndex++) {
+ const auto qualifierName = qualifierEnum.key(qualifierIndex);
+ const auto qualifierValue = static_cast<QShaderLanguage::StorageQualifier>(qualifierEnum.value(qualifierIndex));
+
+ for (int typeIndex = 0; typeIndex < typeEnum.keyCount(); typeIndex++) {
+ const auto typeName = typeEnum.key(typeIndex);
+ const auto typeValue = static_cast<QShaderLanguage::VariableType>(typeEnum.value(typeIndex));
+
+ auto graph = QShaderGraph();
+
+ auto worldPosition = createNode({
+ createPort(QShaderNodePort::Output, "value")
+ });
+ worldPosition.setParameter("name", "worldPosition");
+ worldPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(qualifierValue));
+ worldPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(typeValue));
+ worldPosition.addRule(es2, QShaderNode::Rule("highp $type $value = $name;",
+ QByteArrayList() << "$qualifier highp $type $name;"));
+ worldPosition.addRule(gl2, QShaderNode::Rule("$type $value = $name;",
+ QByteArrayList() << "$qualifier $type $name;"));
+ worldPosition.addRule(gl3, QShaderNode::Rule("$type $value = $name;",
+ QByteArrayList() << "$qualifier $type $name;"));
+
+ auto fragColor = createNode({
+ createPort(QShaderNodePort::Input, "fragColor")
+ });
+ fragColor.addRule(es2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
+ fragColor.addRule(gl2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
+ fragColor.addRule(gl3, QShaderNode::Rule("fragColor = $fragColor;",
+ QByteArrayList() << "out vec4 fragColor;"));
+
+ graph.addNode(worldPosition);
+ graph.addNode(fragColor);
+
+ graph.addEdge(createEdge(worldPosition.uuid(), "value", fragColor.uuid(), "fragColor"));
+
+ const auto gl2Code = (QByteArrayList() << "#version 110"
+ << ""
+ << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl2))
+ .arg(toGlsl(typeValue))
+ .toUtf8()
+ << ""
+ << "void main()"
+ << "{"
+ << QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
+ << " gl_fragColor = v0;"
+ << "}"
+ << "").join("\n");
+ const auto gl3Code = (QByteArrayList() << "#version 130"
+ << ""
+ << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl3))
+ .arg(toGlsl(typeValue))
+ .toUtf8()
+ << "out vec4 fragColor;"
+ << ""
+ << "void main()"
+ << "{"
+ << QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
+ << " fragColor = v0;"
+ << "}"
+ << "").join("\n");
+ const auto gl4Code = (QByteArrayList() << "#version 400 core"
+ << ""
+ << QStringLiteral("%1 %2 worldPosition;").arg(toGlsl(qualifierValue, gl4))
+ .arg(toGlsl(typeValue))
+ .toUtf8()
+ << "out vec4 fragColor;"
+ << ""
+ << "void main()"
+ << "{"
+ << QStringLiteral(" %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
+ << " fragColor = v0;"
+ << "}"
+ << "").join("\n");
+ const auto es2Code = (QByteArrayList() << "#version 100"
+ << ""
+ << QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es2))
+ .arg(toGlsl(typeValue))
+ .toUtf8()
+ << ""
+ << "void main()"
+ << "{"
+ << QStringLiteral(" highp %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
+ << " gl_fragColor = v0;"
+ << "}"
+ << "").join("\n");
+ const auto es3Code = (QByteArrayList() << "#version 300 es"
+ << ""
+ << QStringLiteral("%1 highp %2 worldPosition;").arg(toGlsl(qualifierValue, es3))
+ .arg(toGlsl(typeValue))
+ .toUtf8()
+ << ""
+ << "void main()"
+ << "{"
+ << QStringLiteral(" highp %1 v0 = worldPosition;").arg(toGlsl(typeValue)).toUtf8()
+ << " gl_fragColor = v0;"
+ << "}"
+ << "").join("\n");
+
+ QTest::addRow("%s %s ES2", qualifierName, typeName) << graph << es2 << es2Code;
+ QTest::addRow("%s %s ES3", qualifierName, typeName) << graph << es3 << es3Code;
+ QTest::addRow("%s %s GL2", qualifierName, typeName) << graph << gl2 << gl2Code;
+ QTest::addRow("%s %s GL3", qualifierName, typeName) << graph << gl3 << gl3Code;
+ QTest::addRow("%s %s GL4", qualifierName, typeName) << graph << gl4 << gl4Code;
+ }
+ }
+}
+
+void tst_QShaderGenerator::shouldProcessLanguageQualifierAndTypeEnums()
+{
+ // GIVEN
+ QFETCH(QShaderGraph, graph);
+ QFETCH(QShaderFormat, format);
+
+ auto generator = QShaderGenerator();
+ generator.graph = graph;
+ generator.format = format;
+
+ // WHEN
+ const auto code = generator.createShaderCode();
+
+ // THEN
+ QFETCH(QByteArray, expectedCode);
+ QCOMPARE(code, expectedCode);
+}
+
+void tst_QShaderGenerator::shouldGenerateDifferentCodeDependingOnActiveLayers()
+{
+ // GIVEN
+ const auto gl4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
+
+ auto texCoord = createNode({
+ createPort(QShaderNodePort::Output, "texCoord")
+ }, {
+ "diffuseTexture",
+ "normalTexture"
+ });
+ texCoord.addRule(gl4, QShaderNode::Rule("vec2 $texCoord = texCoord;",
+ QByteArrayList() << "in vec2 texCoord;"));
+ auto diffuseUniform = createNode({
+ createPort(QShaderNodePort::Output, "color")
+ }, {"diffuseUniform"});
+ diffuseUniform.addRule(gl4, QShaderNode::Rule("vec4 $color = diffuseUniform;",
+ QByteArrayList() << "uniform vec4 diffuseUniform;"));
+ auto diffuseTexture = createNode({
+ createPort(QShaderNodePort::Input, "coord"),
+ createPort(QShaderNodePort::Output, "color")
+ }, {"diffuseTexture"});
+ diffuseTexture.addRule(gl4, QShaderNode::Rule("vec4 $color = texture2D(diffuseTexture, $coord);",
+ QByteArrayList() << "uniform sampler2D diffuseTexture;"));
+ auto normalUniform = createNode({
+ createPort(QShaderNodePort::Output, "normal")
+ }, {"normalUniform"});
+ normalUniform.addRule(gl4, QShaderNode::Rule("vec3 $normal = normalUniform;",
+ QByteArrayList() << "uniform vec3 normalUniform;"));
+ auto normalTexture = createNode({
+ createPort(QShaderNodePort::Input, "coord"),
+ createPort(QShaderNodePort::Output, "normal")
+ }, {"normalTexture"});
+ normalTexture.addRule(gl4, QShaderNode::Rule("vec3 $normal = texture2D(normalTexture, $coord).rgb;",
+ QByteArrayList() << "uniform sampler2D normalTexture;"));
+ auto lightFunction = createNode({
+ createPort(QShaderNodePort::Input, "color"),
+ createPort(QShaderNodePort::Input, "normal"),
+ createPort(QShaderNodePort::Output, "output")
+ });
+ lightFunction.addRule(gl4, QShaderNode::Rule("vec4 $output = lightModel($color, $normal);",
+ QByteArrayList() << "#pragma include gl4/lightmodel.frag.inc"));
+ auto fragColor = createNode({
+ createPort(QShaderNodePort::Input, "fragColor")
+ });
+ fragColor.addRule(gl4, QShaderNode::Rule("fragColor = $fragColor;",
+ QByteArrayList() << "out vec4 fragColor;"));
+
+ const auto graph = [=] {
+ auto res = QShaderGraph();
+
+ res.addNode(texCoord);
+ res.addNode(diffuseUniform);
+ res.addNode(diffuseTexture);
+ res.addNode(normalUniform);
+ res.addNode(normalTexture);
+ res.addNode(lightFunction);
+ res.addNode(fragColor);
+
+ res.addEdge(createEdge(diffuseUniform.uuid(), "color", lightFunction.uuid(), "color", {"diffuseUniform"}));
+ res.addEdge(createEdge(texCoord.uuid(), "texCoord", diffuseTexture.uuid(), "coord", {"diffuseTexture"}));
+ res.addEdge(createEdge(diffuseTexture.uuid(), "color", lightFunction.uuid(), "color", {"diffuseTexture"}));
+
+ res.addEdge(createEdge(normalUniform.uuid(), "normal", lightFunction.uuid(), "normal", {"normalUniform"}));
+ res.addEdge(createEdge(texCoord.uuid(), "texCoord", normalTexture.uuid(), "coord", {"normalTexture"}));
+ res.addEdge(createEdge(normalTexture.uuid(), "normal", lightFunction.uuid(), "normal", {"normalTexture"}));
+
+ res.addEdge(createEdge(lightFunction.uuid(), "output", fragColor.uuid(), "fragColor"));
+
+ return res;
+ }();
+
+ auto generator = QShaderGenerator();
+ generator.graph = graph;
+ generator.format = gl4;
+
+ {
+ // WHEN
+ const auto code = generator.createShaderCode({"diffuseUniform", "normalUniform"});
+
+ // THEN
+ const auto expected = QByteArrayList()
+ << "#version 400 core"
+ << ""
+ << "uniform vec4 diffuseUniform;"
+ << "uniform vec3 normalUniform;"
+ << "#pragma include gl4/lightmodel.frag.inc"
+ << "out vec4 fragColor;"
+ << ""
+ << "void main()"
+ << "{"
+ << " vec3 v1 = normalUniform;"
+ << " vec4 v0 = diffuseUniform;"
+ << " vec4 v2 = lightModel(v0, v1);"
+ << " fragColor = v2;"
+ << "}"
+ << "";
+ QCOMPARE(code, expected.join("\n"));
+ }
+
+ {
+ // WHEN
+ const auto code = generator.createShaderCode({"diffuseUniform", "normalTexture"});
+
+ // THEN
+ const auto expected = QByteArrayList()
+ << "#version 400 core"
+ << ""
+ << "in vec2 texCoord;"
+ << "uniform vec4 diffuseUniform;"
+ << "uniform sampler2D normalTexture;"
+ << "#pragma include gl4/lightmodel.frag.inc"
+ << "out vec4 fragColor;"
+ << ""
+ << "void main()"
+ << "{"
+ << " vec2 v0 = texCoord;"
+ << " vec3 v2 = texture2D(normalTexture, v0).rgb;"
+ << " vec4 v1 = diffuseUniform;"
+ << " vec4 v3 = lightModel(v1, v2);"
+ << " fragColor = v3;"
+ << "}"
+ << "";
+ QCOMPARE(code, expected.join("\n"));
+ }
+
+ {
+ // WHEN
+ const auto code = generator.createShaderCode({"diffuseTexture", "normalUniform"});
+
+ // THEN
+ const auto expected = QByteArrayList()
+ << "#version 400 core"
+ << ""
+ << "in vec2 texCoord;"
+ << "uniform sampler2D diffuseTexture;"
+ << "uniform vec3 normalUniform;"
+ << "#pragma include gl4/lightmodel.frag.inc"
+ << "out vec4 fragColor;"
+ << ""
+ << "void main()"
+ << "{"
+ << " vec2 v0 = texCoord;"
+ << " vec3 v2 = normalUniform;"
+ << " vec4 v1 = texture2D(diffuseTexture, v0);"
+ << " vec4 v3 = lightModel(v1, v2);"
+ << " fragColor = v3;"
+ << "}"
+ << "";
+ QCOMPARE(code, expected.join("\n"));
+ }
+
+ {
+ // WHEN
+ const auto code = generator.createShaderCode({"diffuseTexture", "normalTexture"});
+
+ // THEN
+ const auto expected = QByteArrayList()
+ << "#version 400 core"
+ << ""
+ << "in vec2 texCoord;"
+ << "uniform sampler2D diffuseTexture;"
+ << "uniform sampler2D normalTexture;"
+ << "#pragma include gl4/lightmodel.frag.inc"
+ << "out vec4 fragColor;"
+ << ""
+ << "void main()"
+ << "{"
+ << " vec2 v0 = texCoord;"
+ << " vec3 v2 = texture2D(normalTexture, v0).rgb;"
+ << " vec4 v1 = texture2D(diffuseTexture, v0);"
+ << " vec4 v3 = lightModel(v1, v2);"
+ << " fragColor = v3;"
+ << "}"
+ << "";
+ QCOMPARE(code, expected.join("\n"));
+ }
+}
+
+QTEST_MAIN(tst_QShaderGenerator)
+
+#include "tst_qshadergenerator.moc"
diff --git a/tests/auto/gui/util/qshadergraph/qshadergraph.pro b/tests/auto/gui/util/qshadergraph/qshadergraph.pro
new file mode 100644
index 0000000000..ec54941c77
--- /dev/null
+++ b/tests/auto/gui/util/qshadergraph/qshadergraph.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+QT += testlib gui-private
+
+SOURCES += tst_qshadergraph.cpp
+TARGET = tst_qshadergraph
diff --git a/tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp b/tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp
new file mode 100644
index 0000000000..ce2d38c24f
--- /dev/null
+++ b/tests/auto/gui/util/qshadergraph/tst_qshadergraph.cpp
@@ -0,0 +1,779 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QtGui/private/qshadergraph_p.h>
+
+namespace
+{
+ QShaderNodePort createPort(QShaderNodePort::Direction portDirection, const QString &portName)
+ {
+ auto port = QShaderNodePort();
+ port.direction = portDirection;
+ port.name = portName;
+ return port;
+ }
+
+ QShaderNode createNode(const QVector<QShaderNodePort> &ports, const QStringList &layers = QStringList())
+ {
+ auto node = QShaderNode();
+ node.setUuid(QUuid::createUuid());
+ node.setLayers(layers);
+ for (const auto &port : ports)
+ node.addPort(port);
+ return node;
+ }
+
+ QShaderGraph::Edge createEdge(const QUuid &sourceUuid, const QString &sourceName,
+ const QUuid &targetUuid, const QString &targetName,
+ const QStringList &layers = QStringList())
+ {
+ auto edge = QShaderGraph::Edge();
+ edge.sourceNodeUuid = sourceUuid;
+ edge.sourcePortName = sourceName;
+ edge.targetNodeUuid = targetUuid;
+ edge.targetPortName = targetName;
+ edge.layers = layers;
+ return edge;
+ }
+
+ QShaderGraph::Statement createStatement(const QShaderNode &node,
+ const QVector<int> &inputs = QVector<int>(),
+ const QVector<int> &outputs = QVector<int>())
+ {
+ auto statement = QShaderGraph::Statement();
+ statement.node = node;
+ statement.inputs = inputs;
+ statement.outputs = outputs;
+ return statement;
+ }
+
+ void debugStatement(const QString &prefix, const QShaderGraph::Statement &statement)
+ {
+ qDebug() << prefix << statement.inputs << statement.uuid().toString() << statement.outputs;
+ }
+
+ void dumpStatementsIfNeeded(const QVector<QShaderGraph::Statement> &statements, const QVector<QShaderGraph::Statement> &expected)
+ {
+ if (statements != expected) {
+ for (int i = 0; i < qMax(statements.size(), expected.size()); i++) {
+ qDebug() << "----" << i << "----";
+ if (i < statements.size())
+ debugStatement("A:", statements.at(i));
+ if (i < expected.size())
+ debugStatement("E:", expected.at(i));
+ qDebug() << "-----------";
+ }
+ }
+ }
+}
+
+class tst_QShaderGraph : public QObject
+{
+ Q_OBJECT
+private slots:
+ void shouldHaveEdgeDefaultState();
+ void shouldTestEdgesEquality_data();
+ void shouldTestEdgesEquality();
+ void shouldManipulateStatementMembers();
+ void shouldTestStatementsEquality_data();
+ void shouldTestStatementsEquality();
+ void shouldFindIndexFromPortNameInStatements_data();
+ void shouldFindIndexFromPortNameInStatements();
+ void shouldManageNodeList();
+ void shouldManageEdgeList();
+ void shouldSerializeGraphForCodeGeneration();
+ void shouldHandleUnboundPortsDuringGraphSerialization();
+ void shouldSurviveCyclesDuringGraphSerialization();
+ void shouldDealWithEdgesJumpingOverLayers();
+ void shouldGenerateDifferentStatementsDependingOnActiveLayers();
+};
+
+void tst_QShaderGraph::shouldHaveEdgeDefaultState()
+{
+ // GIVEN
+ auto edge = QShaderGraph::Edge();
+
+ // THEN
+ QVERIFY(edge.sourceNodeUuid.isNull());
+ QVERIFY(edge.sourcePortName.isEmpty());
+ QVERIFY(edge.targetNodeUuid.isNull());
+ QVERIFY(edge.targetPortName.isEmpty());
+}
+
+void tst_QShaderGraph::shouldTestEdgesEquality_data()
+{
+ QTest::addColumn<QShaderGraph::Edge>("left");
+ QTest::addColumn<QShaderGraph::Edge>("right");
+ QTest::addColumn<bool>("expected");
+
+ const auto sourceUuid1 = QUuid::createUuid();
+ const auto sourceUuid2 = QUuid::createUuid();
+ const auto targetUuid1 = QUuid::createUuid();
+ const auto targetUuid2 = QUuid::createUuid();
+
+ QTest::newRow("Equals") << createEdge(sourceUuid1, "foo", targetUuid1, "bar")
+ << createEdge(sourceUuid1, "foo", targetUuid1, "bar")
+ << true;
+ QTest::newRow("SourceUuid") << createEdge(sourceUuid1, "foo", targetUuid1, "bar")
+ << createEdge(sourceUuid2, "foo", targetUuid1, "bar")
+ << false;
+ QTest::newRow("SourceName") << createEdge(sourceUuid1, "foo", targetUuid1, "bar")
+ << createEdge(sourceUuid1, "bleh", targetUuid1, "bar")
+ << false;
+ QTest::newRow("TargetUuid") << createEdge(sourceUuid1, "foo", targetUuid1, "bar")
+ << createEdge(sourceUuid1, "foo", targetUuid2, "bar")
+ << false;
+ QTest::newRow("TargetName") << createEdge(sourceUuid1, "foo", targetUuid1, "bar")
+ << createEdge(sourceUuid1, "foo", targetUuid1, "bleh")
+ << false;
+}
+
+void tst_QShaderGraph::shouldTestEdgesEquality()
+{
+ // GIVEN
+ QFETCH(QShaderGraph::Edge, left);
+ QFETCH(QShaderGraph::Edge, right);
+
+ // WHEN
+ const auto equal = (left == right);
+ const auto notEqual = (left != right);
+
+ // THEN
+ QFETCH(bool, expected);
+ QCOMPARE(equal, expected);
+ QCOMPARE(notEqual, !expected);
+}
+
+void tst_QShaderGraph::shouldManipulateStatementMembers()
+{
+ // GIVEN
+ auto statement = QShaderGraph::Statement();
+
+ // THEN (default state)
+ QVERIFY(statement.inputs.isEmpty());
+ QVERIFY(statement.outputs.isEmpty());
+ QVERIFY(statement.node.uuid().isNull());
+ QVERIFY(statement.uuid().isNull());
+
+ // WHEN
+ const auto node = createNode({});
+ statement.node = node;
+
+ // THEN
+ QCOMPARE(statement.uuid(), node.uuid());
+
+ // WHEN
+ statement.node = QShaderNode();
+
+ // THEN
+ QVERIFY(statement.uuid().isNull());
+}
+
+void tst_QShaderGraph::shouldTestStatementsEquality_data()
+{
+ QTest::addColumn<QShaderGraph::Statement>("left");
+ QTest::addColumn<QShaderGraph::Statement>("right");
+ QTest::addColumn<bool>("expected");
+
+ const auto node1 = createNode({});
+ const auto node2 = createNode({});
+
+ QTest::newRow("EqualNodes") << createStatement(node1, {1, 2}, {3, 4})
+ << createStatement(node1, {1, 2}, {3, 4})
+ << true;
+ QTest::newRow("EqualInvalids") << createStatement(QShaderNode(), {1, 2}, {3, 4})
+ << createStatement(QShaderNode(), {1, 2}, {3, 4})
+ << true;
+ QTest::newRow("Nodes") << createStatement(node1, {1, 2}, {3, 4})
+ << createStatement(node2, {1, 2}, {3, 4})
+ << false;
+ QTest::newRow("Inputs") << createStatement(node1, {1, 2}, {3, 4})
+ << createStatement(node1, {1, 2, 0}, {3, 4})
+ << false;
+ QTest::newRow("Outputs") << createStatement(node1, {1, 2}, {3, 4})
+ << createStatement(node1, {1, 2}, {3, 0, 4})
+ << false;
+}
+
+void tst_QShaderGraph::shouldTestStatementsEquality()
+{
+ // GIVEN
+ QFETCH(QShaderGraph::Statement, left);
+ QFETCH(QShaderGraph::Statement, right);
+
+ // WHEN
+ const auto equal = (left == right);
+ const auto notEqual = (left != right);
+
+ // THEN
+ QFETCH(bool, expected);
+ QCOMPARE(equal, expected);
+ QCOMPARE(notEqual, !expected);
+}
+
+void tst_QShaderGraph::shouldFindIndexFromPortNameInStatements_data()
+{
+ QTest::addColumn<QShaderGraph::Statement>("statement");
+ QTest::addColumn<QString>("portName");
+ QTest::addColumn<int>("expectedInputIndex");
+ QTest::addColumn<int>("expectedOutputIndex");
+
+ const auto inputNodeStatement = createStatement(createNode({
+ createPort(QShaderNodePort::Output, "input")
+ }));
+ const auto outputNodeStatement = createStatement(createNode({
+ createPort(QShaderNodePort::Input, "output")
+ }));
+ const auto functionNodeStatement = createStatement(createNode({
+ createPort(QShaderNodePort::Input, "input1"),
+ createPort(QShaderNodePort::Output, "output1"),
+ createPort(QShaderNodePort::Input, "input2"),
+ createPort(QShaderNodePort::Output, "output2"),
+ createPort(QShaderNodePort::Output, "output3"),
+ createPort(QShaderNodePort::Input, "input3")
+ }));
+
+ QTest::newRow("Invalid") << QShaderGraph::Statement() << "foo" << -1 << -1;
+ QTest::newRow("InputNodeWrongName") << inputNodeStatement << "foo" << -1 << -1;
+ QTest::newRow("InputNodeExistingName") << inputNodeStatement << "input" << -1 << 0;
+ QTest::newRow("OutputNodeWrongName") << outputNodeStatement << "foo" << -1 << -1;
+ QTest::newRow("OutputNodeExistingName") << outputNodeStatement << "output" << 0 << -1;
+ QTest::newRow("FunctionNodeWrongName") << functionNodeStatement << "foo" << -1 << -1;
+ QTest::newRow("FunctionNodeInput1") << functionNodeStatement << "input1" << 0 << -1;
+ QTest::newRow("FunctionNodeOutput1") << functionNodeStatement << "output1" << -1 << 0;
+ QTest::newRow("FunctionNodeInput2") << functionNodeStatement << "input2" << 1 << -1;
+ QTest::newRow("FunctionNodeOutput2") << functionNodeStatement << "output2" << -1 << 1;
+ QTest::newRow("FunctionNodeInput3") << functionNodeStatement << "input3" << 2 << -1;
+ QTest::newRow("FunctionNodeOutput3") << functionNodeStatement << "output3" << -1 << 2;
+}
+
+void tst_QShaderGraph::shouldFindIndexFromPortNameInStatements()
+{
+ // GIVEN
+ QFETCH(QShaderGraph::Statement, statement);
+ QFETCH(QString, portName);
+ QFETCH(int, expectedInputIndex);
+ QFETCH(int, expectedOutputIndex);
+
+ // WHEN
+ const auto inputIndex = statement.portIndex(QShaderNodePort::Input, portName);
+ const auto outputIndex = statement.portIndex(QShaderNodePort::Output, portName);
+
+ // THEN
+ QCOMPARE(inputIndex, expectedInputIndex);
+ QCOMPARE(outputIndex, expectedOutputIndex);
+}
+
+void tst_QShaderGraph::shouldManageNodeList()
+{
+ // GIVEN
+ const auto node1 = createNode({createPort(QShaderNodePort::Output, "node1")});
+ const auto node2 = createNode({createPort(QShaderNodePort::Output, "node2")});
+
+ auto graph = QShaderGraph();
+
+ // THEN (default state)
+ QVERIFY(graph.nodes().isEmpty());
+
+ // WHEN
+ graph.addNode(node1);
+
+ // THEN
+ QCOMPARE(graph.nodes().size(), 1);
+ QCOMPARE(graph.nodes().at(0).uuid(), node1.uuid());
+ QCOMPARE(graph.nodes().at(0).ports().at(0).name, node1.ports().at(0).name);
+
+ // WHEN
+ graph.addNode(node2);
+
+ // THEN
+ QCOMPARE(graph.nodes().size(), 2);
+ QCOMPARE(graph.nodes().at(0).uuid(), node1.uuid());
+ QCOMPARE(graph.nodes().at(0).ports().at(0).name, node1.ports().at(0).name);
+ QCOMPARE(graph.nodes().at(1).uuid(), node2.uuid());
+ QCOMPARE(graph.nodes().at(1).ports().at(0).name, node2.ports().at(0).name);
+
+
+ // WHEN
+ graph.removeNode(node2);
+
+ // THEN
+ QCOMPARE(graph.nodes().size(), 1);
+ QCOMPARE(graph.nodes().at(0).uuid(), node1.uuid());
+ QCOMPARE(graph.nodes().at(0).ports().at(0).name, node1.ports().at(0).name);
+
+ // WHEN
+ graph.addNode(node2);
+
+ // THEN
+ QCOMPARE(graph.nodes().size(), 2);
+ QCOMPARE(graph.nodes().at(0).uuid(), node1.uuid());
+ QCOMPARE(graph.nodes().at(0).ports().at(0).name, node1.ports().at(0).name);
+ QCOMPARE(graph.nodes().at(1).uuid(), node2.uuid());
+ QCOMPARE(graph.nodes().at(1).ports().at(0).name, node2.ports().at(0).name);
+
+ // WHEN
+ const auto node1bis = [node1] {
+ auto res = node1;
+ auto port = res.ports().at(0);
+ port.name = QStringLiteral("node1bis");
+ res.addPort(port);
+ return res;
+ }();
+ graph.addNode(node1bis);
+
+ // THEN
+ QCOMPARE(graph.nodes().size(), 2);
+ QCOMPARE(graph.nodes().at(0).uuid(), node2.uuid());
+ QCOMPARE(graph.nodes().at(0).ports().at(0).name, node2.ports().at(0).name);
+ QCOMPARE(graph.nodes().at(1).uuid(), node1bis.uuid());
+ QCOMPARE(graph.nodes().at(1).ports().at(0).name, node1bis.ports().at(0).name);
+}
+
+void tst_QShaderGraph::shouldManageEdgeList()
+{
+ // GIVEN
+ const auto edge1 = createEdge(QUuid::createUuid(), "foo", QUuid::createUuid(), "bar");
+ const auto edge2 = createEdge(QUuid::createUuid(), "baz", QUuid::createUuid(), "boo");
+
+ auto graph = QShaderGraph();
+
+ // THEN (default state)
+ QVERIFY(graph.edges().isEmpty());
+
+ // WHEN
+ graph.addEdge(edge1);
+
+ // THEN
+ QCOMPARE(graph.edges().size(), 1);
+ QCOMPARE(graph.edges().at(0), edge1);
+
+ // WHEN
+ graph.addEdge(edge2);
+
+ // THEN
+ QCOMPARE(graph.edges().size(), 2);
+ QCOMPARE(graph.edges().at(0), edge1);
+ QCOMPARE(graph.edges().at(1), edge2);
+
+
+ // WHEN
+ graph.removeEdge(edge2);
+
+ // THEN
+ QCOMPARE(graph.edges().size(), 1);
+ QCOMPARE(graph.edges().at(0), edge1);
+
+ // WHEN
+ graph.addEdge(edge2);
+
+ // THEN
+ QCOMPARE(graph.edges().size(), 2);
+ QCOMPARE(graph.edges().at(0), edge1);
+ QCOMPARE(graph.edges().at(1), edge2);
+
+ // WHEN
+ graph.addEdge(edge1);
+
+ // THEN
+ QCOMPARE(graph.edges().size(), 2);
+ QCOMPARE(graph.edges().at(0), edge1);
+ QCOMPARE(graph.edges().at(1), edge2);
+}
+
+void tst_QShaderGraph::shouldSerializeGraphForCodeGeneration()
+{
+ // GIVEN
+ const auto input1 = createNode({
+ createPort(QShaderNodePort::Output, "input1Value")
+ });
+ const auto input2 = createNode({
+ createPort(QShaderNodePort::Output, "input2Value")
+ });
+ const auto output1 = createNode({
+ createPort(QShaderNodePort::Input, "output1Value")
+ });
+ const auto output2 = createNode({
+ createPort(QShaderNodePort::Input, "output2Value")
+ });
+ const auto function1 = createNode({
+ createPort(QShaderNodePort::Input, "function1Input"),
+ createPort(QShaderNodePort::Output, "function1Output")
+ });
+ const auto function2 = createNode({
+ createPort(QShaderNodePort::Input, "function2Input1"),
+ createPort(QShaderNodePort::Input, "function2Input2"),
+ createPort(QShaderNodePort::Output, "function2Output")
+ });
+ const auto function3 = createNode({
+ createPort(QShaderNodePort::Input, "function3Input1"),
+ createPort(QShaderNodePort::Input, "function3Input2"),
+ createPort(QShaderNodePort::Output, "function3Output1"),
+ createPort(QShaderNodePort::Output, "function3Output2")
+ });
+
+ const auto graph = [=] {
+ auto res = QShaderGraph();
+ res.addNode(input1);
+ res.addNode(input2);
+ res.addNode(output1);
+ res.addNode(output2);
+ res.addNode(function1);
+ res.addNode(function2);
+ res.addNode(function3);
+ res.addEdge(createEdge(input1.uuid(), "input1Value", function1.uuid(), "function1Input"));
+ res.addEdge(createEdge(input1.uuid(), "input1Value", function2.uuid(), "function2Input1"));
+ res.addEdge(createEdge(input2.uuid(), "input2Value", function2.uuid(), "function2Input2"));
+ res.addEdge(createEdge(function1.uuid(), "function1Output", function3.uuid(), "function3Input1"));
+ res.addEdge(createEdge(function2.uuid(), "function2Output", function3.uuid(), "function3Input2"));
+ res.addEdge(createEdge(function3.uuid(), "function3Output1", output1.uuid(), "output1Value"));
+ res.addEdge(createEdge(function3.uuid(), "function3Output2", output2.uuid(), "output2Value"));
+ return res;
+ }();
+
+ // WHEN
+ const auto statements = graph.createStatements();
+
+ // THEN
+ const auto expected = QVector<QShaderGraph::Statement>()
+ << createStatement(input2, {}, {1})
+ << createStatement(input1, {}, {0})
+ << createStatement(function2, {0, 1}, {3})
+ << createStatement(function1, {0}, {2})
+ << createStatement(function3, {2, 3}, {4, 5})
+ << createStatement(output2, {5}, {})
+ << createStatement(output1, {4}, {});
+ dumpStatementsIfNeeded(statements, expected);
+ QCOMPARE(statements, expected);
+}
+
+void tst_QShaderGraph::shouldHandleUnboundPortsDuringGraphSerialization()
+{
+ // GIVEN
+ const auto input = createNode({
+ createPort(QShaderNodePort::Output, "input")
+ });
+ const auto unboundInput = createNode({
+ createPort(QShaderNodePort::Output, "unbound")
+ });
+ const auto output = createNode({
+ createPort(QShaderNodePort::Input, "output")
+ });
+ const auto unboundOutput = createNode({
+ createPort(QShaderNodePort::Input, "unbound")
+ });
+ const auto function = createNode({
+ createPort(QShaderNodePort::Input, "functionInput1"),
+ createPort(QShaderNodePort::Input, "functionInput2"),
+ createPort(QShaderNodePort::Input, "functionInput3"),
+ createPort(QShaderNodePort::Output, "functionOutput1"),
+ createPort(QShaderNodePort::Output, "functionOutput2"),
+ createPort(QShaderNodePort::Output, "functionOutput3")
+ });
+
+ const auto graph = [=] {
+ auto res = QShaderGraph();
+ res.addNode(input);
+ res.addNode(unboundInput);
+ res.addNode(output);
+ res.addNode(unboundOutput);
+ res.addNode(function);
+ res.addEdge(createEdge(input.uuid(), "input", function.uuid(), "functionInput2"));
+ res.addEdge(createEdge(function.uuid(), "functionOutput2", output.uuid(), "output"));
+ return res;
+ }();
+
+ // WHEN
+ const auto statements = graph.createStatements();
+
+ // THEN
+ // Note that no edge leads to the unbound input
+ const auto expected = QVector<QShaderGraph::Statement>()
+ << createStatement(input, {}, {0})
+ << createStatement(function, {-1, 0, -1}, {2, 3, 4})
+ << createStatement(unboundOutput, {-1}, {})
+ << createStatement(output, {3}, {});
+ dumpStatementsIfNeeded(statements, expected);
+ QCOMPARE(statements, expected);
+}
+
+void tst_QShaderGraph::shouldSurviveCyclesDuringGraphSerialization()
+{
+ // GIVEN
+ const auto input = createNode({
+ createPort(QShaderNodePort::Output, "input")
+ });
+ const auto output = createNode({
+ createPort(QShaderNodePort::Input, "output")
+ });
+ const auto function1 = createNode({
+ createPort(QShaderNodePort::Input, "function1Input1"),
+ createPort(QShaderNodePort::Input, "function1Input2"),
+ createPort(QShaderNodePort::Output, "function1Output")
+ });
+ const auto function2 = createNode({
+ createPort(QShaderNodePort::Input, "function2Input"),
+ createPort(QShaderNodePort::Output, "function2Output")
+ });
+ const auto function3 = createNode({
+ createPort(QShaderNodePort::Input, "function3Input"),
+ createPort(QShaderNodePort::Output, "function3Output")
+ });
+
+ const auto graph = [=] {
+ auto res = QShaderGraph();
+ res.addNode(input);
+ res.addNode(output);
+ res.addNode(function1);
+ res.addNode(function2);
+ res.addNode(function3);
+ res.addEdge(createEdge(input.uuid(), "input", function1.uuid(), "function1Input1"));
+ res.addEdge(createEdge(function1.uuid(), "function1Output", function2.uuid(), "function2Input"));
+ res.addEdge(createEdge(function2.uuid(), "function2Output", function3.uuid(), "function3Input"));
+ res.addEdge(createEdge(function3.uuid(), "function3Output", function1.uuid(), "function1Input2"));
+ res.addEdge(createEdge(function2.uuid(), "function2Output", output.uuid(), "output"));
+ return res;
+ }();
+
+ // WHEN
+ const auto statements = graph.createStatements();
+
+ // THEN
+ // Obviously will lead to a compile failure later on since it cuts everything beyond the cycle
+ const auto expected = QVector<QShaderGraph::Statement>()
+ << createStatement(output, {2}, {});
+ dumpStatementsIfNeeded(statements, expected);
+ QCOMPARE(statements, expected);
+}
+
+void tst_QShaderGraph::shouldDealWithEdgesJumpingOverLayers()
+{
+ // GIVEN
+ const auto worldPosition = createNode({
+ createPort(QShaderNodePort::Output, "worldPosition")
+ });
+ const auto texture = createNode({
+ createPort(QShaderNodePort::Output, "texture")
+ });
+ const auto texCoord = createNode({
+ createPort(QShaderNodePort::Output, "texCoord")
+ });
+ const auto lightIntensity = createNode({
+ createPort(QShaderNodePort::Output, "lightIntensity")
+ });
+ const auto exposure = createNode({
+ createPort(QShaderNodePort::Output, "exposure")
+ });
+ const auto fragColor = createNode({
+ createPort(QShaderNodePort::Input, "fragColor")
+ });
+ const auto sampleTexture = createNode({
+ createPort(QShaderNodePort::Input, "sampler"),
+ createPort(QShaderNodePort::Input, "coord"),
+ createPort(QShaderNodePort::Output, "color")
+ });
+ const auto lightFunction = createNode({
+ createPort(QShaderNodePort::Input, "baseColor"),
+ createPort(QShaderNodePort::Input, "position"),
+ createPort(QShaderNodePort::Input, "lightIntensity"),
+ createPort(QShaderNodePort::Output, "outputColor")
+ });
+ const auto exposureFunction = createNode({
+ createPort(QShaderNodePort::Input, "inputColor"),
+ createPort(QShaderNodePort::Input, "exposure"),
+ createPort(QShaderNodePort::Output, "outputColor")
+ });
+
+ const auto graph = [=] {
+ auto res = QShaderGraph();
+
+ res.addNode(worldPosition);
+ res.addNode(texture);
+ res.addNode(texCoord);
+ res.addNode(lightIntensity);
+ res.addNode(exposure);
+ res.addNode(fragColor);
+ res.addNode(sampleTexture);
+ res.addNode(lightFunction);
+ res.addNode(exposureFunction);
+
+ res.addEdge(createEdge(texture.uuid(), "texture", sampleTexture.uuid(), "sampler"));
+ res.addEdge(createEdge(texCoord.uuid(), "texCoord", sampleTexture.uuid(), "coord"));
+
+ res.addEdge(createEdge(worldPosition.uuid(), "worldPosition", lightFunction.uuid(), "position"));
+ res.addEdge(createEdge(sampleTexture.uuid(), "color", lightFunction.uuid(), "baseColor"));
+ res.addEdge(createEdge(lightIntensity.uuid(), "lightIntensity", lightFunction.uuid(), "lightIntensity"));
+
+ res.addEdge(createEdge(lightFunction.uuid(), "outputColor", exposureFunction.uuid(), "inputColor"));
+ res.addEdge(createEdge(exposure.uuid(), "exposure", exposureFunction.uuid(), "exposure"));
+
+ res.addEdge(createEdge(exposureFunction.uuid(), "outputColor", fragColor.uuid(), "fragColor"));
+
+ return res;
+ }();
+
+ // WHEN
+ const auto statements = graph.createStatements();
+
+ // THEN
+ const auto expected = QVector<QShaderGraph::Statement>()
+ << createStatement(texCoord, {}, {2})
+ << createStatement(texture, {}, {1})
+ << createStatement(lightIntensity, {}, {3})
+ << createStatement(sampleTexture, {1, 2}, {5})
+ << createStatement(worldPosition, {}, {0})
+ << createStatement(exposure, {}, {4})
+ << createStatement(lightFunction, {5, 0, 3}, {6})
+ << createStatement(exposureFunction, {6, 4}, {7})
+ << createStatement(fragColor, {7}, {});
+ dumpStatementsIfNeeded(statements, expected);
+ QCOMPARE(statements, expected);
+}
+
+void tst_QShaderGraph::shouldGenerateDifferentStatementsDependingOnActiveLayers()
+{
+ // GIVEN
+ const auto texCoord = createNode({
+ createPort(QShaderNodePort::Output, "texCoord")
+ }, {
+ "diffuseTexture",
+ "normalTexture"
+ });
+ const auto diffuseUniform = createNode({
+ createPort(QShaderNodePort::Output, "color")
+ }, {"diffuseUniform"});
+ const auto diffuseTexture = createNode({
+ createPort(QShaderNodePort::Input, "coord"),
+ createPort(QShaderNodePort::Output, "color")
+ }, {"diffuseTexture"});
+ const auto normalUniform = createNode({
+ createPort(QShaderNodePort::Output, "normal")
+ }, {"normalUniform"});
+ const auto normalTexture = createNode({
+ createPort(QShaderNodePort::Input, "coord"),
+ createPort(QShaderNodePort::Output, "normal")
+ }, {"normalTexture"});
+ const auto lightFunction = createNode({
+ createPort(QShaderNodePort::Input, "color"),
+ createPort(QShaderNodePort::Input, "normal"),
+ createPort(QShaderNodePort::Output, "output")
+ });
+ const auto fragColor = createNode({
+ createPort(QShaderNodePort::Input, "fragColor")
+ });
+
+ const auto graph = [=] {
+ auto res = QShaderGraph();
+
+ res.addNode(texCoord);
+ res.addNode(diffuseUniform);
+ res.addNode(diffuseTexture);
+ res.addNode(normalUniform);
+ res.addNode(normalTexture);
+ res.addNode(lightFunction);
+ res.addNode(fragColor);
+
+ res.addEdge(createEdge(diffuseUniform.uuid(), "color", lightFunction.uuid(), "color", {"diffuseUniform"}));
+ res.addEdge(createEdge(texCoord.uuid(), "texCoord", diffuseTexture.uuid(), "coord", {"diffuseTexture"}));
+ res.addEdge(createEdge(diffuseTexture.uuid(), "color", lightFunction.uuid(), "color", {"diffuseTexture"}));
+
+ res.addEdge(createEdge(normalUniform.uuid(), "normal", lightFunction.uuid(), "normal", {"normalUniform"}));
+ res.addEdge(createEdge(texCoord.uuid(), "texCoord", normalTexture.uuid(), "coord", {"normalTexture"}));
+ res.addEdge(createEdge(normalTexture.uuid(), "normal", lightFunction.uuid(), "normal", {"normalTexture"}));
+
+ res.addEdge(createEdge(lightFunction.uuid(), "output", fragColor.uuid(), "fragColor"));
+
+ return res;
+ }();
+
+ {
+ // WHEN
+ const auto statements = graph.createStatements({"diffuseUniform", "normalUniform"});
+
+ // THEN
+ const auto expected = QVector<QShaderGraph::Statement>()
+ << createStatement(normalUniform, {}, {1})
+ << createStatement(diffuseUniform, {}, {0})
+ << createStatement(lightFunction, {0, 1}, {2})
+ << createStatement(fragColor, {2}, {});
+ dumpStatementsIfNeeded(statements, expected);
+ QCOMPARE(statements, expected);
+ }
+
+ {
+ // WHEN
+ const auto statements = graph.createStatements({"diffuseUniform", "normalTexture"});
+
+ // THEN
+ const auto expected = QVector<QShaderGraph::Statement>()
+ << createStatement(texCoord, {}, {0})
+ << createStatement(normalTexture, {0}, {2})
+ << createStatement(diffuseUniform, {}, {1})
+ << createStatement(lightFunction, {1, 2}, {3})
+ << createStatement(fragColor, {3}, {});
+ dumpStatementsIfNeeded(statements, expected);
+ QCOMPARE(statements, expected);
+ }
+
+ {
+ // WHEN
+ const auto statements = graph.createStatements({"diffuseTexture", "normalUniform"});
+
+ // THEN
+ const auto expected = QVector<QShaderGraph::Statement>()
+ << createStatement(texCoord, {}, {0})
+ << createStatement(normalUniform, {}, {2})
+ << createStatement(diffuseTexture, {0}, {1})
+ << createStatement(lightFunction, {1, 2}, {3})
+ << createStatement(fragColor, {3}, {});
+ dumpStatementsIfNeeded(statements, expected);
+ QCOMPARE(statements, expected);
+ }
+
+ {
+ // WHEN
+ const auto statements = graph.createStatements({"diffuseTexture", "normalTexture"});
+
+ // THEN
+ const auto expected = QVector<QShaderGraph::Statement>()
+ << createStatement(texCoord, {}, {0})
+ << createStatement(normalTexture, {0}, {2})
+ << createStatement(diffuseTexture, {0}, {1})
+ << createStatement(lightFunction, {1, 2}, {3})
+ << createStatement(fragColor, {3}, {});
+ dumpStatementsIfNeeded(statements, expected);
+ QCOMPARE(statements, expected);
+ }
+}
+
+QTEST_MAIN(tst_QShaderGraph)
+
+#include "tst_qshadergraph.moc"
diff --git a/tests/auto/gui/util/qshadergraphloader/qshadergraphloader.pro b/tests/auto/gui/util/qshadergraphloader/qshadergraphloader.pro
new file mode 100644
index 0000000000..e80a93f9e8
--- /dev/null
+++ b/tests/auto/gui/util/qshadergraphloader/qshadergraphloader.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+QT += testlib gui-private
+
+SOURCES += tst_qshadergraphloader.cpp
+TARGET = tst_qshadergraphloader
diff --git a/tests/auto/gui/util/qshadergraphloader/tst_qshadergraphloader.cpp b/tests/auto/gui/util/qshadergraphloader/tst_qshadergraphloader.cpp
new file mode 100644
index 0000000000..761e03a195
--- /dev/null
+++ b/tests/auto/gui/util/qshadergraphloader/tst_qshadergraphloader.cpp
@@ -0,0 +1,625 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QtCore/qbuffer.h>
+
+#include <QtGui/private/qshadergraphloader_p.h>
+#include <QtGui/private/qshaderlanguage_p.h>
+
+using QBufferPointer = QSharedPointer<QBuffer>;
+Q_DECLARE_METATYPE(QBufferPointer);
+
+using PrototypeHash = QHash<QString, QShaderNode>;
+Q_DECLARE_METATYPE(PrototypeHash);
+
+namespace
+{
+ QBufferPointer createBuffer(const QByteArray &data, QIODevice::OpenMode openMode = QIODevice::ReadOnly)
+ {
+ auto buffer = QBufferPointer::create();
+ buffer->setData(data);
+ if (openMode != QIODevice::NotOpen)
+ buffer->open(openMode);
+ return buffer;
+ }
+
+ QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion)
+ {
+ auto format = QShaderFormat();
+ format.setApi(api);
+ format.setVersion(QVersionNumber(majorVersion, minorVersion));
+ return format;
+ }
+
+ QShaderNodePort createPort(QShaderNodePort::Direction portDirection, const QString &portName)
+ {
+ auto port = QShaderNodePort();
+ port.direction = portDirection;
+ port.name = portName;
+ return port;
+ }
+
+ QShaderNode createNode(const QVector<QShaderNodePort> &ports, const QStringList &layers = QStringList())
+ {
+ auto node = QShaderNode();
+ node.setUuid(QUuid::createUuid());
+ node.setLayers(layers);
+ for (const auto &port : ports)
+ node.addPort(port);
+ return node;
+ }
+
+ QShaderGraph::Edge createEdge(const QUuid &sourceUuid, const QString &sourceName,
+ const QUuid &targetUuid, const QString &targetName,
+ const QStringList &layers = QStringList())
+ {
+ auto edge = QShaderGraph::Edge();
+ edge.sourceNodeUuid = sourceUuid;
+ edge.sourcePortName = sourceName;
+ edge.targetNodeUuid = targetUuid;
+ edge.targetPortName = targetName;
+ edge.layers = layers;
+ return edge;
+ }
+
+ QShaderGraph createGraph()
+ {
+ const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
+ const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
+
+ auto graph = QShaderGraph();
+
+ auto worldPosition = createNode({
+ createPort(QShaderNodePort::Output, "value")
+ });
+ worldPosition.setUuid(QUuid("{00000000-0000-0000-0000-000000000001}"));
+ worldPosition.setParameter("name", "worldPosition");
+ worldPosition.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Input));
+ worldPosition.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Vec3));
+ worldPosition.addRule(openGLES2, QShaderNode::Rule("highp $type $value = $name;",
+ QByteArrayList() << "$qualifier highp $type $name;"));
+ worldPosition.addRule(openGL3, QShaderNode::Rule("$type $value = $name;",
+ QByteArrayList() << "$qualifier $type $name;"));
+
+ auto texture = createNode({
+ createPort(QShaderNodePort::Output, "texture")
+ });
+ texture.setUuid(QUuid("{00000000-0000-0000-0000-000000000002}"));
+ texture.addRule(openGLES2, QShaderNode::Rule("sampler2D $texture = texture;",
+ QByteArrayList() << "uniform sampler2D texture;"));
+ texture.addRule(openGL3, QShaderNode::Rule("sampler2D $texture = texture;",
+ QByteArrayList() << "uniform sampler2D texture;"));
+
+ auto texCoord = createNode({
+ createPort(QShaderNodePort::Output, "texCoord")
+ });
+ texCoord.setUuid(QUuid("{00000000-0000-0000-0000-000000000003}"));
+ texCoord.addRule(openGLES2, QShaderNode::Rule("highp vec2 $texCoord = texCoord;",
+ QByteArrayList() << "varying highp vec2 texCoord;"));
+ texCoord.addRule(openGL3, QShaderNode::Rule("vec2 $texCoord = texCoord;",
+ QByteArrayList() << "in vec2 texCoord;"));
+
+ auto lightIntensity = createNode({
+ createPort(QShaderNodePort::Output, "value")
+ });
+ lightIntensity.setUuid(QUuid("{00000000-0000-0000-0000-000000000004}"));
+ lightIntensity.setParameter("name", "defaultName");
+ lightIntensity.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Uniform));
+ lightIntensity.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Float));
+ lightIntensity.addRule(openGLES2, QShaderNode::Rule("highp $type $value = $name;",
+ QByteArrayList() << "$qualifier highp $type $name;"));
+ lightIntensity.addRule(openGL3, QShaderNode::Rule("$type $value = $name;",
+ QByteArrayList() << "$qualifier $type $name;"));
+
+ auto exposure = createNode({
+ createPort(QShaderNodePort::Output, "exposure")
+ });
+ exposure.setUuid(QUuid("{00000000-0000-0000-0000-000000000005}"));
+ exposure.addRule(openGLES2, QShaderNode::Rule("highp float $exposure = exposure;",
+ QByteArrayList() << "uniform highp float exposure;"));
+ exposure.addRule(openGL3, QShaderNode::Rule("float $exposure = exposure;",
+ QByteArrayList() << "uniform float exposure;"));
+
+ auto fragColor = createNode({
+ createPort(QShaderNodePort::Input, "fragColor")
+ });
+ fragColor.setUuid(QUuid("{00000000-0000-0000-0000-000000000006}"));
+ fragColor.addRule(openGLES2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
+ fragColor.addRule(openGL3, QShaderNode::Rule("fragColor = $fragColor;",
+ QByteArrayList() << "out vec4 fragColor;"));
+
+ auto sampleTexture = createNode({
+ createPort(QShaderNodePort::Input, "sampler"),
+ createPort(QShaderNodePort::Input, "coord"),
+ createPort(QShaderNodePort::Output, "color")
+ });
+ sampleTexture.setUuid(QUuid("{00000000-0000-0000-0000-000000000007}"));
+ sampleTexture.addRule(openGLES2, QShaderNode::Rule("highp vec4 $color = texture2D($sampler, $coord);"));
+ sampleTexture.addRule(openGL3, QShaderNode::Rule("vec4 $color = texture2D($sampler, $coord);"));
+
+ auto lightFunction = createNode({
+ createPort(QShaderNodePort::Input, "baseColor"),
+ createPort(QShaderNodePort::Input, "position"),
+ createPort(QShaderNodePort::Input, "lightIntensity"),
+ createPort(QShaderNodePort::Output, "outputColor")
+ });
+ lightFunction.setUuid(QUuid("{00000000-0000-0000-0000-000000000008}"));
+ lightFunction.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);",
+ QByteArrayList() << "#pragma include es2/lightmodel.frag.inc"));
+ lightFunction.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);",
+ QByteArrayList() << "#pragma include gl3/lightmodel.frag.inc"));
+
+ auto exposureFunction = createNode({
+ createPort(QShaderNodePort::Input, "inputColor"),
+ createPort(QShaderNodePort::Input, "exposure"),
+ createPort(QShaderNodePort::Output, "outputColor")
+ });
+ exposureFunction.setUuid(QUuid("{00000000-0000-0000-0000-000000000009}"));
+ exposureFunction.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = $inputColor * pow(2.0, $exposure);"));
+ exposureFunction.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = $inputColor * pow(2.0, $exposure);"));
+
+ graph.addNode(worldPosition);
+ graph.addNode(texture);
+ graph.addNode(texCoord);
+ graph.addNode(lightIntensity);
+ graph.addNode(exposure);
+ graph.addNode(fragColor);
+ graph.addNode(sampleTexture);
+ graph.addNode(lightFunction);
+ graph.addNode(exposureFunction);
+
+ graph.addEdge(createEdge(texture.uuid(), "texture", sampleTexture.uuid(), "sampler"));
+ graph.addEdge(createEdge(texCoord.uuid(), "texCoord", sampleTexture.uuid(), "coord"));
+
+ graph.addEdge(createEdge(worldPosition.uuid(), "value", lightFunction.uuid(), "position"));
+ graph.addEdge(createEdge(sampleTexture.uuid(), "color", lightFunction.uuid(), "baseColor"));
+ graph.addEdge(createEdge(lightIntensity.uuid(), "value", lightFunction.uuid(), "lightIntensity"));
+
+ graph.addEdge(createEdge(lightFunction.uuid(), "outputColor", exposureFunction.uuid(), "inputColor"));
+ graph.addEdge(createEdge(exposure.uuid(), "exposure", exposureFunction.uuid(), "exposure"));
+
+ graph.addEdge(createEdge(exposureFunction.uuid(), "outputColor", fragColor.uuid(), "fragColor"));
+
+ return graph;
+ }
+
+ void debugStatement(const QString &prefix, const QShaderGraph::Statement &statement)
+ {
+ qDebug() << prefix << statement.inputs << statement.uuid().toString() << statement.outputs;
+ }
+
+ void dumpStatementsIfNeeded(const QVector<QShaderGraph::Statement> &statements, const QVector<QShaderGraph::Statement> &expected)
+ {
+ if (statements != expected) {
+ for (int i = 0; i < qMax(statements.size(), expected.size()); i++) {
+ qDebug() << "----" << i << "----";
+ if (i < statements.size())
+ debugStatement("A:", statements.at(i));
+ if (i < expected.size())
+ debugStatement("E:", expected.at(i));
+ qDebug() << "-----------";
+ }
+ }
+ }
+}
+
+class tst_QShaderGraphLoader : public QObject
+{
+ Q_OBJECT
+private slots:
+ void shouldManipulateLoaderMembers();
+ void shouldLoadFromJsonStream_data();
+ void shouldLoadFromJsonStream();
+};
+
+void tst_QShaderGraphLoader::shouldManipulateLoaderMembers()
+{
+ // GIVEN
+ auto loader = QShaderGraphLoader();
+
+ // THEN (default state)
+ QCOMPARE(loader.status(), QShaderGraphLoader::Null);
+ QVERIFY(!loader.device());
+ QVERIFY(loader.graph().nodes().isEmpty());
+ QVERIFY(loader.graph().edges().isEmpty());
+ QVERIFY(loader.prototypes().isEmpty());
+
+ // WHEN
+ auto device1 = createBuffer(QByteArray("..........."), QIODevice::NotOpen);
+ loader.setDevice(device1.data());
+
+ // THEN
+ QCOMPARE(loader.status(), QShaderGraphLoader::Error);
+ QCOMPARE(loader.device(), device1.data());
+ QVERIFY(loader.graph().nodes().isEmpty());
+ QVERIFY(loader.graph().edges().isEmpty());
+
+ // WHEN
+ auto device2 = createBuffer(QByteArray("..........."), QIODevice::ReadOnly);
+ loader.setDevice(device2.data());
+
+ // THEN
+ QCOMPARE(loader.status(), QShaderGraphLoader::Waiting);
+ QCOMPARE(loader.device(), device2.data());
+ QVERIFY(loader.graph().nodes().isEmpty());
+ QVERIFY(loader.graph().edges().isEmpty());
+
+
+ // WHEN
+ const auto prototypes = [this]{
+ auto res = QHash<QString, QShaderNode>();
+ res.insert("foo", createNode({}));
+ return res;
+ }();
+ loader.setPrototypes(prototypes);
+
+ // THEN
+ QCOMPARE(loader.prototypes().size(), prototypes.size());
+ QVERIFY(loader.prototypes().contains("foo"));
+ QCOMPARE(loader.prototypes().value("foo").uuid(), prototypes.value("foo").uuid());
+}
+
+void tst_QShaderGraphLoader::shouldLoadFromJsonStream_data()
+{
+ QTest::addColumn<QBufferPointer>("device");
+ QTest::addColumn<PrototypeHash>("prototypes");
+ QTest::addColumn<QShaderGraph>("graph");
+ QTest::addColumn<QShaderGraphLoader::Status>("status");
+
+ QTest::newRow("empty") << createBuffer("", QIODevice::ReadOnly) << PrototypeHash()
+ << QShaderGraph() << QShaderGraphLoader::Error;
+
+ const auto smallJson = "{"
+ " \"nodes\": ["
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000001}\","
+ " \"type\": \"MyInput\","
+ " \"layers\": [\"foo\", \"bar\"]"
+ " },"
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000002}\","
+ " \"type\": \"MyOutput\""
+ " },"
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000003}\","
+ " \"type\": \"MyFunction\""
+ " }"
+ " ],"
+ " \"edges\": ["
+ " {"
+ " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000001}\","
+ " \"sourcePort\": \"input\","
+ " \"targetUuid\": \"{00000000-0000-0000-0000-000000000003}\","
+ " \"targetPort\": \"functionInput\","
+ " \"layers\": [\"bar\", \"baz\"]"
+ " },"
+ " {"
+ " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000003}\","
+ " \"sourcePort\": \"functionOutput\","
+ " \"targetUuid\": \"{00000000-0000-0000-0000-000000000002}\","
+ " \"targetPort\": \"output\""
+ " }"
+ " ]"
+ "}";
+
+ const auto smallProtos = [this]{
+ auto protos = PrototypeHash();
+
+ auto input = createNode({
+ createPort(QShaderNodePort::Output, "input")
+ });
+ protos.insert("MyInput", input);
+
+ auto output = createNode({
+ createPort(QShaderNodePort::Input, "output")
+ });
+ protos.insert("MyOutput", output);
+
+ auto function = createNode({
+ createPort(QShaderNodePort::Input, "functionInput"),
+ createPort(QShaderNodePort::Output, "functionOutput")
+ });
+ protos.insert("MyFunction", function);
+ return protos;
+ }();
+
+ const auto smallGraph = [this]{
+ auto graph = QShaderGraph();
+
+ auto input = createNode({
+ createPort(QShaderNodePort::Output, "input")
+ }, {"foo", "bar"});
+ input.setUuid(QUuid("{00000000-0000-0000-0000-000000000001}"));
+ auto output = createNode({
+ createPort(QShaderNodePort::Input, "output")
+ });
+ output.setUuid(QUuid("{00000000-0000-0000-0000-000000000002}"));
+ auto function = createNode({
+ createPort(QShaderNodePort::Input, "functionInput"),
+ createPort(QShaderNodePort::Output, "functionOutput")
+ });
+ function.setUuid(QUuid("{00000000-0000-0000-0000-000000000003}"));
+
+ graph.addNode(input);
+ graph.addNode(output);
+ graph.addNode(function);
+ graph.addEdge(createEdge(input.uuid(), "input", function.uuid(), "functionInput", {"bar", "baz"}));
+ graph.addEdge(createEdge(function.uuid(), "functionOutput", output.uuid(), "output"));
+
+ return graph;
+ }();
+
+ QTest::newRow("TwoNodesOneEdge") << createBuffer(smallJson) << smallProtos << smallGraph << QShaderGraphLoader::Ready;
+ QTest::newRow("NotOpen") << createBuffer(smallJson, QIODevice::NotOpen) << smallProtos << QShaderGraph() << QShaderGraphLoader::Error;
+ QTest::newRow("NoPrototype") << createBuffer(smallJson) << PrototypeHash() << QShaderGraph() << QShaderGraphLoader::Error;
+
+ const auto complexJson = "{"
+ " \"nodes\": ["
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000001}\","
+ " \"type\": \"inputValue\","
+ " \"parameters\": {"
+ " \"name\": \"worldPosition\","
+ " \"qualifier\": {"
+ " \"type\": \"QShaderLanguage::StorageQualifier\","
+ " \"value\": \"QShaderLanguage::Input\""
+ " },"
+ " \"type\": {"
+ " \"type\": \"QShaderLanguage::VariableType\","
+ " \"value\": \"QShaderLanguage::Vec3\""
+ " }"
+ " }"
+ " },"
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000002}\","
+ " \"type\": \"texture\""
+ " },"
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000003}\","
+ " \"type\": \"texCoord\""
+ " },"
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000004}\","
+ " \"type\": \"inputValue\""
+ " },"
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000005}\","
+ " \"type\": \"exposure\""
+ " },"
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000006}\","
+ " \"type\": \"fragColor\""
+ " },"
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000007}\","
+ " \"type\": \"sampleTexture\""
+ " },"
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000008}\","
+ " \"type\": \"lightModel\""
+ " },"
+ " {"
+ " \"uuid\": \"{00000000-0000-0000-0000-000000000009}\","
+ " \"type\": \"exposureFunction\""
+ " }"
+ " ],"
+ " \"edges\": ["
+ " {"
+ " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000002}\","
+ " \"sourcePort\": \"texture\","
+ " \"targetUuid\": \"{00000000-0000-0000-0000-000000000007}\","
+ " \"targetPort\": \"sampler\""
+ " },"
+ " {"
+ " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000003}\","
+ " \"sourcePort\": \"texCoord\","
+ " \"targetUuid\": \"{00000000-0000-0000-0000-000000000007}\","
+ " \"targetPort\": \"coord\""
+ " },"
+ " {"
+ " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000001}\","
+ " \"sourcePort\": \"value\","
+ " \"targetUuid\": \"{00000000-0000-0000-0000-000000000008}\","
+ " \"targetPort\": \"position\""
+ " },"
+ " {"
+ " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000007}\","
+ " \"sourcePort\": \"color\","
+ " \"targetUuid\": \"{00000000-0000-0000-0000-000000000008}\","
+ " \"targetPort\": \"baseColor\""
+ " },"
+ " {"
+ " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000004}\","
+ " \"sourcePort\": \"value\","
+ " \"targetUuid\": \"{00000000-0000-0000-0000-000000000008}\","
+ " \"targetPort\": \"lightIntensity\""
+ " },"
+ " {"
+ " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000008}\","
+ " \"sourcePort\": \"outputColor\","
+ " \"targetUuid\": \"{00000000-0000-0000-0000-000000000009}\","
+ " \"targetPort\": \"inputColor\""
+ " },"
+ " {"
+ " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000005}\","
+ " \"sourcePort\": \"exposure\","
+ " \"targetUuid\": \"{00000000-0000-0000-0000-000000000009}\","
+ " \"targetPort\": \"exposure\""
+ " },"
+ " {"
+ " \"sourceUuid\": \"{00000000-0000-0000-0000-000000000009}\","
+ " \"sourcePort\": \"outputColor\","
+ " \"targetUuid\": \"{00000000-0000-0000-0000-000000000006}\","
+ " \"targetPort\": \"fragColor\""
+ " }"
+ " ]"
+ "}";
+
+ const auto complexProtos = [this]{
+ const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
+ const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
+
+ auto protos = PrototypeHash();
+
+ auto inputValue = createNode({
+ createPort(QShaderNodePort::Output, "value")
+ });
+ inputValue.setParameter("name", "defaultName");
+ inputValue.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Uniform));
+ inputValue.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Float));
+ inputValue.addRule(openGLES2, QShaderNode::Rule("highp $type $value = $name;",
+ QByteArrayList() << "$qualifier highp $type $name;"));
+ inputValue.addRule(openGL3, QShaderNode::Rule("$type $value = $name;",
+ QByteArrayList() << "$qualifier $type $name;"));
+ protos.insert("inputValue", inputValue);
+
+ auto texture = createNode({
+ createPort(QShaderNodePort::Output, "texture")
+ });
+ texture.addRule(openGLES2, QShaderNode::Rule("sampler2D $texture = texture;",
+ QByteArrayList() << "uniform sampler2D texture;"));
+ texture.addRule(openGL3, QShaderNode::Rule("sampler2D $texture = texture;",
+ QByteArrayList() << "uniform sampler2D texture;"));
+ protos.insert("texture", texture);
+
+ auto texCoord = createNode({
+ createPort(QShaderNodePort::Output, "texCoord")
+ });
+ texCoord.addRule(openGLES2, QShaderNode::Rule("highp vec2 $texCoord = texCoord;",
+ QByteArrayList() << "varying highp vec2 texCoord;"));
+ texCoord.addRule(openGL3, QShaderNode::Rule("vec2 $texCoord = texCoord;",
+ QByteArrayList() << "in vec2 texCoord;"));
+ protos.insert("texCoord", texCoord);
+
+ auto exposure = createNode({
+ createPort(QShaderNodePort::Output, "exposure")
+ });
+ exposure.addRule(openGLES2, QShaderNode::Rule("highp float $exposure = exposure;",
+ QByteArrayList() << "uniform highp float exposure;"));
+ exposure.addRule(openGL3, QShaderNode::Rule("float $exposure = exposure;",
+ QByteArrayList() << "uniform float exposure;"));
+ protos.insert("exposure", exposure);
+
+ auto fragColor = createNode({
+ createPort(QShaderNodePort::Input, "fragColor")
+ });
+ fragColor.addRule(openGLES2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
+ fragColor.addRule(openGL3, QShaderNode::Rule("fragColor = $fragColor;",
+ QByteArrayList() << "out vec4 fragColor;"));
+ protos.insert("fragColor", fragColor);
+
+ auto sampleTexture = createNode({
+ createPort(QShaderNodePort::Input, "sampler"),
+ createPort(QShaderNodePort::Input, "coord"),
+ createPort(QShaderNodePort::Output, "color")
+ });
+ sampleTexture.addRule(openGLES2, QShaderNode::Rule("highp vec4 $color = texture2D($sampler, $coord);"));
+ sampleTexture.addRule(openGL3, QShaderNode::Rule("vec4 $color = texture2D($sampler, $coord);"));
+ protos.insert("sampleTexture", sampleTexture);
+
+ auto lightModel = createNode({
+ createPort(QShaderNodePort::Input, "baseColor"),
+ createPort(QShaderNodePort::Input, "position"),
+ createPort(QShaderNodePort::Input, "lightIntensity"),
+ createPort(QShaderNodePort::Output, "outputColor")
+ });
+ lightModel.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);",
+ QByteArrayList() << "#pragma include es2/lightmodel.frag.inc"));
+ lightModel.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);",
+ QByteArrayList() << "#pragma include gl3/lightmodel.frag.inc"));
+ protos.insert("lightModel", lightModel);
+
+ auto exposureFunction = createNode({
+ createPort(QShaderNodePort::Input, "inputColor"),
+ createPort(QShaderNodePort::Input, "exposure"),
+ createPort(QShaderNodePort::Output, "outputColor")
+ });
+ exposureFunction.addRule(openGLES2, QShaderNode::Rule("highp vec4 $outputColor = $inputColor * pow(2.0, $exposure);"));
+ exposureFunction.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = $inputColor * pow(2.0, $exposure);"));
+ protos.insert("exposureFunction", exposureFunction);
+
+ return protos;
+ }();
+
+ const auto complexGraph = createGraph();
+
+ QTest::newRow("ComplexGraph") << createBuffer(complexJson) << complexProtos << complexGraph << QShaderGraphLoader::Ready;
+}
+
+void tst_QShaderGraphLoader::shouldLoadFromJsonStream()
+{
+ // GIVEN
+ QFETCH(QBufferPointer, device);
+ QFETCH(PrototypeHash, prototypes);
+
+ auto loader = QShaderGraphLoader();
+
+ // WHEN
+ loader.setPrototypes(prototypes);
+ loader.setDevice(device.data());
+ loader.load();
+
+ // THEN
+ QFETCH(QShaderGraphLoader::Status, status);
+ QCOMPARE(loader.status(), status);
+
+ QFETCH(QShaderGraph, graph);
+ const auto statements = loader.graph().createStatements({"foo", "bar", "baz"});
+ const auto expected = graph.createStatements({"foo", "bar", "baz"});
+ dumpStatementsIfNeeded(statements, expected);
+ QCOMPARE(statements, expected);
+
+ const auto sortedParameters = [](const QShaderNode &node) {
+ auto res = node.parameterNames();
+ res.sort();
+ return res;
+ };
+
+ for (int i = 0; i < statements.size(); i++) {
+ const auto actualNode = statements.at(i).node;
+ const auto expectedNode = expected.at(i).node;
+
+ QCOMPARE(actualNode.layers(), expectedNode.layers());
+ QCOMPARE(actualNode.ports(), expectedNode.ports());
+ QCOMPARE(sortedParameters(actualNode), sortedParameters(expectedNode));
+ for (const auto &name : expectedNode.parameterNames()) {
+ QCOMPARE(actualNode.parameter(name), expectedNode.parameter(name));
+ }
+ QCOMPARE(actualNode.availableFormats(), expectedNode.availableFormats());
+ for (const auto &format : expectedNode.availableFormats()) {
+ QCOMPARE(actualNode.rule(format), expectedNode.rule(format));
+ }
+ }
+}
+
+QTEST_MAIN(tst_QShaderGraphLoader)
+
+#include "tst_qshadergraphloader.moc"
diff --git a/tests/auto/gui/util/qshadernodes/qshadernodes.pro b/tests/auto/gui/util/qshadernodes/qshadernodes.pro
new file mode 100644
index 0000000000..5ab8b73a51
--- /dev/null
+++ b/tests/auto/gui/util/qshadernodes/qshadernodes.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+QT += testlib gui-private
+
+SOURCES += tst_qshadernodes.cpp
+TARGET = tst_qshadernodes
diff --git a/tests/auto/gui/util/qshadernodes/tst_qshadernodes.cpp b/tests/auto/gui/util/qshadernodes/tst_qshadernodes.cpp
new file mode 100644
index 0000000000..9eb738a1b2
--- /dev/null
+++ b/tests/auto/gui/util/qshadernodes/tst_qshadernodes.cpp
@@ -0,0 +1,548 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QtGui/private/qshaderformat_p.h>
+#include <QtGui/private/qshadernode_p.h>
+#include <QtGui/private/qshadernodeport_p.h>
+
+namespace
+{
+ QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion,
+ const QStringList &extensions = QStringList(),
+ const QString &vendor = QString())
+ {
+ auto format = QShaderFormat();
+ format.setApi(api);
+ format.setVersion(QVersionNumber(majorVersion, minorVersion));
+ format.setExtensions(extensions);
+ format.setVendor(vendor);
+ return format;
+ }
+
+ QShaderNodePort createPort(QShaderNodePort::Direction direction, const QString &name)
+ {
+ auto port = QShaderNodePort();
+ port.direction = direction;
+ port.name = name;
+ return port;
+ }
+}
+
+class tst_QShaderNodes : public QObject
+{
+ Q_OBJECT
+private slots:
+ void shouldManipulateFormatMembers();
+ void shouldVerifyFormatsEquality_data();
+ void shouldVerifyFormatsEquality();
+ void shouldVerifyFormatsCompatibilities_data();
+ void shouldVerifyFormatsCompatibilities();
+
+ void shouldHaveDefaultPortState();
+ void shouldVerifyPortsEquality_data();
+ void shouldVerifyPortsEquality();
+
+ void shouldManipulateNodeMembers();
+ void shouldHandleNodeRulesSupportAndOrder();
+};
+
+void tst_QShaderNodes::shouldManipulateFormatMembers()
+{
+ // GIVEN
+ auto format = QShaderFormat();
+
+ // THEN (default state)
+ QCOMPARE(format.api(), QShaderFormat::NoApi);
+ QCOMPARE(format.version().majorVersion(), 0);
+ QCOMPARE(format.version().minorVersion(), 0);
+ QCOMPARE(format.extensions(), QStringList());
+ QCOMPARE(format.vendor(), QString());
+ QVERIFY(!format.isValid());
+
+ // WHEN
+ format.setApi(QShaderFormat::OpenGLES);
+
+ // THEN
+ QCOMPARE(format.api(), QShaderFormat::OpenGLES);
+ QCOMPARE(format.version().majorVersion(), 0);
+ QCOMPARE(format.version().minorVersion(), 0);
+ QCOMPARE(format.extensions(), QStringList());
+ QCOMPARE(format.vendor(), QString());
+ QVERIFY(!format.isValid());
+
+ // WHEN
+ format.setVersion(QVersionNumber(3));
+
+ // THEN
+ QCOMPARE(format.api(), QShaderFormat::OpenGLES);
+ QCOMPARE(format.version().majorVersion(), 3);
+ QCOMPARE(format.version().minorVersion(), 0);
+ QCOMPARE(format.extensions(), QStringList());
+ QCOMPARE(format.vendor(), QString());
+ QVERIFY(format.isValid());
+
+ // WHEN
+ format.setVersion(QVersionNumber(3, 2));
+
+ // THEN
+ QCOMPARE(format.api(), QShaderFormat::OpenGLES);
+ QCOMPARE(format.version().majorVersion(), 3);
+ QCOMPARE(format.version().minorVersion(), 2);
+ QCOMPARE(format.extensions(), QStringList());
+ QCOMPARE(format.vendor(), QString());
+ QVERIFY(format.isValid());
+
+ // WHEN
+ format.setExtensions({"foo", "bar"});
+
+ // THEN
+ QCOMPARE(format.api(), QShaderFormat::OpenGLES);
+ QCOMPARE(format.version().majorVersion(), 3);
+ QCOMPARE(format.version().minorVersion(), 2);
+ QCOMPARE(format.extensions(), QStringList({"bar", "foo"}));
+ QCOMPARE(format.vendor(), QString());
+ QVERIFY(format.isValid());
+
+ // WHEN
+ format.setVendor(QStringLiteral("KDAB"));
+
+ // THEN
+ QCOMPARE(format.api(), QShaderFormat::OpenGLES);
+ QCOMPARE(format.version().majorVersion(), 3);
+ QCOMPARE(format.version().minorVersion(), 2);
+ QCOMPARE(format.extensions(), QStringList({"bar", "foo"}));
+ QCOMPARE(format.vendor(), QStringLiteral("KDAB"));
+ QVERIFY(format.isValid());
+}
+
+void tst_QShaderNodes::shouldVerifyFormatsEquality_data()
+{
+ QTest::addColumn<QShaderFormat>("left");
+ QTest::addColumn<QShaderFormat>("right");
+ QTest::addColumn<bool>("expected");
+
+ QTest::newRow("Equals") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB")
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB")
+ << true;
+ QTest::newRow("Apis") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB")
+ << createFormat(QShaderFormat::OpenGLNoProfile, 3, 0, {"foo", "bar"}, "KDAB")
+ << false;
+ QTest::newRow("Major") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB")
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0, {"foo", "bar"}, "KDAB")
+ << false;
+ QTest::newRow("Minor") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB")
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 1, {"foo", "bar"}, "KDAB")
+ << false;
+ QTest::newRow("Extensions") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB")
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo"}, "KDAB")
+ << false;
+ QTest::newRow("Vendor") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"}, "KDAB")
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"})
+ << false;
+}
+
+void tst_QShaderNodes::shouldVerifyFormatsEquality()
+{
+ // GIVEN
+ QFETCH(QShaderFormat, left);
+ QFETCH(QShaderFormat, right);
+
+ // WHEN
+ const auto equal = (left == right);
+ const auto notEqual = (left != right);
+
+ // THEN
+ QFETCH(bool, expected);
+ QCOMPARE(equal, expected);
+ QCOMPARE(notEqual, !expected);
+}
+
+void tst_QShaderNodes::shouldVerifyFormatsCompatibilities_data()
+{
+ QTest::addColumn<QShaderFormat>("reference");
+ QTest::addColumn<QShaderFormat>("tested");
+ QTest::addColumn<bool>("expected");
+
+ QTest::newRow("NoProfileVsES") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLES, 2, 0)
+ << true;
+ QTest::newRow("CoreProfileVsES") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLES, 2, 0)
+ << false;
+ QTest::newRow("CompatProfileVsES") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLES, 2, 0)
+ << true;
+
+ QTest::newRow("ESVsNoProfile") << createFormat(QShaderFormat::OpenGLES, 2, 0)
+ << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0)
+ << false;
+ QTest::newRow("ESVsCoreProfile") << createFormat(QShaderFormat::OpenGLES, 2, 0)
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0)
+ << false;
+ QTest::newRow("ESVsCompatProfile") << createFormat(QShaderFormat::OpenGLES, 2, 0)
+ << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0)
+ << false;
+
+ QTest::newRow("CoreVsNoProfile") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0)
+ << false;
+ QTest::newRow("CoreVsCompat") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0)
+ << false;
+ QTest::newRow("CoreVsCore") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0)
+ << true;
+
+ QTest::newRow("NoProfileVsCore") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0)
+ << true;
+ QTest::newRow("NoProvileVsCompat") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0)
+ << true;
+ QTest::newRow("NoProfileVsNoProfile") << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0)
+ << true;
+
+ QTest::newRow("CompatVsCore") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0)
+ << true;
+ QTest::newRow("CompatVsCompat") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0)
+ << true;
+ QTest::newRow("CompatVsNoProfile") << createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLNoProfile, 2, 0)
+ << true;
+
+ QTest::newRow("MajorForwardCompat_1") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0)
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0)
+ << true;
+ QTest::newRow("MajorForwardCompat_2") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0)
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 4)
+ << true;
+ QTest::newRow("MajorForwardCompat_3") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 0)
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0)
+ << false;
+ QTest::newRow("MajorForwardCompat_4") << createFormat(QShaderFormat::OpenGLCoreProfile, 2, 4)
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0)
+ << false;
+
+ QTest::newRow("MinorForwardCompat_1") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 1)
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0)
+ << true;
+ QTest::newRow("MinorForwardCompat_2") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0)
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 1)
+ << false;
+
+ QTest::newRow("Extensions_1") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"})
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo"})
+ << true;
+ QTest::newRow("Extensions_2") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo"})
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {"foo", "bar"})
+ << false;
+
+ QTest::newRow("Vendor_1") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {}, "KDAB")
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {})
+ << true;
+ QTest::newRow("Vendor_2") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {})
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {}, "KDAB")
+ << false;
+ QTest::newRow("Vendor_2") << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {}, "KDAB")
+ << createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0, {}, "KDAB")
+ << true;
+}
+
+void tst_QShaderNodes::shouldVerifyFormatsCompatibilities()
+{
+ // GIVEN
+ QFETCH(QShaderFormat, reference);
+ QFETCH(QShaderFormat, tested);
+
+ // WHEN
+ const auto supported = reference.supports(tested);
+
+ // THEN
+ QFETCH(bool, expected);
+ QCOMPARE(supported, expected);
+}
+
+void tst_QShaderNodes::shouldHaveDefaultPortState()
+{
+ // GIVEN
+ auto port = QShaderNodePort();
+
+ // THEN
+ QCOMPARE(port.direction, QShaderNodePort::Output);
+ QVERIFY(port.name.isEmpty());
+}
+
+void tst_QShaderNodes::shouldVerifyPortsEquality_data()
+{
+ QTest::addColumn<QShaderNodePort>("left");
+ QTest::addColumn<QShaderNodePort>("right");
+ QTest::addColumn<bool>("expected");
+
+ QTest::newRow("Equals") << createPort(QShaderNodePort::Input, "foo")
+ << createPort(QShaderNodePort::Input, "foo")
+ << true;
+ QTest::newRow("Direction") << createPort(QShaderNodePort::Input, "foo")
+ << createPort(QShaderNodePort::Output, "foo")
+ << false;
+ QTest::newRow("Name") << createPort(QShaderNodePort::Input, "foo")
+ << createPort(QShaderNodePort::Input, "bar")
+ << false;
+}
+
+void tst_QShaderNodes::shouldVerifyPortsEquality()
+{
+ // GIVEN
+ QFETCH(QShaderNodePort, left);
+ QFETCH(QShaderNodePort, right);
+
+ // WHEN
+ const auto equal = (left == right);
+ const auto notEqual = (left != right);
+
+ // THEN
+ QFETCH(bool, expected);
+ QCOMPARE(equal, expected);
+ QCOMPARE(notEqual, !expected);
+}
+
+void tst_QShaderNodes::shouldManipulateNodeMembers()
+{
+ // GIVEN
+ const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
+ const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
+
+ const auto es2Rule = QShaderNode::Rule(QByteArrayLiteral("gles2"), {"#pragma include es2/foo.inc", "#pragma include es2/bar.inc"});
+ const auto gl3Rule = QShaderNode::Rule(QByteArrayLiteral("gl3"), {"#pragma include gl3/foo.inc", "#pragma include gl3/bar.inc"});
+ const auto gl3bisRule = QShaderNode::Rule(QByteArrayLiteral("gl3bis"), {"#pragma include gl3/foo.inc", "#pragma include gl3/bar.inc"});
+
+ auto node = QShaderNode();
+
+ // THEN (default state)
+ QCOMPARE(node.type(), QShaderNode::Invalid);
+ QVERIFY(node.uuid().isNull());
+ QVERIFY(node.layers().isEmpty());
+ QVERIFY(node.ports().isEmpty());
+ QVERIFY(node.parameterNames().isEmpty());
+ QVERIFY(node.availableFormats().isEmpty());
+
+ // WHEN
+ const auto uuid = QUuid::createUuid();
+ node.setUuid(uuid);
+
+ // THEN
+ QCOMPARE(node.uuid(), uuid);
+
+ // WHEN
+ node.setLayers({"foo", "bar"});
+
+ // THEN
+ QCOMPARE(node.layers(), QStringList({"foo", "bar"}));
+
+ // WHEN
+ auto firstPort = QShaderNodePort();
+ firstPort.direction = QShaderNodePort::Input;
+ firstPort.name = QStringLiteral("foo");
+ node.addPort(firstPort);
+
+ // THEN
+ QCOMPARE(node.type(), QShaderNode::Output);
+ QCOMPARE(node.ports().size(), 1);
+ QCOMPARE(node.ports().at(0), firstPort);
+ QVERIFY(node.availableFormats().isEmpty());
+
+ // WHEN
+ auto secondPort = QShaderNodePort();
+ secondPort.direction = QShaderNodePort::Output;
+ secondPort.name = QStringLiteral("bar");
+ node.addPort(secondPort);
+
+ // THEN
+ QCOMPARE(node.type(), QShaderNode::Function);
+ QCOMPARE(node.ports().size(), 2);
+ QCOMPARE(node.ports().at(0), firstPort);
+ QCOMPARE(node.ports().at(1), secondPort);
+ QVERIFY(node.availableFormats().isEmpty());
+
+ // WHEN
+ node.removePort(firstPort);
+
+ // THEN
+ QCOMPARE(node.type(), QShaderNode::Input);
+ QCOMPARE(node.ports().size(), 1);
+ QCOMPARE(node.ports().at(0), secondPort);
+ QVERIFY(node.availableFormats().isEmpty());
+
+ // WHEN
+ node.setParameter(QStringLiteral("baz"), 42);
+
+ // THEN
+ QCOMPARE(node.type(), QShaderNode::Input);
+ QCOMPARE(node.ports().size(), 1);
+ QCOMPARE(node.ports().at(0), secondPort);
+ auto parameterNames = node.parameterNames();
+ parameterNames.sort();
+ QCOMPARE(parameterNames.size(), 1);
+ QCOMPARE(parameterNames.at(0), QStringLiteral("baz"));
+ QCOMPARE(node.parameter(QStringLiteral("baz")), QVariant(42));
+ QVERIFY(node.availableFormats().isEmpty());
+
+ // WHEN
+ node.setParameter(QStringLiteral("bleh"), QStringLiteral("value"));
+
+ // THEN
+ QCOMPARE(node.type(), QShaderNode::Input);
+ QCOMPARE(node.ports().size(), 1);
+ QCOMPARE(node.ports().at(0), secondPort);
+ parameterNames = node.parameterNames();
+ parameterNames.sort();
+ QCOMPARE(parameterNames.size(), 2);
+ QCOMPARE(parameterNames.at(0), QStringLiteral("baz"));
+ QCOMPARE(parameterNames.at(1), QStringLiteral("bleh"));
+ QCOMPARE(node.parameter(QStringLiteral("baz")), QVariant(42));
+ QCOMPARE(node.parameter(QStringLiteral("bleh")), QVariant(QStringLiteral("value")));
+ QVERIFY(node.availableFormats().isEmpty());
+
+ // WHEN
+ node.clearParameter(QStringLiteral("baz"));
+
+ // THEN
+ QCOMPARE(node.type(), QShaderNode::Input);
+ QCOMPARE(node.ports().size(), 1);
+ QCOMPARE(node.ports().at(0), secondPort);
+ parameterNames = node.parameterNames();
+ parameterNames.sort();
+ QCOMPARE(parameterNames.size(), 1);
+ QCOMPARE(parameterNames.at(0), QStringLiteral("bleh"));
+ QCOMPARE(node.parameter(QStringLiteral("baz")), QVariant());
+ QCOMPARE(node.parameter(QStringLiteral("bleh")), QVariant(QStringLiteral("value")));
+ QVERIFY(node.availableFormats().isEmpty());
+
+ // WHEN
+ node.addRule(openGLES2, es2Rule);
+ node.addRule(openGL3, gl3Rule);
+
+ // THEN
+ QCOMPARE(node.availableFormats().size(), 2);
+ QCOMPARE(node.availableFormats().at(0), openGLES2);
+ QCOMPARE(node.availableFormats().at(1), openGL3);
+ QCOMPARE(node.rule(openGLES2), es2Rule);
+ QCOMPARE(node.rule(openGL3), gl3Rule);
+
+ // WHEN
+ node.removeRule(openGLES2);
+
+ // THEN
+ QCOMPARE(node.availableFormats().size(), 1);
+ QCOMPARE(node.availableFormats().at(0), openGL3);
+ QCOMPARE(node.rule(openGL3), gl3Rule);
+
+ // WHEN
+ node.addRule(openGLES2, es2Rule);
+
+ // THEN
+ QCOMPARE(node.availableFormats().size(), 2);
+ QCOMPARE(node.availableFormats().at(0), openGL3);
+ QCOMPARE(node.availableFormats().at(1), openGLES2);
+ QCOMPARE(node.rule(openGLES2), es2Rule);
+ QCOMPARE(node.rule(openGL3), gl3Rule);
+
+ // WHEN
+ node.addRule(openGL3, gl3bisRule);
+
+ // THEN
+ QCOMPARE(node.availableFormats().size(), 2);
+ QCOMPARE(node.availableFormats().at(0), openGLES2);
+ QCOMPARE(node.availableFormats().at(1), openGL3);
+ QCOMPARE(node.rule(openGLES2), es2Rule);
+ QCOMPARE(node.rule(openGL3), gl3bisRule);
+}
+
+void tst_QShaderNodes::shouldHandleNodeRulesSupportAndOrder()
+{
+ // GIVEN
+ const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
+ const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 0);
+ const auto openGL32 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 2);
+ const auto openGL4 = createFormat(QShaderFormat::OpenGLCoreProfile, 4, 0);
+
+ const auto es2Rule = QShaderNode::Rule(QByteArrayLiteral("gles2"), {"#pragma include es2/foo.inc", "#pragma include es2/bar.inc"});
+ const auto gl3Rule = QShaderNode::Rule(QByteArrayLiteral("gl3"), {"#pragma include gl3/foo.inc", "#pragma include gl3/bar.inc"});
+ const auto gl32Rule = QShaderNode::Rule(QByteArrayLiteral("gl32"), {"#pragma include gl32/foo.inc", "#pragma include gl32/bar.inc"});
+ const auto gl3bisRule = QShaderNode::Rule(QByteArrayLiteral("gl3bis"), {"#pragma include gl3/foo.inc", "#pragma include gl3/bar.inc"});
+
+ auto node = QShaderNode();
+
+ // WHEN
+ node.addRule(openGLES2, es2Rule);
+ node.addRule(openGL3, gl3Rule);
+
+ // THEN
+ QCOMPARE(node.availableFormats().size(), 2);
+ QCOMPARE(node.availableFormats().at(0), openGLES2);
+ QCOMPARE(node.availableFormats().at(1), openGL3);
+ QCOMPARE(node.rule(openGLES2), es2Rule);
+ QCOMPARE(node.rule(openGL3), gl3Rule);
+ QCOMPARE(node.rule(openGL32), gl3Rule);
+ QCOMPARE(node.rule(openGL4), gl3Rule);
+
+ // WHEN
+ node.addRule(openGL32, gl32Rule);
+
+ // THEN
+ QCOMPARE(node.availableFormats().size(), 3);
+ QCOMPARE(node.availableFormats().at(0), openGLES2);
+ QCOMPARE(node.availableFormats().at(1), openGL3);
+ QCOMPARE(node.availableFormats().at(2), openGL32);
+ QCOMPARE(node.rule(openGLES2), es2Rule);
+ QCOMPARE(node.rule(openGL3), gl3Rule);
+ QCOMPARE(node.rule(openGL32), gl32Rule);
+ QCOMPARE(node.rule(openGL4), gl32Rule);
+
+ // WHEN
+ node.addRule(openGL3, gl3bisRule);
+
+ // THEN
+ QCOMPARE(node.availableFormats().size(), 3);
+ QCOMPARE(node.availableFormats().at(0), openGLES2);
+ QCOMPARE(node.availableFormats().at(1), openGL32);
+ QCOMPARE(node.availableFormats().at(2), openGL3);
+ QCOMPARE(node.rule(openGLES2), es2Rule);
+ QCOMPARE(node.rule(openGL3), gl3bisRule);
+ QCOMPARE(node.rule(openGL32), gl3bisRule);
+ QCOMPARE(node.rule(openGL4), gl3bisRule);
+}
+
+QTEST_MAIN(tst_QShaderNodes)
+
+#include "tst_qshadernodes.moc"
diff --git a/tests/auto/gui/util/qshadernodesloader/qshadernodesloader.pro b/tests/auto/gui/util/qshadernodesloader/qshadernodesloader.pro
new file mode 100644
index 0000000000..b9c26a2942
--- /dev/null
+++ b/tests/auto/gui/util/qshadernodesloader/qshadernodesloader.pro
@@ -0,0 +1,5 @@
+CONFIG += testcase
+QT += testlib gui-private
+
+SOURCES += tst_qshadernodesloader.cpp
+TARGET = tst_qshadernodesloader
diff --git a/tests/auto/gui/util/qshadernodesloader/tst_qshadernodesloader.cpp b/tests/auto/gui/util/qshadernodesloader/tst_qshadernodesloader.cpp
new file mode 100644
index 0000000000..4782e40ed8
--- /dev/null
+++ b/tests/auto/gui/util/qshadernodesloader/tst_qshadernodesloader.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+
+#include <QtCore/qbuffer.h>
+
+#include <QtGui/private/qshadernodesloader_p.h>
+#include <QtGui/private/qshaderlanguage_p.h>
+
+using QBufferPointer = QSharedPointer<QBuffer>;
+Q_DECLARE_METATYPE(QBufferPointer);
+
+using NodeHash = QHash<QString, QShaderNode>;
+Q_DECLARE_METATYPE(NodeHash);
+
+namespace
+{
+ QBufferPointer createBuffer(const QByteArray &data, QIODevice::OpenMode openMode = QIODevice::ReadOnly)
+ {
+ auto buffer = QBufferPointer::create();
+ buffer->setData(data);
+ if (openMode != QIODevice::NotOpen)
+ buffer->open(openMode);
+ return buffer;
+ }
+
+ QShaderFormat createFormat(QShaderFormat::Api api, int majorVersion, int minorVersion,
+ const QStringList &extensions = QStringList(),
+ const QString &vendor = QString())
+ {
+ auto format = QShaderFormat();
+ format.setApi(api);
+ format.setVersion(QVersionNumber(majorVersion, minorVersion));
+ format.setExtensions(extensions);
+ format.setVendor(vendor);
+ return format;
+ }
+
+ QShaderNodePort createPort(QShaderNodePort::Direction portDirection, const QString &portName)
+ {
+ auto port = QShaderNodePort();
+ port.direction = portDirection;
+ port.name = portName;
+ return port;
+ }
+
+ QShaderNode createNode(const QVector<QShaderNodePort> &ports)
+ {
+ auto node = QShaderNode();
+ for (const auto &port : ports)
+ node.addPort(port);
+ return node;
+ }
+}
+
+class tst_QShaderNodesLoader : public QObject
+{
+ Q_OBJECT
+private slots:
+ void shouldManipulateLoaderMembers();
+ void shouldLoadFromJsonStream_data();
+ void shouldLoadFromJsonStream();
+};
+
+void tst_QShaderNodesLoader::shouldManipulateLoaderMembers()
+{
+ // GIVEN
+ auto loader = QShaderNodesLoader();
+
+ // THEN (default state)
+ QCOMPARE(loader.status(), QShaderNodesLoader::Null);
+ QVERIFY(!loader.device());
+ QVERIFY(loader.nodes().isEmpty());
+
+ // WHEN
+ auto device1 = createBuffer(QByteArray("..........."), QIODevice::NotOpen);
+ loader.setDevice(device1.data());
+
+ // THEN
+ QCOMPARE(loader.status(), QShaderNodesLoader::Error);
+ QCOMPARE(loader.device(), device1.data());
+ QVERIFY(loader.nodes().isEmpty());
+
+ // WHEN
+ auto device2 = createBuffer(QByteArray("..........."), QIODevice::ReadOnly);
+ loader.setDevice(device2.data());
+
+ // THEN
+ QCOMPARE(loader.status(), QShaderNodesLoader::Waiting);
+ QCOMPARE(loader.device(), device2.data());
+ QVERIFY(loader.nodes().isEmpty());
+}
+
+void tst_QShaderNodesLoader::shouldLoadFromJsonStream_data()
+{
+ QTest::addColumn<QBufferPointer>("device");
+ QTest::addColumn<NodeHash>("nodes");
+ QTest::addColumn<QShaderNodesLoader::Status>("status");
+
+ QTest::newRow("empty") << createBuffer("", QIODevice::ReadOnly) << NodeHash() << QShaderNodesLoader::Error;
+
+ const auto smallJson = "{"
+ " \"inputValue\": {"
+ " \"outputs\": ["
+ " \"value\""
+ " ],"
+ " \"parameters\": {"
+ " \"name\": \"defaultName\","
+ " \"qualifier\": {"
+ " \"type\": \"QShaderLanguage::StorageQualifier\","
+ " \"value\": \"QShaderLanguage::Uniform\""
+ " },"
+ " \"type\": {"
+ " \"type\": \"QShaderLanguage::VariableType\","
+ " \"value\": \"QShaderLanguage::Vec3\""
+ " },"
+ " \"defaultValue\": {"
+ " \"type\": \"float\","
+ " \"value\": \"1.25\""
+ " }"
+ " },"
+ " \"rules\": ["
+ " {"
+ " \"format\": {"
+ " \"api\": \"OpenGLES\","
+ " \"major\": 2,"
+ " \"minor\": 0"
+ " },"
+ " \"substitution\": \"highp vec3 $value = $name;\","
+ " \"headerSnippets\": [ \"varying highp vec3 $name;\" ]"
+ " },"
+ " {"
+ " \"format\": {"
+ " \"api\": \"OpenGLCompatibilityProfile\","
+ " \"major\": 2,"
+ " \"minor\": 1"
+ " },"
+ " \"substitution\": \"vec3 $value = $name;\","
+ " \"headerSnippets\": [ \"in vec3 $name;\" ]"
+ " }"
+ " ]"
+ " },"
+ " \"fragColor\": {"
+ " \"inputs\": ["
+ " \"fragColor\""
+ " ],"
+ " \"rules\": ["
+ " {"
+ " \"format\": {"
+ " \"api\": \"OpenGLES\","
+ " \"major\": 2,"
+ " \"minor\": 0"
+ " },"
+ " \"substitution\": \"gl_fragColor = $fragColor;\""
+ " },"
+ " {"
+ " \"format\": {"
+ " \"api\": \"OpenGLNoProfile\","
+ " \"major\": 4,"
+ " \"minor\": 0"
+ " },"
+ " \"substitution\": \"fragColor = $fragColor;\","
+ " \"headerSnippets\": [ \"out vec4 fragColor;\" ]"
+ " }"
+ " ]"
+ " },"
+ " \"lightModel\": {"
+ " \"inputs\": ["
+ " \"baseColor\","
+ " \"position\","
+ " \"lightIntensity\""
+ " ],"
+ " \"outputs\": ["
+ " \"outputColor\""
+ " ],"
+ " \"rules\": ["
+ " {"
+ " \"format\": {"
+ " \"api\": \"OpenGLES\","
+ " \"major\": 2,"
+ " \"minor\": 0,"
+ " \"extensions\": [ \"ext1\", \"ext2\" ],"
+ " \"vendor\": \"kdab\""
+ " },"
+ " \"substitution\": \"highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);\","
+ " \"headerSnippets\": [ \"#pragma include es2/lightmodel.frag.inc\" ]"
+ " },"
+ " {"
+ " \"format\": {"
+ " \"api\": \"OpenGLCoreProfile\","
+ " \"major\": 3,"
+ " \"minor\": 3"
+ " },"
+ " \"substitution\": \"vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);\","
+ " \"headerSnippets\": [ \"#pragma include gl3/lightmodel.frag.inc\" ]"
+ " }"
+ " ]"
+ " }"
+ "}";
+
+ const auto smallProtos = [this]{
+ const auto openGLES2 = createFormat(QShaderFormat::OpenGLES, 2, 0);
+ const auto openGLES2Extended = createFormat(QShaderFormat::OpenGLES, 2, 0, {"ext1", "ext2"}, "kdab");
+ const auto openGL2 = createFormat(QShaderFormat::OpenGLCompatibilityProfile, 2, 1);
+ const auto openGL3 = createFormat(QShaderFormat::OpenGLCoreProfile, 3, 3);
+ const auto openGL4 = createFormat(QShaderFormat::OpenGLNoProfile, 4, 0);
+
+ auto protos = NodeHash();
+
+ auto inputValue = createNode({
+ createPort(QShaderNodePort::Output, "value")
+ });
+ inputValue.setParameter("name", "defaultName");
+ inputValue.setParameter("qualifier", QVariant::fromValue<QShaderLanguage::StorageQualifier>(QShaderLanguage::Uniform));
+ inputValue.setParameter("type", QVariant::fromValue<QShaderLanguage::VariableType>(QShaderLanguage::Vec3));
+ inputValue.setParameter("defaultValue", QVariant(1.25f));
+ inputValue.addRule(openGLES2, QShaderNode::Rule("highp vec3 $value = $name;",
+ QByteArrayList() << "varying highp vec3 $name;"));
+ inputValue.addRule(openGL2, QShaderNode::Rule("vec3 $value = $name;",
+ QByteArrayList() << "in vec3 $name;"));
+ protos.insert("inputValue", inputValue);
+
+ auto fragColor = createNode({
+ createPort(QShaderNodePort::Input, "fragColor")
+ });
+ fragColor.addRule(openGLES2, QShaderNode::Rule("gl_fragColor = $fragColor;"));
+ fragColor.addRule(openGL4, QShaderNode::Rule("fragColor = $fragColor;",
+ QByteArrayList() << "out vec4 fragColor;"));
+ protos.insert(QStringLiteral("fragColor"), fragColor);
+
+ auto lightModel = createNode({
+ createPort(QShaderNodePort::Input, "baseColor"),
+ createPort(QShaderNodePort::Input, "position"),
+ createPort(QShaderNodePort::Input, "lightIntensity"),
+ createPort(QShaderNodePort::Output, "outputColor")
+ });
+ lightModel.addRule(openGLES2Extended, QShaderNode::Rule("highp vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);",
+ QByteArrayList() << "#pragma include es2/lightmodel.frag.inc"));
+ lightModel.addRule(openGL3, QShaderNode::Rule("vec4 $outputColor = lightModel($baseColor, $position, $lightIntensity);",
+ QByteArrayList() << "#pragma include gl3/lightmodel.frag.inc"));
+ protos.insert("lightModel", lightModel);
+
+ return protos;
+ }();
+
+ QTest::newRow("NotOpen") << createBuffer(smallJson, QIODevice::NotOpen) << NodeHash() << QShaderNodesLoader::Error;
+ QTest::newRow("CorrectJSON") << createBuffer(smallJson) << smallProtos << QShaderNodesLoader::Ready;
+}
+
+void tst_QShaderNodesLoader::shouldLoadFromJsonStream()
+{
+ // GIVEN
+ QFETCH(QBufferPointer, device);
+
+ auto loader = QShaderNodesLoader();
+
+ // WHEN
+ loader.setDevice(device.data());
+ loader.load();
+
+ // THEN
+ QFETCH(QShaderNodesLoader::Status, status);
+ QCOMPARE(loader.status(), status);
+
+ QFETCH(NodeHash, nodes);
+ const auto sortedKeys = [](const NodeHash &nodes) {
+ auto res = nodes.keys();
+ res.sort();
+ return res;
+ };
+ const auto sortedParameters = [](const QShaderNode &node) {
+ auto res = node.parameterNames();
+ res.sort();
+ return res;
+ };
+ QCOMPARE(sortedKeys(loader.nodes()), sortedKeys(nodes));
+ for (const auto &key : nodes.keys()) {
+ const auto actual = loader.nodes().value(key);
+ const auto expected = nodes.value(key);
+
+ QVERIFY(actual.uuid().isNull());
+ QCOMPARE(actual.ports(), expected.ports());
+ QCOMPARE(sortedParameters(actual), sortedParameters(expected));
+ for (const auto &name : expected.parameterNames()) {
+ QCOMPARE(actual.parameter(name), expected.parameter(name));
+ }
+ QCOMPARE(actual.availableFormats(), expected.availableFormats());
+ for (const auto &format : expected.availableFormats()) {
+ QCOMPARE(actual.rule(format), expected.rule(format));
+ }
+ }
+}
+
+QTEST_MAIN(tst_QShaderNodesLoader)
+
+#include "tst_qshadernodesloader.moc"
diff --git a/tests/auto/gui/util/util.pro b/tests/auto/gui/util/util.pro
index f2c4515dc2..940e892e5f 100644
--- a/tests/auto/gui/util/util.pro
+++ b/tests/auto/gui/util/util.pro
@@ -5,4 +5,9 @@ SUBDIRS= \
qintvalidator \
qregexpvalidator \
qregularexpressionvalidator \
+ qshadergenerator \
+ qshadergraph \
+ qshadergraphloader \
+ qshadernodes \
+ qshadernodesloader \
diff --git a/tests/auto/network/access/hsts/tst_qhsts.cpp b/tests/auto/network/access/hsts/tst_qhsts.cpp
index 656516f46b..d72991a2eb 100644
--- a/tests/auto/network/access/hsts/tst_qhsts.cpp
+++ b/tests/auto/network/access/hsts/tst_qhsts.cpp
@@ -32,7 +32,9 @@
#include <QtCore/qvector.h>
#include <QtCore/qpair.h>
#include <QtCore/qurl.h>
+#include <QtCore/qdir.h>
+#include <QtNetwork/private/qhstsstore_p.h>
#include <QtNetwork/private/qhsts_p.h>
QT_USE_NAMESPACE
@@ -46,6 +48,7 @@ private Q_SLOTS:
void testMultilpeKnownHosts();
void testPolicyExpiration();
void testSTSHeaderParser();
+ void testStore();
};
void tst_QHsts::testSingleKnownHost_data()
@@ -313,6 +316,75 @@ void tst_QHsts::testSTSHeaderParser()
QVERIFY(!parser.expirationDate().isValid());
}
+const QLatin1String storeDir(".");
+
+struct TestStoreDeleter
+{
+ ~TestStoreDeleter()
+ {
+ QDir cwd;
+ if (!cwd.remove(QHstsStore::absoluteFilePath(storeDir)))
+ qWarning() << "tst_QHsts::testStore: failed to remove the hsts store file";
+ }
+};
+
+void tst_QHsts::testStore()
+{
+ // Delete the store's file after we finish the test.
+ TestStoreDeleter cleaner;
+
+ const QUrl exampleCom(QStringLiteral("http://example.com"));
+ const QUrl subDomain(QStringLiteral("http://subdomain.example.com"));
+ const QDateTime validDate(QDateTime::currentDateTimeUtc().addDays(1));
+
+ {
+ // We start from an empty cache and empty store:
+ QHstsCache cache;
+ QHstsStore store(storeDir);
+ cache.setStore(&store);
+ QVERIFY(!cache.isKnownHost(exampleCom));
+ QVERIFY(!cache.isKnownHost(subDomain));
+ // (1) This will also store the policy:
+ cache.updateKnownHost(exampleCom, validDate, true);
+ QVERIFY(cache.isKnownHost(exampleCom));
+ QVERIFY(cache.isKnownHost(subDomain));
+ }
+ {
+ // Test the policy stored at (1):
+ QHstsCache cache;
+ QHstsStore store(storeDir);
+ cache.setStore(&store);
+ QVERIFY(cache.isKnownHost(exampleCom));
+ QVERIFY(cache.isKnownHost(subDomain));
+ // (2) Remove subdomains:
+ cache.updateKnownHost(exampleCom, validDate, false);
+ QVERIFY(!cache.isKnownHost(subDomain));
+ }
+ {
+ // Test the previous update (2):
+ QHstsCache cache;
+ QHstsStore store(storeDir);
+ cache.setStore(&store);
+ QVERIFY(cache.isKnownHost(exampleCom));
+ QVERIFY(!cache.isKnownHost(subDomain));
+ }
+ {
+ QHstsCache cache;
+ cache.updateKnownHost(subDomain, validDate, false);
+ QVERIFY(cache.isKnownHost(subDomain));
+ QHstsStore store(storeDir);
+ // (3) This should store policy from cache, over old policy from store:
+ cache.setStore(&store);
+ }
+ {
+ // Test that (3) was stored:
+ QHstsCache cache;
+ QHstsStore store(storeDir);
+ cache.setStore(&store);
+ QVERIFY(cache.isKnownHost(subDomain));
+ }
+}
+
QTEST_MAIN(tst_QHsts)
#include "tst_qhsts.moc"
diff --git a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
index 2671c253cb..cb7e66bad4 100644
--- a/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
+++ b/tests/auto/network/kernel/qhostinfo/tst_qhostinfo.cpp
@@ -86,6 +86,8 @@ class tst_QHostInfo : public QObject
private slots:
void init();
void initTestCase();
+ void swapFunction();
+ void moveOperator();
void getSetCheck();
void staticInformation();
void lookupIPv4_data();
@@ -129,6 +131,29 @@ private:
#endif
};
+void tst_QHostInfo::swapFunction()
+{
+ QHostInfo obj1, obj2;
+ obj1.setError(QHostInfo::HostInfoError(0));
+ obj2.setError(QHostInfo::HostInfoError(1));
+ obj1.swap(obj2);
+ QCOMPARE(QHostInfo::HostInfoError(0), obj2.error());
+ QCOMPARE(QHostInfo::HostInfoError(1), obj1.error());
+}
+
+void tst_QHostInfo::moveOperator()
+{
+ QHostInfo obj1, obj2, obj3(1);
+ obj1.setError(QHostInfo::HostInfoError(0));
+ obj2.setError(QHostInfo::HostInfoError(1));
+ obj1 = std::move(obj2);
+ obj2 = obj3;
+ QCOMPARE(QHostInfo::HostInfoError(1), obj1.error());
+ QCOMPARE(obj3.lookupId(), obj2.lookupId());
+}
+
+
+
// Testing get/set functions
void tst_QHostInfo::getSetCheck()
{
diff --git a/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp b/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp
index 4f947a5738..81d598641b 100644
--- a/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp
+++ b/tests/auto/network/kernel/qnetworkproxyfactory/tst_qnetworkproxyfactory.cpp
@@ -34,10 +34,8 @@
#include <qdebug.h>
#include <qnetworkproxy.h>
-#include <QNetworkConfiguration>
-#include <QNetworkConfigurationManager>
-#include <QNetworkSession>
#include <QNetworkAccessManager>
+#include <QNetworkInterface>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QList>
@@ -69,11 +67,6 @@ private slots:
void systemProxyForQuery_data();
void systemProxyForQuery() const;
void systemProxyForQuery_local();
-#ifndef QT_NO_BEARERMANAGEMENT
- void fromConfigurations();
- void inNetworkAccessManager_data();
- void inNetworkAccessManager();
-#endif
void genericSystemProxy();
void genericSystemProxy_data();
@@ -251,111 +244,6 @@ void tst_QNetworkProxyFactory::systemProxyForQuery_local()
QVERIFY(list.isEmpty() || (list[0].type() == QNetworkProxy::NoProxy));
}
-#ifndef QT_NO_BEARERMANAGEMENT
-
-//Purpose of this test is just to check systemProxyForQuery doesn't hang or crash
-//with any given configuration including no configuration.
-//We can't test it returns the right proxies without implementing the native proxy code
-//again here, which would be testing our implementation against itself.
-//Therefore it's just testing that something valid is returned (at least a NoProxy entry)
-void tst_QNetworkProxyFactory::fromConfigurations()
-{
- QNetworkConfigurationManager manager;
- QList<QNetworkProxy> proxies;
- QUrl url(QLatin1String("http://qt-project.org"));
- //get from known configurations
- foreach (QNetworkConfiguration config, manager.allConfigurations()) {
- QNetworkProxyQuery query(config, url, QNetworkProxyQuery::UrlRequest);
- proxies = QNetworkProxyFactory::systemProxyForQuery(query);
- QVERIFY(!proxies.isEmpty());
- foreach (QNetworkProxy proxy, proxies) {
- qDebug() << config.name() << " - " << config.identifier() << " - " << formatProxyName(proxy);
- }
- }
-
- //get from default configuration
- QNetworkProxyQuery defaultquery(url, QNetworkProxyQuery::UrlRequest);
- proxies = QNetworkProxyFactory::systemProxyForQuery(defaultquery);
- QVERIFY(!proxies.isEmpty());
- foreach (QNetworkProxy proxy, proxies) {
- qDebug() << "default - " << formatProxyName(proxy);
- }
-
- //get from active configuration
- QNetworkSession session(manager.defaultConfiguration());
- session.open();
- QVERIFY(session.waitForOpened(30000));
- proxies = QNetworkProxyFactory::systemProxyForQuery(defaultquery);
- QVERIFY(!proxies.isEmpty());
- foreach (QNetworkProxy proxy, proxies) {
- qDebug() << "active - " << formatProxyName(proxy);
- }
-
- //get from known configurations while there is one active
- foreach (QNetworkConfiguration config, manager.allConfigurations()) {
- QNetworkProxyQuery query(config, url, QNetworkProxyQuery::UrlRequest);
- proxies = QNetworkProxyFactory::systemProxyForQuery(query);
- QVERIFY(!proxies.isEmpty());
- foreach (QNetworkProxy proxy, proxies) {
- qDebug() << config.name() << " - " << config.identifier() << " - " << formatProxyName(proxy);
- }
- }
-}
-
-void tst_QNetworkProxyFactory::inNetworkAccessManager_data()
-{
- QTest::addColumn<QNetworkConfiguration>("config");
- QTest::addColumn<QList<QNetworkProxy> >("proxies");
- QNetworkConfigurationManager manager;
- //get from known configurations
- foreach (QNetworkConfiguration config, manager.allConfigurations()) {
- QNetworkProxyQuery query(config, QUrl(QString("http://qt-project.org")), QNetworkProxyQuery::UrlRequest);
- QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery(query);
- QTest::newRow(config.name().toUtf8()) << config << proxies;
- }
-}
-
-//Purpose of this test is to check that QNetworkAccessManager uses the proxy from the configuration it
-//has been given. Needs two or more working configurations to be a good test.
-void tst_QNetworkProxyFactory::inNetworkAccessManager()
-{
- QFETCH(QNetworkConfiguration, config);
- QFETCH(QList<QNetworkProxy>, proxies);
-
- int count = QDebugProxyFactory::requestCounter;
-
- QNetworkAccessManager manager;
- manager.setConfiguration(config);
-
- //using an internet server, because cellular APs won't have a route to the test server.
- QNetworkRequest req(QUrl(QString("http://qt-project.org")));
- QNetworkReply *reply = manager.get(req);
- connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
- QTestEventLoop::instance().enterLoop(30);
- delete reply;
-
- if (count == QDebugProxyFactory::requestCounter) {
- //RND phones are preconfigured with several test access points which won't work without a matching SIM
- //If the network fails to start, QNAM won't ask the factory for proxies so we can't test.
- QSKIP("network configuration didn't start");
- }
- QVERIFY(factory);
-
- qDebug() << "testing network configuration for" << config.name();
- foreach (QNetworkProxy proxy, factory->returnedList) {
- qDebug() << formatProxyName(proxy);
- }
- qDebug() << " <vs> ";
- foreach (QNetworkProxy proxy, proxies) {
- qDebug() << formatProxyName(proxy);
- }
- if (config.type() != QNetworkConfiguration::InternetAccessPoint)
- QEXPECT_FAIL("","QNetworkProxyFactory::systemProxyForQuery doesn't work for service networks yet", Continue);
- QCOMPARE(factory->returnedList, proxies);
-}
-
-#endif //QT_NO_BEARERMANAGEMENT
-
Q_DECLARE_METATYPE(QNetworkProxy::ProxyType)
void tst_QNetworkProxyFactory::genericSystemProxy()
diff --git a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
index 60ee4eb471..7760138067 100644
--- a/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
+++ b/tests/auto/network/socket/qlocalsocket/tst_qlocalsocket.cpp
@@ -306,9 +306,11 @@ void tst_QLocalSocket::listen()
// already isListening
QTest::ignoreMessage(QtWarningMsg, "QLocalServer::listen() called when already listening");
QVERIFY(!server.listen(name));
+ QVERIFY(server.socketDescriptor() != -1);
} else {
QVERIFY(!server.errorString().isEmpty());
QCOMPARE(server.serverError(), QAbstractSocket::HostNotFoundError);
+ QCOMPARE(server.socketDescriptor(), -1);
}
QCOMPARE(server.maxPendingConnections(), 30);
bool timedOut = false;
diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
index 8a8522760c..74bdcfc5f0 100644
--- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
+++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp
@@ -1097,6 +1097,9 @@ public:
QString m_interFile;
QString ciphers;
+signals:
+ void socketError(QAbstractSocket::SocketError);
+
protected:
void incomingConnection(qintptr socketDescriptor)
{
@@ -1106,6 +1109,7 @@ protected:
socket->setProtocol(protocol);
if (ignoreSslErrors)
connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
+ connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SIGNAL(socketError(QAbstractSocket::SocketError)));
QFile file(m_keyFile);
QVERIFY(file.open(QIODevice::ReadOnly));
@@ -1166,6 +1170,19 @@ void tst_QSslSocket::protocolServerSide_data()
QTest::addColumn<QSsl::SslProtocol>("clientProtocol");
QTest::addColumn<bool>("works");
+#if QT_CONFIG(opensslv11)
+#if !defined(OPENSSL_NO_SSL2)
+ // OpenSSL 1.1 has removed SSL2 support. But there is no OPENSSL_NO_SSL2 macro ...
+#define OPENSSL_NO_SSL2
+#endif
+ // A client using our OpenSSL1.1 backend will negotiate up from TLS 1.0 or 1.1
+ // to TLS 1.2 if the server asks for it, where our older backend fails to compromise.
+ // So some tests that fail for the old pass with the new.
+ const bool willUseTLS12 = true;
+#else
+ const bool willUseTLS12 = false;
+#endif // opensslv11
+
#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
QTest::newRow("ssl2-ssl2") << QSsl::SslV2 << QSsl::SslV2 << false; // no idea why it does not work, but we don't care about SSL 2
#endif
@@ -1241,6 +1258,38 @@ void tst_QSslSocket::protocolServerSide_data()
#if !defined(OPENSSL_NO_SSL3)
QTest::newRow("any-ssl3") << QSsl::AnyProtocol << QSsl::SslV3 << true;
#endif
+
+#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
+ QTest::newRow("tls1.0orlater-ssl2") << QSsl::TlsV1_0OrLater << QSsl::SslV2 << false;
+#endif
+#if !defined(OPENSSL_NO_SSL3)
+ QTest::newRow("tls1.0orlater-ssl3") << QSsl::TlsV1_0OrLater << QSsl::SslV3 << false;
+#endif
+ QTest::newRow("tls1.0orlater-tls1.0") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_0 << true;
+ QTest::newRow("tls1.0orlater-tls1.1") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_1 << true;
+ QTest::newRow("tls1.0orlater-tls1.2") << QSsl::TlsV1_0OrLater << QSsl::TlsV1_2 << true;
+
+#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
+ QTest::newRow("tls1.1orlater-ssl2") << QSsl::TlsV1_1OrLater << QSsl::SslV2 << false;
+#endif
+#if !defined(OPENSSL_NO_SSL3)
+ QTest::newRow("tls1.1orlater-ssl3") << QSsl::TlsV1_1OrLater << QSsl::SslV3 << false;
+#endif
+
+ QTest::newRow("tls1.1orlater-tls1.0") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_0 << willUseTLS12;
+ QTest::newRow("tls1.1orlater-tls1.1") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_1 << true;
+ QTest::newRow("tls1.1orlater-tls1.2") << QSsl::TlsV1_1OrLater << QSsl::TlsV1_2 << true;
+
+#if !defined(OPENSSL_NO_SSL2) && !defined(QT_SECURETRANSPORT)
+ QTest::newRow("tls1.2orlater-ssl2") << QSsl::TlsV1_2OrLater << QSsl::SslV2 << false;
+#endif
+#if !defined(OPENSSL_NO_SSL3)
+ QTest::newRow("tls1.2orlater-ssl3") << QSsl::TlsV1_2OrLater << QSsl::SslV3 << false;
+#endif
+ QTest::newRow("tls1.2orlater-tls1.0") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_0 << willUseTLS12;
+ QTest::newRow("tls1.2orlater-tls1.1") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_1 << willUseTLS12;
+ QTest::newRow("tls1.2orlater-tls1.2") << QSsl::TlsV1_2OrLater << QSsl::TlsV1_2 << true;
+
QTest::newRow("any-tls1.0") << QSsl::AnyProtocol << QSsl::TlsV1_0 << true;
QTest::newRow("any-tls1ssl3") << QSsl::AnyProtocol << QSsl::TlsV1SslV3 << true;
QTest::newRow("any-secure") << QSsl::AnyProtocol << QSsl::SecureProtocols << true;
@@ -1263,6 +1312,7 @@ void tst_QSslSocket::protocolServerSide()
QVERIFY(server.listen());
QEventLoop loop;
+ connect(&server, SIGNAL(socketError(QAbstractSocket::SocketError)), &loop, SLOT(quit()));
QTimer::singleShot(5000, &loop, SLOT(quit()));
QSslSocket client;
@@ -1280,7 +1330,15 @@ void tst_QSslSocket::protocolServerSide()
QFETCH(bool, works);
QAbstractSocket::SocketState expectedState = (works) ? QAbstractSocket::ConnectedState : QAbstractSocket::UnconnectedState;
- QCOMPARE(int(client.state()), int(expectedState));
+ // Determine whether the client or the server caused the event loop
+ // to quit due to a socket error, and investigate the culprit.
+ if (server.socket->error() != QAbstractSocket::UnknownSocketError) {
+ QVERIFY(client.error() == QAbstractSocket::UnknownSocketError);
+ QCOMPARE(int(server.socket->state()), int(expectedState));
+ } else if (client.error() != QAbstractSocket::UnknownSocketError) {
+ QVERIFY(server.socket->error() == QAbstractSocket::UnknownSocketError);
+ QCOMPARE(int(client.state()), int(expectedState));
+ }
QCOMPARE(client.isEncrypted(), works);
}
@@ -2118,6 +2176,13 @@ void tst_QSslSocket::waitForMinusOne()
// fifth verification: it should wait for 200 ms more
QVERIFY(socket.waitForDisconnected(-1));
+
+ // sixth verification: reading from a disconnected socket returns -1
+ // once we deplete the read buffer
+ QCOMPARE(socket.state(), QAbstractSocket::UnconnectedState);
+ socket.readAll();
+ char aux;
+ QCOMPARE(socket.read(&aux, 1), -1);
}
class VerifyServer : public QTcpServer
@@ -3620,7 +3685,9 @@ void tst_QSslSocket::ephemeralServerKey_data()
QTest::addColumn<QString>("cipher");
QTest::addColumn<bool>("emptyKey");
+#if !QT_CONFIG(opensslv11) // 1.1 drops support for RC4-SHA
QTest::newRow("NonForwardSecrecyCipher") << "RC4-SHA" << true;
+#endif // !opensslv11
QTest::newRow("ForwardSecrecyCipher") << "ECDHE-RSA-AES256-SHA" << (QSslSocket::sslLibraryVersionNumber() < 0x10002000L);
}
diff --git a/tests/auto/opengl/qgl/tst_qgl.cpp b/tests/auto/opengl/qgl/tst_qgl.cpp
index 7dfa8e4e22..f110b9cb0d 100644
--- a/tests/auto/opengl/qgl/tst_qgl.cpp
+++ b/tests/auto/opengl/qgl/tst_qgl.cpp
@@ -868,7 +868,7 @@ void tst_QGL::graphicsViewClipping()
scene.setSceneRect(view.viewport()->rect());
- QVERIFY(QTest::qWaitForWindowExposed(&view));
+ QVERIFY(QTest::qWaitForWindowExposed(view.viewport()->windowHandle()));
#ifdef Q_OS_MAC
// The black rectangle jumps from the center to the upper left for some reason.
QTest::qWait(100);
diff --git a/tests/auto/other/lancelot/scripts/gradientxform_device.qps b/tests/auto/other/lancelot/scripts/gradientxform_device.qps
new file mode 100644
index 0000000000..82ebb536bb
--- /dev/null
+++ b/tests/auto/other/lancelot/scripts/gradientxform_device.qps
@@ -0,0 +1,67 @@
+# Version: 1
+# CheckVsReference: 5%
+
+gradient_clearStops
+gradient_appendStop 0 black
+gradient_appendStop 0.4 yellow
+gradient_appendStop 1 gray
+
+gradient_setSpread PadSpread
+
+gradient_setCoordinateMode StretchToDeviceMode
+
+# first run is dummy, make it offscreen
+save
+translate -500 -500
+
+begin_block row
+save
+
+setPen nopen
+drawRect 50 0 100 100
+
+setPen brush 30
+setBrush lightblue
+drawRect 175 15 70 70
+
+setFont "times" 110 99
+drawText 270 100 "X"
+
+restore
+end_block row
+
+restore
+
+drawText 160 20 "PLAIN"
+drawText 560 20 "BRUSH XFORM"
+translate 0 20
+
+begin_block block
+save
+
+drawText 75 20 "Brush Fill"
+drawText 176 20 "Pen Stroke"
+drawText 277 20 "Text Stroke"
+translate 0 30
+drawText 0 50 "Linear"
+drawText 0 160 "Radial"
+drawText 0 270 "Conical"
+
+gradient_setLinear 0.0 0.0 0.4 0.0
+repeat_block row
+
+translate 0 110
+gradient_setRadial 0.04 0.08 0.3 0.3 0.05
+repeat_block row
+
+translate 0 110
+gradient_setConical 0.25 0.1 45
+repeat_block row
+restore
+end_block block
+
+translate 400 0
+brushRotate 30.0
+brushScale 1.5 .5
+brushTranslate 0 -80
+repeat_block block
diff --git a/tests/auto/other/lancelot/scripts/gradientxform_logical.qps b/tests/auto/other/lancelot/scripts/gradientxform_logical.qps
new file mode 100644
index 0000000000..1bb157b635
--- /dev/null
+++ b/tests/auto/other/lancelot/scripts/gradientxform_logical.qps
@@ -0,0 +1,67 @@
+# Version: 1
+# CheckVsReference: 5%
+
+gradient_clearStops
+gradient_appendStop 0 black
+gradient_appendStop 0.4 yellow
+gradient_appendStop 1 gray
+
+gradient_setSpread PadSpread
+
+gradient_setCoordinateMode LogicalMode
+
+# first run is dummy, make it offscreen
+save
+translate -500 -500
+
+begin_block row
+save
+
+setPen nopen
+drawRect 50 0 100 100
+
+setPen brush 30
+setBrush lightblue
+drawRect 175 15 70 70
+
+setFont "times" 110 99
+drawText 270 100 "X"
+
+restore
+end_block row
+
+restore
+
+drawText 160 20 "PLAIN"
+drawText 560 20 "BRUSH XFORM"
+translate 0 20
+
+begin_block block
+save
+
+drawText 75 20 "Brush Fill"
+drawText 176 20 "Pen Stroke"
+drawText 277 20 "Text Stroke"
+translate 0 30
+drawText 0 50 "Linear"
+drawText 0 160 "Radial"
+drawText 0 270 "Conical"
+
+gradient_setLinear 0 0 400 0
+repeat_block row
+
+translate 0 110
+gradient_setRadial 200 50 140 70 20
+repeat_block row
+
+translate 0 110
+gradient_setConical 220 60 45
+repeat_block row
+restore
+end_block block
+
+translate 400 0
+brushRotate 30.0
+brushScale 1.5 .5
+brushTranslate 0 -80
+repeat_block block
diff --git a/tests/auto/other/lancelot/scripts/gradientxform_object.qps b/tests/auto/other/lancelot/scripts/gradientxform_object.qps
new file mode 100644
index 0000000000..d785a008c0
--- /dev/null
+++ b/tests/auto/other/lancelot/scripts/gradientxform_object.qps
@@ -0,0 +1,68 @@
+# Version: 1
+# CheckVsReference: 5%
+
+gradient_clearStops
+gradient_appendStop 0 black
+gradient_appendStop 0.4 yellow
+gradient_appendStop 1 gray
+
+gradient_setSpread PadSpread
+
+gradient_setCoordinateMode ObjectBoundingMode
+
+# first run is dummy, make it offscreen
+save
+translate -500 -500
+
+begin_block row
+save
+
+setPen nopen
+drawRect 50 0 100 100
+
+setPen brush 30
+setBrush lightblue
+translate 110 0
+drawRect 65 15 70 70
+
+translate 110 0
+setFont "times" 110 99
+drawText 50 100 "X"
+
+restore
+end_block row
+
+restore
+
+drawText 160 20 "PLAIN"
+drawText 560 20 "BRUSH XFORM"
+translate 0 20
+
+begin_block block
+save
+
+drawText 75 20 "Brush Fill"
+drawText 176 20 "Pen Stroke"
+drawText 277 20 "Text Stroke"
+translate 0 30
+drawText 0 50 "Linear"
+drawText 0 160 "Radial"
+drawText 0 270 "Conical"
+
+gradient_setLinear 0.1 0.0 0.5 0.0
+repeat_block row
+
+translate 0 110
+gradient_setRadial 0.3 0.2 0.5 0.4 0.5
+repeat_block row
+
+translate 0 110
+gradient_setConical 0.5 0.7 45
+repeat_block row
+restore
+end_block block
+
+translate 400 0
+brushRotate 30.0
+brushScale 1.5 .5
+repeat_block block
diff --git a/tests/auto/other/macnativeevents/BLACKLIST b/tests/auto/other/macnativeevents/BLACKLIST
index 3998eb616a..1bc530ecc8 100644
--- a/tests/auto/other/macnativeevents/BLACKLIST
+++ b/tests/auto/other/macnativeevents/BLACKLIST
@@ -21,22 +21,22 @@ osx
osx
[testMouseDragToNonClientArea]
osx
-# QTQAINFRA-1292
-[testPushButtonPressRelease]
-osx-10.11 ci
osx-10.12 ci
-# QTQAINFRA-1292
+# The following key tests fail after switching to synchronous
+# expose events, and we don't know why yet. QTBUG-62042
[testKeyPressOnToplevel]
-osx-10.12 ci
-# QTQAINFRA-1292
+osx
[testModifierShift]
-osx-10.12 ci
-# QTQAINFRA-1292
+osx
[testModifierAlt]
-osx-10.12 ci
-# QTQAINFRA-1292
+osx
[testModifierCtrl]
+osx
+# QTQAINFRA-1292
+[testPushButtonPressRelease]
+osx-10.11 ci
osx-10.12 ci
+
# QTQAINFRA-1292
[testModifierCtrlWithDontSwapCtrlAndMeta]
osx-10.12 ci
diff --git a/tests/auto/other/macnativeevents/macnativeevents.pro b/tests/auto/other/macnativeevents/macnativeevents.pro
index 48ad04bbff..0611377d0b 100644
--- a/tests/auto/other/macnativeevents/macnativeevents.pro
+++ b/tests/auto/other/macnativeevents/macnativeevents.pro
@@ -1,9 +1,8 @@
CONFIG += testcase
TARGET = tst_macnativeevents
-LIBS += -framework Carbon
QT += widgets testlib
HEADERS += qnativeevents.h nativeeventlist.h expectedeventlist.h
-SOURCES += qnativeevents.cpp qnativeevents_mac.cpp
+SOURCES += qnativeevents.cpp qnativeevents_mac.cpp
SOURCES += expectedeventlist.cpp nativeeventlist.cpp
SOURCES += tst_macnativeevents.cpp
diff --git a/tests/auto/other/macnativeevents/qnativeevents.cpp b/tests/auto/other/macnativeevents/qnativeevents.cpp
index 758c0a94b8..f04b33151a 100644
--- a/tests/auto/other/macnativeevents/qnativeevents.cpp
+++ b/tests/auto/other/macnativeevents/qnativeevents.cpp
@@ -72,7 +72,7 @@ void QNativeInput::nativeEvent(QNativeEvent *event)
}
}
-Qt::Native::Status QNativeInput::sendNativeEvent(const QNativeEvent &event, int pid)
+Qt::Native::Status QNativeInput::sendNativeEvent(const QNativeEvent &event)
{
switch (event.id()){
case QNativeMouseMoveEvent::eventId:
@@ -84,7 +84,7 @@ Qt::Native::Status QNativeInput::sendNativeEvent(const QNativeEvent &event, int
case QNativeMouseWheelEvent::eventId:
return sendNativeMouseWheelEvent(static_cast<const QNativeMouseWheelEvent &>(event));
case QNativeKeyEvent::eventId:
- return sendNativeKeyEvent(static_cast<const QNativeKeyEvent &>(event), pid);
+ return sendNativeKeyEvent(static_cast<const QNativeKeyEvent &>(event));
case QNativeModifierEvent::eventId:
return sendNativeModifierEvent(static_cast<const QNativeModifierEvent &>(event));
case QNativeEvent::eventId:
diff --git a/tests/auto/other/macnativeevents/qnativeevents.h b/tests/auto/other/macnativeevents/qnativeevents.h
index 605d6d196e..2e30d849f2 100644
--- a/tests/auto/other/macnativeevents/qnativeevents.h
+++ b/tests/auto/other/macnativeevents/qnativeevents.h
@@ -204,10 +204,10 @@ class QNativeInput
static Qt::Native::Status sendNativeMouseMoveEvent(const QNativeMouseMoveEvent &event);
static Qt::Native::Status sendNativeMouseDragEvent(const QNativeMouseDragEvent &event);
static Qt::Native::Status sendNativeMouseWheelEvent(const QNativeMouseWheelEvent &event);
- static Qt::Native::Status sendNativeKeyEvent(const QNativeKeyEvent &event, int pid = 0);
+ static Qt::Native::Status sendNativeKeyEvent(const QNativeKeyEvent &event);
static Qt::Native::Status sendNativeModifierEvent(const QNativeModifierEvent &event);
// sendNativeEvent will NOT differ from OS to OS.
- static Qt::Native::Status sendNativeEvent(const QNativeEvent &event, int pid = 0);
+ static Qt::Native::Status sendNativeEvent(const QNativeEvent &event);
// The following methods will differ in implementation from OS to OS:
Qt::Native::Status subscribeForNativeEvents();
diff --git a/tests/auto/other/macnativeevents/qnativeevents_mac.cpp b/tests/auto/other/macnativeevents/qnativeevents_mac.cpp
index 6671813188..6d7fbbecc1 100644
--- a/tests/auto/other/macnativeevents/qnativeevents_mac.cpp
+++ b/tests/auto/other/macnativeevents/qnativeevents_mac.cpp
@@ -27,7 +27,7 @@
****************************************************************************/
#include "qnativeevents.h"
-#include <Carbon/Carbon.h>
+#include <CoreGraphics/CoreGraphics.h>
#include <QtCore>
// ************************************************************
@@ -176,28 +176,18 @@ static CGEventRef EventHandler_Quartz(CGEventTapProxy proxy, CGEventType type, C
return inEvent;
}
-Qt::Native::Status insertEventHandler_Quartz(QNativeInput *nativeInput, int pid = 0)
+Qt::Native::Status insertEventHandler_Quartz(QNativeInput *nativeInput)
{
uid_t uid = geteuid();
if (uid != 0)
qWarning("MacNativeEvents: You must be root to listen for key events!");
- CFMachPortRef port;
- if (!pid){
- port = CGEventTapCreate(kCGHIDEventTap,
- kCGHeadInsertEventTap, kCGEventTapOptionListenOnly,
- kCGEventMaskForAllEvents, EventHandler_Quartz, nativeInput);
- } else {
- ProcessSerialNumber psn;
- GetProcessForPID(pid, &psn);
- port = CGEventTapCreateForPSN(&psn,
- kCGHeadInsertEventTap, kCGEventTapOptionListenOnly,
- kCGEventMaskForAllEvents, EventHandler_Quartz, nativeInput);
- }
+ CFMachPortRef port = CGEventTapCreate(kCGHIDEventTap,
+ kCGHeadInsertEventTap, kCGEventTapOptionListenOnly,
+ kCGEventMaskForAllEvents, EventHandler_Quartz, nativeInput);
CFRunLoopSourceRef eventSrc = CFMachPortCreateRunLoopSource(NULL, port, 0);
- CFRunLoopAddSource((CFRunLoopRef) GetCFRunLoopFromEventLoop(GetMainEventLoop()),
- eventSrc, kCFRunLoopCommonModes);
+ CFRunLoopAddSource(CFRunLoopGetMain(), eventSrc, kCFRunLoopCommonModes);
return Qt::Native::Success;
}
@@ -207,19 +197,6 @@ Qt::Native::Status removeEventHandler_Quartz()
return Qt::Native::Success; // ToDo:
}
-Qt::Native::Status sendNativeKeyEventToProcess_Quartz(const QNativeKeyEvent &event, int pid)
-{
- ProcessSerialNumber psn;
- GetProcessForPID(pid, &psn);
-
- CGEventRef e = CGEventCreateKeyboardEvent(0, (uint)event.nativeKeyCode, event.press);
- setModifiersFromQNativeEvent(e, event);
- SetFrontProcess(&psn);
- CGEventPostToPSN(&psn, e);
- CFRelease(e);
- return Qt::Native::Success;
-}
-
Qt::Native::Status sendNativeKeyEvent_Quartz(const QNativeKeyEvent &event)
{
CGEventRef e = CGEventCreateKeyboardEvent(0, (uint)event.nativeKeyCode, event.press);
@@ -344,12 +321,9 @@ Qt::Native::Status QNativeInput::sendNativeMouseWheelEvent(const QNativeMouseWhe
return sendNativeMouseWheelEvent_Quartz(event);
}
-Qt::Native::Status QNativeInput::sendNativeKeyEvent(const QNativeKeyEvent &event, int pid)
+Qt::Native::Status QNativeInput::sendNativeKeyEvent(const QNativeKeyEvent &event)
{
- if (!pid)
- return sendNativeKeyEvent_Quartz(event);
- else
- return sendNativeKeyEventToProcess_Quartz(event, pid);
+ return sendNativeKeyEvent_Quartz(event);
}
Qt::Native::Status QNativeInput::sendNativeModifierEvent(const QNativeModifierEvent &event)
diff --git a/tests/auto/other/macnativeevents/tst_macnativeevents.cpp b/tests/auto/other/macnativeevents/tst_macnativeevents.cpp
index 5edff7aabe..e8970e6f24 100644
--- a/tests/auto/other/macnativeevents/tst_macnativeevents.cpp
+++ b/tests/auto/other/macnativeevents/tst_macnativeevents.cpp
@@ -35,10 +35,14 @@
#include "qnativeevents.h"
#include "nativeeventlist.h"
#include "expectedeventlist.h"
-#include <Carbon/Carbon.h>
QT_USE_NAMESPACE
+// Unicode code points for the glyphs associated with these keys
+// Defined by Carbon headers but not anywhere in Cocoa
+static const int kControlUnicode = 0x2303;
+static const int kCommandUnicode = 0x2318;
+
class tst_MacNativeEvents : public QObject
{
Q_OBJECT
diff --git a/tests/auto/other/modeltest/dynamictreemodel.cpp b/tests/auto/other/modeltest/dynamictreemodel.cpp
index 1f6463db8a..fc979bce2d 100644
--- a/tests/auto/other/modeltest/dynamictreemodel.cpp
+++ b/tests/auto/other/modeltest/dynamictreemodel.cpp
@@ -33,9 +33,8 @@
#include <QtCore/QTimer>
#include <QtCore/QDebug>
-
-DynamicTreeModel::DynamicTreeModel(QObject *parent)
- : QAbstractItemModel(parent),
+DynamicTreeModel::DynamicTreeModel(QObject *parent) :
+ QAbstractItemModel(parent),
nextId(1)
{
}
@@ -45,186 +44,172 @@ QModelIndex DynamicTreeModel::index(int row, int column, const QModelIndex &pare
// if (column != 0)
// return QModelIndex();
+ if (column < 0 || row < 0)
+ return QModelIndex();
- if ( column < 0 || row < 0 )
- return QModelIndex();
-
- QList<QList<qint64> > childIdColumns = m_childItems.value(parent.internalId());
+ QList<QList<qint64> > childIdColumns = m_childItems.value(parent.internalId());
- const qint64 grandParent = findParentId(parent.internalId());
- if (grandParent >= 0) {
- QList<QList<qint64> > parentTable = m_childItems.value(grandParent);
- if (parent.column() >= parentTable.size())
- qFatal("%s: parent.column() must be less than parentTable.size()", Q_FUNC_INFO);
- QList<qint64> parentSiblings = parentTable.at(parent.column());
- if (parent.row() >= parentSiblings.size())
- qFatal("%s: parent.row() must be less than parentSiblings.size()", Q_FUNC_INFO);
- }
-
- if (childIdColumns.size() == 0)
- return QModelIndex();
+ const qint64 grandParent = findParentId(parent.internalId());
+ if (grandParent >= 0) {
+ QList<QList<qint64> > parentTable = m_childItems.value(grandParent);
+ if (parent.column() >= parentTable.size())
+ qFatal("%s: parent.column() must be less than parentTable.size()", Q_FUNC_INFO);
+ QList<qint64> parentSiblings = parentTable.at(parent.column());
+ if (parent.row() >= parentSiblings.size())
+ qFatal("%s: parent.row() must be less than parentSiblings.size()", Q_FUNC_INFO);
+ }
- if (column >= childIdColumns.size())
- return QModelIndex();
+ if (childIdColumns.size() == 0)
+ return QModelIndex();
- QList<qint64> rowIds = childIdColumns.at(column);
+ if (column >= childIdColumns.size())
+ return QModelIndex();
- if ( row >= rowIds.size())
- return QModelIndex();
+ QList<qint64> rowIds = childIdColumns.at(column);
- qint64 id = rowIds.at(row);
+ if (row >= rowIds.size())
+ return QModelIndex();
- return createIndex(row, column, reinterpret_cast<void *>(id));
+ qint64 id = rowIds.at(row);
+ return createIndex(row, column, reinterpret_cast<void *>(id));
}
qint64 DynamicTreeModel::findParentId(qint64 searchId) const
{
- if (searchId <= 0)
- return -1;
-
- QHashIterator<qint64, QList<QList<qint64> > > i(m_childItems);
- while (i.hasNext())
- {
- i.next();
- QListIterator<QList<qint64> > j(i.value());
- while (j.hasNext())
- {
- QList<qint64> l = j.next();
- if (l.contains(searchId))
- {
- return i.key();
- }
+ if (searchId <= 0)
+ return -1;
+
+ QHashIterator<qint64, QList<QList<qint64> > > i(m_childItems);
+ while (i.hasNext()) {
+ i.next();
+ QListIterator<QList<qint64> > j(i.value());
+ while (j.hasNext()) {
+ QList<qint64> l = j.next();
+ if (l.contains(searchId))
+ return i.key();
+ }
}
- }
- return -1;
+ return -1;
}
QModelIndex DynamicTreeModel::parent(const QModelIndex &index) const
{
- if (!index.isValid())
- return QModelIndex();
+ if (!index.isValid())
+ return QModelIndex();
- qint64 searchId = index.internalId();
- qint64 parentId = findParentId(searchId);
- // Will never happen for valid index, but what the hey...
- if (parentId <= 0)
- return QModelIndex();
+ qint64 searchId = index.internalId();
+ qint64 parentId = findParentId(searchId);
+ // Will never happen for valid index, but what the hey...
+ if (parentId <= 0)
+ return QModelIndex();
- qint64 grandParentId = findParentId(parentId);
- if (grandParentId < 0)
- grandParentId = 0;
+ qint64 grandParentId = findParentId(parentId);
+ if (grandParentId < 0)
+ grandParentId = 0;
- int column = 0;
- QList<qint64> childList = m_childItems.value(grandParentId).at(column);
+ int column = 0;
+ QList<qint64> childList = m_childItems.value(grandParentId).at(column);
- int row = childList.indexOf(parentId);
-
- return createIndex(row, column, reinterpret_cast<void *>(parentId));
+ int row = childList.indexOf(parentId);
+ return createIndex(row, column, reinterpret_cast<void *>(parentId));
}
-int DynamicTreeModel::rowCount(const QModelIndex &index ) const
+int DynamicTreeModel::rowCount(const QModelIndex &index) const
{
- QList<QList<qint64> > cols = m_childItems.value(index.internalId());
+ QList<QList<qint64> > cols = m_childItems.value(index.internalId());
- if (cols.size() == 0 )
- return 0;
+ if (cols.size() == 0)
+ return 0;
- if (index.column() > 0)
- return 0;
+ if (index.column() > 0)
+ return 0;
- return cols.at(0).size();
+ return cols.at(0).size();
}
-int DynamicTreeModel::columnCount(const QModelIndex &index ) const
+int DynamicTreeModel::columnCount(const QModelIndex &index) const
{
// Q_UNUSED(index);
- return m_childItems.value(index.internalId()).size();
+ return m_childItems.value(index.internalId()).size();
}
QVariant DynamicTreeModel::data(const QModelIndex &index, int role) const
{
- if (!index.isValid())
- return QVariant();
+ if (!index.isValid())
+ return QVariant();
- if (Qt::DisplayRole == role)
- {
- return m_items.value(index.internalId());
- }
- return QVariant();
+ if (Qt::DisplayRole == role)
+ return m_items.value(index.internalId());
+ return QVariant();
}
void DynamicTreeModel::clear()
{
- beginResetModel();
- m_items.clear();
- m_childItems.clear();
- nextId = 1;
- endResetModel();
+ beginResetModel();
+ m_items.clear();
+ m_childItems.clear();
+ nextId = 1;
+ endResetModel();
}
-
-ModelChangeCommand::ModelChangeCommand( DynamicTreeModel *model, QObject *parent )
- : QObject(parent), m_model(model), m_numCols(1), m_startRow(-1), m_endRow(-1)
+ModelChangeCommand::ModelChangeCommand(DynamicTreeModel *model, QObject *parent) :
+ QObject(parent),
+ m_model(model),
+ m_numCols(1),
+ m_startRow(-1),
+ m_endRow(-1)
{
-
}
QModelIndex ModelChangeCommand::findIndex(QList<int> rows)
{
- const int col = 0;
- QModelIndex parent = QModelIndex();
- QListIterator<int> i(rows);
- while (i.hasNext())
- {
- parent = m_model->index(i.next(), col, parent);
- if (!parent.isValid())
- qFatal("%s: parent must be valid", Q_FUNC_INFO);
- }
- return parent;
+ const int col = 0;
+ QModelIndex parent = QModelIndex();
+ QListIterator<int> i(rows);
+ while (i.hasNext()) {
+ parent = m_model->index(i.next(), col, parent);
+ if (!parent.isValid())
+ qFatal("%s: parent must be valid", Q_FUNC_INFO);
+ }
+ return parent;
}
-ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent )
- : ModelChangeCommand(model, parent)
+ModelInsertCommand::ModelInsertCommand(DynamicTreeModel *model, QObject *parent) :
+ ModelChangeCommand(model, parent)
{
-
}
void ModelInsertCommand::doCommand()
{
- QModelIndex parent = findIndex(m_rowNumbers);
- m_model->beginInsertRows(parent, m_startRow, m_endRow);
- qint64 parentId = parent.internalId();
- for (int row = m_startRow; row <= m_endRow; row++)
- {
- for(int col = 0; col < m_numCols; col++ )
- {
- if (m_model->m_childItems[parentId].size() <= col)
- {
- m_model->m_childItems[parentId].append(QList<qint64>());
- }
+ QModelIndex parent = findIndex(m_rowNumbers);
+ m_model->beginInsertRows(parent, m_startRow, m_endRow);
+ qint64 parentId = parent.internalId();
+ for (int row = m_startRow; row <= m_endRow; row++) {
+ for (int col = 0; col < m_numCols; col++) {
+ if (m_model->m_childItems[parentId].size() <= col)
+ m_model->m_childItems[parentId].append(QList<qint64>());
// QString name = QUuid::createUuid().toString();
- qint64 id = m_model->newId();
- QString name = QString::number(id);
-
- m_model->m_items.insert(id, name);
- m_model->m_childItems[parentId][col].insert(row, id);
+ qint64 id = m_model->newId();
+ QString name = QString::number(id);
+ m_model->m_items.insert(id, name);
+ m_model->m_childItems[parentId][col].insert(row, id);
+ }
}
- }
- m_model->endInsertRows();
+ m_model->endInsertRows();
}
-
-ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent)
- : ModelChangeCommand(model, parent)
+ModelMoveCommand::ModelMoveCommand(DynamicTreeModel *model, QObject *parent) :
+ ModelChangeCommand(model, parent)
{
-
}
-bool ModelMoveCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow)
+
+bool ModelMoveCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd,
+ const QModelIndex &destParent, int destRow)
{
- return m_model->beginMoveRows(srcParent, srcStart, srcEnd, destParent, destRow);
+ return m_model->beginMoveRows(srcParent, srcStart, srcEnd, destParent, destRow);
}
void ModelMoveCommand::doCommand()
@@ -233,33 +218,26 @@ void ModelMoveCommand::doCommand()
QModelIndex destParent = findIndex(m_destRowNumbers);
if (!emitPreSignal(srcParent, m_startRow, m_endRow, destParent, m_destRow))
- {
return;
- }
- for (int column = 0; column < m_numCols; ++column)
- {
- QList<qint64> l = m_model->m_childItems.value(srcParent.internalId())[column].mid(m_startRow, m_endRow - m_startRow + 1 );
+ for (int column = 0; column < m_numCols; ++column) {
+ QList<qint64> l = m_model->m_childItems.value(srcParent.internalId())[column].mid(
+ m_startRow, m_endRow - m_startRow + 1);
- for (int i = m_startRow; i <= m_endRow ; i++)
- {
+ for (int i = m_startRow; i <= m_endRow; i++)
m_model->m_childItems[srcParent.internalId()][column].removeAt(m_startRow);
- }
int d;
- if (m_destRow < m_startRow)
+ if (m_destRow < m_startRow) {
d = m_destRow;
- else
- {
+ } else {
if (srcParent == destParent)
d = m_destRow - (m_endRow - m_startRow + 1);
else
d = m_destRow - (m_endRow - m_startRow) + 1;
}
- foreach(const qint64 id, l)
- {
+ foreach (const qint64 id, l)
m_model->m_childItems[destParent.internalId()][column].insert(d++, id);
- }
}
emitPostSignal();
@@ -270,18 +248,17 @@ void ModelMoveCommand::emitPostSignal()
m_model->endMoveRows();
}
-ModelResetCommand::ModelResetCommand(DynamicTreeModel* model, QObject* parent)
- : ModelMoveCommand(model, parent)
+ModelResetCommand::ModelResetCommand(DynamicTreeModel *model, QObject *parent) :
+ ModelMoveCommand(model, parent)
{
-
}
ModelResetCommand::~ModelResetCommand()
{
-
}
-bool ModelResetCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow)
+bool ModelResetCommand::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd,
+ const QModelIndex &destParent, int destRow)
{
Q_UNUSED(srcParent);
Q_UNUSED(srcStart);
@@ -298,18 +275,17 @@ void ModelResetCommand::emitPostSignal()
m_model->endResetModel();
}
-ModelResetCommandFixed::ModelResetCommandFixed(DynamicTreeModel* model, QObject* parent)
- : ModelMoveCommand(model, parent)
+ModelResetCommandFixed::ModelResetCommandFixed(DynamicTreeModel *model, QObject *parent) :
+ ModelMoveCommand(model, parent)
{
-
}
ModelResetCommandFixed::~ModelResetCommandFixed()
{
-
}
-bool ModelResetCommandFixed::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow)
+bool ModelResetCommandFixed::emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd,
+ const QModelIndex &destParent, int destRow)
{
Q_UNUSED(srcParent);
Q_UNUSED(srcStart);
@@ -326,10 +302,10 @@ void ModelResetCommandFixed::emitPostSignal()
m_model->endResetModel();
}
-ModelChangeChildrenLayoutsCommand::ModelChangeChildrenLayoutsCommand(DynamicTreeModel* model, QObject* parent)
- : ModelChangeCommand(model, parent)
+ModelChangeChildrenLayoutsCommand::ModelChangeChildrenLayoutsCommand(DynamicTreeModel *model,
+ QObject *parent) :
+ ModelChangeCommand(model, parent)
{
-
}
void ModelChangeChildrenLayoutsCommand::doCommand()
@@ -346,17 +322,16 @@ void ModelChangeChildrenLayoutsCommand::doCommand()
int rowSize1 = -1;
int rowSize2 = -1;
- for (int column = 0; column < m_numCols; ++column)
- {
+ for (int column = 0; column < m_numCols; ++column) {
{
- QList<qint64> &l = m_model->m_childItems[parent1.internalId()][column];
- rowSize1 = l.size();
- l.prepend(l.takeLast());
+ QList<qint64> &l = m_model->m_childItems[parent1.internalId()][column];
+ rowSize1 = l.size();
+ l.prepend(l.takeLast());
}
{
- QList<qint64> &l = m_model->m_childItems[parent2.internalId()][column];
- rowSize2 = l.size();
- l.append(l.takeFirst());
+ QList<qint64> &l = m_model->m_childItems[parent2.internalId()][column];
+ rowSize2 = l.size();
+ l.append(l.takeFirst());
}
}
@@ -373,15 +348,23 @@ void ModelChangeChildrenLayoutsCommand::doCommand()
foreach (const QModelIndex &idx, persistent) {
if (idx.parent() == parent1) {
if (idx.row() == rowSize1 - 1) {
- m_model->changePersistentIndex(idx, m_model->createIndex(0, idx.column(), idx.internalPointer()));
+ m_model->changePersistentIndex(idx,
+ m_model->createIndex(0, idx.column(),
+ idx.internalPointer()));
} else {
- m_model->changePersistentIndex(idx, m_model->createIndex(idx.row() + 1, idx.column(), idx.internalPointer()));
+ m_model->changePersistentIndex(idx,
+ m_model->createIndex(idx.row() + 1, idx.column(),
+ idx.internalPointer()));
}
} else if (idx.parent() == parent2) {
if (idx.row() == 0) {
- m_model->changePersistentIndex(idx, m_model->createIndex(rowSize2 - 1, idx.column(), idx.internalPointer()));
+ m_model->changePersistentIndex(idx,
+ m_model->createIndex(rowSize2 - 1, idx.column(),
+ idx.internalPointer()));
} else {
- m_model->changePersistentIndex(idx, m_model->createIndex(idx.row() - 1, idx.column(), idx.internalPointer()));
+ m_model->changePersistentIndex(idx,
+ m_model->createIndex(idx.row() - 1, idx.column(),
+ idx.internalPointer()));
}
}
}
diff --git a/tests/auto/other/modeltest/dynamictreemodel.h b/tests/auto/other/modeltest/dynamictreemodel.h
index e31c4569fd..709751dd27 100644
--- a/tests/auto/other/modeltest/dynamictreemodel.h
+++ b/tests/auto/other/modeltest/dynamictreemodel.h
@@ -34,119 +34,142 @@
#include <QtCore/QHash>
#include <QtCore/QList>
-
class DynamicTreeModel : public QAbstractItemModel
{
- Q_OBJECT
+ Q_OBJECT
public:
- DynamicTreeModel(QObject *parent = 0);
+ DynamicTreeModel(QObject *parent = 0);
- QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
- QModelIndex parent(const QModelIndex &index) const;
- int rowCount(const QModelIndex &index = QModelIndex()) const;
- int columnCount(const QModelIndex &index = QModelIndex()) const;
+ QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
+ QModelIndex parent(const QModelIndex &index) const;
+ int rowCount(const QModelIndex &index = QModelIndex()) const;
+ int columnCount(const QModelIndex &index = QModelIndex()) const;
- QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
- void clear();
+ void clear();
protected slots:
- /**
- Finds the parent id of the string with id @p searchId.
+ /**
+ Finds the parent id of the string with id @p searchId.
- Returns -1 if not found.
- */
- qint64 findParentId(qint64 searchId) const;
+ Returns -1 if not found.
+ */
+ qint64 findParentId(qint64 searchId) const;
private:
- QHash<qint64, QString> m_items;
- QHash<qint64, QList<QList<qint64> > > m_childItems;
- qint64 nextId;
- qint64 newId() { return nextId++; };
-
- QModelIndex m_nextParentIndex;
- int m_nextRow;
-
- int m_depth;
- int maxDepth;
-
- friend class ModelInsertCommand;
- friend class ModelMoveCommand;
- friend class ModelResetCommand;
- friend class ModelResetCommandFixed;
- friend class ModelChangeChildrenLayoutsCommand;
-
+ QHash<qint64, QString> m_items;
+ QHash<qint64, QList<QList<qint64> > > m_childItems;
+ qint64 nextId;
+ qint64 newId()
+ {
+ return nextId++;
+ }
+
+ QModelIndex m_nextParentIndex;
+ int m_nextRow;
+
+ int m_depth;
+ int maxDepth;
+
+ friend class ModelInsertCommand;
+ friend class ModelMoveCommand;
+ friend class ModelResetCommand;
+ friend class ModelResetCommandFixed;
+ friend class ModelChangeChildrenLayoutsCommand;
};
-
class ModelChangeCommand : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- ModelChangeCommand( DynamicTreeModel *model, QObject *parent = 0 );
+ ModelChangeCommand(DynamicTreeModel *model, QObject *parent = 0);
- virtual ~ModelChangeCommand() {}
+ virtual ~ModelChangeCommand()
+ {
+ }
- void setAncestorRowNumbers(QList<int> rowNumbers) { m_rowNumbers = rowNumbers; }
+ void setAncestorRowNumbers(QList<int> rowNumbers)
+ {
+ m_rowNumbers = rowNumbers;
+ }
- QModelIndex findIndex(QList<int> rows);
+ QModelIndex findIndex(QList<int> rows);
- void setStartRow(int row) { m_startRow = row; }
+ void setStartRow(int row)
+ {
+ m_startRow = row;
+ }
- void setEndRow(int row) { m_endRow = row; }
+ void setEndRow(int row)
+ {
+ m_endRow = row;
+ }
- void setNumCols(int cols) { m_numCols = cols; }
+ void setNumCols(int cols)
+ {
+ m_numCols = cols;
+ }
- virtual void doCommand() = 0;
+ virtual void doCommand() = 0;
protected:
- DynamicTreeModel* m_model;
- QList<int> m_rowNumbers;
- int m_numCols;
- int m_startRow;
- int m_endRow;
-
+ DynamicTreeModel *m_model;
+ QList<int> m_rowNumbers;
+ int m_numCols;
+ int m_startRow;
+ int m_endRow;
};
-typedef QList<ModelChangeCommand*> ModelChangeCommandList;
+typedef QList<ModelChangeCommand *> ModelChangeCommandList;
class ModelInsertCommand : public ModelChangeCommand
{
- Q_OBJECT
+ Q_OBJECT
public:
- ModelInsertCommand(DynamicTreeModel *model, QObject *parent = 0 );
- virtual ~ModelInsertCommand() {}
+ ModelInsertCommand(DynamicTreeModel *model, QObject *parent = 0);
+ virtual ~ModelInsertCommand()
+ {
+ }
- virtual void doCommand();
+ virtual void doCommand();
};
-
class ModelMoveCommand : public ModelChangeCommand
{
- Q_OBJECT
+ Q_OBJECT
public:
- ModelMoveCommand(DynamicTreeModel *model, QObject *parent);
+ ModelMoveCommand(DynamicTreeModel *model, QObject *parent);
- virtual ~ModelMoveCommand() {}
+ virtual ~ModelMoveCommand()
+ {
+ }
- virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow);
+ virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd,
+ const QModelIndex &destParent, int destRow);
- virtual void doCommand();
+ virtual void doCommand();
- virtual void emitPostSignal();
+ virtual void emitPostSignal();
- void setDestAncestors( QList<int> rows ) { m_destRowNumbers = rows; }
+ void setDestAncestors(QList<int> rows)
+ {
+ m_destRowNumbers = rows;
+ }
- void setDestRow(int row) { m_destRow = row; }
+ void setDestRow(int row)
+ {
+ m_destRow = row;
+ }
protected:
- QList<int> m_destRowNumbers;
- int m_destRow;
+ QList<int> m_destRowNumbers;
+ int m_destRow;
};
/**
@@ -154,15 +177,15 @@ protected:
*/
class ModelResetCommand : public ModelMoveCommand
{
- Q_OBJECT
+ Q_OBJECT
public:
- ModelResetCommand(DynamicTreeModel* model, QObject* parent = 0);
+ ModelResetCommand(DynamicTreeModel *model, QObject *parent = 0);
- virtual ~ModelResetCommand();
-
- virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow);
- virtual void emitPostSignal();
+ virtual ~ModelResetCommand();
+ virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd,
+ const QModelIndex &destParent, int destRow);
+ virtual void emitPostSignal();
};
/**
@@ -170,32 +193,37 @@ public:
*/
class ModelResetCommandFixed : public ModelMoveCommand
{
- Q_OBJECT
+ Q_OBJECT
public:
- ModelResetCommandFixed(DynamicTreeModel* model, QObject* parent = 0);
-
- virtual ~ModelResetCommandFixed();
+ ModelResetCommandFixed(DynamicTreeModel *model, QObject *parent = 0);
- virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd, const QModelIndex &destParent, int destRow);
- virtual void emitPostSignal();
+ virtual ~ModelResetCommandFixed();
+ virtual bool emitPreSignal(const QModelIndex &srcParent, int srcStart, int srcEnd,
+ const QModelIndex &destParent, int destRow);
+ virtual void emitPostSignal();
};
class ModelChangeChildrenLayoutsCommand : public ModelChangeCommand
{
- Q_OBJECT
+ Q_OBJECT
public:
- ModelChangeChildrenLayoutsCommand(DynamicTreeModel *model, QObject *parent);
+ ModelChangeChildrenLayoutsCommand(DynamicTreeModel *model, QObject *parent);
- virtual ~ModelChangeChildrenLayoutsCommand() {}
+ virtual ~ModelChangeChildrenLayoutsCommand()
+ {
+ }
- virtual void doCommand();
+ virtual void doCommand();
- void setSecondAncestorRowNumbers( QList<int> rows ) { m_secondRowNumbers = rows; }
+ void setSecondAncestorRowNumbers(QList<int> rows)
+ {
+ m_secondRowNumbers = rows;
+ }
protected:
- QList<int> m_secondRowNumbers;
- int m_destRow;
+ QList<int> m_secondRowNumbers;
+ int m_destRow;
};
#endif
diff --git a/tests/auto/other/modeltest/modeltest.cpp b/tests/auto/other/modeltest/modeltest.cpp
index 4da00bda4d..611f9e904b 100644
--- a/tests/auto/other/modeltest/modeltest.cpp
+++ b/tests/auto/other/modeltest/modeltest.cpp
@@ -34,60 +34,62 @@
/*!
Connect to all of the models signals. Whenever anything happens recheck everything.
*/
-ModelTest::ModelTest ( QAbstractItemModel *_model, QObject *parent ) : QObject ( parent ), model ( _model ), fetchingMore ( false )
+ModelTest::ModelTest(QAbstractItemModel *_model, QObject *parent) : QObject(parent),
+ model(_model),
+ fetchingMore(false)
{
if (!model)
qFatal("%s: model must not be null", Q_FUNC_INFO);
connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(runAllTests()) );
+ this, SLOT(runAllTests()));
connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(runAllTests()) );
+ this, SLOT(runAllTests()));
connect(model, SIGNAL(columnsInserted(QModelIndex,int,int)),
- this, SLOT(runAllTests()) );
+ this, SLOT(runAllTests()));
connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(runAllTests()) );
+ this, SLOT(runAllTests()));
connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(runAllTests()) );
+ this, SLOT(runAllTests()));
connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
- this, SLOT(runAllTests()) );
- connect(model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(runAllTests()) );
- connect(model, SIGNAL(layoutChanged()), this, SLOT(runAllTests()) );
- connect(model, SIGNAL(modelReset()), this, SLOT(runAllTests()) );
+ this, SLOT(runAllTests()));
+ connect(model, SIGNAL(layoutAboutToBeChanged()), this, SLOT(runAllTests()));
+ connect(model, SIGNAL(layoutChanged()), this, SLOT(runAllTests()));
+ connect(model, SIGNAL(modelReset()), this, SLOT(runAllTests()));
connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(runAllTests()) );
+ this, SLOT(runAllTests()));
connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(runAllTests()) );
+ this, SLOT(runAllTests()));
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(runAllTests()) );
+ this, SLOT(runAllTests()));
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(runAllTests()) );
+ this, SLOT(runAllTests()));
// Special checks for changes
connect(model, SIGNAL(layoutAboutToBeChanged()),
- this, SLOT(layoutAboutToBeChanged()) );
+ this, SLOT(layoutAboutToBeChanged()));
connect(model, SIGNAL(layoutChanged()),
- this, SLOT(layoutChanged()) );
+ this, SLOT(layoutChanged()));
connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)),
- this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)) );
+ this, SLOT(rowsAboutToBeInserted(QModelIndex,int,int)));
connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)) );
+ this, SLOT(rowsAboutToBeRemoved(QModelIndex,int,int)));
connect(model, SIGNAL(rowsInserted(QModelIndex,int,int)),
- this, SLOT(rowsInserted(QModelIndex,int,int)) );
+ this, SLOT(rowsInserted(QModelIndex,int,int)));
connect(model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SLOT(rowsRemoved(QModelIndex,int,int)) );
+ this, SLOT(rowsRemoved(QModelIndex,int,int)));
connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
- this, SLOT(dataChanged(QModelIndex,QModelIndex)) );
+ this, SLOT(dataChanged(QModelIndex,QModelIndex)));
connect(model, SIGNAL(headerDataChanged(Qt::Orientation,int,int)),
- this, SLOT(headerDataChanged(Qt::Orientation,int,int)) );
+ this, SLOT(headerDataChanged(Qt::Orientation,int,int)));
runAllTests();
}
void ModelTest::runAllTests()
{
- if ( fetchingMore )
+ if (fetchingMore)
return;
nonDestructiveBasicTest();
rowCount();
@@ -105,31 +107,31 @@ void ModelTest::runAllTests()
void ModelTest::nonDestructiveBasicTest()
{
QVERIFY(!model->buddy(QModelIndex()).isValid());
- model->canFetchMore ( QModelIndex() );
- QVERIFY( model->columnCount ( QModelIndex() ) >= 0 );
+ model->canFetchMore(QModelIndex());
+ QVERIFY(model->columnCount(QModelIndex()) >= 0);
QCOMPARE(model->data(QModelIndex()), QVariant());
fetchingMore = true;
- model->fetchMore ( QModelIndex() );
+ model->fetchMore(QModelIndex());
fetchingMore = false;
- Qt::ItemFlags flags = model->flags ( QModelIndex() );
- QVERIFY( flags == Qt::ItemIsDropEnabled || flags == 0 );
- model->hasChildren ( QModelIndex() );
- model->hasIndex ( 0, 0 );
- model->headerData ( 0, Qt::Horizontal );
- model->index ( 0, 0 );
- model->itemData ( QModelIndex() );
+ Qt::ItemFlags flags = model->flags(QModelIndex());
+ QVERIFY(flags == Qt::ItemIsDropEnabled || flags == 0);
+ model->hasChildren(QModelIndex());
+ model->hasIndex(0, 0);
+ model->headerData(0, Qt::Horizontal);
+ model->index(0, 0);
+ model->itemData(QModelIndex());
QVariant cache;
- model->match ( QModelIndex(), -1, cache );
+ model->match(QModelIndex(), -1, cache);
model->mimeTypes();
QVERIFY(!model->parent(QModelIndex()).isValid());
- QVERIFY( model->rowCount() >= 0 );
+ QVERIFY(model->rowCount() >= 0);
QVariant variant;
- model->setData ( QModelIndex(), variant, -1 );
- model->setHeaderData ( -1, Qt::Horizontal, QVariant() );
- model->setHeaderData ( 999999, Qt::Horizontal, QVariant() );
+ model->setData(QModelIndex(), variant, -1);
+ model->setHeaderData(-1, Qt::Horizontal, QVariant());
+ model->setHeaderData(999999, Qt::Horizontal, QVariant());
QMap<int, QVariant> roles;
- model->sibling ( 0, 0, QModelIndex() );
- model->span ( QModelIndex() );
+ model->sibling(0, 0, QModelIndex());
+ model->span(QModelIndex());
model->supportedDropActions();
}
@@ -142,19 +144,19 @@ void ModelTest::rowCount()
{
// qDebug() << "rc";
// check top row
- QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
- int rows = model->rowCount ( topIndex );
- QVERIFY( rows >= 0 );
- if ( rows > 0 )
- QVERIFY( model->hasChildren ( topIndex ) );
-
- QModelIndex secondLevelIndex = model->index ( 0, 0, topIndex );
- if ( secondLevelIndex.isValid() ) { // not the top level
+ QModelIndex topIndex = model->index(0, 0, QModelIndex());
+ int rows = model->rowCount(topIndex);
+ QVERIFY(rows >= 0);
+ if (rows > 0)
+ QVERIFY(model->hasChildren(topIndex));
+
+ QModelIndex secondLevelIndex = model->index(0, 0, topIndex);
+ if (secondLevelIndex.isValid()) { // not the top level
// check a row count where parent is valid
- rows = model->rowCount ( secondLevelIndex );
- QVERIFY( rows >= 0 );
- if ( rows > 0 )
- QVERIFY( model->hasChildren ( secondLevelIndex ) );
+ rows = model->rowCount(secondLevelIndex);
+ QVERIFY(rows >= 0);
+ if (rows > 0)
+ QVERIFY(model->hasChildren(secondLevelIndex));
}
// The models rowCount() is tested more extensively in checkChildren(),
@@ -167,13 +169,13 @@ void ModelTest::rowCount()
void ModelTest::columnCount()
{
// check top row
- QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
- QVERIFY( model->columnCount ( topIndex ) >= 0 );
+ QModelIndex topIndex = model->index(0, 0, QModelIndex());
+ QVERIFY(model->columnCount(topIndex) >= 0);
// check a column count where parent is valid
- QModelIndex childIndex = model->index ( 0, 0, topIndex );
- if ( childIndex.isValid() )
- QVERIFY( model->columnCount ( childIndex ) >= 0 );
+ QModelIndex childIndex = model->index(0, 0, topIndex);
+ if (childIndex.isValid())
+ QVERIFY(model->columnCount(childIndex) >= 0);
// columnCount() is tested more extensively in checkChildren(),
// but this catches the big mistakes
@@ -186,19 +188,19 @@ void ModelTest::hasIndex()
{
// qDebug() << "hi";
// Make sure that invalid values returns an invalid index
- QVERIFY( !model->hasIndex ( -2, -2 ) );
- QVERIFY( !model->hasIndex ( -2, 0 ) );
- QVERIFY( !model->hasIndex ( 0, -2 ) );
+ QVERIFY(!model->hasIndex(-2, -2));
+ QVERIFY(!model->hasIndex(-2, 0));
+ QVERIFY(!model->hasIndex(0, -2));
int rows = model->rowCount();
int columns = model->columnCount();
// check out of bounds
- QVERIFY( !model->hasIndex ( rows, columns ) );
- QVERIFY( !model->hasIndex ( rows + 1, columns + 1 ) );
+ QVERIFY(!model->hasIndex(rows, columns));
+ QVERIFY(!model->hasIndex(rows + 1, columns + 1));
- if ( rows > 0 )
- QVERIFY( model->hasIndex ( 0, 0 ) );
+ if (rows > 0)
+ QVERIFY(model->hasIndex(0, 0));
// hasIndex() is tested more extensively in checkChildren(),
// but this catches the big mistakes
@@ -218,7 +220,7 @@ void ModelTest::index()
int rows = model->rowCount();
int columns = model->columnCount();
- if ( rows == 0 )
+ if (rows == 0)
return;
// Catch off by one errors
@@ -226,8 +228,8 @@ void ModelTest::index()
QVERIFY(model->index(0, 0).isValid());
// Make sure that the same index is *always* returned
- QModelIndex a = model->index ( 0, 0 );
- QModelIndex b = model->index ( 0, 0 );
+ QModelIndex a = model->index(0, 0);
+ QModelIndex b = model->index(0, 0);
QCOMPARE(a, b);
// index() is tested more extensively in checkChildren(),
@@ -244,7 +246,7 @@ void ModelTest::parent()
// when asked for the parent of an invalid index.
QVERIFY(!model->parent(QModelIndex()).isValid());
- if ( model->rowCount() == 0 )
+ if (model->rowCount() == 0)
return;
// Column 0 | Column 1 |
@@ -254,29 +256,29 @@ void ModelTest::parent()
// Common error test #1, make sure that a top level index has a parent
// that is a invalid QModelIndex.
- QModelIndex topIndex = model->index ( 0, 0, QModelIndex() );
+ QModelIndex topIndex = model->index(0, 0, QModelIndex());
QVERIFY(!model->parent(topIndex).isValid());
// Common error test #2, make sure that a second level index has a parent
// that is the first level index.
- if ( model->rowCount ( topIndex ) > 0 ) {
- QModelIndex childIndex = model->index ( 0, 0, topIndex );
+ if (model->rowCount(topIndex) > 0) {
+ QModelIndex childIndex = model->index(0, 0, topIndex);
QCOMPARE(model->parent(childIndex), topIndex);
}
// Common error test #3, the second column should NOT have the same children
// as the first column in a row.
// Usually the second column shouldn't have children.
- QModelIndex topIndex1 = model->index ( 0, 1, QModelIndex() );
- if ( model->rowCount ( topIndex1 ) > 0 ) {
- QModelIndex childIndex = model->index ( 0, 0, topIndex );
- QModelIndex childIndex1 = model->index ( 0, 0, topIndex1 );
- QVERIFY( childIndex != childIndex1 );
+ QModelIndex topIndex1 = model->index(0, 1, QModelIndex());
+ if (model->rowCount(topIndex1) > 0) {
+ QModelIndex childIndex = model->index(0, 0, topIndex);
+ QModelIndex childIndex1 = model->index(0, 0, topIndex1);
+ QVERIFY(childIndex != childIndex1);
}
// Full test, walk n levels deep through the model making sure that all
// parent's children correctly specify their parent.
- checkChildren ( QModelIndex() );
+ checkChildren(QModelIndex());
}
/*!
@@ -293,73 +295,75 @@ void ModelTest::parent()
found the basic bugs because it is easier to figure out the problem in
those tests then this one.
*/
-void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth )
+void ModelTest::checkChildren(const QModelIndex &parent, int currentDepth)
{
// First just try walking back up the tree.
QModelIndex p = parent;
- while ( p.isValid() )
+ while (p.isValid())
p = p.parent();
// For models that are dynamically populated
- if ( model->canFetchMore ( parent ) ) {
+ if (model->canFetchMore(parent)) {
fetchingMore = true;
- model->fetchMore ( parent );
+ model->fetchMore(parent);
fetchingMore = false;
}
- int rows = model->rowCount ( parent );
- int columns = model->columnCount ( parent );
+ int rows = model->rowCount(parent);
+ int columns = model->columnCount(parent);
- if ( rows > 0 )
- QVERIFY( model->hasChildren ( parent ) );
+ if (rows > 0)
+ QVERIFY(model->hasChildren(parent));
// Some further testing against rows(), columns(), and hasChildren()
- QVERIFY( rows >= 0 );
- QVERIFY( columns >= 0 );
- if ( rows > 0 )
- QVERIFY( model->hasChildren ( parent ) );
+ QVERIFY(rows >= 0);
+ QVERIFY(columns >= 0);
+ if (rows > 0)
+ QVERIFY(model->hasChildren(parent));
//qDebug() << "parent:" << model->data(parent).toString() << "rows:" << rows
// << "columns:" << columns << "parent column:" << parent.column();
- const QModelIndex topLeftChild = model->index( 0, 0, parent );
+ const QModelIndex topLeftChild = model->index(0, 0, parent);
- QVERIFY( !model->hasIndex ( rows + 1, 0, parent ) );
- for ( int r = 0; r < rows; ++r ) {
- if ( model->canFetchMore ( parent ) ) {
+ QVERIFY(!model->hasIndex(rows + 1, 0, parent));
+ for (int r = 0; r < rows; ++r) {
+ if (model->canFetchMore(parent)) {
fetchingMore = true;
- model->fetchMore ( parent );
+ model->fetchMore(parent);
fetchingMore = false;
}
- QVERIFY( !model->hasIndex ( r, columns + 1, parent ) );
- for ( int c = 0; c < columns; ++c ) {
- QVERIFY( model->hasIndex ( r, c, parent ) );
- QModelIndex index = model->index ( r, c, parent );
+ QVERIFY(!model->hasIndex(r, columns + 1, parent));
+ for (int c = 0; c < columns; ++c) {
+ QVERIFY(model->hasIndex(r, c, parent));
+ QModelIndex index = model->index(r, c, parent);
// rowCount() and columnCount() said that it existed...
+ if (!index.isValid())
+ qWarning() << "Got invalid index at row=" << r << "col=" << c << "parent=" << parent;
QVERIFY(index.isValid());
// index() should always return the same index when called twice in a row
- QModelIndex modifiedIndex = model->index ( r, c, parent );
+ QModelIndex modifiedIndex = model->index(r, c, parent);
QCOMPARE(index, modifiedIndex);
// Make sure we get the same index if we request it twice in a row
- QModelIndex a = model->index ( r, c, parent );
- QModelIndex b = model->index ( r, c, parent );
+ QModelIndex a = model->index(r, c, parent);
+ QModelIndex b = model->index(r, c, parent);
QCOMPARE(a, b);
{
- const QModelIndex sibling = model->sibling( r, c, topLeftChild );
+ const QModelIndex sibling = model->sibling(r, c, topLeftChild);
QCOMPARE(index, sibling);
}
{
- const QModelIndex sibling = topLeftChild.sibling( r, c );
+ const QModelIndex sibling = topLeftChild.sibling(r, c);
QCOMPARE(index, sibling);
}
// Some basic checking on the index that is returned
QCOMPARE(index.model(), model);
- QCOMPARE( index.row(), r );
- QCOMPARE( index.column(), c );
+ QCOMPARE(index.row(), r);
+ QCOMPARE(index.column(), c);
// While you can technically return a QVariant usually this is a sign
// of a bug in data(). Disable if this really is ok in your model.
// QVERIFY( model->data ( index, Qt::DisplayRole ).isValid() );
@@ -377,16 +381,16 @@ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth )
}
// Check that we can get back our real parent.
- QCOMPARE( model->parent ( index ), parent );
+ QCOMPARE(model->parent(index), parent);
// recursively go down the children
- if ( model->hasChildren ( index ) && currentDepth < 10 ) {
+ if (model->hasChildren(index) && currentDepth < 10) {
//qDebug() << r << c << "has children" << model->rowCount(index);
- checkChildren ( index, ++currentDepth );
+ checkChildren(index, ++currentDepth);
}/* else { if (currentDepth >= 10) qDebug() << "checked 10 deep"; };*/
// make sure that after testing the children that the index doesn't change.
- QModelIndex newerIndex = model->index ( r, c, parent );
+ QModelIndex newerIndex = model->index(r, c, parent);
QCOMPARE(index, newerIndex);
}
}
@@ -398,68 +402,61 @@ void ModelTest::checkChildren ( const QModelIndex &parent, int currentDepth )
void ModelTest::data()
{
// Invalid index should return an invalid qvariant
- QVERIFY( !model->data ( QModelIndex() ).isValid() );
+ QVERIFY(!model->data(QModelIndex()).isValid());
- if ( model->rowCount() == 0 )
+ if (model->rowCount() == 0)
return;
// A valid index should have a valid QVariant data
- QVERIFY( model->index ( 0, 0 ).isValid() );
+ QVERIFY(model->index(0, 0).isValid());
// shouldn't be able to set data on an invalid index
- QVERIFY( !model->setData ( QModelIndex(), QLatin1String ( "foo" ), Qt::DisplayRole ) );
+ QVERIFY(!model->setData(QModelIndex(), QLatin1String("foo"), Qt::DisplayRole));
// General Purpose roles that should return a QString
- QVariant variant = model->data ( model->index ( 0, 0 ), Qt::ToolTipRole );
- if ( variant.isValid() ) {
- QVERIFY( variant.canConvert<QString>() );
- }
- variant = model->data ( model->index ( 0, 0 ), Qt::StatusTipRole );
- if ( variant.isValid() ) {
- QVERIFY( variant.canConvert<QString>() );
- }
- variant = model->data ( model->index ( 0, 0 ), Qt::WhatsThisRole );
- if ( variant.isValid() ) {
- QVERIFY( variant.canConvert<QString>() );
- }
+ QVariant variant = model->data(model->index(0, 0), Qt::ToolTipRole);
+ if (variant.isValid())
+ QVERIFY(variant.canConvert<QString>());
+ variant = model->data(model->index(0, 0), Qt::StatusTipRole);
+ if (variant.isValid())
+ QVERIFY(variant.canConvert<QString>());
+ variant = model->data(model->index(0, 0), Qt::WhatsThisRole);
+ if (variant.isValid())
+ QVERIFY(variant.canConvert<QString>());
// General Purpose roles that should return a QSize
- variant = model->data ( model->index ( 0, 0 ), Qt::SizeHintRole );
- if ( variant.isValid() ) {
- QVERIFY( variant.canConvert<QSize>() );
- }
+ variant = model->data(model->index(0, 0), Qt::SizeHintRole);
+ if (variant.isValid())
+ QVERIFY(variant.canConvert<QSize>());
// General Purpose roles that should return a QFont
- QVariant fontVariant = model->data ( model->index ( 0, 0 ), Qt::FontRole );
- if ( fontVariant.isValid() ) {
- QVERIFY( fontVariant.canConvert<QFont>() );
- }
+ QVariant fontVariant = model->data(model->index(0, 0), Qt::FontRole);
+ if (fontVariant.isValid())
+ QVERIFY(fontVariant.canConvert<QFont>());
// Check that the alignment is one we know about
- QVariant textAlignmentVariant = model->data ( model->index ( 0, 0 ), Qt::TextAlignmentRole );
- if ( textAlignmentVariant.isValid() ) {
+ QVariant textAlignmentVariant = model->data(model->index(0, 0), Qt::TextAlignmentRole);
+ if (textAlignmentVariant.isValid()) {
Qt::Alignment alignment = textAlignmentVariant.value<Qt::Alignment>();
- QCOMPARE( alignment, ( alignment & ( Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask ) ) );
+ QCOMPARE(alignment, (alignment & (Qt::AlignHorizontal_Mask | Qt::AlignVertical_Mask)));
}
// General Purpose roles that should return a QColor
- QVariant colorVariant = model->data ( model->index ( 0, 0 ), Qt::BackgroundColorRole );
- if ( colorVariant.isValid() ) {
- QVERIFY( colorVariant.canConvert<QColor>() );
- }
+ QVariant colorVariant = model->data(model->index(0, 0), Qt::BackgroundColorRole);
+ if (colorVariant.isValid())
+ QVERIFY(colorVariant.canConvert<QColor>());
- colorVariant = model->data ( model->index ( 0, 0 ), Qt::TextColorRole );
- if ( colorVariant.isValid() ) {
- QVERIFY( colorVariant.canConvert<QColor>() );
- }
+ colorVariant = model->data(model->index(0, 0), Qt::TextColorRole);
+ if (colorVariant.isValid())
+ QVERIFY(colorVariant.canConvert<QColor>());
// Check that the "check state" is one we know about.
- QVariant checkStateVariant = model->data ( model->index ( 0, 0 ), Qt::CheckStateRole );
- if ( checkStateVariant.isValid() ) {
+ QVariant checkStateVariant = model->data(model->index(0, 0), Qt::CheckStateRole);
+ if (checkStateVariant.isValid()) {
int state = checkStateVariant.toInt();
- QVERIFY( state == Qt::Unchecked ||
- state == Qt::PartiallyChecked ||
- state == Qt::Checked );
+ QVERIFY(state == Qt::Unchecked
+ || state == Qt::PartiallyChecked
+ || state == Qt::Checked);
}
}
@@ -468,7 +465,7 @@ void ModelTest::data()
\sa rowsInserted()
*/
-void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, int /* end */)
+void ModelTest::rowsAboutToBeInserted(const QModelIndex &parent, int start, int /* end */)
{
// Q_UNUSED(end);
// qDebug() << "rowsAboutToBeInserted" << "start=" << start << "end=" << end << "parent=" << model->data ( parent ).toString()
@@ -476,10 +473,10 @@ void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, in
// qDebug() << model->index(start-1, 0, parent) << model->data( model->index(start-1, 0, parent) );
Changing c;
c.parent = parent;
- c.oldSize = model->rowCount ( parent );
- c.last = model->data ( model->index ( start - 1, 0, parent ) );
- c.next = model->data ( model->index ( start, 0, parent ) );
- insert.push ( c );
+ c.oldSize = model->rowCount(parent);
+ c.last = model->data(model->index(start - 1, 0, parent));
+ c.next = model->data(model->index(start, 0, parent));
+ insert.push(c);
}
/*!
@@ -487,10 +484,10 @@ void ModelTest::rowsAboutToBeInserted ( const QModelIndex &parent, int start, in
\sa rowsAboutToBeInserted()
*/
-void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end )
+void ModelTest::rowsInserted(const QModelIndex &parent, int start, int end)
{
Changing c = insert.pop();
- QCOMPARE(c.parent, parent);
+ QCOMPARE(parent, c.parent);
// qDebug() << "rowsInserted" << "start=" << start << "end=" << end << "oldsize=" << c.oldSize
// << "parent=" << model->data ( parent ).toString() << "current rowcount of parent=" << model->rowCount ( parent );
@@ -500,30 +497,30 @@ void ModelTest::rowsInserted ( const QModelIndex & parent, int start, int end )
// }
// qDebug();
- QCOMPARE(c.oldSize + (end - start + 1), model->rowCount(parent));
- QCOMPARE(c.last, model->data(model->index(start - 1, 0, c.parent)));
+ QCOMPARE(model->rowCount(parent), c.oldSize + (end - start + 1));
+ QCOMPARE(model->data(model->index(start - 1, 0, c.parent)), c.last);
if (c.next != model->data(model->index(end + 1, 0, c.parent))) {
qDebug() << start << end;
- for (int i=0; i < model->rowCount(); ++i)
+ for (int i = 0; i < model->rowCount(); ++i)
qDebug() << model->index(i, 0).data().toString();
qDebug() << c.next << model->data(model->index(end + 1, 0, c.parent));
}
- QCOMPARE(c.next, model->data(model->index(end + 1, 0, c.parent)));
+ QCOMPARE(model->data(model->index(end + 1, 0, c.parent)), c.next);
}
void ModelTest::layoutAboutToBeChanged()
{
- for ( int i = 0; i < qBound ( 0, model->rowCount(), 100 ); ++i )
- changing.append ( QPersistentModelIndex ( model->index ( i, 0 ) ) );
+ for (int i = 0; i < qBound(0, model->rowCount(), 100); ++i)
+ changing.append(QPersistentModelIndex(model->index(i, 0)));
}
void ModelTest::layoutChanged()
{
- for ( int i = 0; i < changing.count(); ++i ) {
+ for (int i = 0; i < changing.count(); ++i) {
QPersistentModelIndex p = changing[i];
- QCOMPARE(QModelIndex(p), model->index(p.row(), p.column(), p.parent()));
+ QCOMPARE(model->index(p.row(), p.column(), p.parent()), QModelIndex(p));
}
changing.clear();
}
@@ -533,15 +530,15 @@ void ModelTest::layoutChanged()
\sa rowsRemoved()
*/
-void ModelTest::rowsAboutToBeRemoved ( const QModelIndex &parent, int start, int end )
+void ModelTest::rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
-qDebug() << "ratbr" << parent << start << end;
+ qDebug() << "ratbr" << parent << start << end;
Changing c;
c.parent = parent;
- c.oldSize = model->rowCount ( parent );
- c.last = model->data ( model->index ( start - 1, 0, parent ) );
- c.next = model->data ( model->index ( end + 1, 0, parent ) );
- remove.push ( c );
+ c.oldSize = model->rowCount(parent);
+ c.last = model->data(model->index(start - 1, 0, parent));
+ c.next = model->data(model->index(end + 1, 0, parent));
+ remove.push(c);
}
/*!
@@ -549,14 +546,14 @@ qDebug() << "ratbr" << parent << start << end;
\sa rowsAboutToBeRemoved()
*/
-void ModelTest::rowsRemoved ( const QModelIndex & parent, int start, int end )
+void ModelTest::rowsRemoved(const QModelIndex &parent, int start, int end)
{
- qDebug() << "rr" << parent << start << end;
+ qDebug() << "rr" << parent << start << end;
Changing c = remove.pop();
- QCOMPARE(c.parent, parent);
- QCOMPARE(c.oldSize - (end - start + 1), model->rowCount(parent));
- QCOMPARE(c.last, model->data(model->index(start - 1, 0, c.parent)));
- QCOMPARE(c.next, model->data(model->index(start, 0, c.parent)));
+ QCOMPARE(parent, c.parent);
+ QCOMPARE(model->rowCount(parent), c.oldSize - (end - start + 1));
+ QCOMPARE(model->data(model->index(start - 1, 0, c.parent)), c.last);
+ QCOMPARE(model->data(model->index(start, 0, c.parent)), c.next);
}
void ModelTest::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
@@ -582,4 +579,3 @@ void ModelTest::headerDataChanged(Qt::Orientation orientation, int start, int en
QVERIFY(start < itemCount);
QVERIFY(end < itemCount);
}
-
diff --git a/tests/auto/other/modeltest/modeltest.h b/tests/auto/other/modeltest/modeltest.h
index 735a422729..4676bf4434 100644
--- a/tests/auto/other/modeltest/modeltest.h
+++ b/tests/auto/other/modeltest/modeltest.h
@@ -26,7 +26,6 @@
**
****************************************************************************/
-
#ifndef MODELTEST_H
#define MODELTEST_H
@@ -36,48 +35,48 @@
class ModelTest : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- ModelTest( QAbstractItemModel *model, QObject *parent = 0 );
+ ModelTest(QAbstractItemModel *model, QObject *parent = 0);
private Q_SLOTS:
- void nonDestructiveBasicTest();
- void rowCount();
- void columnCount();
- void hasIndex();
- void index();
- void parent();
- void data();
+ void nonDestructiveBasicTest();
+ void rowCount();
+ void columnCount();
+ void hasIndex();
+ void index();
+ void parent();
+ void data();
protected Q_SLOTS:
- void runAllTests();
- void layoutAboutToBeChanged();
- void layoutChanged();
- void rowsAboutToBeInserted( const QModelIndex &parent, int start, int end );
- void rowsInserted( const QModelIndex & parent, int start, int end );
- void rowsAboutToBeRemoved( const QModelIndex &parent, int start, int end );
- void rowsRemoved( const QModelIndex & parent, int start, int end );
- void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
- void headerDataChanged(Qt::Orientation orientation, int start, int end);
+ void runAllTests();
+ void layoutAboutToBeChanged();
+ void layoutChanged();
+ void rowsAboutToBeInserted(const QModelIndex &parent, int start, int end);
+ void rowsInserted(const QModelIndex &parent, int start, int end);
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void rowsRemoved(const QModelIndex &parent, int start, int end);
+ void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void headerDataChanged(Qt::Orientation orientation, int start, int end);
private:
- void checkChildren( const QModelIndex &parent, int currentDepth = 0 );
+ void checkChildren(const QModelIndex &parent, int currentDepth = 0);
- QAbstractItemModel *model;
+ QAbstractItemModel *model;
- struct Changing {
- QModelIndex parent;
- int oldSize;
- QVariant last;
- QVariant next;
- };
- QStack<Changing> insert;
- QStack<Changing> remove;
+ struct Changing {
+ QModelIndex parent;
+ int oldSize;
+ QVariant last;
+ QVariant next;
+ };
+ QStack<Changing> insert;
+ QStack<Changing> remove;
- bool fetchingMore;
+ bool fetchingMore;
- QList<QPersistentModelIndex> changing;
+ QList<QPersistentModelIndex> changing;
};
#endif
diff --git a/tests/auto/other/modeltest/tst_modeltest.cpp b/tests/auto/other/modeltest/tst_modeltest.cpp
index f81fefe9d1..e2d002844b 100644
--- a/tests/auto/other/modeltest/tst_modeltest.cpp
+++ b/tests/auto/other/modeltest/tst_modeltest.cpp
@@ -26,7 +26,6 @@
**
****************************************************************************/
-
#include <QtTest/QtTest>
#include <QtGui/QtGui>
#include <QtWidgets/QtWidgets>
@@ -34,7 +33,6 @@
#include "modeltest.h"
#include "dynamictreemodel.h"
-
class tst_ModelTest : public QObject
{
Q_OBJECT
@@ -63,7 +61,7 @@ void tst_ModelTest::stringListModel()
proxy.setSourceModel(&model);
model.setStringList(QStringList() << "2" << "3" << "1");
- model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c" );
+ model.setStringList(QStringList() << "a" << "e" << "plop" << "b" << "c");
proxy.setDynamicSortFilter(true);
proxy.setFilterRegExp(QRegExp("[^b]"));
@@ -76,9 +74,8 @@ void tst_ModelTest::treeWidgetModel()
ModelTest t1(widget.model());
QTreeWidgetItem *root = new QTreeWidgetItem(&widget, QStringList("root"));
- for (int i = 0; i < 20; ++i) {
+ for (int i = 0; i < 20; ++i)
new QTreeWidgetItem(root, QStringList(QString::number(i)));
- }
QTreeWidgetItem *remove = root->child(2);
root->removeChild(remove);
QTreeWidgetItem *parent = new QTreeWidgetItem(&widget, QStringList("parent"));
@@ -90,10 +87,9 @@ void tst_ModelTest::treeWidgetModel()
void tst_ModelTest::standardItemModel()
{
- QStandardItemModel model(10,10);
+ QStandardItemModel model(10, 10);
QSortFilterProxyModel proxy;
-
ModelTest t1(&model);
ModelTest t2(&proxy);
@@ -105,8 +101,8 @@ void tst_ModelTest::standardItemModel()
model.insertColumns(2, 5);
model.removeColumns(4, 5);
- model.insertRows(0,5, model.index(1,1));
- model.insertColumns(0,5, model.index(1,3));
+ model.insertRows(0, 5, model.index(1, 1));
+ model.insertColumns(0, 5, model.index(1, 3));
}
void tst_ModelTest::testInsertThroughProxy()
@@ -148,7 +144,9 @@ class AccessibleProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
- AccessibleProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent) {}
+ AccessibleProxyModel(QObject *parent = 0) : QSortFilterProxyModel(parent)
+ {
+ }
QModelIndexList persistent()
{
@@ -160,14 +158,16 @@ class ObservingObject : public QObject
{
Q_OBJECT
public:
- ObservingObject(AccessibleProxyModel *proxy, QObject *parent = 0)
- : QObject(parent)
- , m_proxy(proxy)
- , storePersistentFailureCount(0)
- , checkPersistentFailureCount(0)
+ ObservingObject(AccessibleProxyModel *proxy, QObject *parent = 0) :
+ QObject(parent),
+ m_proxy(proxy),
+ storePersistentFailureCount(0),
+ checkPersistentFailureCount(0)
{
- connect(m_proxy, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(storePersistent()));
- connect(m_proxy, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)), SLOT(checkPersistent()));
+ connect(m_proxy, SIGNAL(rowsAboutToBeMoved(QModelIndex,int,int,QModelIndex,int)),
+ SLOT(storePersistent()));
+ connect(m_proxy, SIGNAL(rowsMoved(QModelIndex,int,int,QModelIndex,int)),
+ SLOT(checkPersistent()));
}
public slots:
@@ -195,7 +195,7 @@ public slots:
void storePersistent()
{
// This method is called from rowsAboutToBeMoved. Persistent indexes should be valid
- foreach(const QModelIndex &idx, m_persistentProxyIndexes)
+ foreach (const QModelIndex &idx, m_persistentProxyIndexes)
if (!idx.isValid()) {
qWarning("%s: persistentProxyIndexes contains invalid index", Q_FUNC_INFO);
++storePersistentFailureCount;
@@ -233,7 +233,7 @@ public slots:
}
private:
- AccessibleProxyModel *m_proxy;
+ AccessibleProxyModel *m_proxy;
QList<QPersistentModelIndex> m_persistentSourceIndexes;
QList<QPersistentModelIndex> m_persistentProxyIndexes;
public:
@@ -296,6 +296,5 @@ void tst_ModelTest::testResetThroughProxy()
QCOMPARE(observer.checkPersistentFailureCount, 0);
}
-
QTEST_MAIN(tst_ModelTest)
#include "tst_modeltest.moc"
diff --git a/tests/auto/other/qaccessibilitymac/qaccessibilitymac.pro b/tests/auto/other/qaccessibilitymac/qaccessibilitymac.pro
index ceed81c914..e55757775e 100644
--- a/tests/auto/other/qaccessibilitymac/qaccessibilitymac.pro
+++ b/tests/auto/other/qaccessibilitymac/qaccessibilitymac.pro
@@ -1,6 +1,5 @@
CONFIG += testcase
TARGET = tst_qaccessibilitymac
-# LIBS += -framework Carbon
QT += widgets testlib
HEADERS += tst_qaccessibilitymac_helpers.h
diff --git a/tests/auto/other/qfocusevent/tst_qfocusevent.cpp b/tests/auto/other/qfocusevent/tst_qfocusevent.cpp
index 2e2945ee5d..35441010f7 100644
--- a/tests/auto/other/qfocusevent/tst_qfocusevent.cpp
+++ b/tests/auto/other/qfocusevent/tst_qfocusevent.cpp
@@ -287,7 +287,7 @@ void tst_QFocusEvent::checkReason_Shortcut()
void tst_QFocusEvent::checkReason_focusWidget()
{
// This test checks that a widget doesn't loose
- // its focuswidget just because the focuswidget looses focus.
+ // its focuswidget just because the focuswidget loses focus.
QWidget window1;
QWidget frame1;
QWidget frame2;
diff --git a/tests/auto/shared/platformclipboard.h b/tests/auto/shared/platformclipboard.h
index c5f1a64dce..15801f6add 100644
--- a/tests/auto/shared/platformclipboard.h
+++ b/tests/auto/shared/platformclipboard.h
@@ -31,22 +31,12 @@
#include <qglobal.h>
-#ifdef Q_OS_OSX
-#include <Carbon/Carbon.h>
-#endif
-
struct PlatformClipboard
{
static inline bool isAvailable()
{
#if defined(QT_NO_CLIPBOARD)
return false;
-#elif defined(Q_OS_OSX)
- PasteboardRef pasteboard;
- OSStatus status = PasteboardCreate(0, &pasteboard);
- if (status == noErr)
- CFRelease(pasteboard);
- return status == noErr;
#else
return true;
#endif
diff --git a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
index d7772f5c34..e3f088e763 100644
--- a/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
+++ b/tests/auto/sql/kernel/qsqldatabase/tst_qsqldatabase.cpp
@@ -188,6 +188,9 @@ private slots:
void sqlite_enable_cache_mode_data() { generic_data("QSQLITE"); }
void sqlite_enable_cache_mode();
+ void sqlite_enableRegexp_data() { generic_data("QSQLITE"); }
+ void sqlite_enableRegexp();
+
private:
void createTestTables(QSqlDatabase db);
void dropTestTables(QSqlDatabase db);
@@ -345,7 +348,8 @@ void tst_QSqlDatabase::dropTestTables(QSqlDatabase db)
<< qTableName("qtest_sqlguid", __FILE__, db)
<< qTableName("uint_table", __FILE__, db)
<< qTableName("uint_test", __FILE__, db)
- << qTableName("bug_249059", __FILE__, db);
+ << qTableName("bug_249059", __FILE__, db)
+ << qTableName("regexp_test", __FILE__, db);
QSqlQuery q(0, db);
if (dbType == QSqlDriver::PostgreSQL) {
@@ -2259,5 +2263,33 @@ void tst_QSqlDatabase::sqlite_enable_cache_mode()
db2.close();
}
+void tst_QSqlDatabase::sqlite_enableRegexp()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ if (db.driverName().startsWith("QSQLITE2"))
+ QSKIP("SQLite3 specific test");
+
+ db.close();
+ db.setConnectOptions("QSQLITE_ENABLE_REGEXP");
+ QVERIFY_SQL(db, open());
+
+ QSqlQuery q(db);
+ const QString tableName(qTableName("regexp_test", __FILE__, db));
+ QVERIFY_SQL(q, exec(QString("CREATE TABLE %1(text TEXT)").arg(tableName)));
+ QVERIFY_SQL(q, prepare(QString("INSERT INTO %1 VALUES(?)").arg(tableName)));
+ q.addBindValue("a0");
+ QVERIFY_SQL(q, exec());
+ q.addBindValue("a1");
+ QVERIFY_SQL(q, exec());
+
+ QVERIFY_SQL(q, exec(QString("SELECT text FROM %1 WHERE text REGEXP 'a[^0]' "
+ "ORDER BY text").arg(tableName)));
+ QVERIFY_SQL(q, next());
+ QCOMPARE(q.value(0).toString(), QString("a1"));
+ QFAIL_SQL(q, next());
+}
+
QTEST_MAIN(tst_QSqlDatabase)
#include "tst_qsqldatabase.moc"
diff --git a/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp b/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp
index 07a6c9c835..08c6039e37 100644
--- a/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp
+++ b/tests/auto/sql/kernel/qsqlerror/tst_qsqlerror.cpp
@@ -44,6 +44,7 @@ public:
private slots:
void getSetCheck();
void construction();
+ void moveOperator();
void operators();
};
@@ -143,6 +144,26 @@ void tst_QSqlError::construction()
QCOMPARE(obj7.number(), -1);
QCOMPARE(obj7.nativeErrorCode(), QString());
+ // Move constructor
+ QSqlError obj8(std::move(obj3));
+ QCOMPARE(obj8.driverText(), obj2.driverText());
+ QCOMPARE(obj8.databaseText(), obj2.databaseText());
+ QCOMPARE(obj8.type(), obj2.type());
+ QCOMPARE(obj8.number(), obj2.number());
+ QCOMPARE(obj8.nativeErrorCode(), obj2.nativeErrorCode());
+ QVERIFY(obj8.isValid());
+}
+
+void tst_QSqlError::moveOperator()
+{
+ QSqlError obj1("drivertext", "databasetext", QSqlError::UnknownError, 123), obj2;
+ obj2 = std::move(obj1);
+ QCOMPARE(obj2.driverText(), QString("drivertext"));
+ QCOMPARE(obj2.databaseText(), QString("databasetext"));
+ QCOMPARE(obj2.type(), QSqlError::UnknownError);
+ QCOMPARE(obj2.number(), 123);
+ QCOMPARE(obj2.nativeErrorCode(), QStringLiteral("123"));
+ QVERIFY(obj2.isValid());
}
void tst_QSqlError::operators()
diff --git a/tests/auto/sql/kernel/qsqlfield/tst_qsqlfield.cpp b/tests/auto/sql/kernel/qsqlfield/tst_qsqlfield.cpp
index cee33be3df..7efd19a2b8 100644
--- a/tests/auto/sql/kernel/qsqlfield/tst_qsqlfield.cpp
+++ b/tests/auto/sql/kernel/qsqlfield/tst_qsqlfield.cpp
@@ -62,6 +62,8 @@ private slots:
void isNull();
void clear_data();
void clear();
+ void setTableName_data();
+ void setTableName();
};
// Testing get/set functions
@@ -212,6 +214,9 @@ void tst_QSqlField::operator_Assign()
field3.clear();
field1 = field3;
QVERIFY( field1 == field3 );
+ QSqlField field4("test", QVariant::String, "ATable");
+ field1 = field4;
+ QVERIFY(field1 == field4);
}
void tst_QSqlField::operator_Equal()
@@ -219,8 +224,18 @@ void tst_QSqlField::operator_Equal()
QSqlField field1( "test", QVariant::String );
QSqlField field2( "test2", QVariant::String );
QSqlField field3( "test", QVariant::Int );
+ QSqlField field4("test", QVariant::String, QString("ATable"));
+ QSqlField field5("test2", QVariant::String, QString("ATable"));
+ QSqlField field6("test", QVariant::String, QString("BTable"));
+
QVERIFY( !(field1 == field2) );
QVERIFY( !(field1 == field3) );
+ QVERIFY(field1 != field4);
+ QVERIFY(field1 != field5);
+ QVERIFY(field1 != field6);
+ QVERIFY(field4 != field5);
+ QVERIFY(field4 != field6);
+
field2.setName( "test" );
QVERIFY( field1 == field2 );
QVERIFY( field1 == field2 );
@@ -232,6 +247,10 @@ void tst_QSqlField::operator_Equal()
QVERIFY( !(field1 == field2) );
field2.setReadOnly( true );
QVERIFY( field1 == field2 );
+ field4.setTableName("BTable");
+ QCOMPARE(field4, field6);
+ field6.setName("test3");
+ QVERIFY(field4 != field6);
}
void tst_QSqlField::setName_data()
@@ -333,5 +352,22 @@ void tst_QSqlField::type()
QVERIFY( field3.type() == QVariant::Double );
}
+void tst_QSqlField::setTableName_data()
+{
+ QTest::addColumn<QString>("tableName");
+
+ QTest::newRow("data0") << QString("");
+ QTest::newRow("data1") << QString("tbl");
+}
+
+void tst_QSqlField::setTableName()
+{
+ QSqlField field("test", QVariant::String, "test");
+ QFETCH(QString, tableName);
+ QCOMPARE(field.tableName(), QLatin1String("test"));
+ field.setTableName(tableName);
+ QCOMPARE(field.tableName(), tableName);
+}
+
QTEST_MAIN(tst_QSqlField)
#include "tst_qsqlfield.moc"
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
index 35f86772e2..92e4b580e7 100644
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
@@ -170,6 +170,8 @@ private slots:
void blobsPreparedQuery();
void emptyTableNavigate_data() { generic_data(); }
void emptyTableNavigate();
+ void timeStampParsing_data() { generic_data(); }
+ void timeStampParsing();
#ifdef NOT_READY_YET
void task_229811();
@@ -2887,6 +2889,25 @@ void tst_QSqlQuery::emptyTableNavigate()
}
}
+void tst_QSqlQuery::timeStampParsing()
+{
+ QFETCH(QString, dbName);
+ QSqlDatabase db = QSqlDatabase::database(dbName);
+ CHECK_DATABASE(db);
+ QSqlQuery q(db);
+ QVERIFY_SQL(q, exec(
+ "CREATE TABLE \"main\".\"datetest\" ("
+ "\"id\" integer NOT NULL PRIMARY KEY AUTOINCREMENT,"
+ "\"datefield\" timestamp);"
+ ));
+ QVERIFY_SQL(q, exec(
+ "INSERT INTO datetest (datefield) VALUES (current_timestamp);"
+ ));
+ QVERIFY_SQL(q, exec("SELECT * FROM datetest;"));
+ while (q.next())
+ QVERIFY(q.value(1).toDateTime().isValid());
+}
+
void tst_QSqlQuery::task_217003()
{
QFETCH( QString, dbName );
diff --git a/tests/auto/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp b/tests/auto/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp
index c5cca6c33b..83a61b91d7 100644
--- a/tests/auto/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp
+++ b/tests/auto/sql/kernel/qsqlrecord/tst_qsqlrecord.cpp
@@ -111,10 +111,10 @@ void tst_QSqlRecord::createTestRecord()
{
delete rec;
rec = new QSqlRecord();
- fields[ 0 ] = new QSqlField( "string", QVariant::String );
- fields[ 1 ] = new QSqlField( "int", QVariant::Int );
- fields[ 2 ] = new QSqlField( "double", QVariant::Double );
- fields[ 3 ] = new QSqlField( "bool", QVariant::Bool );
+ fields[0] = new QSqlField(QStringLiteral("string"), QVariant::String, QStringLiteral("stringtable"));
+ fields[1] = new QSqlField(QStringLiteral("int"), QVariant::Int, QStringLiteral("inttable"));
+ fields[2] = new QSqlField(QStringLiteral("double"), QVariant::Double, QStringLiteral("doubletable"));
+ fields[3] = new QSqlField(QStringLiteral("bool"), QVariant::Bool);
for ( int i = 0; i < NUM_FIELDS; ++i )
rec->append( *(fields[ i ] ) );
}
@@ -124,12 +124,14 @@ void tst_QSqlRecord::append()
{
delete rec;
rec = new QSqlRecord();
- rec->append( QSqlField( "string", QVariant::String ) );
+ rec->append(QSqlField("string", QVariant::String, QStringLiteral("stringtable")));
QCOMPARE( rec->field( 0 ).name(), (QString) "string" );
+ QCOMPARE(rec->field(0).tableName(), QStringLiteral("stringtable"));
QVERIFY( !rec->isEmpty() );
QCOMPARE( (int)rec->count(), 1 );
- rec->append( QSqlField( "int", QVariant::Int ) );
+ rec->append(QSqlField("int", QVariant::Int, QStringLiteral("inttable")));
QCOMPARE( rec->field( 1 ).name(), (QString) "int" );
+ QCOMPARE(rec->field(1).tableName(), QStringLiteral("inttable"));
QCOMPARE( (int)rec->count(), 2 );
rec->append( QSqlField( "double", QVariant::Double ) );
QCOMPARE( rec->field( 2 ).name(), (QString) "double" );
@@ -381,7 +383,7 @@ void tst_QSqlRecord::operator_Assign()
buf3.remove( NUM_FIELDS - 1 );
QSqlRecord buf5 = buf3;
for ( i = 0; i < NUM_FIELDS - 1; ++i ) {
- QSqlField fi ( fields[ i ]->name(), fields[ i ]->type() );
+ QSqlField fi(fields[i]->name(), fields[i]->type(), fields[i]->tableName());
fi.clear();
QVERIFY( buf5.field( i ) == fi );
QVERIFY( buf5.isGenerated( i ) );
@@ -394,6 +396,8 @@ void tst_QSqlRecord::position()
int i;
for ( i = 0; i < NUM_FIELDS; ++i ) {
QCOMPARE( rec->indexOf( fields[ i ]->name() ), i );
+ if (!fields[i]->tableName().isEmpty())
+ QCOMPARE(rec->indexOf(fields[i]->tableName() + QChar('.') + fields[i]->name()), i);
}
}
diff --git a/tests/auto/testlib/selftests/expected_pairdiagnostics.lightxml b/tests/auto/testlib/selftests/expected_pairdiagnostics.lightxml
new file mode 100644
index 0000000000..95b932e3c4
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_pairdiagnostics.lightxml
@@ -0,0 +1,30 @@
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="testQPair">
+<Incident type="fail" file="../../../qt5/qtbase_fixItemData/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp" line="51">
+ <Description><![CDATA[Compared values are not the same
+ Actual (pair1): "QPair(1,1)"
+ Expected (pair2): "QPair(1,2)"]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="testStdPair">
+<Incident type="fail" file="../../../qt5/qtbase_fixItemData/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp" line="58">
+ <Description><![CDATA[Compared values are not the same
+ Actual (pair1): "std::pair(1,1)"
+ Expected (pair2): "std::pair(1,2)"]]></Description>
+</Incident>
+ <Duration msecs="0"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0"/>
+</TestFunction>
+<Duration msecs="0"/>
diff --git a/tests/auto/testlib/selftests/expected_pairdiagnostics.teamcity b/tests/auto/testlib/selftests/expected_pairdiagnostics.teamcity
new file mode 100644
index 0000000000..06883570ac
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_pairdiagnostics.teamcity
@@ -0,0 +1,12 @@
+##teamcity[testSuiteStarted name='tst_PairDiagnostics' flowId='tst_PairDiagnostics']
+##teamcity[testStarted name='initTestCase()' flowId='tst_PairDiagnostics']
+##teamcity[testFinished name='initTestCase()' flowId='tst_PairDiagnostics']
+##teamcity[testStarted name='testQPair()' flowId='tst_PairDiagnostics']
+##teamcity[testFailed name='testQPair()' message='Failure! |[Loc: ../../../qt5/qtbase_fixItemData/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp(51)|]' details='Compared values are not the same|n Actual (pair1): "QPair(1,1)"|n Expected (pair2): "QPair(1,2)"' flowId='tst_PairDiagnostics']
+##teamcity[testFinished name='testQPair()' flowId='tst_PairDiagnostics']
+##teamcity[testStarted name='testStdPair()' flowId='tst_PairDiagnostics']
+##teamcity[testFailed name='testStdPair()' message='Failure! |[Loc: ../../../qt5/qtbase_fixItemData/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp(58)|]' details='Compared values are not the same|n Actual (pair1): "std::pair(1,1)"|n Expected (pair2): "std::pair(1,2)"' flowId='tst_PairDiagnostics']
+##teamcity[testFinished name='testStdPair()' flowId='tst_PairDiagnostics']
+##teamcity[testStarted name='cleanupTestCase()' flowId='tst_PairDiagnostics']
+##teamcity[testFinished name='cleanupTestCase()' flowId='tst_PairDiagnostics']
+##teamcity[testSuiteFinished name='tst_PairDiagnostics' flowId='tst_PairDiagnostics']
diff --git a/tests/auto/testlib/selftests/expected_pairdiagnostics.txt b/tests/auto/testlib/selftests/expected_pairdiagnostics.txt
new file mode 100644
index 0000000000..e09b9a560f
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_pairdiagnostics.txt
@@ -0,0 +1,14 @@
+********* Start testing of tst_PairDiagnostics *********
+Config: Using QtTest library @INSERT_QT_VERSION_HERE@, Qt @INSERT_QT_VERSION_HERE@
+PASS : tst_PairDiagnostics::initTestCase()
+FAIL! : tst_PairDiagnostics::testQPair() Compared values are not the same
+ Actual (pair1): "QPair(1,1)"
+ Expected (pair2): "QPair(1,2)"
+ Loc: [../../../qt5/qtbase_fixItemData/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp(51)]
+FAIL! : tst_PairDiagnostics::testStdPair() Compared values are not the same
+ Actual (pair1): "std::pair(1,1)"
+ Expected (pair2): "std::pair(1,2)"
+ Loc: [../../../qt5/qtbase_fixItemData/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp(58)]
+PASS : tst_PairDiagnostics::cleanupTestCase()
+Totals: 2 passed, 2 failed, 0 skipped, 0 blacklisted, 1ms
+********* Finished testing of tst_PairDiagnostics *********
diff --git a/tests/auto/testlib/selftests/expected_pairdiagnostics.xml b/tests/auto/testlib/selftests/expected_pairdiagnostics.xml
new file mode 100644
index 0000000000..47921e0b8a
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_pairdiagnostics.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<TestCase name="tst_PairDiagnostics">
+<Environment>
+ <QtVersion>@INSERT_QT_VERSION_HERE@</QtVersion>
+ <QtBuild/>
+ <QTestVersion>@INSERT_QT_VERSION_HERE@</QTestVersion>
+</Environment>
+<TestFunction name="initTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0.680795"/>
+</TestFunction>
+<TestFunction name="testQPair">
+<Incident type="fail" file="../../../qt5/qtbase_fixItemData/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp" line="51">
+ <Description><![CDATA[Compared values are not the same
+ Actual (pair1): "QPair(1,1)"
+ Expected (pair2): "QPair(1,2)"]]></Description>
+</Incident>
+ <Duration msecs="0.085705"/>
+</TestFunction>
+<TestFunction name="testStdPair">
+<Incident type="fail" file="../../../qt5/qtbase_fixItemData/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp" line="58">
+ <Description><![CDATA[Compared values are not the same
+ Actual (pair1): "std::pair(1,1)"
+ Expected (pair2): "std::pair(1,2)"]]></Description>
+</Incident>
+ <Duration msecs="0.030780"/>
+</TestFunction>
+<TestFunction name="cleanupTestCase">
+<Incident type="pass" file="" line="0" />
+ <Duration msecs="0.039052"/>
+</TestFunction>
+<Duration msecs="0.995227"/>
+</TestCase>
diff --git a/tests/auto/testlib/selftests/expected_pairdiagnostics.xunitxml b/tests/auto/testlib/selftests/expected_pairdiagnostics.xunitxml
new file mode 100644
index 0000000000..cf2a30b84a
--- /dev/null
+++ b/tests/auto/testlib/selftests/expected_pairdiagnostics.xunitxml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<testsuite errors="0" failures="2" tests="4" name="tst_PairDiagnostics">
+ <properties>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QTestVersion"/>
+ <property value="@INSERT_QT_VERSION_HERE@" name="QtVersion"/>
+ <property value="" name="QtBuild"/>
+ </properties>
+ <testcase result="pass" name="initTestCase"/>
+ <testcase result="fail" name="testQPair">
+ <failure message="Compared values are not the same
+ Actual (pair1): &quot;QPair(1,1)&quot;
+ Expected (pair2): &quot;QPair(1,2)&quot;" result="fail"/>
+ </testcase>
+ <testcase result="fail" name="testStdPair">
+ <failure message="Compared values are not the same
+ Actual (pair1): &quot;std::pair(1,1)&quot;
+ Expected (pair2): &quot;std::pair(1,2)&quot;" result="fail"/>
+ </testcase>
+ <testcase result="pass" name="cleanupTestCase"/>
+ <system-err/>
+</testsuite>
diff --git a/tests/auto/testlib/selftests/generate_expected_output.py b/tests/auto/testlib/selftests/generate_expected_output.py
index 202c4cc426..a3a66da98b 100755
--- a/tests/auto/testlib/selftests/generate_expected_output.py
+++ b/tests/auto/testlib/selftests/generate_expected_output.py
@@ -32,9 +32,18 @@
# Usage: cd to the build directory corresponding to this script's
# location; invoke this script; optionally pass the names of sub-dirs
# to limit which tests to regenerate expected_* files for.
+#
+# The saved test output is used by ./tst_selftests.cpp, which compares
+# it to the output of each test, ignoring various boring changes.
+# This script canonicalises the parts that would exhibit those boring
+# changes, so as to avoid noise in git (and conflicts in merges) for
+# the saved copies of the output. If you add or remove any files, be
+# sure to update selftests.qrc to match; the selftest only sees files
+# listed there.
import os
import subprocess
+import re
class Fail (Exception): pass
@@ -55,17 +64,18 @@ class Cleaner (object):
def __init__(self, here, command):
"""Set up the details we need for later cleaning.
- Takes two parameters: here is $PWD and command is how this
- script was invoked, from which we'll work out where it is; in
- a shadow build, the former is the build tree's location
- corresponding to this last. Checks $PWD does look as expected
- in a build tree - raising Fail() if not - then invokes qmake
- to discover Qt version (saved as .version for the benefit of
- clients) and prepares the sequence of (regex, replace) pairs
- that .clean() needs to do its job."""
- self.version, self.__replace = self.__getPatterns(here, command)
-
- import re
+ Takes two parameters: here is os.getcwd() and command is how
+ this script was invoked, from which we'll work out where it
+ is; in a shadow build, the former is the build tree's location
+ corresponding to this last. Saves the directory of this
+ script as self.sourceDir, so client can find tst_selftests.cpp
+ there. Checks here does look as expected in a build tree -
+ raising Fail() if not - then invokes qmake to discover Qt
+ version (saved as .version for the benefit of clients) and
+ prepares the sequence of (regex, replace) pairs that .clean()
+ needs to do its job."""
+ self.version, self.sourceDir, self.__replace = self.__getPatterns(here, command)
+
@staticmethod
def __getPatterns(here, command,
patterns = (
@@ -80,9 +90,10 @@ class Cleaner (object):
(r'( *<QtBuild)>[^<]+</QtBuild>', r'\1/>'), # xml, lightxml
(r'(<property value=")[^"]+(" name="QtBuild"/>)', r'\1\2'), # xunitxml
# Line numbers in source files:
+ (r'(ASSERT: ".*" in file .*, line) \d+', r'\1 0'), # lightxml
(r'(Loc: \[[^[\]()]+)\(\d+\)', r'\1(0)'), # txt
(r'(\[Loc: [^[\]()]+)\(\d+\)', r'\1(0)'), # teamcity
- (r'(<Incident.*\bfile=.*\bline=)"\d+"', r'\1"0"'), # lightxml, xml
+ (r'(<(?:Incident|Message)\b.*\bfile=.*\bline=)"\d+"', r'\1"0"'), # lightxml, xml
),
precook = re.compile):
"""Private implementation details of __init__()."""
@@ -131,8 +142,7 @@ class Cleaner (object):
patterns += tuple((root.replace('-', '&#x0*2D;'), r'')
for root in roots if '-' in root)
- return qtver, tuple((precook(p), r) for p, r in patterns)
- del re
+ return qtver, scriptPath, tuple((precook(p), r) for p, r in patterns)
def clean(self, data):
"""Remove volatile details from test output.
@@ -145,6 +155,62 @@ class Cleaner (object):
line = searchRe.sub(replaceExp, line)
yield line
+class Scanner (object):
+ """Knows which subdirectories to generate output for.
+
+ Tell its constructor the name of this source directory (see
+ Cleaner's .sourceDir) and it'll scan tst_selftests.cpp for the
+ list. Its .subdirs() can then filter a user-supplied list of
+ subdirs or generate the full list, when the user supplied
+ none."""
+ def __init__(self, srcDir):
+ self.__tested = tuple(self.__scan_cpp(os.path.join(srcDir, 'tst_selftests.cpp')))
+
+ @staticmethod
+ def __scan_cpp(name,
+ trimc = re.compile(r'/\*.*?\*/').sub,
+ trimcpp = re.compile(r'//.*$').sub,
+ first = re.compile(r'(QStringList|auto)\s+tests\s*=\s*QStringList\(\)').match,
+ match = re.compile(r'(?:tests\s*)?<<\s*"(\w+)"').match,
+ last = re.compile(r'\bfor.*\b(LoggerSet|auto)\b.*\ballLoggerSets\(\)').search):
+ """Scans tst_selftests.cpp to find which subdirs matter.
+
+ There's a list, tests, to which all subdir names get added, if
+ they're to be tested. Other sub-dirs aren't tested, so
+ there's no sense in generating output for them."""
+ scan = False
+ with open(name) as src:
+ for line in src:
+ line = trimcpp('', trimc('', line.strip())).strip()
+ if not scan:
+ got = first(line)
+ if got:
+ scan, line = True, line[len(got.group()):]
+ if scan:
+ if last(line): break
+ got = match(line)
+ while got:
+ yield got.group(1)
+ line = line[len(got.group()):].strip()
+ got = match(line)
+
+ def subdirs(self, given):
+ if given:
+ for d in given:
+ if not os.path.isdir(d):
+ print('No such directory:', d, '- skipped')
+ elif d in self.__tested:
+ yield d
+ else:
+ print('Directory', d, 'is not tested by tst_selftests.cpp')
+ else:
+ for d in self.__tested:
+ if os.path.isdir(d):
+ yield d
+ else:
+ print('tst_selftests.cpp names', d, "as a test, but it doesn't exist")
+del re
+
def generateTestData(testname, clean,
formats = ('xml', 'txt', 'xunitxml', 'lightxml', 'teamcity'),
extraArgs = {
@@ -190,7 +256,7 @@ def main(name, *args):
herePath = os.getcwd()
cleaner = Cleaner(herePath, name)
- tests = args if args else [d for d in os.listdir('.') if os.path.isdir(d)]
+ tests = tuple(Scanner(cleaner.sourceDir).subdirs(args))
print("Generating", len(tests), "test results for", cleaner.version, "in:", herePath)
for path in tests:
generateTestData(path, cleaner.clean)
diff --git a/tests/auto/testlib/selftests/pairdiagnostics/pairdiagnostics.pro b/tests/auto/testlib/selftests/pairdiagnostics/pairdiagnostics.pro
new file mode 100644
index 0000000000..1c07c93e9d
--- /dev/null
+++ b/tests/auto/testlib/selftests/pairdiagnostics/pairdiagnostics.pro
@@ -0,0 +1,6 @@
+SOURCES += tst_pairdiagnostics.cpp
+QT = core testlib
+
+CONFIG -= app_bundle debug_and_release_target
+
+TARGET = pairdiagnostics
diff --git a/src/tools/uic/cpp/cppwriteiconinitialization.h b/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp
index 588cb1bc67..bbee5334fe 100644
--- a/src/tools/uic/cpp/cppwriteiconinitialization.h
+++ b/tests/auto/testlib/selftests/pairdiagnostics/tst_pairdiagnostics.cpp
@@ -3,7 +3,7 @@
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
-** This file is part of the tools applications of the Qt Toolkit.
+** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
@@ -26,43 +26,38 @@
**
****************************************************************************/
-#ifndef CPPWRITEICONINITIALIZATION_H
-#define CPPWRITEICONINITIALIZATION_H
+// Make sure we get a real Q_ASSERT even in release builds
+#ifdef QT_NO_DEBUG
+# undef QT_NO_DEBUG
+#endif
-#include "treewalker.h"
+#include <QtCore/QCoreApplication>
+#include <QtCore/QPair>
+#include <QtTest/QtTest>
-class QString;
-
-QT_BEGIN_NAMESPACE
-
-class QTextStream;
-class Driver;
-class Uic;
-
-struct Option;
-
-namespace CPP {
-
-class WriteIconInitialization : public TreeWalker
+class tst_PairDiagnostics: public QObject
{
-public:
- WriteIconInitialization(Uic *uic);
+ Q_OBJECT
- void acceptUI(DomUI *node) Q_DECL_OVERRIDE;
- void acceptImages(DomImages *images) Q_DECL_OVERRIDE;
- void acceptImage(DomImage *image) Q_DECL_OVERRIDE;
-
- static QString iconFromDataFunction();
-
-private:
- Uic *uic;
- Driver *driver;
- QTextStream &output;
- const Option &option;
+private slots:
+ void testQPair() const;
+ void testStdPair() const;
};
-} // namespace CPP
+void tst_PairDiagnostics::testQPair() const
+{
+ QPair<int, int> pair1 = qMakePair(1, 1);
+ QPair<int, int> pair2 = qMakePair(1, 2);
+ QCOMPARE(pair1, pair2);
+}
+
+void tst_PairDiagnostics::testStdPair() const
+{
+ std::pair<int, int> pair1 = std::make_pair(1, 1);
+ std::pair<int, int> pair2 = std::make_pair(1, 2);
+ QCOMPARE(pair1, pair2);
+}
-QT_END_NAMESPACE
+QTEST_MAIN(tst_PairDiagnostics)
-#endif // CPPWRITEICONINITIALIZATION_H
+#include "tst_pairdiagnostics.moc"
diff --git a/tests/auto/testlib/selftests/selftests.pri b/tests/auto/testlib/selftests/selftests.pri
index 66c7e06760..0287e35447 100644
--- a/tests/auto/testlib/selftests/selftests.pri
+++ b/tests/auto/testlib/selftests/selftests.pri
@@ -28,6 +28,7 @@ SUBPROGRAMS = \
longstring \
maxwarnings \
multiexec \
+ pairdiagnostics \
printdatatags \
printdatatagswithglobaltags \
qexecstringlist \
diff --git a/tests/auto/testlib/selftests/selftests.qrc b/tests/auto/testlib/selftests/selftests.qrc
index 3c3fef28d9..02e8adb6b4 100644
--- a/tests/auto/testlib/selftests/selftests.qrc
+++ b/tests/auto/testlib/selftests/selftests.qrc
@@ -115,6 +115,11 @@
<file>expected_maxwarnings.xml</file>
<file>expected_maxwarnings.xunitxml</file>
<file>expected_multiexec.txt</file>
+ <file>expected_pairdiagnostics.lightxml</file>
+ <file>expected_pairdiagnostics.teamcity</file>
+ <file>expected_pairdiagnostics.txt</file>
+ <file>expected_pairdiagnostics.xml</file>
+ <file>expected_pairdiagnostics.xunitxml</file>
<file>expected_printdatatags.txt</file>
<file>expected_printdatatagswithglobaltags.txt</file>
<file>expected_qexecstringlist.txt</file>
diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp
index e7123fc059..64f324e26c 100644
--- a/tests/auto/testlib/selftests/tst_selftests.cpp
+++ b/tests/auto/testlib/selftests/tst_selftests.cpp
@@ -395,6 +395,7 @@ void tst_Selftests::runSubTest_data()
<< "longstring"
<< "maxwarnings"
<< "multiexec"
+ << "pairdiagnostics"
<< "printdatatags"
<< "printdatatagswithglobaltags"
<< "qexecstringlist"
diff --git a/tests/auto/tools/moc/error-on-wrong-notify.h b/tests/auto/tools/moc/error-on-wrong-notify.h
index 11f5e954db..9e6b27bff3 100644
--- a/tests/auto/tools/moc/error-on-wrong-notify.h
+++ b/tests/auto/tools/moc/error-on-wrong-notify.h
@@ -28,7 +28,7 @@
#ifndef ERROR_ON_WRONG_NOTIFY_H
#define ERROR_ON_WRONG_NOTIFY_H
-#include <QObject>
+#include <QtCore/QObject>
class ClassWithWrongNOTIFY : public QObject
{
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index 8189227cbe..55e8054a70 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -1830,13 +1830,25 @@ void tst_Moc::notifyError()
const QString header = m_sourceDirectory + QStringLiteral("/error-on-wrong-notify.h");
proc.start(m_moc, QStringList(header));
QVERIFY(proc.waitForFinished());
- QCOMPARE(proc.exitCode(), 1);
+ QCOMPARE(proc.exitCode(), 0);
QCOMPARE(proc.exitStatus(), QProcess::NormalExit);
QByteArray mocOut = proc.readAllStandardOutput();
- QVERIFY(mocOut.isEmpty());
- QString mocError = QString::fromLocal8Bit(proc.readAllStandardError());
- QCOMPARE(mocError, header +
- QString(":42: Error: NOTIFY signal 'fooChanged' of property 'foo' does not exist in class ClassWithWrongNOTIFY.\n"));
+ QVERIFY(!mocOut.isEmpty());
+ QCOMPARE(proc.readAllStandardError(), QByteArray());
+
+ QStringList args;
+ args << "-c" << "-x" << "c++" << "-I" << "."
+ << "-I" << qtIncludePath << "-o" << "/dev/null" << "-fPIC" << "-std=c++11" << "-";
+ proc.start("gcc", args);
+ QVERIFY(proc.waitForStarted());
+ proc.write(mocOut);
+ proc.closeWriteChannel();
+
+ QVERIFY(proc.waitForFinished());
+ QCOMPARE(proc.exitCode(), 1);
+ const QString gccOutput = QString::fromLocal8Bit(proc.readAllStandardError());
+ QVERIFY(gccOutput.contains(QLatin1String("error")));
+ QVERIFY(gccOutput.contains(QLatin1String("fooChanged")));
#else
QSKIP("Only tested on linux/gcc");
#endif
diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp
index 03fd4753fd..387a2fb84e 100644
--- a/tests/auto/tools/qmakelib/evaltest.cpp
+++ b/tests/auto/tools/qmakelib/evaltest.cpp
@@ -2191,6 +2191,44 @@ void tst_qmakelib::addTestFunctions(const QString &qindir)
<< ""
<< true;
+ QTest::newRow("versionAtLeast(): true")
+ << "VAR = 1.2.3\nversionAtLeast(VAR, 1.2.3): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("versionAtLeast(): false")
+ << "VAR = 1.2.2\nversionAtLeast(VAR, 1.2.3): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("versionAtLeast(): bad number of arguments")
+ << "versionAtLeast(1): OK = 1\nversionAtLeast(1, 2, 3): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: versionAtLeast(variable, versionNumber) requires two arguments.\n"
+ "##:2: versionAtLeast(variable, versionNumber) requires two arguments."
+ << true;
+
+ QTest::newRow("versionAtMost(): true")
+ << "VAR = 1.2.3\nversionAtMost(VAR, 1.2.3): OK = 1"
+ << "OK = 1"
+ << ""
+ << true;
+
+ QTest::newRow("versionAtMost(): false")
+ << "VAR = 1.2.3\nversionAtMost(VAR, 1.2.2): OK = 1"
+ << "OK = UNDEF"
+ << ""
+ << true;
+
+ QTest::newRow("versionAtMost(): bad number of arguments")
+ << "versionAtMost(1): OK = 1\nversionAtMost(1, 2, 3): OK = 1"
+ << "OK = UNDEF"
+ << "##:1: versionAtMost(variable, versionNumber) requires two arguments.\n"
+ "##:2: versionAtMost(variable, versionNumber) requires two arguments."
+ << true;
+
QTest::newRow("clear(): top-level")
<< "VAR = there\nclear(VAR): OK = 1"
<< "OK = 1\nVAR ="
diff --git a/tests/auto/tools/uic/baseline/config.ui.h b/tests/auto/tools/uic/baseline/config.ui.h
index 2dadae383e..002eababb9 100644
--- a/tests/auto/tools/uic/baseline/config.ui.h
+++ b/tests/auto/tools/uic/baseline/config.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'config.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.10.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -286,6 +286,7 @@ public:
hboxLayout2->addWidget(TextLabel1_3);
skin = new QComboBox(Config);
+ skin->addItem(QString());
skin->setObjectName(QStringLiteral("skin"));
QSizePolicy sizePolicy2(QSizePolicy::Expanding, QSizePolicy::Fixed);
sizePolicy2.setHorizontalStretch(0);
@@ -729,10 +730,8 @@ public:
depth_32->setText(QApplication::translate("Config", "32 bit", Q_NULLPTR));
depth_32_argb->setText(QApplication::translate("Config", "32 bit ARGB", Q_NULLPTR));
TextLabel1_3->setText(QApplication::translate("Config", "Skin", Q_NULLPTR));
- skin->clear();
- skin->insertItems(0, QStringList()
- << QApplication::translate("Config", "None", Q_NULLPTR)
- );
+ skin->setItemText(0, QApplication::translate("Config", "None", Q_NULLPTR));
+
touchScreen->setText(QApplication::translate("Config", "Emulate touch screen (no mouse move)", Q_NULLPTR));
lcdScreen->setText(QApplication::translate("Config", "Emulate LCD screen (Only with fixed zoom of 3.0 times magnification)", Q_NULLPTR));
TextLabel1->setText(QApplication::translate("Config", "<p>Note that any applications using the virtual framebuffer will be terminated if you change the Size or Depth <i>above</i>. You may freely modify the Gamma <i>below</i>.", Q_NULLPTR));
diff --git a/tests/auto/tools/uic/baseline/default.ui.h b/tests/auto/tools/uic/baseline/default.ui.h
index 03d97f86f1..e81f1bc2ca 100644
--- a/tests/auto/tools/uic/baseline/default.ui.h
+++ b/tests/auto/tools/uic/baseline/default.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'default.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.10.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -91,6 +91,10 @@ public:
gridLayout->addWidget(nameLabel, 0, 0, 1, 1);
nameCombo = new QComboBox(centralwidget);
+ nameCombo->addItem(QString());
+ nameCombo->addItem(QString());
+ nameCombo->addItem(QString());
+ nameCombo->addItem(QString());
nameCombo->setObjectName(QStringLiteral("nameCombo"));
nameCombo->setEditable(true);
@@ -169,6 +173,11 @@ public:
gridLayout->addWidget(professionList, 5, 1, 1, 3);
countryCombo = new QComboBox(centralwidget);
+ countryCombo->addItem(QString());
+ countryCombo->addItem(QString());
+ countryCombo->addItem(QString());
+ countryCombo->addItem(QString());
+ countryCombo->addItem(QString());
countryCombo->setObjectName(QStringLiteral("countryCombo"));
gridLayout->addWidget(countryCombo, 4, 1, 1, 3);
@@ -225,13 +234,11 @@ public:
editStyleAction->setText(QApplication::translate("MainWindow", "Edit &Style", Q_NULLPTR));
aboutAction->setText(QApplication::translate("MainWindow", "About", Q_NULLPTR));
nameLabel->setText(QApplication::translate("MainWindow", "&Name:", Q_NULLPTR));
- nameCombo->clear();
- nameCombo->insertItems(0, QStringList()
- << QApplication::translate("MainWindow", "Girish", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Jasmin", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Simon", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Zack", Q_NULLPTR)
- );
+ nameCombo->setItemText(0, QApplication::translate("MainWindow", "Girish", Q_NULLPTR));
+ nameCombo->setItemText(1, QApplication::translate("MainWindow", "Jasmin", Q_NULLPTR));
+ nameCombo->setItemText(2, QApplication::translate("MainWindow", "Simon", Q_NULLPTR));
+ nameCombo->setItemText(3, QApplication::translate("MainWindow", "Zack", Q_NULLPTR));
+
#ifndef QT_NO_TOOLTIP
nameCombo->setToolTip(QApplication::translate("MainWindow", "Specify your name", Q_NULLPTR));
#endif // QT_NO_TOOLTIP
@@ -285,14 +292,12 @@ public:
#ifndef QT_NO_WHATSTHIS
professionList->setWhatsThis(QApplication::translate("MainWindow", "Select your profession", Q_NULLPTR));
#endif // QT_NO_WHATSTHIS
- countryCombo->clear();
- countryCombo->insertItems(0, QStringList()
- << QApplication::translate("MainWindow", "Germany", Q_NULLPTR)
- << QApplication::translate("MainWindow", "India", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Norway", Q_NULLPTR)
- << QApplication::translate("MainWindow", "United States Of America", Q_NULLPTR)
- << QApplication::translate("MainWindow", "United Kingdom", Q_NULLPTR)
- );
+ countryCombo->setItemText(0, QApplication::translate("MainWindow", "Germany", Q_NULLPTR));
+ countryCombo->setItemText(1, QApplication::translate("MainWindow", "India", Q_NULLPTR));
+ countryCombo->setItemText(2, QApplication::translate("MainWindow", "Norway", Q_NULLPTR));
+ countryCombo->setItemText(3, QApplication::translate("MainWindow", "United States Of America", Q_NULLPTR));
+ countryCombo->setItemText(4, QApplication::translate("MainWindow", "United Kingdom", Q_NULLPTR));
+
#ifndef QT_NO_TOOLTIP
countryCombo->setToolTip(QApplication::translate("MainWindow", "Specify your country", Q_NULLPTR));
#endif // QT_NO_TOOLTIP
diff --git a/tests/auto/tools/uic/baseline/embeddeddialog.ui.h b/tests/auto/tools/uic/baseline/embeddeddialog.ui.h
index 69027286b6..446c5d54ff 100644
--- a/tests/auto/tools/uic/baseline/embeddeddialog.ui.h
+++ b/tests/auto/tools/uic/baseline/embeddeddialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'embeddeddialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.10.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -49,6 +49,8 @@ public:
formLayout->setWidget(0, QFormLayout::LabelRole, label);
layoutDirection = new QComboBox(embeddedDialog);
+ layoutDirection->addItem(QString());
+ layoutDirection->addItem(QString());
layoutDirection->setObjectName(QStringLiteral("layoutDirection"));
formLayout->setWidget(0, QFormLayout::FieldRole, layoutDirection);
@@ -100,11 +102,9 @@ public:
{
embeddedDialog->setWindowTitle(QApplication::translate("embeddedDialog", "Embedded Dialog", Q_NULLPTR));
label->setText(QApplication::translate("embeddedDialog", "Layout Direction:", Q_NULLPTR));
- layoutDirection->clear();
- layoutDirection->insertItems(0, QStringList()
- << QApplication::translate("embeddedDialog", "Left to Right", Q_NULLPTR)
- << QApplication::translate("embeddedDialog", "Right to Left", Q_NULLPTR)
- );
+ layoutDirection->setItemText(0, QApplication::translate("embeddedDialog", "Left to Right", Q_NULLPTR));
+ layoutDirection->setItemText(1, QApplication::translate("embeddedDialog", "Right to Left", Q_NULLPTR));
+
label_2->setText(QApplication::translate("embeddedDialog", "Select Font:", Q_NULLPTR));
label_3->setText(QApplication::translate("embeddedDialog", "Style:", Q_NULLPTR));
label_4->setText(QApplication::translate("embeddedDialog", "Layout spacing:", Q_NULLPTR));
diff --git a/tests/auto/tools/uic/baseline/pagefold.ui.h b/tests/auto/tools/uic/baseline/pagefold.ui.h
index b82c8d7fbd..5a6277089d 100644
--- a/tests/auto/tools/uic/baseline/pagefold.ui.h
+++ b/tests/auto/tools/uic/baseline/pagefold.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'pagefold.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.10.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -102,6 +102,10 @@ public:
#endif
gridLayout->setObjectName(QStringLiteral("gridLayout"));
nameCombo = new QComboBox(mainFrame);
+ nameCombo->addItem(QString());
+ nameCombo->addItem(QString());
+ nameCombo->addItem(QString());
+ nameCombo->addItem(QString());
nameCombo->setObjectName(QStringLiteral("nameCombo"));
nameCombo->setEditable(true);
@@ -180,6 +184,13 @@ public:
gridLayout->addWidget(label, 5, 0, 1, 1);
countryCombo = new QComboBox(mainFrame);
+ countryCombo->addItem(QString());
+ countryCombo->addItem(QString());
+ countryCombo->addItem(QString());
+ countryCombo->addItem(QString());
+ countryCombo->addItem(QString());
+ countryCombo->addItem(QString());
+ countryCombo->addItem(QString());
countryCombo->setObjectName(QStringLiteral("countryCombo"));
gridLayout->addWidget(countryCombo, 4, 1, 1, 3);
@@ -238,13 +249,11 @@ public:
aboutQtAction->setText(QApplication::translate("MainWindow", "About Qt", Q_NULLPTR));
editStyleAction->setText(QApplication::translate("MainWindow", "Edit &Style", Q_NULLPTR));
aboutAction->setText(QApplication::translate("MainWindow", "About", Q_NULLPTR));
- nameCombo->clear();
- nameCombo->insertItems(0, QStringList()
- << QApplication::translate("MainWindow", "Girish", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Jasmin", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Simon", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Zack", Q_NULLPTR)
- );
+ nameCombo->setItemText(0, QApplication::translate("MainWindow", "Girish", Q_NULLPTR));
+ nameCombo->setItemText(1, QApplication::translate("MainWindow", "Jasmin", Q_NULLPTR));
+ nameCombo->setItemText(2, QApplication::translate("MainWindow", "Simon", Q_NULLPTR));
+ nameCombo->setItemText(3, QApplication::translate("MainWindow", "Zack", Q_NULLPTR));
+
#ifndef QT_NO_TOOLTIP
nameCombo->setToolTip(QApplication::translate("MainWindow", "Specify your name", Q_NULLPTR));
#endif // QT_NO_TOOLTIP
@@ -296,16 +305,14 @@ public:
professionList->setWhatsThis(QApplication::translate("MainWindow", "Specify your name here", Q_NULLPTR));
#endif // QT_NO_WHATSTHIS
label->setText(QApplication::translate("MainWindow", "Profession:", Q_NULLPTR));
- countryCombo->clear();
- countryCombo->insertItems(0, QStringList()
- << QApplication::translate("MainWindow", "Egypt", Q_NULLPTR)
- << QApplication::translate("MainWindow", "France", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Germany", Q_NULLPTR)
- << QApplication::translate("MainWindow", "India", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Italy", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Korea", Q_NULLPTR)
- << QApplication::translate("MainWindow", "Norway", Q_NULLPTR)
- );
+ countryCombo->setItemText(0, QApplication::translate("MainWindow", "Egypt", Q_NULLPTR));
+ countryCombo->setItemText(1, QApplication::translate("MainWindow", "France", Q_NULLPTR));
+ countryCombo->setItemText(2, QApplication::translate("MainWindow", "Germany", Q_NULLPTR));
+ countryCombo->setItemText(3, QApplication::translate("MainWindow", "India", Q_NULLPTR));
+ countryCombo->setItemText(4, QApplication::translate("MainWindow", "Italy", Q_NULLPTR));
+ countryCombo->setItemText(5, QApplication::translate("MainWindow", "Korea", Q_NULLPTR));
+ countryCombo->setItemText(6, QApplication::translate("MainWindow", "Norway", Q_NULLPTR));
+
#ifndef QT_NO_TOOLTIP
countryCombo->setToolTip(QApplication::translate("MainWindow", "Specify country of origin", Q_NULLPTR));
#endif // QT_NO_TOOLTIP
diff --git a/tests/auto/tools/uic/baseline/previewwidget.ui.h b/tests/auto/tools/uic/baseline/previewwidget.ui.h
index 1fb96c8c70..f537924ca9 100644
--- a/tests/auto/tools/uic/baseline/previewwidget.ui.h
+++ b/tests/auto/tools/uic/baseline/previewwidget.ui.h
@@ -31,7 +31,7 @@
/********************************************************************************
** Form generated from reading UI file 'previewwidget.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.10.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -122,6 +122,7 @@ public:
vboxLayout->addWidget(LineEdit1);
ComboBox1 = new QComboBox(qdesigner_internal__PreviewWidget);
+ ComboBox1->addItem(QString());
ComboBox1->setObjectName(QStringLiteral("ComboBox1"));
vboxLayout->addWidget(ComboBox1);
@@ -239,10 +240,8 @@ public:
{
qdesigner_internal__PreviewWidget->setWindowTitle(QApplication::translate("qdesigner_internal::PreviewWidget", "Preview Window", Q_NULLPTR));
LineEdit1->setText(QApplication::translate("qdesigner_internal::PreviewWidget", "LineEdit", Q_NULLPTR));
- ComboBox1->clear();
- ComboBox1->insertItems(0, QStringList()
- << QApplication::translate("qdesigner_internal::PreviewWidget", "ComboBox", Q_NULLPTR)
- );
+ ComboBox1->setItemText(0, QApplication::translate("qdesigner_internal::PreviewWidget", "ComboBox", Q_NULLPTR));
+
PushButton1->setText(QApplication::translate("qdesigner_internal::PreviewWidget", "PushButton", Q_NULLPTR));
ButtonGroup2->setTitle(QApplication::translate("qdesigner_internal::PreviewWidget", "ButtonGroup2", Q_NULLPTR));
CheckBox1->setText(QApplication::translate("qdesigner_internal::PreviewWidget", "CheckBox1", Q_NULLPTR));
diff --git a/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h b/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h
index 94ffa45509..d7b6f38d1e 100644
--- a/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h
+++ b/tests/auto/tools/uic/baseline/stylesheeteditor.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'stylesheeteditor.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.10.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -63,6 +63,9 @@ public:
gridLayout->addItem(spacerItem1, 0, 0, 1, 1);
styleSheetCombo = new QComboBox(StyleSheetEditor);
+ styleSheetCombo->addItem(QString());
+ styleSheetCombo->addItem(QString());
+ styleSheetCombo->addItem(QString());
styleSheetCombo->setObjectName(QStringLiteral("styleSheetCombo"));
gridLayout->addWidget(styleSheetCombo, 0, 5, 1, 1);
@@ -131,12 +134,10 @@ public:
void retranslateUi(QWidget *StyleSheetEditor)
{
StyleSheetEditor->setWindowTitle(QApplication::translate("StyleSheetEditor", "Style Editor", Q_NULLPTR));
- styleSheetCombo->clear();
- styleSheetCombo->insertItems(0, QStringList()
- << QApplication::translate("StyleSheetEditor", "Default", Q_NULLPTR)
- << QApplication::translate("StyleSheetEditor", "Coffee", Q_NULLPTR)
- << QApplication::translate("StyleSheetEditor", "Pagefold", Q_NULLPTR)
- );
+ styleSheetCombo->setItemText(0, QApplication::translate("StyleSheetEditor", "Default", Q_NULLPTR));
+ styleSheetCombo->setItemText(1, QApplication::translate("StyleSheetEditor", "Coffee", Q_NULLPTR));
+ styleSheetCombo->setItemText(2, QApplication::translate("StyleSheetEditor", "Pagefold", Q_NULLPTR));
+
label_7->setText(QApplication::translate("StyleSheetEditor", "Style:", Q_NULLPTR));
applyButton->setText(QApplication::translate("StyleSheetEditor", "&Apply", Q_NULLPTR));
label_8->setText(QApplication::translate("StyleSheetEditor", "Style Sheet:", Q_NULLPTR));
diff --git a/tests/auto/tools/uic/baseline/validators.ui.h b/tests/auto/tools/uic/baseline/validators.ui.h
index e8548f1454..fab7e41e0e 100644
--- a/tests/auto/tools/uic/baseline/validators.ui.h
+++ b/tests/auto/tools/uic/baseline/validators.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'validators.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.10.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -268,6 +268,8 @@ public:
gridLayout1->addWidget(label_5, 0, 2, 1, 1);
doubleFormat = new QComboBox(groupBox_2);
+ doubleFormat->addItem(QString());
+ doubleFormat->addItem(QString());
doubleFormat->setObjectName(QStringLiteral("doubleFormat"));
gridLayout1->addWidget(doubleFormat, 0, 3, 1, 1);
@@ -384,11 +386,9 @@ public:
groupBox_2->setTitle(QApplication::translate("ValidatorsForm", "QDoubleValidator", Q_NULLPTR));
label_3->setText(QApplication::translate("ValidatorsForm", "Min:", Q_NULLPTR));
label_5->setText(QApplication::translate("ValidatorsForm", "Format:", Q_NULLPTR));
- doubleFormat->clear();
- doubleFormat->insertItems(0, QStringList()
- << QApplication::translate("ValidatorsForm", "Standard", Q_NULLPTR)
- << QApplication::translate("ValidatorsForm", "Scientific", Q_NULLPTR)
- );
+ doubleFormat->setItemText(0, QApplication::translate("ValidatorsForm", "Standard", Q_NULLPTR));
+ doubleFormat->setItemText(1, QApplication::translate("ValidatorsForm", "Scientific", Q_NULLPTR));
+
label_4->setText(QApplication::translate("ValidatorsForm", "Max:", Q_NULLPTR));
label_6->setText(QApplication::translate("ValidatorsForm", "Decimals:", Q_NULLPTR));
doubleLedWidget->setText(QString());
diff --git a/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h b/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h
index 348a83a8da..c84a6e2631 100644
--- a/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h
+++ b/tests/auto/tools/uic/baseline/wateringconfigdialog.ui.h
@@ -1,7 +1,7 @@
/********************************************************************************
** Form generated from reading UI file 'wateringconfigdialog.ui'
**
-** Created by: Qt User Interface Compiler version 5.0.0
+** Created by: Qt User Interface Compiler version 5.10.0
**
** WARNING! All changes made in this file will be lost when recompiling UI file!
********************************************************************************/
@@ -79,6 +79,12 @@ public:
gridLayout->addWidget(label_3, 0, 0, 1, 1);
plantComboBox = new QComboBox(WateringConfigDialog);
+ plantComboBox->addItem(QString());
+ plantComboBox->addItem(QString());
+ plantComboBox->addItem(QString());
+ plantComboBox->addItem(QString());
+ plantComboBox->addItem(QString());
+ plantComboBox->addItem(QString());
plantComboBox->setObjectName(QStringLiteral("plantComboBox"));
QSizePolicy sizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
sizePolicy.setHorizontalStretch(0);
@@ -173,6 +179,10 @@ public:
gridLayout->addWidget(label_5, 10, 0, 1, 1);
sourceComboBox = new QComboBox(WateringConfigDialog);
+ sourceComboBox->addItem(QString());
+ sourceComboBox->addItem(QString());
+ sourceComboBox->addItem(QString());
+ sourceComboBox->addItem(QString());
sourceComboBox->setObjectName(QStringLiteral("sourceComboBox"));
gridLayout->addWidget(sourceComboBox, 10, 1, 1, 3);
@@ -245,15 +255,13 @@ public:
{
WateringConfigDialog->setWindowTitle(QApplication::translate("WateringConfigDialog", "Watering Configuration", Q_NULLPTR));
label_3->setText(QApplication::translate("WateringConfigDialog", "Plant:", Q_NULLPTR));
- plantComboBox->clear();
- plantComboBox->insertItems(0, QStringList()
- << QApplication::translate("WateringConfigDialog", "Squash", Q_NULLPTR)
- << QApplication::translate("WateringConfigDialog", "Bean", Q_NULLPTR)
- << QApplication::translate("WateringConfigDialog", "Carrot", Q_NULLPTR)
- << QApplication::translate("WateringConfigDialog", "Strawberry", Q_NULLPTR)
- << QApplication::translate("WateringConfigDialog", "Raspberry", Q_NULLPTR)
- << QApplication::translate("WateringConfigDialog", "Blueberry", Q_NULLPTR)
- );
+ plantComboBox->setItemText(0, QApplication::translate("WateringConfigDialog", "Squash", Q_NULLPTR));
+ plantComboBox->setItemText(1, QApplication::translate("WateringConfigDialog", "Bean", Q_NULLPTR));
+ plantComboBox->setItemText(2, QApplication::translate("WateringConfigDialog", "Carrot", Q_NULLPTR));
+ plantComboBox->setItemText(3, QApplication::translate("WateringConfigDialog", "Strawberry", Q_NULLPTR));
+ plantComboBox->setItemText(4, QApplication::translate("WateringConfigDialog", "Raspberry", Q_NULLPTR));
+ plantComboBox->setItemText(5, QApplication::translate("WateringConfigDialog", "Blueberry", Q_NULLPTR));
+
label_2->setText(QApplication::translate("WateringConfigDialog", "Water when:", Q_NULLPTR));
temperatureCheckBox->setText(QApplication::translate("WateringConfigDialog", "Temperature is higher than:", Q_NULLPTR));
temperatureSpinBox->setSpecialValueText(QString());
@@ -265,13 +273,11 @@ public:
label_4->setText(QApplication::translate("WateringConfigDialog", "Amount:", Q_NULLPTR));
amountSpinBox->setSuffix(QApplication::translate("WateringConfigDialog", "l", Q_NULLPTR));
label_5->setText(QApplication::translate("WateringConfigDialog", "Source:", Q_NULLPTR));
- sourceComboBox->clear();
- sourceComboBox->insertItems(0, QStringList()
- << QApplication::translate("WateringConfigDialog", "Foundain", Q_NULLPTR)
- << QApplication::translate("WateringConfigDialog", "River", Q_NULLPTR)
- << QApplication::translate("WateringConfigDialog", "Lake", Q_NULLPTR)
- << QApplication::translate("WateringConfigDialog", "Public Water System", Q_NULLPTR)
- );
+ sourceComboBox->setItemText(0, QApplication::translate("WateringConfigDialog", "Foundain", Q_NULLPTR));
+ sourceComboBox->setItemText(1, QApplication::translate("WateringConfigDialog", "River", Q_NULLPTR));
+ sourceComboBox->setItemText(2, QApplication::translate("WateringConfigDialog", "Lake", Q_NULLPTR));
+ sourceComboBox->setItemText(3, QApplication::translate("WateringConfigDialog", "Public Water System", Q_NULLPTR));
+
label_6->setText(QApplication::translate("WateringConfigDialog", "Filter:", Q_NULLPTR));
filterCheckBox->setText(QString());
helpLabel->setText(QApplication::translate("WateringConfigDialog", "<a href=\"test\">Show Details</a>", Q_NULLPTR));
diff --git a/tests/auto/tools/uic/tst_uic.cpp b/tests/auto/tools/uic/tst_uic.cpp
index cf43cb02d3..85668c96d4 100644
--- a/tests/auto/tools/uic/tst_uic.cpp
+++ b/tests/auto/tools/uic/tst_uic.cpp
@@ -34,6 +34,7 @@
#include <QtCore/QByteArray>
#include <QtCore/QLibraryInfo>
#include <QtCore/QTemporaryDir>
+#include <QtCore/QRegularExpression>
#include <QtCore/QStandardPaths>
class tst_uic : public QObject
@@ -63,12 +64,12 @@ private:
const QString m_command;
QString m_baseline;
QTemporaryDir m_generated;
- QRegExp m_versionRegexp;
+ QRegularExpression m_versionRegexp;
};
tst_uic::tst_uic()
: m_command(QLibraryInfo::location(QLibraryInfo::BinariesPath) + QLatin1String("/uic"))
- , m_versionRegexp(QLatin1String("Created by: Qt User Interface Compiler version [.\\d]{5,5}"))
+ , m_versionRegexp(QLatin1String("\\*\\* Created by: Qt User Interface Compiler version \\d{1,2}\\.\\d{1,2}\\.\\d{1,2}"))
{
}
diff --git a/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp b/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp
index 8da6ef0363..62286d703f 100644
--- a/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp
+++ b/tests/auto/widgets/dialogs/qinputdialog/tst_qinputdialog.cpp
@@ -47,6 +47,7 @@ class tst_QInputDialog : public QObject
static void testFuncGetDouble(QInputDialog *dialog);
static void testFuncGetText(QInputDialog *dialog);
static void testFuncGetItem(QInputDialog *dialog);
+ static void testFuncSingleStepDouble(QInputDialog *dialog);
void timerEvent(QTimerEvent *event);
private slots:
void getInt_data();
@@ -61,6 +62,8 @@ private slots:
void getItem();
void task256299_getTextReturnNullStringOnRejected();
void inputMethodHintsOfChildWidget();
+ void setDoubleStep_data();
+ void setDoubleStep();
};
QString stripFraction(const QString &s)
@@ -498,5 +501,45 @@ void tst_QInputDialog::inputMethodHintsOfChildWidget()
QCOMPARE(editWidget->inputMethodHints(), Qt::ImhDigitsOnly);
}
+void tst_QInputDialog::testFuncSingleStepDouble(QInputDialog *dialog)
+{
+ QDoubleSpinBox *sbox = dialog->findChild<QDoubleSpinBox *>();
+ QVERIFY(sbox);
+ QTest::keyClick(sbox, Qt::Key_Up);
+}
+
+void tst_QInputDialog::setDoubleStep_data()
+{
+ QTest::addColumn<double>("min");
+ QTest::addColumn<double>("max");
+ QTest::addColumn<int>("decimals");
+ QTest::addColumn<double>("doubleStep");
+ QTest::addColumn<double>("actualResult");
+ QTest::newRow("step 2.0") << 0.0 << 10.0 << 0 << 2.0 << 2.0;
+ QTest::newRow("step 2.5") << 0.5 << 10.5 << 1 << 2.5 << 3.0;
+ QTest::newRow("step 2.25") << 10.05 << 20.05 << 2 << 2.25 << 12.30;
+ QTest::newRow("step 2.25 fewer decimals") << 0.5 << 10.5 << 1 << 2.25 << 2.75;
+}
+
+void tst_QInputDialog::setDoubleStep()
+{
+ QFETCH(double, min);
+ QFETCH(double, max);
+ QFETCH(int, decimals);
+ QFETCH(double, doubleStep);
+ QFETCH(double, actualResult);
+ QWidget p;
+ parent = &p;
+ doneCode = QDialog::Accepted;
+ testFunc = &tst_QInputDialog::testFuncSingleStepDouble;
+ startTimer(0);
+ bool ok = false;
+ const double result = QInputDialog::getDouble(parent, QString(), QString(), min, min,
+ max, decimals, &ok, QFlags<Qt::WindowType>(),
+ doubleStep);
+ QVERIFY(ok);
+ QCOMPARE(result, actualResult);
+}
+
QTEST_MAIN(tst_QInputDialog)
#include "tst_qinputdialog.moc"
diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
index d6c4841b22..4441337f6e 100644
--- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
+++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
@@ -185,6 +185,12 @@ void tst_QMessageBox::cleanup()
void tst_QMessageBox::sanityTest()
{
+#if defined(Q_OS_MACOS)
+ if (QSysInfo::productVersion() == QLatin1String("10.12")) {
+ QSKIP("Test hangs on macOS 10.12 -- QTQAINFRA-1362");
+ return;
+ }
+#endif
QMessageBox msgBox;
msgBox.setText("This is insane");
for (int i = 0; i < 10; i++)
diff --git a/tests/auto/widgets/gestures/gestures.pro b/tests/auto/widgets/gestures/gestures.pro
deleted file mode 100644
index 5a87a01ee2..0000000000
--- a/tests/auto/widgets/gestures/gestures.pro
+++ /dev/null
@@ -1,6 +0,0 @@
-TEMPLATE=subdirs
-SUBDIRS=\
- qgesturerecognizer \
-
-mac: SUBDIRS -= \ # Uses native recognizers
- qgesturerecognizer \
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index 121836234d..1430911cf0 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -2903,7 +2903,7 @@ void tst_QGraphicsView::scrollBarRanges()
QFETCH(ExpectedValueDescription, vmax);
QFETCH(bool, useStyledPanel);
- if (useStyledPanel && style == "Macintosh" && platformName == QStringLiteral("cocoa"))
+ if (useStyledPanel && style == "macintosh" && platformName == QStringLiteral("cocoa"))
QSKIP("Insignificant on OSX");
QScopedPointer<QStyle> stylePtr;
diff --git a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
index 83912fa2c3..a63ca49cbb 100644
--- a/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
+++ b/tests/auto/widgets/itemviews/qabstractitemview/tst_qabstractitemview.cpp
@@ -627,7 +627,9 @@ void tst_QAbstractItemView::rowDelegate()
QVERIFY(QTest::qWaitForWindowExposed(&view));
QModelIndex index = model.index(3, 0);
+ QVERIFY(!view.isPersistentEditorOpen(index));
view.openPersistentEditor(index);
+ QVERIFY(view.isPersistentEditorOpen(index));
QWidget *w = view.indexWidget(index);
QVERIFY(w);
QCOMPARE(w->metaObject()->className(), "QWidget");
@@ -647,7 +649,9 @@ void tst_QAbstractItemView::columnDelegate()
QVERIFY(QTest::qWaitForWindowExposed(&view));
QModelIndex index = model.index(0, 3);
+ QVERIFY(!view.isPersistentEditorOpen(index));
view.openPersistentEditor(index);
+ QVERIFY(view.isPersistentEditorOpen(index));
QWidget *w = view.indexWidget(index);
QVERIFY(w);
QCOMPARE(w->metaObject()->className(), "QWidget");
@@ -1235,8 +1239,8 @@ void tst_QAbstractItemView::task200665_itemEntered()
moveCursorAway(&view);
view.show();
QVERIFY(QTest::qWaitForWindowExposed(&view));
- QCursor::setPos( view.geometry().center() );
- QCoreApplication::processEvents();
+ QCursor::setPos(view.geometry().center());
+ QTRY_COMPARE(QCursor::pos(), view.geometry().center());
QSignalSpy spy(&view, SIGNAL(entered(QModelIndex)));
view.verticalScrollBar()->setValue(view.verticalScrollBar()->maximum());
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
index 5b353bb2ae..2a5895583d 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
+++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
@@ -1021,7 +1021,7 @@ void tst_QItemDelegate::decoration()
}
case QVariant::Image: {
QImage img(size, QImage::Format_Mono);
- memset(img.bits(), 0, img.byteCount());
+ memset(img.bits(), 0, img.sizeInBytes());
value = img;
break;
}
diff --git a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
index 6547bb8985..d4cb54b9ff 100644
--- a/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
+++ b/tests/auto/widgets/itemviews/qlistwidget/tst_qlistwidget.cpp
@@ -1710,12 +1710,11 @@ void tst_QListWidget::QTBUG50891_ensureSelectionModelSignalConnectionsAreSet()
list.setSelectionModel(new QItemSelectionModel(list.model()));
list.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&list));
QSignalSpy currentItemChangedSpy(&list, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)));
QSignalSpy itemSelectionChangedSpy(&list, SIGNAL(itemSelectionChanged()));
- QVERIFY(QTest::qWaitForWindowExposed(&list));
-
QCOMPARE(currentItemChangedSpy.count(), 0);
QCOMPARE(itemSelectionChangedSpy.count(), 0);
diff --git a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
index e2886cfcfe..45d33df356 100644
--- a/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
+++ b/tests/auto/widgets/itemviews/qtreeview/tst_qtreeview.cpp
@@ -169,6 +169,9 @@ private slots:
void styleOptionViewItem();
void keyboardNavigationWithDisabled();
+ void statusTip_data();
+ void statusTip();
+
// task-specific tests:
void task174627_moveLeftToRoot();
void task171902_expandWith1stColHidden();
@@ -213,6 +216,7 @@ public:
void init() {
decorationsEnabled = false;
+ statusTipsEnabled = false;
}
inline qint32 level(const QModelIndex &index) const {
@@ -294,6 +298,19 @@ public:
pm.fill(QColor::fromHsv((idx.column() % 16)*8 + 64, 254, (idx.row() % 16)*8 + 32));
return pm;
}
+ if (statusTipsEnabled && role == Qt::StatusTipRole)
+ return QString("[%1,%2,%3] -- Status").arg(idx.row()).arg(idx.column()).arg(level(idx));
+ return QVariant();
+ }
+
+ QVariant headerData(int section, Qt::Orientation orientation,
+ int role = Qt::DisplayRole) const override
+ {
+ Q_UNUSED(orientation);
+ if (section < 0 || section >= columnCount())
+ return QVariant();
+ if (statusTipsEnabled && role == Qt::StatusTipRole)
+ return QString("Header %1 -- Status").arg(section);
return QVariant();
}
@@ -339,6 +356,7 @@ public:
mutable bool fetched;
bool decorationsEnabled;
+ bool statusTipsEnabled;
int rows, cols;
int levels;
mutable bool wrongIndex;
@@ -4405,5 +4423,52 @@ void tst_QTreeView::taskQTBUG_7232_AllowUserToControlSingleStep()
QCOMPARE(hStep1, t.horizontalScrollBar()->singleStep());
}
+void tst_QTreeView::statusTip_data()
+{
+ QTest::addColumn<bool>("intermediateParent");
+ QTest::newRow("noIntermediate") << false;
+ QTest::newRow("intermediate") << true;
+}
+
+void tst_QTreeView::statusTip()
+{
+ QFETCH(bool, intermediateParent);
+ QMainWindow mw;
+ QtTestModel model;
+ model.statusTipsEnabled = true;
+ model.rows = model.cols = 5;
+ QTreeView *view = new QTreeView;
+ view->setModel(&model);
+ view->viewport()->setMouseTracking(true);
+ view->header()->viewport()->setMouseTracking(true);
+ if (intermediateParent) {
+ QWidget *inter = new QWidget;
+ QVBoxLayout *vbox = new QVBoxLayout;
+ inter->setLayout(vbox);
+ vbox->addWidget(view);
+ mw.setCentralWidget(inter);
+ } else {
+ mw.setCentralWidget(view);
+ }
+ mw.statusBar();
+ mw.setGeometry(QRect(QPoint(QApplication::desktop()->geometry().center() - QPoint(250, 250)),
+ QSize(500, 500)));
+ mw.show();
+ qApp->setActiveWindow(&mw);
+ QTest::qWaitForWindowActive(&mw);
+ // Ensure it is moved away first and then moved to the relevant section
+ QTest::mouseMove(mw.windowHandle(), view->mapTo(&mw, view->rect().bottomLeft() + QPoint(20, 20)));
+ QPoint centerPoint = view->viewport()->mapTo(&mw, view->visualRect(model.index(0, 0)).center());
+ QTest::mouseMove(mw.windowHandle(), centerPoint);
+ QTRY_COMPARE(mw.statusBar()->currentMessage(), QLatin1String("[0,0,0] -- Status"));
+ centerPoint = view->viewport()->mapTo(&mw, view->visualRect(model.index(0, 1)).center());
+ QTest::mouseMove(mw.windowHandle(), centerPoint);
+ QTRY_COMPARE(mw.statusBar()->currentMessage(), QLatin1String("[0,1,0] -- Status"));
+ centerPoint = view->header()->viewport()->mapTo(&mw,
+ QPoint(view->header()->sectionViewportPosition(0) + view->header()->sectionSize(0) / 2,
+ view->header()->height() / 2));
+ QTest::mouseMove(mw.windowHandle(), centerPoint);
+ QTRY_COMPARE(mw.statusBar()->currentMessage(), QLatin1String("Header 0 -- Status"));
+}
QTEST_MAIN(tst_QTreeView)
#include "tst_qtreeview.moc"
diff --git a/tests/auto/widgets/kernel/kernel.pro b/tests/auto/widgets/kernel/kernel.pro
index 20720dc928..73fd934502 100644
--- a/tests/auto/widgets/kernel/kernel.pro
+++ b/tests/auto/widgets/kernel/kernel.pro
@@ -6,6 +6,7 @@ SUBDIRS=\
qboxlayout \
qdesktopwidget \
qformlayout \
+ qgesturerecognizer \
qgridlayout \
qlayout \
qstackedlayout \
@@ -19,4 +20,7 @@ SUBDIRS=\
qshortcut \
qsizepolicy
+darwin:SUBDIRS -= \ # Uses native recognizers
+ qgesturerecognizer \
+
SUBDIRS -= qsound
diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
index 83e1850524..ac6362168e 100644
--- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
+++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
@@ -62,6 +62,7 @@ private slots:
void task229128TriggeredSignalWithoutActiongroup();
void task229128TriggeredSignalWhenInActiongroup();
void repeat();
+ void keysequence(); // QTBUG-53381
private:
int m_lastEventType;
@@ -276,6 +277,40 @@ void tst_QAction::alternateShortcuts()
QTest::keyClick(&testWidget, Qt::Key_A, Qt::ControlModifier);
}
+void tst_QAction::keysequence()
+{
+ MyWidget testWidget(this);
+ testWidget.show();
+ QApplication::setActiveWindow(&testWidget);
+
+ {
+ QAction act(&testWidget);
+ testWidget.addAction(&act);
+
+ QKeySequence ks(QKeySequence::SelectAll);
+
+ act.setShortcut(ks);
+
+ QSignalSpy spy(&act, &QAction::triggered);
+
+ act.setAutoRepeat(true);
+ QTest::keySequence(&testWidget, ks);
+ QCoreApplication::processEvents();
+ QCOMPARE(spy.count(), 1); // act should have been triggered
+
+ act.setAutoRepeat(false);
+ QTest::keySequence(&testWidget, ks);
+ QCoreApplication::processEvents();
+ QCOMPARE(spy.count(), 2); //act should have been triggered a 2nd time
+
+ // end of the scope of the action, it will be destroyed and removed from widget
+ // This action should also unregister its shortcuts
+ }
+
+ // this tests a crash (if the action did not unregister its alternate shortcuts)
+ QTest::keyClick(&testWidget, Qt::Key_A, Qt::ControlModifier);
+}
+
void tst_QAction::enabledVisibleInteraction()
{
MyWidget testWidget(this);
diff --git a/tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST b/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST
index 7f55c2dae0..7f55c2dae0 100644
--- a/tests/auto/widgets/gestures/qgesturerecognizer/BLACKLIST
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/BLACKLIST
diff --git a/tests/auto/widgets/gestures/qgesturerecognizer/qgesturerecognizer.pro b/tests/auto/widgets/kernel/qgesturerecognizer/qgesturerecognizer.pro
index 7c9ddcfb03..7c9ddcfb03 100644
--- a/tests/auto/widgets/gestures/qgesturerecognizer/qgesturerecognizer.pro
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/qgesturerecognizer.pro
diff --git a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
index c3ebb838bb..c3ebb838bb 100644
--- a/tests/auto/widgets/gestures/qgesturerecognizer/tst_qgesturerecognizer.cpp
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index 0750526464..5648218d04 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -71,7 +71,7 @@ osx
[setClearAndResizeMask]
osx
[setToolTip]
-osx-10.9
+osx
[moveInResizeEvent]
ubuntu-14.04
[moveChild:right]
diff --git a/tests/auto/widgets/kernel/qwidget/qwidget.pro b/tests/auto/widgets/kernel/qwidget/qwidget.pro
index 499ca65516..0e95d454cf 100644
--- a/tests/auto/widgets/kernel/qwidget/qwidget.pro
+++ b/tests/auto/widgets/kernel/qwidget/qwidget.pro
@@ -12,7 +12,7 @@ aix-g++*:QMAKE_CXXFLAGS+=-fpermissive
CONFIG += x11inc
mac {
- LIBS += -framework Security -framework AppKit -framework Carbon
+ LIBS += -framework Security -framework AppKit
OBJECTIVE_SOURCES += tst_qwidget_mac_helpers.mm
}
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index ef851f38b2..d328163a05 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -1815,9 +1815,11 @@ void tst_QWidget::windowState()
QCOMPARE(widget1.pos(), pos);
QCOMPARE(widget1.size(), size);
-#define VERIFY_STATE(s) QCOMPARE(int(widget1.windowState() & stateMask), int(s))
+#define VERIFY_STATE(s) \
+ QCOMPARE(int(widget1.windowState() & stateMask), int(s)); \
+ QCOMPARE(int(widget1.windowHandle()->windowStates() & stateMask), int(s))
- const int stateMask = Qt::WindowMaximized|Qt::WindowMinimized|Qt::WindowFullScreen;
+ const auto stateMask = Qt::WindowMaximized | Qt::WindowMinimized | Qt::WindowFullScreen;
widget1.setWindowState(Qt::WindowMaximized);
QTest::qWait(100);
@@ -8085,8 +8087,8 @@ void tst_QWidget::setMaskInResizeEvent()
QRegion expectedParentUpdate(0, 0, 100, 10); // Old testWidget area.
expectedParentUpdate += testWidget.geometry(); // New testWidget area.
- QCOMPARE(w.paintedRegion, expectedParentUpdate);
- QCOMPARE(testWidget.paintedRegion, testWidget.mask());
+ QTRY_COMPARE(w.paintedRegion, expectedParentUpdate);
+ QTRY_COMPARE(testWidget.paintedRegion, testWidget.mask());
testWidget.paintedRegion = QRegion();
// Now resize the widget again, but in the oposite direction
@@ -10514,6 +10516,8 @@ void tst_QWidget::qmlSetParentHelper()
void tst_QWidget::testForOutsideWSRangeFlag()
{
+ QSKIP("Test assumes QWindows can have 0x0 size, see QTBUG-61953");
+
// QTBUG-49445
{
QWidget widget;
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
index 6aaac6d135..a6855a417e 100644
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -99,6 +99,11 @@ private slots:
void tst_eventfilter_on_toplevel();
void QTBUG_50561_QCocoaBackingStore_paintDevice_crash();
+
+ void setWindowState_data();
+ void setWindowState();
+
+ void nativeShow();
};
void tst_QWidget_window::initTestCase()
@@ -861,5 +866,70 @@ void tst_QWidget_window::QTBUG_50561_QCocoaBackingStore_paintDevice_crash()
w.close();
}
+void tst_QWidget_window::setWindowState_data()
+{
+ QString platformName = QGuiApplication::platformName().toLower();
+
+ QTest::addColumn<Qt::WindowStates>("state");
+ QTest::newRow("0") << Qt::WindowStates();
+ QTest::newRow("Qt::WindowMaximized") << Qt::WindowStates(Qt::WindowMaximized);
+ QTest::newRow("Qt::WindowMinimized") << Qt::WindowStates(Qt::WindowMinimized);
+ QTest::newRow("Qt::WindowFullScreen") << Qt::WindowStates(Qt::WindowFullScreen);
+
+ if (platformName != "xcb" && platformName != "windows" && !platformName.startsWith("wayland")
+ && platformName != "offscreen")
+ return; // Combination of states is not preserved on all platforms.
+ if (platformName == "xcb" && qgetenv("XDG_CURRENT_DESKTOP") != "KDE"
+ && qgetenv("XDG_CURRENT_DESKTOP") != "Unity")
+ return; // Not all window managers support state combinations.
+
+ QTest::newRow("Qt::WindowMaximized|Qt::WindowMinimized")
+ << (Qt::WindowMaximized | Qt::WindowMinimized);
+ QTest::newRow("Qt::WindowFullScreen|Qt::WindowMinimized")
+ << (Qt::WindowFullScreen | Qt::WindowMinimized);
+ QTest::newRow("Qt::WindowMaximized|Qt::WindowFullScreen")
+ << (Qt::WindowMaximized | Qt::WindowFullScreen);
+ QTest::newRow("Qt::WindowMaximized|Qt::WindowFullScreen|Qt::WindowMinimized")
+ << (Qt::WindowMaximized | Qt::WindowFullScreen | Qt::WindowMinimized);
+}
+
+void tst_QWidget_window::setWindowState()
+{
+ QFETCH(Qt::WindowStates, state);
+
+ // This tests make sure that the states are preserved when the window is shown.
+
+ QWidget w;
+ w.setWindowState(state);
+ QCOMPARE(w.windowState(), state);
+ w.show();
+ QCOMPARE(w.windowState(), state);
+ QCOMPARE(w.windowHandle()->windowStates(), state);
+ QTest::qWaitForWindowExposed(&w);
+ QTRY_COMPARE(w.windowState(), state);
+ QCOMPARE(w.windowHandle()->windowStates(), state);
+
+ // Minimizing keeps other states
+ w.showMinimized();
+ QCOMPARE(w.windowState(), state | Qt::WindowMinimized);
+ QTest::qWait(100);
+ QCOMPARE(w.windowState(), state | Qt::WindowMinimized);
+ QCOMPARE(w.windowHandle()->windowStates(), state | Qt::WindowMinimized);
+}
+
+void tst_QWidget_window::nativeShow()
+{
+ // Verify that a native widget can be shown using the QWindow::setVisible() API
+ QWidget w;
+ w.winId();
+ w.windowHandle()->setVisible(true);
+ QTest::qWaitForWindowExposed(&w);
+ QVERIFY(w.isVisible());
+
+ // ... and that we can hide it
+ w.windowHandle()->setVisible(false);
+ QTRY_VERIFY(!w.isVisible());
+}
+
QTEST_MAIN(tst_QWidget_window)
#include "tst_qwidget_window.moc"
diff --git a/tests/auto/widgets/styles/qmacstyle/qmacstyle.pro b/tests/auto/widgets/styles/qmacstyle/qmacstyle.pro
index 4cd85ab7f2..90bf134ef1 100644
--- a/tests/auto/widgets/styles/qmacstyle/qmacstyle.pro
+++ b/tests/auto/widgets/styles/qmacstyle/qmacstyle.pro
@@ -1,4 +1,4 @@
CONFIG += testcase
TARGET = tst_qmacstyle
-QT += widgets testlib
+QT += widgets-private testlib
SOURCES += tst_qmacstyle.cpp
diff --git a/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp b/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp
index fbd1505b30..2ab2fa4c86 100644
--- a/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp
+++ b/tests/auto/widgets/styles/qmacstyle/tst_qmacstyle.cpp
@@ -29,12 +29,11 @@
#include <QtTest/QtTest>
#include <QtWidgets>
+#include <private/qstylehelper_p.h>
const int N = 1;
-enum Size { Normal, Small, Mini };
-
-Q_DECLARE_METATYPE(Size);
+Q_DECLARE_METATYPE(QStyleHelper::WidgetSizePolicy);
#define CT(E) \
static const ControlType E = QSizePolicy::E;
@@ -63,7 +62,7 @@ class tst_QMacStyle : public QObject
Q_OBJECT
public:
- tst_QMacStyle() { qRegisterMetaType<Size>("Size"); }
+ tst_QMacStyle() { qRegisterMetaType<QStyleHelper::WidgetSizePolicy>("WidgetSizePolicy"); }
private slots:
void sizeHints_data();
@@ -85,27 +84,27 @@ private:
static QSize gap(QWidget *widget1, QWidget *widget2);
static int hgap(QWidget *widget1, QWidget *widget2) { return gap(widget1, widget2).width(); }
static int vgap(QWidget *widget1, QWidget *widget2) { return gap(widget1, widget2).height(); }
- static void setSize(QWidget *widget, Size size);
+ static void setSize(QWidget *widget, QStyleHelper::WidgetSizePolicy size);
static int spacing(ControlType control1, ControlType control2, Qt::Orientation orientation,
QStyleOption *option = 0, QWidget *widget = 0);
- static int hspacing(ControlType control1, ControlType control2, Size size = Normal);
- static int vspacing(ControlType control1, ControlType control2, Size size = Normal);
+ static int hspacing(ControlType control1, ControlType control2, QStyleHelper::WidgetSizePolicy size = QStyleHelper::SizeLarge);
+ static int vspacing(ControlType control1, ControlType control2, QStyleHelper::WidgetSizePolicy size = QStyleHelper::SizeLarge);
};
#define SIZE(x, y, z) \
- ((size == Normal) ? (x) : (size == Small) ? (y) : (z))
+ ((size == QStyleHelper::SizeLarge) ? (x) : (size == QStyleHelper::SizeSmall) ? (y) : (z))
void tst_QMacStyle::sizeHints_data()
{
- QTest::addColumn<Size>("size");
- QTest::newRow("normal") << Normal;
-// QTest::newRow("small") << Small;
-// QTest::newRow("mini") << Mini;
+ QTest::addColumn<QStyleHelper::WidgetSizePolicy>("size");
+ QTest::newRow("normal") << QStyleHelper::SizeLarge;
+// QTest::newRow("small") << QStyleHelper::SizeSmall;
+// QTest::newRow("mini") << QStyleHelper::SizeMini;
}
void tst_QMacStyle::sizeHints()
{
- QFETCH(Size, size);
+ QFETCH(QStyleHelper::WidgetSizePolicy, size);
QDialog w;
setSize(&w, size);
@@ -160,7 +159,7 @@ void tst_QMacStyle::sizeHints()
QPushButton cancel1("Cancel", &w);
QSize s1 = sh(&ok1);
- if (size == Normal) {
+ if (size == QStyleHelper::SizeLarge) {
// AHIG says 68, Builder does 70, and Qt seems to do 69
QVERIFY(s1.width() >= 68 && s1.width() <= 70);
}
@@ -222,7 +221,7 @@ void tst_QMacStyle::layoutMargins_data()
void tst_QMacStyle::layoutMargins()
{
- QFETCH(Size, size);
+ QFETCH(QStyleHelper::WidgetSizePolicy, size);
QWidget w;
setSize(&w, size);
@@ -235,7 +234,7 @@ void tst_QMacStyle::layoutSpacings_data()
void tst_QMacStyle::layoutSpacings()
{
- QFETCH(Size, size);
+ QFETCH(QStyleHelper::WidgetSizePolicy, size);
/*
Constraints specified by AHIG.
@@ -304,16 +303,16 @@ QSize tst_QMacStyle::gap(QWidget *widget1, QWidget *widget2)
return s + QSize(d.x(), d.y());
}
-void tst_QMacStyle::setSize(QWidget *widget, Size size)
+void tst_QMacStyle::setSize(QWidget *widget, QStyleHelper::WidgetSizePolicy size)
{
switch (size) {
- case Normal:
+ case QStyleHelper::SizeLarge:
widget->setAttribute(Qt::WA_MacNormalSize, true);
break;
- case Small:
+ case QStyleHelper::SizeSmall:
widget->setAttribute(Qt::WA_MacSmallSize, true);
break;
- case Mini:
+ case QStyleHelper::SizeMini:
widget->setAttribute(Qt::WA_MacMiniSize, true);
}
}
@@ -324,7 +323,7 @@ int tst_QMacStyle::spacing(ControlType control1, ControlType control2, Qt::Orien
return QApplication::style()->layoutSpacing(control1, control2, orientation, option, widget);
}
-int tst_QMacStyle::hspacing(ControlType control1, ControlType control2, Size size)
+int tst_QMacStyle::hspacing(ControlType control1, ControlType control2, QStyleHelper::WidgetSizePolicy size)
{
QWidget w;
setSize(&w, size);
@@ -335,7 +334,7 @@ int tst_QMacStyle::hspacing(ControlType control1, ControlType control2, Size siz
return spacing(control1, control2, Qt::Horizontal, &opt);
}
-int tst_QMacStyle::vspacing(ControlType control1, ControlType control2, Size size)
+int tst_QMacStyle::vspacing(ControlType control1, ControlType control2, QStyleHelper::WidgetSizePolicy size)
{
QWidget w;
setSize(&w, size);
diff --git a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
index fcb05f6b74..d5ef2fe94b 100644
--- a/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
+++ b/tests/auto/widgets/styles/qstyle/tst_qstyle.cpp
@@ -88,9 +88,6 @@ private slots:
void testFusionStyle();
#endif
void testWindowsStyle();
-#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSXP)
- void testWindowsXPStyle();
-#endif
#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA)
void testWindowsVistaStyle();
#endif
@@ -148,14 +145,6 @@ void tst_QStyle::testStyleFactory()
#ifndef QT_NO_STYLE_WINDOWS
QVERIFY(keys.contains("Windows"));
#endif
-#ifdef Q_OS_WIN
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_XP &&
- (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))
- QVERIFY(keys.contains("WindowsXP"));
- if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA &&
- (QSysInfo::WindowsVersion & QSysInfo::WV_NT_based))
- QVERIFY(keys.contains("WindowsVista"));
-#endif
foreach (QString styleName , keys) {
QStyle *style = QStyleFactory::create(styleName);
@@ -301,16 +290,22 @@ bool tst_QStyle::testAllFunctions(QStyle *style)
bool tst_QStyle::testScrollBarSubControls()
{
+ const auto *style = testWidget->style();
+ const bool isMacStyle = style->objectName().toLower() == "macintosh";
QScrollBar scrollBar;
setFrameless(&scrollBar);
scrollBar.show();
const QStyleOptionSlider opt = qt_qscrollbarStyleOption(&scrollBar);
- foreach (int subControl, QList<int>() << 1 << 2 << 4 << 8) {
- QRect sr = testWidget->style()->subControlRect(QStyle::CC_ScrollBar, &opt,
- QStyle::SubControl(subControl), &scrollBar);
+ foreach (int sc, QList<int>() << 1 << 2 << 4 << 8) {
+ const auto subControl = static_cast<QStyle::SubControl>(sc);
+ const QRect sr = style->subControlRect(QStyle::CC_ScrollBar, &opt, subControl, &scrollBar);
if (sr.isNull()) {
- qWarning("Null rect for subcontrol %d", subControl);
- return false;
+ // macOS scrollbars no longer have these, so there's no reason to fail
+ if (!(isMacStyle && (subControl == QStyle::SC_ScrollBarAddLine ||
+ subControl == QStyle::SC_ScrollBarSubLine))) {
+ qWarning() << "Unexpected null rect for subcontrol" << subControl;
+ return false;
+ }
}
}
return true;
@@ -341,17 +336,6 @@ void tst_QStyle::testWindowsStyle()
delete wstyle;
}
-#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSXP)
-// WindowsXP style
-void tst_QStyle::testWindowsXPStyle()
-{
- QStyle *xpstyle = QStyleFactory::create("WindowsXP");
- QVERIFY(testAllFunctions(xpstyle));
- lineUpLayoutTest(xpstyle);
- delete xpstyle;
-}
-#endif
-
void writeImage(const QString &fileName, QImage image)
{
QImageWriter imageWriter(fileName);
@@ -374,8 +358,6 @@ void tst_QStyle::testWindowsVistaStyle()
if (QSysInfo::WindowsVersion == QSysInfo::WV_VISTA)
testPainting(vistastyle, "vista");
- else if (QSysInfo::WindowsVersion == QSysInfo::WV_XP)
- testPainting(vistastyle, "xp");
delete vistastyle;
}
#endif
diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro
index efcc47171d..8b6c4722be 100644
--- a/tests/auto/widgets/widgets.pro
+++ b/tests/auto/widgets/widgets.pro
@@ -8,4 +8,3 @@ SUBDIRS=\
styles \
util \
widgets \
- gestures \
diff --git a/tests/auto/widgets/widgets/qcombobox/BLACKLIST b/tests/auto/widgets/widgets/qcombobox/BLACKLIST
index 4a270c085b..c04351e5ca 100644
--- a/tests/auto/widgets/widgets/qcombobox/BLACKLIST
+++ b/tests/auto/widgets/widgets/qcombobox/BLACKLIST
@@ -1,3 +1,7 @@
QTBUG-45531
[task260974_menuItemRectangleForComboBoxPopup]
osx-10.10
+
+[task_QTBUG_56693_itemFontFromModel]
+# Counts draw calls, but we could have multiple expose events QTBUG-62080
+osx
diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
index bf190cf60a..2f4e1a32f3 100644
--- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
+++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp
@@ -168,6 +168,7 @@ private slots:
void task_QTBUG_49831_scrollerNotActivated();
void task_QTBUG_56693_itemFontFromModel();
void inputMethodUpdate();
+ void task_QTBUG_52027_mapCompleterIndex();
private:
PlatformInputContext m_platformInputContext;
@@ -3399,5 +3400,62 @@ void tst_QComboBox::inputMethodUpdate()
QVERIFY(m_platformInputContext.m_updateCallCount >= 1);
}
+void tst_QComboBox::task_QTBUG_52027_mapCompleterIndex()
+{
+ QStringList words;
+ words << "" << "foobar1" << "foobar2";
+
+ QStringList altWords;
+ altWords << "foobar2" << "hello" << "," << "world" << "" << "foobar0" << "foobar1";
+
+ QComboBox cbox;
+ setFrameless(&cbox);
+ cbox.setEditable(true);
+ cbox.setInsertPolicy(QComboBox::NoInsert);
+ cbox.addItems(words);
+
+ QCompleter *completer = new QCompleter(altWords);
+ completer->setCaseSensitivity(Qt::CaseInsensitive);
+ cbox.setCompleter(completer);
+
+ QSignalSpy spy(&cbox, SIGNAL(activated(int)));
+ QCOMPARE(spy.count(), 0);
+ cbox.move(200, 200);
+ cbox.show();
+ QApplication::setActiveWindow(&cbox);
+ QVERIFY(QTest::qWaitForWindowActive(&cbox));
+
+ QTest::keyClicks(&cbox, "foobar2");
+ QApplication::processEvents();
+ QTRY_VERIFY(completer->popup());
+ QTest::keyClick(completer->popup(), Qt::Key_Down);
+ QApplication::processEvents();
+ QTest::keyClick(completer->popup(), Qt::Key_Return);
+ QApplication::processEvents();
+ QList<QVariant> arguments = spy.takeLast();
+ QCOMPARE(arguments.at(0).toInt(), 2);
+
+ cbox.lineEdit()->selectAll();
+ cbox.lineEdit()->del();
+
+ QSortFilterProxyModel* model = new QSortFilterProxyModel();
+ model->setSourceModel(cbox.model());
+ model->setFilterFixedString("foobar1");
+ completer->setModel(model);
+
+ QApplication::setActiveWindow(&cbox);
+ QVERIFY(QTest::qWaitForWindowActive(&cbox));
+
+ QTest::keyClicks(&cbox, "foobar1");
+ QApplication::processEvents();
+ QTRY_VERIFY(completer->popup());
+ QTest::keyClick(completer->popup(), Qt::Key_Down);
+ QApplication::processEvents();
+ QTest::keyClick(completer->popup(), Qt::Key_Return);
+ QApplication::processEvents();
+ arguments = spy.takeLast();
+ QCOMPARE(arguments.at(0).toInt(), 1);
+}
+
QTEST_MAIN(tst_QComboBox)
#include "tst_qcombobox.moc"
diff --git a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
index 94e4fc005c..a3571cd9c5 100644
--- a/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
+++ b/tests/auto/widgets/widgets/qdatetimeedit/tst_qdatetimeedit.cpp
@@ -239,6 +239,8 @@ private slots:
void deleteCalendarWidget();
+ void setLocaleOnCalendarWidget();
+
#ifdef QT_BUILD_INTERNAL
void dateEditCorrectSectionSize_data();
void dateEditCorrectSectionSize();
@@ -3409,6 +3411,25 @@ void tst_QDateTimeEdit::deleteCalendarWidget()
}
}
+void tst_QDateTimeEdit::setLocaleOnCalendarWidget()
+{
+ QDateEdit dateEdit;
+ QList<QLocale> allLocales = QLocale::matchingLocales(
+ QLocale::AnyLanguage,
+ QLocale::AnyScript,
+ QLocale::AnyCountry);
+ QLocale c = QLocale::c();
+ dateEdit.setCalendarPopup(true);
+ dateEdit.setLocale(c);
+ for (const QLocale& l : allLocales) {
+ dateEdit.setLocale(l);
+ const QLocale locCal = dateEdit.calendarWidget()->locale();
+ const QLocale locEdit = dateEdit.locale();
+ QCOMPARE(locCal.name(), locEdit.name());
+ QVERIFY(locCal == locEdit);
+ }
+}
+
#ifdef QT_BUILD_INTERNAL
typedef QPair<Qt::Key, Qt::KeyboardModifier> KeyPair;
diff --git a/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_0.png b/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_0.png
index f1d6392779..2647ac98b2 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_1.png b/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_1.png
index f1d6392779..2647ac98b2 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_2.png b/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_2.png
index f1d6392779..2647ac98b2 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_noshadow_0_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_0.png b/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_0.png
index 0cc9090e3b..84be445138 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_1.png b/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_1.png
index 0cc9090e3b..84be445138 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_2.png b/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_2.png
index 0cc9090e3b..84be445138 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_noshadow_1_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_0.png b/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_0.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_1.png b/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_1.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_2.png b/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_2.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_noshadow_2_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_plain_0_0.png b/tests/auto/widgets/widgets/qframe/images/box_plain_0_0.png
index f1d6392779..2647ac98b2 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_plain_0_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_plain_0_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_plain_0_1.png b/tests/auto/widgets/widgets/qframe/images/box_plain_0_1.png
index f1d6392779..2647ac98b2 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_plain_0_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_plain_0_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_plain_0_2.png b/tests/auto/widgets/widgets/qframe/images/box_plain_0_2.png
index f1d6392779..2647ac98b2 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_plain_0_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_plain_0_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_plain_1_0.png b/tests/auto/widgets/widgets/qframe/images/box_plain_1_0.png
index 0cc9090e3b..84be445138 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_plain_1_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_plain_1_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_plain_1_1.png b/tests/auto/widgets/widgets/qframe/images/box_plain_1_1.png
index 0cc9090e3b..84be445138 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_plain_1_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_plain_1_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_plain_1_2.png b/tests/auto/widgets/widgets/qframe/images/box_plain_1_2.png
index 0cc9090e3b..84be445138 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_plain_1_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_plain_1_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_plain_2_0.png b/tests/auto/widgets/widgets/qframe/images/box_plain_2_0.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_plain_2_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_plain_2_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_plain_2_1.png b/tests/auto/widgets/widgets/qframe/images/box_plain_2_1.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_plain_2_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_plain_2_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_plain_2_2.png b/tests/auto/widgets/widgets/qframe/images/box_plain_2_2.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_plain_2_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_plain_2_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_raised_0_0.png b/tests/auto/widgets/widgets/qframe/images/box_raised_0_0.png
index f1d6392779..2647ac98b2 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_raised_0_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_raised_0_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_raised_0_1.png b/tests/auto/widgets/widgets/qframe/images/box_raised_0_1.png
index b2ab941d30..e35498674c 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_raised_0_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_raised_0_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_raised_0_2.png b/tests/auto/widgets/widgets/qframe/images/box_raised_0_2.png
index 21ebe53eff..b958b62259 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_raised_0_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_raised_0_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_raised_1_0.png b/tests/auto/widgets/widgets/qframe/images/box_raised_1_0.png
index 4f097cee48..879f6ddc31 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_raised_1_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_raised_1_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_raised_1_1.png b/tests/auto/widgets/widgets/qframe/images/box_raised_1_1.png
index 86f9ed6186..343caa06e4 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_raised_1_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_raised_1_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_raised_1_2.png b/tests/auto/widgets/widgets/qframe/images/box_raised_1_2.png
index 51a7899d05..377e1377f2 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_raised_1_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_raised_1_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_raised_2_0.png b/tests/auto/widgets/widgets/qframe/images/box_raised_2_0.png
index 8c3769c32d..d59309bb3e 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_raised_2_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_raised_2_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_raised_2_1.png b/tests/auto/widgets/widgets/qframe/images/box_raised_2_1.png
index 81e0c2a152..36f6c0a9f3 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_raised_2_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_raised_2_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_raised_2_2.png b/tests/auto/widgets/widgets/qframe/images/box_raised_2_2.png
index 107272d0b9..c6bdab7eb4 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_raised_2_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_raised_2_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_sunken_0_0.png b/tests/auto/widgets/widgets/qframe/images/box_sunken_0_0.png
index f1d6392779..2647ac98b2 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_sunken_0_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_sunken_0_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_sunken_0_1.png b/tests/auto/widgets/widgets/qframe/images/box_sunken_0_1.png
index b2ab941d30..e35498674c 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_sunken_0_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_sunken_0_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_sunken_0_2.png b/tests/auto/widgets/widgets/qframe/images/box_sunken_0_2.png
index 21ebe53eff..b958b62259 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_sunken_0_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_sunken_0_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_sunken_1_0.png b/tests/auto/widgets/widgets/qframe/images/box_sunken_1_0.png
index 6905baa1fd..7e57872d19 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_sunken_1_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_sunken_1_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_sunken_1_1.png b/tests/auto/widgets/widgets/qframe/images/box_sunken_1_1.png
index 9d5440b3aa..8bf9170f89 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_sunken_1_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_sunken_1_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_sunken_1_2.png b/tests/auto/widgets/widgets/qframe/images/box_sunken_1_2.png
index 17eb7f59c0..bb34a4db29 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_sunken_1_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_sunken_1_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_sunken_2_0.png b/tests/auto/widgets/widgets/qframe/images/box_sunken_2_0.png
index a6ccd54a39..4aa344ad54 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_sunken_2_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_sunken_2_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_sunken_2_1.png b/tests/auto/widgets/widgets/qframe/images/box_sunken_2_1.png
index 3736bf6c99..da5f2ba6b9 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_sunken_2_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_sunken_2_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/box_sunken_2_2.png b/tests/auto/widgets/widgets/qframe/images/box_sunken_2_2.png
index 5750751c58..80ce6d846e 100644
--- a/tests/auto/widgets/widgets/qframe/images/box_sunken_2_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/box_sunken_2_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_0.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_1.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_2.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_0_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_0.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_1.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_2.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_1_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_0.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_1.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_2.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_noshadow_2_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_0.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_1.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_2.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_0_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_0.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_1.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_2.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_1_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_0.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_1.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_2.png
index 61f683df52..8c29cd9965 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_plain_2_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png
index 00447760ec..a28358ec55 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png
index 00447760ec..a28358ec55 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png
index 00447760ec..a28358ec55 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png
index 00447760ec..a28358ec55 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png
index 00447760ec..a28358ec55 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png
index 00447760ec..a28358ec55 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png
index 00447760ec..a28358ec55 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png
index 00447760ec..a28358ec55 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png
index 00447760ec..a28358ec55 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png
index 4c809a2c80..b5ea56f422 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png
index 4c809a2c80..b5ea56f422 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png
index 4c809a2c80..b5ea56f422 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png
index 4c809a2c80..b5ea56f422 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png
index 4c809a2c80..b5ea56f422 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png
index 4c809a2c80..b5ea56f422 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png
index 4c809a2c80..b5ea56f422 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png
index 4c809a2c80..b5ea56f422 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png
index 4c809a2c80..b5ea56f422 100644
--- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png
+++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png
Binary files differ
diff --git a/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp b/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp
index 62224217d6..420ef56106 100644
--- a/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp
+++ b/tests/auto/widgets/widgets/qgroupbox/tst_qgroupbox.cpp
@@ -67,7 +67,7 @@ private slots:
void toggledVsClicked();
void childrenAreDisabled();
void propagateFocus();
- void task_QTBUG_19170_ignoreMouseReleseEvent();
+ void task_QTBUG_19170_ignoreMouseReleaseEvent();
void task_QTBUG_15519_propagateMouseEvents();
private:
@@ -477,7 +477,7 @@ void tst_QGroupBox::propagateFocus()
QTRY_COMPARE(qApp->focusWidget(), static_cast<QWidget*>(&lineEdit));
}
-void tst_QGroupBox::task_QTBUG_19170_ignoreMouseReleseEvent()
+void tst_QGroupBox::task_QTBUG_19170_ignoreMouseReleaseEvent()
{
QGroupBox box;
box.setCheckable(true);
diff --git a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
index b434e48500..8f0dd10940 100644
--- a/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
+++ b/tests/auto/widgets/widgets/qlineedit/tst_qlineedit.cpp
@@ -1969,9 +1969,8 @@ static void figureOutProperKey(Qt::Key &key, Qt::KeyboardModifiers &pressState)
break;
}
#else
- // Naively kill the warning.
- key = key;
- pressState = pressState;
+ Q_UNUSED(key);
+ Q_UNUSED(pressState);
#endif
}
@@ -3985,6 +3984,8 @@ void tst_QLineEdit::QTBUG16850_setSelection()
le.setText(" 1");
le.setSelection(3, 1);
QCOMPARE(le.selectionStart(), 3);
+ QCOMPARE(le.selectionEnd(), 4);
+ QCOMPARE(le.selectionLength(), 1);
QCOMPARE(le.selectedText(), QString("1"));
}
@@ -4179,11 +4180,16 @@ void tst_QLineEdit::inputMethodSelection()
QCOMPARE(selectionSpy.count(), 0);
QCOMPARE(testWidget->selectionStart(), -1);
+ QCOMPARE(testWidget->selectionEnd(), -1);
+ QCOMPARE(testWidget->selectionLength(), 0);
testWidget->setSelection(0,5);
QCOMPARE(selectionSpy.count(), 1);
QCOMPARE(testWidget->selectionStart(), 0);
+ QCOMPARE(testWidget->selectionEnd(), 5);
+ QCOMPARE(testWidget->selectionLength(), 5);
+
// selection gained
{
@@ -4195,6 +4201,8 @@ void tst_QLineEdit::inputMethodSelection()
QCOMPARE(selectionSpy.count(), 2);
QCOMPARE(testWidget->selectionStart(), 12);
+ QCOMPARE(testWidget->selectionEnd(), 17);
+ QCOMPARE(testWidget->selectionLength(), 5);
// selection removed
{
@@ -4205,6 +4213,10 @@ void tst_QLineEdit::inputMethodSelection()
}
QCOMPARE(selectionSpy.count(), 3);
+ QCOMPARE(testWidget->selectionStart(), -1);
+ QCOMPARE(testWidget->selectionEnd(), -1);
+ QCOMPARE(testWidget->selectionLength(), 0);
+
}
Q_DECLARE_METATYPE(Qt::InputMethodHints)
diff --git a/tests/auto/widgets/widgets/qmenu/BLACKLIST b/tests/auto/widgets/widgets/qmenu/BLACKLIST
index cfd6bb1247..1c970c43b3 100644
--- a/tests/auto/widgets/widgets/qmenu/BLACKLIST
+++ b/tests/auto/widgets/widgets/qmenu/BLACKLIST
@@ -3,3 +3,10 @@ osx
[submenuTearOffDontClose]
osx-10.11 ci
osx-10.12 ci
+[layoutDirection]
+# Fails when enabling synchronous expose events QTBUG-62092
+osx ci
+[pushButtonPopulateOnAboutToShow]
+osx
+[tearOff]
+osx
diff --git a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
index f0fb7bc367..da37a9a968 100644
--- a/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
+++ b/tests/auto/widgets/widgets/qmenu/tst_qmenu.cpp
@@ -126,6 +126,8 @@ private slots:
#ifdef Q_OS_MAC
void QTBUG_37933_ampersands_data();
void QTBUG_37933_ampersands();
+#else
+ void click_while_dismissing_submenu();
#endif
void QTBUG_56917_wideMenuSize();
void QTBUG_56917_wideMenuScreenNumber();
@@ -1171,6 +1173,39 @@ void tst_QMenu::QTBUG20403_nested_popup_on_shortcut_trigger()
QVERIFY(!subsub1.isVisible());
}
+#ifndef Q_OS_MACOS
+void tst_QMenu::click_while_dismissing_submenu()
+{
+ QMenu menu("Test Menu");
+ QAction *action = menu.addAction("action");
+ QMenu sub("&sub");
+ sub.addAction("subaction");
+ menu.addMenu(&sub);
+ centerOnScreen(&menu, QSize(120, 100));
+ menu.show();
+ QSignalSpy spy(action, SIGNAL(triggered()));
+ QSignalSpy menuShownSpy(&sub, SIGNAL(aboutToShow()));
+ QSignalSpy menuHiddenSpy(&sub, SIGNAL(aboutToHide()));
+ QVERIFY(QTest::qWaitForWindowExposed(&menu));
+ //go over the submenu, press, move and release over the top level action
+ //this opens the submenu, move two times to emulate user interaction (d->motions > 0 in QMenu)
+ QTest::mouseMove(&menu, menu.rect().center() + QPoint(0,2));
+ QTest::mouseMove(&menu, menu.rect().center() + QPoint(1,3), 60);
+ QVERIFY(menuShownSpy.wait());
+ QVERIFY(sub.isVisible());
+ QVERIFY(QTest::qWaitForWindowExposed(&sub));
+ //press over the submenu entry
+ QTest::mousePress(&menu, Qt::LeftButton, 0, menu.rect().center() + QPoint(0,2), 300);
+ //move over the main action
+ QTest::mouseMove(&menu, menu.rect().center() - QPoint(0,2));
+ QVERIFY(menuHiddenSpy.wait());
+ //the submenu must have been hidden for the bug to be triggered
+ QVERIFY(!sub.isVisible());
+ QTest::mouseRelease(&menu, Qt::LeftButton, 0, menu.rect().center() - QPoint(0,2), 300);
+ QCOMPARE(spy.count(), 1);
+}
+#endif
+
class MyWidget : public QWidget
{
public:
diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
index 2a05900adc..e10c7591d5 100644
--- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
+++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
@@ -62,6 +62,8 @@ private slots:
void showHide();
void nativeWindow();
void stackWidgetOpaqueChildIsVisible();
+ void offscreen();
+ void offscreenThenOnscreen();
};
void tst_QOpenGLWidget::initTestCase()
@@ -75,6 +77,7 @@ void tst_QOpenGLWidget::create()
{
QScopedPointer<QOpenGLWidget> w(new QOpenGLWidget);
QVERIFY(!w->isValid());
+ QVERIFY(w->textureFormat() == 0);
QSignalSpy frameSwappedSpy(w.data(), SIGNAL(frameSwapped()));
w->show();
QTest::qWaitForWindowExposed(w.data());
@@ -84,6 +87,7 @@ void tst_QOpenGLWidget::create()
QVERIFY(w->context());
QCOMPARE(w->context()->format(), w->format());
QVERIFY(w->defaultFramebufferObject() != 0);
+ QVERIFY(w->textureFormat() != 0);
}
class ClearWidget : public QOpenGLWidget, protected QOpenGLFunctions
@@ -603,6 +607,74 @@ void tst_QOpenGLWidget::stackWidgetOpaqueChildIsVisible()
#undef VERIFY_COLOR
}
+void tst_QOpenGLWidget::offscreen()
+{
+ {
+ QScopedPointer<ClearWidget> w(new ClearWidget(0, 800, 600));
+ w->resize(800, 600);
+
+ w->setClearColor(0, 0, 1);
+ QImage image = w->grabFramebuffer();
+
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.width(), w->width());
+ QCOMPARE(image.height(), w->height());
+ QVERIFY(image.pixel(30, 40) == qRgb(0, 0, 255));
+ }
+
+ // QWidget::grab() should eventually end up in grabFramebuffer() as well
+ {
+ QScopedPointer<ClearWidget> w(new ClearWidget(0, 800, 600));
+ w->resize(800, 600);
+
+ w->setClearColor(0, 0, 1);
+ QPixmap pm = w->grab();
+ QImage image = pm.toImage();
+
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.width(), w->width());
+ QCOMPARE(image.height(), w->height());
+ QVERIFY(image.pixel(30, 40) == qRgb(0, 0, 255));
+ }
+
+ // ditto for QWidget::render()
+ {
+ QScopedPointer<ClearWidget> w(new ClearWidget(0, 800, 600));
+ w->resize(800, 600);
+
+ w->setClearColor(0, 0, 1);
+ QImage image(800, 600, QImage::Format_ARGB32);
+ w->render(&image);
+
+ QVERIFY(image.pixel(30, 40) == qRgb(0, 0, 255));
+ }
+}
+
+void tst_QOpenGLWidget::offscreenThenOnscreen()
+{
+ QScopedPointer<ClearWidget> w(new ClearWidget(0, 800, 600));
+ w->resize(800, 600);
+
+ w->setClearColor(0, 0, 1);
+ QImage image = w->grabFramebuffer();
+
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.width(), w->width());
+ QCOMPARE(image.height(), w->height());
+ QVERIFY(image.pixel(30, 40) == qRgb(0, 0, 255));
+
+ // now let's make things more challenging: show. Internally this needs
+ // recreating the context.
+ w->show();
+ QTest::qWaitForWindowExposed(w.data());
+
+ image = w->grabFramebuffer();
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.width(), w->width());
+ QCOMPARE(image.height(), w->height());
+ QVERIFY(image.pixel(30, 40) == qRgb(0, 0, 255));
+}
+
QTEST_MAIN(tst_QOpenGLWidget)
#include "tst_qopenglwidget.moc"
diff --git a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
index 205ef34958..9f64335930 100644
--- a/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
+++ b/tests/auto/widgets/widgets/qprogressbar/tst_qprogressbar.cpp
@@ -45,6 +45,7 @@ private slots:
void destroyIndeterminate();
void text();
void format();
+ void setValueRepaint_data();
void setValueRepaint();
#ifndef Q_OS_MAC
void setMinMaxRepaint();
@@ -191,21 +192,49 @@ void tst_QProgressBar::format()
QCOMPARE(bar.text(), QString());
}
+void tst_QProgressBar::setValueRepaint_data()
+{
+ QTest::addColumn<int>("min");
+ QTest::addColumn<int>("max");
+ QTest::addColumn<int>("increment");
+
+ auto add = [](int min, int max, int increment) {
+ QTest::addRow("%d-%d@%d", min, max, increment) << min << max << increment;
+ };
+
+ add(0, 10, 1);
+
+ auto add_set = [=](int min, int max, int increment) {
+ // check corner cases, and adjacent values (to circumvent explicit checks for corner cases)
+ add(min, max, increment);
+ add(min + 1, max, increment);
+ add(min, max - 1, increment);
+ add(min + 1, max - 1, increment);
+ };
+
+ add_set(INT_MIN, INT_MAX, INT_MAX / 50 + 1);
+ add_set(0, INT_MAX, INT_MAX / 100 + 1);
+ add_set(INT_MIN, 0, INT_MAX / 100 + 1);
+}
+
void tst_QProgressBar::setValueRepaint()
{
+ QFETCH(int, min);
+ QFETCH(int, max);
+ QFETCH(int, increment);
+
ProgressBar pbar;
- pbar.setMinimum(0);
- pbar.setMaximum(10);
+ pbar.setMinimum(min);
+ pbar.setMaximum(max);
pbar.setFormat("%v");
pbar.move(300, 300);
pbar.show();
QVERIFY(QTest::qWaitForWindowExposed(&pbar));
QApplication::processEvents();
- for (int i = pbar.minimum(); i < pbar.maximum(); ++i) {
+ for (qint64 i = min; i < max; i += increment) {
pbar.repainted = false;
- pbar.setValue(i);
- QTest::qWait(50);
+ pbar.setValue(int(i));
QTRY_VERIFY(pbar.repainted);
}
}
diff --git a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
index 7bbbc46b5a..bacab78601 100644
--- a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
+++ b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp
@@ -520,9 +520,6 @@ void tst_QPushButton::sizeHint_data()
#if !defined(QT_NO_STYLE_FUSION)
QTest::newRow("fusion") << QString::fromLatin1("fusion");
#endif
-#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSXP)
- QTest::newRow("windowsxp") << QString::fromLatin1("windowsxp");
-#endif
#if defined(Q_OS_WIN) && !defined(QT_NO_STYLE_WINDOWSVISTA)
QTest::newRow("windowsvista") << QString::fromLatin1("windowsvista");
#endif
diff --git a/tests/baselineserver/shared/baselineprotocol.cpp b/tests/baselineserver/shared/baselineprotocol.cpp
index 1e4d8846c8..80e269ee2a 100644
--- a/tests/baselineserver/shared/baselineprotocol.cpp
+++ b/tests/baselineserver/shared/baselineprotocol.cpp
@@ -235,7 +235,7 @@ quint64 ImageItem::computeChecksum(const QImage &image)
quint32 h1 = 0xfeedbacc;
quint32 h2 = 0x21604894;
- hashword2((const quint32 *)img.constBits(), img.byteCount()/4, &h1, &h2);
+ hashword2((const quint32 *)img.constBits(), img.sizeInBytes()/4, &h1, &h2);
return (quint64(h1) << 32) | h2;
}
diff --git a/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp b/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
index ea08af7608..f2e6973e27 100644
--- a/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
+++ b/tests/benchmarks/gui/painting/qpainter/tst_qpainter.cpp
@@ -33,10 +33,7 @@
#include <QImage>
#include <QPaintEngine>
#include <QTileRules>
-#include <math.h>
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
+#include <qmath.h>
#include <private/qpixmap_raster_p.h>
@@ -1232,7 +1229,7 @@ QTransform tst_QPainter::transformForAngle(qreal angle)
QTransform rotTrans2;
rotTrans2.translate(40, 0);
- qreal rad = angle * 2. * M_PI / 360.;
+ qreal rad = qDegreesToRadians(angle);
qreal c = ::cos(rad);
qreal s = ::sin(rad);
diff --git a/tests/manual/filetest/main.cpp b/tests/manual/filetest/main.cpp
index 396fcdb24b..c278fd87ce 100644
--- a/tests/manual/filetest/main.cpp
+++ b/tests/manual/filetest/main.cpp
@@ -26,6 +26,7 @@
**
****************************************************************************/
+#include <QDateTime>
#include <QDebug>
#include <QCoreApplication>
#include <QFileInfo>
@@ -40,12 +41,25 @@ static const char usage1[] =
"Usage: ";
static const char usage2[] =" [KEYWORD] [ARGUMENTS]\n\n"
"Keywords: ls FILES list file information\n"
+" stat FILES print detailed file information\n"
" mv SOURCE TARGET rename files using QFile::rename\n"
" cp SOURCE TARGET copy files using QFile::copy\n"
" rm FILE remove file using QFile::remove\n"
" rmr DIR remove directory recursively\n"
" using QDir::removeRecursively\n";
+std::ostream &operator<<(std::ostream &o, const QString &str)
+{
+ return o << qPrintable(str);
+}
+
+std::ostream &operator<<(std::ostream &o, const QDateTime &dt)
+{
+ if (dt.isValid())
+ return o << dt.toString(Qt::ISODateWithMs);
+ return o << '-';
+}
+
static inline std::string permissions(QFile::Permissions permissions)
{
std::string result(10, '-');
@@ -102,6 +116,44 @@ static int ls(int argCount, char **args)
return 0;
}
+static int stat(int argCount, char **args)
+{
+ for (int i = 0 ; i < argCount; ++i) {
+ const QFileInfo fi(QFile::decodeName(args[i]));
+ std::cout << "Name:\t" << fi.fileName() << std::endl;
+ std::cout << "Path:\t" << QDir::toNativeSeparators(fi.path())
+ << " (" << QDir::toNativeSeparators(fi.absolutePath()) << ')' << std::endl;
+ std::cout << "Size:\t" << fi.size()
+ << "\tType: "
+ << (fi.isSymLink() && !fi.exists() ? "Broken symlink" :
+ !fi.exists() ? "Non-existent" :
+ fi.isSymLink() ? "Symlink to " : "")
+ << (!fi.exists() ? "" :
+ fi.isFile() ? "Regular file" :
+ fi.isDir() ? "Directory" : "Special node")
+ << std::endl;
+ if (fi.isSymLink())
+ std::cout << "Target:\t" << fi.symLinkTarget() << std::endl;
+ std::cout << "Attrs: "
+ << (fi.isReadable() ? " readable" : "")
+ << (fi.isWritable() ? " writable" : "")
+ << (fi.isExecutable() ? " executable" : "")
+ << (fi.isHidden() ? " hidden" : "")
+ << (fi.isNativePath() ? " nativepath" : "")
+ << (fi.isRoot() ? " root" : "")
+ << (fi.isBundle() ? " bundle" : "")
+ << std::endl;
+ std::cout << "Mode:\t" << permissions(fi) << std::endl;
+ std::cout << "Owner:\t" << fi.owner() << " (" << fi.ownerId()
+ << ")\tGroup:\t" << fi.group() << " (" << fi.groupId() << ')' << std::endl;
+ std::cout << "Access:\t" << fi.lastRead() << std::endl;
+ std::cout << "Birth:\t" << fi.birthTime() << std::endl;
+ std::cout << "Change:\t" << fi.metadataChangeTime() << std::endl;
+ std::cout << "Modified: " << fi.lastModified() << std::endl;
+ }
+ return 0;
+}
+
static int mv(const char *sourceFileName, const char *targetFileName)
{
QFile sourceFile(QString::fromLocal8Bit(sourceFileName));
@@ -155,6 +207,9 @@ int main(int argc, char *argv[])
if (argc >= 3 && !qstrcmp(argv[1], "ls"))
return ls(argc -2, argv + 2);
+ if (argc >= 3 && !qstrcmp(argv[1], "stat"))
+ return stat(argc -2, argv + 2);
+
if (argc == 4 && !qstrcmp(argv[1], "mv"))
return mv(argv[2], argv[3]);
diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro
index a9d27fa488..ab00a5ef60 100644
--- a/tests/manual/manual.pro
+++ b/tests/manual/manual.pro
@@ -67,3 +67,5 @@ win32: SUBDIRS -= network_remote_stresstest network_stresstest
lessThan(QT_MAJOR_VERSION, 5): SUBDIRS -= bearerex lance qnetworkaccessmanager/qget qmimedatabase qnetworkreply \
qpainfo qscreen socketengine xembed-raster xembed-widgets windowtransparency \
embeddedintoforeignwindow foreignwindows
+
+qtConfig(vulkan): SUBDIRS += qvulkaninstance
diff --git a/tests/manual/qvulkaninstance/main.cpp b/tests/manual/qvulkaninstance/main.cpp
new file mode 100644
index 0000000000..9b5f0ad072
--- /dev/null
+++ b/tests/manual/qvulkaninstance/main.cpp
@@ -0,0 +1,713 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QGuiApplication>
+#include <QVulkanInstance>
+#include <QVulkanFunctions>
+#include <QWindow>
+#include <QLoggingCategory>
+#include <qevent.h>
+
+static const int SWAPCHAIN_BUFFER_COUNT = 2;
+static const int FRAME_LAG = 2;
+
+class VWindow : public QWindow
+{
+public:
+ VWindow() { setSurfaceType(VulkanSurface); }
+ ~VWindow() { releaseResources(); }
+
+private:
+ void exposeEvent(QExposeEvent *) override;
+ void resizeEvent(QResizeEvent *) override;
+ bool event(QEvent *) override;
+
+ void init();
+ void releaseResources();
+ void recreateSwapChain();
+ void createDefaultRenderPass();
+ void releaseSwapChain();
+ void render();
+ void buildDrawCalls();
+
+ bool m_inited = false;
+ VkSurfaceKHR m_vkSurface;
+ VkPhysicalDevice m_vkPhysDev;
+ VkPhysicalDeviceProperties m_physDevProps;
+ VkDevice m_vkDev = 0;
+ QVulkanDeviceFunctions *m_devFuncs;
+ VkQueue m_vkGfxQueue;
+ VkQueue m_vkPresQueue;
+ VkCommandPool m_vkCmdPool = 0;
+
+ PFN_vkCreateSwapchainKHR m_vkCreateSwapchainKHR = nullptr;
+ PFN_vkDestroySwapchainKHR m_vkDestroySwapchainKHR;
+ PFN_vkGetSwapchainImagesKHR m_vkGetSwapchainImagesKHR;
+ PFN_vkAcquireNextImageKHR m_vkAcquireNextImageKHR;
+ PFN_vkQueuePresentKHR m_vkQueuePresentKHR;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR m_vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR m_vkGetPhysicalDeviceSurfaceFormatsKHR;
+
+ QSize m_swapChainImageSize;
+ VkFormat m_colorFormat;
+ VkSwapchainKHR m_swapChain = 0;
+ uint32_t m_swapChainBufferCount = 0;
+
+ struct ImageResources {
+ VkImage image = 0;
+ VkImageView imageView = 0;
+ VkCommandBuffer cmdBuf = 0;
+ VkFence cmdFence = 0;
+ bool cmdFenceWaitable = false;
+ VkFramebuffer fb = 0;
+ } m_imageRes[SWAPCHAIN_BUFFER_COUNT];
+
+ uint32_t m_currentImage;
+
+ struct FrameResources {
+ VkFence fence = 0;
+ bool fenceWaitable = false;
+ VkSemaphore imageSem = 0;
+ VkSemaphore drawSem = 0;
+ } m_frameRes[FRAME_LAG];
+
+ uint32_t m_currentFrame;
+
+ VkRenderPass m_defaultRenderPass = 0;
+};
+
+void VWindow::exposeEvent(QExposeEvent *)
+{
+ if (isExposed() && !m_inited) {
+ qDebug("initializing");
+ m_inited = true;
+ init();
+ recreateSwapChain();
+ render();
+ }
+
+ // Release everything when unexposed - the meaning of which is platform specific.
+ // Can be essential on mobile, to release resources while in background.
+#if 1
+ if (!isExposed() && m_inited) {
+ m_inited = false;
+ releaseSwapChain();
+ releaseResources();
+ }
+#endif
+}
+
+void VWindow::resizeEvent(QResizeEvent *)
+{
+ // Nothing to do here - recreating the swapchain is handled in render(),
+ // in fact calling recreateSwapChain() from here leads to problems.
+}
+
+bool VWindow::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::UpdateRequest:
+ render();
+ break;
+
+ // Now the fun part: the swapchain must be destroyed before the surface as per
+ // spec. This is not ideal for us because the surface is managed by the
+ // QPlatformWindow which may be gone already when the unexpose comes, making the
+ // validation layer scream. The solution is to listen to the PlatformSurface events.
+ case QEvent::PlatformSurface:
+ if (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType() == QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed)
+ releaseSwapChain();
+ break;
+
+ default:
+ break;
+ }
+
+ return QWindow::event(e);
+}
+
+void VWindow::init()
+{
+ m_vkSurface = QVulkanInstance::surfaceForWindow(this);
+ if (!m_vkSurface)
+ qFatal("Failed to get surface for window");
+
+ QVulkanInstance *inst = vulkanInstance();
+ QVulkanFunctions *f = inst->functions();
+ uint32_t devCount = 0;
+ f->vkEnumeratePhysicalDevices(inst->vkInstance(), &devCount, nullptr);
+ qDebug("%d physical devices", devCount);
+ if (!devCount)
+ qFatal("No physical devices");
+
+ // Just pick the first physical device for now.
+ devCount = 1;
+ VkResult err = f->vkEnumeratePhysicalDevices(inst->vkInstance(), &devCount, &m_vkPhysDev);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to enumerate physical devices: %d", err);
+
+ f->vkGetPhysicalDeviceProperties(m_vkPhysDev, &m_physDevProps);
+ qDebug("Device name: %s Driver version: %d.%d.%d", m_physDevProps.deviceName,
+ VK_VERSION_MAJOR(m_physDevProps.driverVersion), VK_VERSION_MINOR(m_physDevProps.driverVersion),
+ VK_VERSION_PATCH(m_physDevProps.driverVersion));
+
+ uint32_t queueCount = 0;
+ f->vkGetPhysicalDeviceQueueFamilyProperties(m_vkPhysDev, &queueCount, nullptr);
+ QVector<VkQueueFamilyProperties> queueFamilyProps(queueCount);
+ f->vkGetPhysicalDeviceQueueFamilyProperties(m_vkPhysDev, &queueCount, queueFamilyProps.data());
+ int gfxQueueFamilyIdx = -1;
+ int presQueueFamilyIdx = -1;
+ // First look for a queue that supports both.
+ for (int i = 0; i < queueFamilyProps.count(); ++i) {
+ qDebug("queue family %d: flags=0x%x count=%d", i, queueFamilyProps[i].queueFlags, queueFamilyProps[i].queueCount);
+ if (gfxQueueFamilyIdx == -1
+ && (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
+ && inst->supportsPresent(m_vkPhysDev, i, this))
+ gfxQueueFamilyIdx = i;
+ }
+ if (gfxQueueFamilyIdx != -1) {
+ presQueueFamilyIdx = gfxQueueFamilyIdx;
+ } else {
+ // Separate queues then.
+ qDebug("No queue with graphics+present; trying separate queues");
+ for (int i = 0; i < queueFamilyProps.count(); ++i) {
+ if (gfxQueueFamilyIdx == -1 && (queueFamilyProps[i].queueFlags & VK_QUEUE_GRAPHICS_BIT))
+ gfxQueueFamilyIdx = i;
+ if (presQueueFamilyIdx == -1 && inst->supportsPresent(m_vkPhysDev, i, this))
+ presQueueFamilyIdx = i;
+ }
+ }
+ if (gfxQueueFamilyIdx == -1)
+ qFatal("No graphics queue family found");
+ if (presQueueFamilyIdx == -1)
+ qFatal("No present queue family found");
+
+ VkDeviceQueueCreateInfo queueInfo[2];
+ const float prio[] = { 0 };
+ memset(queueInfo, 0, sizeof(queueInfo));
+ queueInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueInfo[0].queueFamilyIndex = gfxQueueFamilyIdx;
+ queueInfo[0].queueCount = 1;
+ queueInfo[0].pQueuePriorities = prio;
+ if (gfxQueueFamilyIdx != presQueueFamilyIdx) {
+ queueInfo[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ queueInfo[1].queueFamilyIndex = presQueueFamilyIdx;
+ queueInfo[1].queueCount = 1;
+ queueInfo[1].pQueuePriorities = prio;
+ }
+
+ QVector<const char *> devLayers;
+ if (inst->layers().contains("VK_LAYER_LUNARG_standard_validation"))
+ devLayers.append("VK_LAYER_LUNARG_standard_validation");
+
+ QVector<const char *> devExts;
+ devExts.append("VK_KHR_swapchain");
+
+ VkDeviceCreateInfo devInfo;
+ memset(&devInfo, 0, sizeof(devInfo));
+ devInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ devInfo.queueCreateInfoCount = gfxQueueFamilyIdx == presQueueFamilyIdx ? 1 : 2;
+ devInfo.pQueueCreateInfos = queueInfo;
+ devInfo.enabledLayerCount = devLayers.count();
+ devInfo.ppEnabledLayerNames = devLayers.constData();
+ devInfo.enabledExtensionCount = devExts.count();
+ devInfo.ppEnabledExtensionNames = devExts.constData();
+
+ err = f->vkCreateDevice(m_vkPhysDev, &devInfo, nullptr, &m_vkDev);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create device: %d", err);
+
+ m_devFuncs = inst->deviceFunctions(m_vkDev);
+
+ m_devFuncs->vkGetDeviceQueue(m_vkDev, gfxQueueFamilyIdx, 0, &m_vkGfxQueue);
+ if (gfxQueueFamilyIdx == presQueueFamilyIdx)
+ m_vkPresQueue = m_vkGfxQueue;
+ else
+ m_devFuncs->vkGetDeviceQueue(m_vkDev, presQueueFamilyIdx, 0, &m_vkPresQueue);
+
+ VkCommandPoolCreateInfo poolInfo;
+ memset(&poolInfo, 0, sizeof(poolInfo));
+ poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
+ poolInfo.queueFamilyIndex = gfxQueueFamilyIdx;
+ err = m_devFuncs->vkCreateCommandPool(m_vkDev, &poolInfo, nullptr, &m_vkCmdPool);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create command pool: %d", err);
+
+ m_colorFormat = VK_FORMAT_B8G8R8A8_UNORM; // may get changed later when setting up the swapchain
+}
+
+void VWindow::releaseResources()
+{
+ if (!m_vkDev)
+ return;
+
+ m_devFuncs->vkDeviceWaitIdle(m_vkDev);
+
+ if (m_vkCmdPool) {
+ m_devFuncs->vkDestroyCommandPool(m_vkDev, m_vkCmdPool, nullptr);
+ m_vkCmdPool = 0;
+ }
+
+ if (m_vkDev) {
+ m_devFuncs->vkDestroyDevice(m_vkDev, nullptr);
+
+ // Play nice and notify QVulkanInstance that the QVulkanDeviceFunctions
+ // for m_vkDev needs to be invalidated.
+ vulkanInstance()->resetDeviceFunctions(m_vkDev);
+
+ m_vkDev = 0;
+ }
+
+ m_vkSurface = 0;
+}
+
+void VWindow::recreateSwapChain()
+{
+ m_swapChainImageSize = size();
+
+ if (m_swapChainImageSize.isEmpty())
+ return;
+
+ QVulkanInstance *inst = vulkanInstance();
+ QVulkanFunctions *f = inst->functions();
+ m_devFuncs->vkDeviceWaitIdle(m_vkDev);
+
+ if (!m_vkCreateSwapchainKHR) {
+ m_vkGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>(
+ inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfaceCapabilitiesKHR"));
+ m_vkGetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>(
+ inst->getInstanceProcAddr("vkGetPhysicalDeviceSurfaceFormatsKHR"));
+ // note: device-specific functions
+ m_vkCreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>(f->vkGetDeviceProcAddr(m_vkDev, "vkCreateSwapchainKHR"));
+ m_vkDestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>(f->vkGetDeviceProcAddr(m_vkDev, "vkDestroySwapchainKHR"));
+ m_vkGetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>(f->vkGetDeviceProcAddr(m_vkDev, "vkGetSwapchainImagesKHR"));
+ m_vkAcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>(f->vkGetDeviceProcAddr(m_vkDev, "vkAcquireNextImageKHR"));
+ m_vkQueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(f->vkGetDeviceProcAddr(m_vkDev, "vkQueuePresentKHR"));
+ }
+
+ VkColorSpaceKHR colorSpace = VkColorSpaceKHR(0);
+ uint32_t formatCount = 0;
+ m_vkGetPhysicalDeviceSurfaceFormatsKHR(m_vkPhysDev, m_vkSurface, &formatCount, nullptr);
+ if (formatCount) {
+ QVector<VkSurfaceFormatKHR> formats(formatCount);
+ m_vkGetPhysicalDeviceSurfaceFormatsKHR(m_vkPhysDev, m_vkSurface, &formatCount, formats.data());
+ if (formats[0].format != VK_FORMAT_UNDEFINED) {
+ m_colorFormat = formats[0].format;
+ colorSpace = formats[0].colorSpace;
+ }
+ }
+
+ VkSurfaceCapabilitiesKHR surfaceCaps;
+ m_vkGetPhysicalDeviceSurfaceCapabilitiesKHR(m_vkPhysDev, m_vkSurface, &surfaceCaps);
+ uint32_t reqBufferCount = SWAPCHAIN_BUFFER_COUNT;
+ if (surfaceCaps.maxImageCount)
+ reqBufferCount = qBound(surfaceCaps.minImageCount, reqBufferCount, surfaceCaps.maxImageCount);
+
+ VkExtent2D bufferSize = surfaceCaps.currentExtent;
+ if (bufferSize.width == uint32_t(-1))
+ bufferSize.width = m_swapChainImageSize.width();
+ if (bufferSize.height == uint32_t(-1))
+ bufferSize.height = m_swapChainImageSize.height();
+
+ VkSurfaceTransformFlagBitsKHR preTransform =
+ (surfaceCaps.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
+ ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR
+ : surfaceCaps.currentTransform;
+
+ VkCompositeAlphaFlagBitsKHR compositeAlpha =
+ (surfaceCaps.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR)
+ ? VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR
+ : VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
+
+ VkPresentModeKHR presentMode = VK_PRESENT_MODE_FIFO_KHR;
+
+ VkSwapchainKHR oldSwapChain = m_swapChain;
+ VkSwapchainCreateInfoKHR swapChainInfo;
+ memset(&swapChainInfo, 0, sizeof(swapChainInfo));
+ swapChainInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
+ swapChainInfo.surface = m_vkSurface;
+ swapChainInfo.minImageCount = reqBufferCount;
+ swapChainInfo.imageFormat = m_colorFormat;
+ swapChainInfo.imageColorSpace = colorSpace;
+ swapChainInfo.imageExtent = bufferSize;
+ swapChainInfo.imageArrayLayers = 1;
+ swapChainInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+ swapChainInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
+ swapChainInfo.preTransform = preTransform;
+ swapChainInfo.compositeAlpha = compositeAlpha;
+ swapChainInfo.presentMode = presentMode;
+ swapChainInfo.clipped = true;
+ swapChainInfo.oldSwapchain = oldSwapChain;
+
+ qDebug("creating new swap chain of %d buffers, size %dx%d", reqBufferCount, bufferSize.width, bufferSize.height);
+
+ VkSwapchainKHR newSwapChain;
+ VkResult err = m_vkCreateSwapchainKHR(m_vkDev, &swapChainInfo, nullptr, &newSwapChain);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create swap chain: %d", err);
+
+ if (oldSwapChain)
+ releaseSwapChain();
+
+ m_swapChain = newSwapChain;
+
+ m_swapChainBufferCount = 0;
+ err = m_vkGetSwapchainImagesKHR(m_vkDev, m_swapChain, &m_swapChainBufferCount, nullptr);
+ if (err != VK_SUCCESS || m_swapChainBufferCount < 2)
+ qFatal("Failed to get swapchain images: %d (count=%d)", err, m_swapChainBufferCount);
+
+ qDebug("actual swap chain buffer count: %d", m_swapChainBufferCount);
+ Q_ASSERT(m_swapChainBufferCount <= SWAPCHAIN_BUFFER_COUNT);
+
+ VkImage swapChainImages[SWAPCHAIN_BUFFER_COUNT];
+ err = m_vkGetSwapchainImagesKHR(m_vkDev, m_swapChain, &m_swapChainBufferCount, swapChainImages);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to get swapchain images: %d", err);
+
+ // Now that we know m_colorFormat, create the default renderpass, the framebuffers will need it.
+ createDefaultRenderPass();
+
+ VkFenceCreateInfo fenceInfo = { VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, nullptr, VK_FENCE_CREATE_SIGNALED_BIT };
+
+ for (uint32_t i = 0; i < m_swapChainBufferCount; ++i) {
+ ImageResources &image(m_imageRes[i]);
+ image.image = swapChainImages[i];
+
+ VkImageViewCreateInfo imgViewInfo;
+ memset(&imgViewInfo, 0, sizeof(imgViewInfo));
+ imgViewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
+ imgViewInfo.image = swapChainImages[i];
+ imgViewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
+ imgViewInfo.format = m_colorFormat;
+ imgViewInfo.components.r = VK_COMPONENT_SWIZZLE_R;
+ imgViewInfo.components.g = VK_COMPONENT_SWIZZLE_G;
+ imgViewInfo.components.b = VK_COMPONENT_SWIZZLE_B;
+ imgViewInfo.components.a = VK_COMPONENT_SWIZZLE_A;
+ imgViewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
+ imgViewInfo.subresourceRange.levelCount = imgViewInfo.subresourceRange.layerCount = 1;
+ err = m_devFuncs->vkCreateImageView(m_vkDev, &imgViewInfo, nullptr, &image.imageView);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create swapchain image view %d: %d", i, err);
+
+ err = m_devFuncs->vkCreateFence(m_vkDev, &fenceInfo, nullptr, &image.cmdFence);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create command buffer fence: %d", err);
+ image.cmdFenceWaitable = true;
+
+ VkImageView views[1] = { image.imageView };
+ VkFramebufferCreateInfo fbInfo;
+ memset(&fbInfo, 0, sizeof(fbInfo));
+ fbInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
+ fbInfo.renderPass = m_defaultRenderPass;
+ fbInfo.attachmentCount = 1;
+ fbInfo.pAttachments = views;
+ fbInfo.width = m_swapChainImageSize.width();
+ fbInfo.height = m_swapChainImageSize.height();
+ fbInfo.layers = 1;
+ VkResult err = m_devFuncs->vkCreateFramebuffer(m_vkDev, &fbInfo, nullptr, &image.fb);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create framebuffer: %d", err);
+ }
+
+ m_currentImage = 0;
+
+ VkSemaphoreCreateInfo semInfo = { VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, nullptr, 0 };
+ for (uint32_t i = 0; i < FRAME_LAG; ++i) {
+ FrameResources &frame(m_frameRes[i]);
+ m_devFuncs->vkCreateFence(m_vkDev, &fenceInfo, nullptr, &frame.fence);
+ frame.fenceWaitable = true;
+ m_devFuncs->vkCreateSemaphore(m_vkDev, &semInfo, nullptr, &frame.imageSem);
+ m_devFuncs->vkCreateSemaphore(m_vkDev, &semInfo, nullptr, &frame.drawSem);
+ }
+
+ m_currentFrame = 0;
+}
+
+void VWindow::createDefaultRenderPass()
+{
+ VkAttachmentDescription attDesc[1];
+ memset(attDesc, 0, sizeof(attDesc));
+ attDesc[0].format = m_colorFormat;
+ attDesc[0].samples = VK_SAMPLE_COUNT_1_BIT;
+ attDesc[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
+ attDesc[0].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ attDesc[0].stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ attDesc[0].stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ attDesc[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
+ attDesc[0].finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
+
+ VkAttachmentReference colorRef = { 0, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL };
+
+ VkSubpassDescription subPassDesc;
+ memset(&subPassDesc, 0, sizeof(subPassDesc));
+ subPassDesc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
+ subPassDesc.colorAttachmentCount = 1;
+ subPassDesc.pColorAttachments = &colorRef;
+
+ VkRenderPassCreateInfo rpInfo;
+ memset(&rpInfo, 0, sizeof(rpInfo));
+ rpInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
+ rpInfo.attachmentCount = 1;
+ rpInfo.pAttachments = attDesc;
+ rpInfo.subpassCount = 1;
+ rpInfo.pSubpasses = &subPassDesc;
+ VkResult err = m_devFuncs->vkCreateRenderPass(m_vkDev, &rpInfo, nullptr, &m_defaultRenderPass);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to create renderpass: %d", err);
+}
+
+void VWindow::releaseSwapChain()
+{
+ if (!m_vkDev)
+ return;
+
+ m_devFuncs->vkDeviceWaitIdle(m_vkDev);
+
+ if (m_defaultRenderPass) {
+ m_devFuncs->vkDestroyRenderPass(m_vkDev, m_defaultRenderPass, nullptr);
+ m_defaultRenderPass = 0;
+ }
+
+ for (uint32_t i = 0; i < FRAME_LAG; ++i) {
+ FrameResources &frame(m_frameRes[i]);
+ if (frame.fence) {
+ if (frame.fenceWaitable)
+ m_devFuncs->vkWaitForFences(m_vkDev, 1, &frame.fence, VK_TRUE, UINT64_MAX);
+ m_devFuncs->vkDestroyFence(m_vkDev, frame.fence, nullptr);
+ frame.fence = 0;
+ frame.fenceWaitable = false;
+ }
+ if (frame.imageSem) {
+ m_devFuncs->vkDestroySemaphore(m_vkDev, frame.imageSem, nullptr);
+ frame.imageSem = 0;
+ }
+ if (frame.drawSem) {
+ m_devFuncs->vkDestroySemaphore(m_vkDev, frame.drawSem, nullptr);
+ frame.drawSem = 0;
+ }
+ }
+
+ for (uint32_t i = 0; i < m_swapChainBufferCount; ++i) {
+ ImageResources &image(m_imageRes[i]);
+ if (image.cmdFence) {
+ if (image.cmdFenceWaitable)
+ m_devFuncs->vkWaitForFences(m_vkDev, 1, &image.cmdFence, VK_TRUE, UINT64_MAX);
+ m_devFuncs->vkDestroyFence(m_vkDev, image.cmdFence, nullptr);
+ image.cmdFence = 0;
+ image.cmdFenceWaitable = false;
+ }
+ if (image.fb) {
+ m_devFuncs->vkDestroyFramebuffer(m_vkDev, image.fb, nullptr);
+ image.fb = 0;
+ }
+ if (image.imageView) {
+ m_devFuncs->vkDestroyImageView(m_vkDev, image.imageView, nullptr);
+ image.imageView = 0;
+ }
+ if (image.cmdBuf) {
+ m_devFuncs->vkFreeCommandBuffers(m_vkDev, m_vkCmdPool, 1, &image.cmdBuf);
+ image.cmdBuf = 0;
+ }
+ }
+
+ if (m_swapChain) {
+ m_vkDestroySwapchainKHR(m_vkDev, m_swapChain, nullptr);
+ m_swapChain = 0;
+ }
+}
+
+void VWindow::render()
+{
+ if (!m_swapChain)
+ return;
+
+ if (size() != m_swapChainImageSize) {
+ recreateSwapChain();
+ if (!m_swapChain)
+ return;
+ }
+
+ FrameResources &frame(m_frameRes[m_currentFrame]);
+
+ // Wait if we are too far ahead, i.e. the thread gets throttled based on the presentation rate
+ // (note that we are using FIFO mode -> vsync)
+ if (frame.fenceWaitable) {
+ m_devFuncs->vkWaitForFences(m_vkDev, 1, &frame.fence, VK_TRUE, UINT64_MAX);
+ m_devFuncs->vkResetFences(m_vkDev, 1, &frame.fence);
+ }
+
+ // move on to next swapchain image
+ VkResult err = m_vkAcquireNextImageKHR(m_vkDev, m_swapChain, UINT64_MAX,
+ frame.imageSem, frame.fence, &m_currentImage);
+ if (err == VK_SUCCESS || err == VK_SUBOPTIMAL_KHR) {
+ frame.fenceWaitable = true;
+ } else if (err == VK_ERROR_OUT_OF_DATE_KHR) {
+ frame.fenceWaitable = false;
+ recreateSwapChain();
+ requestUpdate();
+ return;
+ } else {
+ qWarning("Failed to acquire next swapchain image: %d", err);
+ frame.fenceWaitable = false;
+ requestUpdate();
+ return;
+ }
+
+ // make sure the previous draw for the same image has finished
+ ImageResources &image(m_imageRes[m_currentImage]);
+ if (image.cmdFenceWaitable) {
+ m_devFuncs->vkWaitForFences(m_vkDev, 1, &image.cmdFence, VK_TRUE, UINT64_MAX);
+ m_devFuncs->vkResetFences(m_vkDev, 1, &image.cmdFence);
+ }
+
+ // build new draw command buffer
+ buildDrawCalls();
+
+ // submit draw calls
+ VkSubmitInfo submitInfo;
+ memset(&submitInfo, 0, sizeof(submitInfo));
+ submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+ submitInfo.commandBufferCount = 1;
+ submitInfo.pCommandBuffers = &image.cmdBuf;
+ submitInfo.waitSemaphoreCount = 1;
+ submitInfo.pWaitSemaphores = &frame.imageSem;
+ submitInfo.signalSemaphoreCount = 1;
+ submitInfo.pSignalSemaphores = &frame.drawSem;
+ VkPipelineStageFlags psf = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ submitInfo.pWaitDstStageMask = &psf;
+
+ err = m_devFuncs->vkQueueSubmit(m_vkGfxQueue, 1, &submitInfo, image.cmdFence);
+ if (err == VK_SUCCESS) {
+ image.cmdFenceWaitable = true;
+ } else {
+ qWarning("Failed to submit to command queue: %d", err);
+ image.cmdFenceWaitable = false;
+ }
+
+ // queue present
+ VkPresentInfoKHR presInfo;
+ memset(&presInfo, 0, sizeof(presInfo));
+ presInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
+ presInfo.swapchainCount = 1;
+ presInfo.pSwapchains = &m_swapChain;
+ presInfo.pImageIndices = &m_currentImage;
+ presInfo.waitSemaphoreCount = 1;
+ presInfo.pWaitSemaphores = &frame.drawSem;
+
+ // we do not currently handle the case when the present queue is separate
+ Q_ASSERT(m_vkGfxQueue == m_vkPresQueue);
+
+ err = m_vkQueuePresentKHR(m_vkGfxQueue, &presInfo);
+ if (err != VK_SUCCESS) {
+ if (err == VK_ERROR_OUT_OF_DATE_KHR) {
+ recreateSwapChain();
+ requestUpdate();
+ return;
+ } else if (err != VK_SUBOPTIMAL_KHR) {
+ qWarning("Failed to present: %d", err);
+ }
+ }
+
+ vulkanInstance()->presentQueued(this);
+
+ m_currentFrame = (m_currentFrame + 1) % FRAME_LAG;
+ requestUpdate();
+}
+
+void VWindow::buildDrawCalls()
+{
+ ImageResources &image(m_imageRes[m_currentImage]);
+
+ if (image.cmdBuf) {
+ m_devFuncs->vkFreeCommandBuffers(m_vkDev, m_vkCmdPool, 1, &image.cmdBuf);
+ image.cmdBuf = 0;
+ }
+
+ VkCommandBufferAllocateInfo cmdBufInfo = {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, nullptr, m_vkCmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY, 1 };
+ VkResult err = m_devFuncs->vkAllocateCommandBuffers(m_vkDev, &cmdBufInfo, &image.cmdBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to allocate frame command buffer: %d", err);
+
+ VkCommandBufferBeginInfo cmdBufBeginInfo = {
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, nullptr, 0, nullptr };
+ err = m_devFuncs->vkBeginCommandBuffer(image.cmdBuf, &cmdBufBeginInfo);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to begin frame command buffer: %d", err);
+
+ static float g = 0;
+ g += 0.005f;
+ if (g > 1.0f)
+ g = 0.0f;
+ VkClearColorValue clearColor = { 0.0f, g, 0.0f, 1.0f };
+ VkClearValue clearValues[1];
+ clearValues[0].color = clearColor;
+
+ VkRenderPassBeginInfo rpBeginInfo;
+ memset(&rpBeginInfo, 0, sizeof(rpBeginInfo));
+ rpBeginInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
+ rpBeginInfo.renderPass = m_defaultRenderPass;
+ rpBeginInfo.framebuffer = image.fb;
+ rpBeginInfo.renderArea.extent.width = m_swapChainImageSize.width();
+ rpBeginInfo.renderArea.extent.height = m_swapChainImageSize.height();
+ rpBeginInfo.clearValueCount = 1;
+ rpBeginInfo.pClearValues = clearValues;
+ m_devFuncs->vkCmdBeginRenderPass(image.cmdBuf, &rpBeginInfo, VK_SUBPASS_CONTENTS_INLINE);
+
+ m_devFuncs->vkCmdEndRenderPass(image.cmdBuf);
+
+ err = m_devFuncs->vkEndCommandBuffer(image.cmdBuf);
+ if (err != VK_SUCCESS)
+ qFatal("Failed to end frame command buffer: %d", err);
+}
+
+int main(int argc, char *argv[])
+{
+ QGuiApplication app(argc, argv);
+
+ QLoggingCategory::setFilterRules(QStringLiteral("qt.vulkan=true"));
+
+ QVulkanInstance inst;
+ // Test the early queries for supported layers/exts.
+ qDebug() << inst.supportedLayers() << inst.supportedExtensions();
+
+ // Enable validation layer, if supported.
+ inst.setLayers(QByteArrayList() << "VK_LAYER_LUNARG_standard_validation");
+
+ bool ok = inst.create();
+ qDebug("QVulkanInstance::create() returned %d", ok);
+ if (!ok)
+ return 1;
+
+ VWindow w;
+ w.setVulkanInstance(&inst);
+ w.resize(1024, 768);
+ w.show();
+
+ return app.exec();
+}
diff --git a/tests/manual/qvulkaninstance/qvulkaninstance.pro b/tests/manual/qvulkaninstance/qvulkaninstance.pro
new file mode 100644
index 0000000000..7305da53c1
--- /dev/null
+++ b/tests/manual/qvulkaninstance/qvulkaninstance.pro
@@ -0,0 +1,6 @@
+TEMPLATE = app
+TARGET = qvulkaninstance
+
+QT += gui-private
+
+SOURCES += main.cpp
diff --git a/tests/manual/windowflags/controllerwindow.cpp b/tests/manual/windowflags/controllerwindow.cpp
index 9a12c8b2c9..4b380d5355 100644
--- a/tests/manual/windowflags/controllerwindow.cpp
+++ b/tests/manual/windowflags/controllerwindow.cpp
@@ -59,24 +59,26 @@ ControllerWidget::ControllerWidget(QWidget *parent)
QLabel *label = new QLabel(tr("Parent window"));
parentWindow->setCentralWidget(label);
- previewWindow = new PreviewWindow;
+ previewWindow = new QWindow;
previewWindow->installEventFilter(this);
+ previewWidget = new PreviewWidget;
+ previewWidget->installEventFilter(this);
previewDialog = new PreviewDialog;
previewDialog->installEventFilter(this);
createTypeGroupBox();
hintsControl = new HintControl;
- hintsControl->setHints(previewWindow->windowFlags());
+ hintsControl->setHints(previewWidget->windowFlags());
connect(hintsControl, SIGNAL(changed(Qt::WindowFlags)), this, SLOT(updatePreview()));
statesControl = new WindowStatesControl;
- statesControl->setStates(previewWindow->windowState());
+ statesControl->setStates(previewWidget->windowState());
statesControl->setVisibleValue(true);
connect(statesControl, SIGNAL(changed()), this, SLOT(updatePreview()));
typeControl = new TypeControl;
- typeControl->setType(previewWindow->windowFlags());
+ typeControl->setType(previewWidget->windowFlags());
connect(typeControl, SIGNAL(changed(Qt::WindowFlags)), this, SLOT(updatePreview()));
QVBoxLayout *mainLayout = new QVBoxLayout(this);
@@ -98,61 +100,99 @@ bool ControllerWidget::eventFilter(QObject *, QEvent *e)
void ControllerWidget::updateStateControl()
{
- if (previewWidget)
- statesControl->setStates(previewWidget->windowState());
+ if (activePreview)
+ statesControl->setStates(activePreview->windowStates());
}
-void ControllerWidget::updatePreview()
+void ControllerWidget::updatePreview(QWindow *preview)
{
- const Qt::WindowFlags flags = typeControl->type() | hintsControl->hints();
+ activePreview = preview;
- if (previewWidgetButton->isChecked()) {
- previewWidget = previewWindow;
- previewDialog->hide();
- } else {
- previewWidget = previewDialog;
- previewWindow->hide();
- }
+ const Qt::WindowFlags flags = typeControl->type() | hintsControl->hints();
if (modalWindowCheckBox->isChecked()) {
parentWindow->show();
- previewWidget->setWindowModality(Qt::WindowModal);
- previewWidget->setParent(parentWindow);
+ preview->setModality(Qt::WindowModal);
+ preview->setParent(parentWindow->windowHandle());
} else {
- previewWidget->setWindowModality(Qt::NonModal);
- previewWidget->setParent(0);
+ preview->setModality(Qt::NonModal);
+ preview->setParent(0);
parentWindow->hide();
}
- if (previewWidgetButton->isChecked())
- previewWindow->setWindowFlags(flags);
- else
- previewDialog->setWindowFlags(flags);
+ preview->setFlags(flags);
if (fixedSizeWindowCheckBox->isChecked()) {
- previewWidget->setFixedSize(300, 300);
+ preview->setMinimumSize(QSize(300, 300));
+ preview->setMaximumSize(QSize(300, 300));
} else {
- previewWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+ preview->setMinimumSize(QSize(0, 0));
+ preview->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX));
}
- QPoint pos = previewWidget->pos();
+ preview->setWindowStates(statesControl->states());
+ preview->setVisible(statesControl->visibleValue());
+}
+
+void ControllerWidget::updatePreview(QWidget *preview)
+{
+ activePreview = preview->windowHandle();
+
+ const Qt::WindowFlags flags = typeControl->type() | hintsControl->hints();
+
+ if (modalWindowCheckBox->isChecked()) {
+ parentWindow->show();
+ preview->setWindowModality(Qt::WindowModal);
+ preview->setParent(parentWindow);
+ } else {
+ preview->setWindowModality(Qt::NonModal);
+ preview->setParent(0);
+ parentWindow->hide();
+ }
+
+ preview->setWindowFlags(flags);
+
+ QSize fixedSize = fixedSizeWindowCheckBox->isChecked() ?
+ QSize(300, 300) : QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
+ preview->setFixedSize(fixedSize);
+
+ QPoint pos = preview->pos();
if (pos.x() < 0)
pos.setX(0);
if (pos.y() < 0)
pos.setY(0);
- previewWidget->move(pos);
+ preview->move(pos);
+
+ preview->setWindowState(statesControl->states());
+ preview->setVisible(statesControl->visibleValue());
+}
- previewWidget->setWindowState(statesControl->states());
- previewWidget->setVisible(statesControl->visibleValue());
+void ControllerWidget::updatePreview()
+{
+ if (previewWindowButton->isChecked()) {
+ previewDialog->hide();
+ previewWidget->close();
+ updatePreview(previewWindow);
+ } else if (previewWidgetButton->isChecked()) {
+ previewWindow->hide();
+ previewDialog->hide();
+ updatePreview(previewWidget);
+ } else {
+ previewWindow->hide();
+ previewWidget->close();
+ updatePreview(previewDialog);
+ }
}
void ControllerWidget::createTypeGroupBox()
{
- widgetTypeGroupBox = new QGroupBox(tr("Widget Type"));
+ widgetTypeGroupBox = new QGroupBox(tr("Window Type"));
+ previewWindowButton = createRadioButton(tr("QWindow"));
previewWidgetButton = createRadioButton(tr("QWidget"));
- previewWidgetButton->setChecked(true);
previewDialogButton = createRadioButton(tr("QDialog"));
+ previewWindowButton->setChecked(true);
QHBoxLayout *l = new QHBoxLayout;
+ l->addWidget(previewWindowButton);
l->addWidget(previewWidgetButton);
l->addWidget(previewDialogButton);
widgetTypeGroupBox->setLayout(l);
diff --git a/tests/manual/windowflags/controllerwindow.h b/tests/manual/windowflags/controllerwindow.h
index 43a125a9ae..c623256112 100644
--- a/tests/manual/windowflags/controllerwindow.h
+++ b/tests/manual/windowflags/controllerwindow.h
@@ -60,20 +60,27 @@ private slots:
void updateStateControl();
private:
+ void updatePreview(QWindow *);
+ void updatePreview(QWidget *);
void createTypeGroupBox();
QCheckBox *createCheckBox(const QString &text);
QRadioButton *createRadioButton(const QString &text);
QMainWindow *parentWindow;
- PreviewWindow *previewWindow;
+
+ QWindow *previewWindow;
+ PreviewWidget *previewWidget;
PreviewDialog *previewDialog;
- QWidget *previewWidget;
+
+ QWindow *activePreview;
+
QGroupBox *widgetTypeGroupBox;
QGroupBox *additionalOptionsGroupBox;
TypeControl *typeControl;
HintControl *hintsControl;
WindowStatesControl *statesControl;
+ QRadioButton *previewWindowButton;
QRadioButton *previewWidgetButton;
QRadioButton *previewDialogButton;
QCheckBox *modalWindowCheckBox;
diff --git a/tests/manual/windowflags/main.cpp b/tests/manual/windowflags/main.cpp
index a7d7307525..4da878d8cc 100644
--- a/tests/manual/windowflags/main.cpp
+++ b/tests/manual/windowflags/main.cpp
@@ -43,5 +43,6 @@ int main(int argc, char *argv[])
if (!arguments.contains(QLatin1String("-e")))
controller.registerEventFilter();
controller.show();
+ controller.lower();
return app.exec();
}
diff --git a/tests/manual/windowflags/previewwindow.cpp b/tests/manual/windowflags/previewwindow.cpp
index 65a287f788..19473c9eee 100644
--- a/tests/manual/windowflags/previewwindow.cpp
+++ b/tests/manual/windowflags/previewwindow.cpp
@@ -172,37 +172,37 @@ static QPlainTextEdit *createControlPanel(QWidget *widget)
QGridLayout *buttonLayout = new QGridLayout;
bottomLayout->addStretch();
bottomLayout->addLayout(buttonLayout);
- QPushButton *showNormalButton = new QPushButton(PreviewWindow::tr("Show normal"));
+ QPushButton *showNormalButton = new QPushButton(PreviewWidget::tr("Show normal"));
QObject::connect(showNormalButton, SIGNAL(clicked()), widget, SLOT(showNormal()));
buttonLayout->addWidget(showNormalButton, 0, 0);
- QPushButton *showMinimizedButton = new QPushButton(PreviewWindow::tr("Show minimized"));
+ QPushButton *showMinimizedButton = new QPushButton(PreviewWidget::tr("Show minimized"));
QObject::connect(showMinimizedButton, SIGNAL(clicked()), widget, SLOT(showMinimized()));
buttonLayout->addWidget(showMinimizedButton, 0, 1);
- QPushButton *showMaximizedButton = new QPushButton(PreviewWindow::tr("Show maximized"));
+ QPushButton *showMaximizedButton = new QPushButton(PreviewWidget::tr("Show maximized"));
QObject::connect(showMaximizedButton, SIGNAL(clicked()), widget, SLOT(showMaximized()));
buttonLayout->addWidget(showMaximizedButton, 0, 2);
- QPushButton *showFullScreenButton = new QPushButton(PreviewWindow::tr("Show fullscreen"));
+ QPushButton *showFullScreenButton = new QPushButton(PreviewWidget::tr("Show fullscreen"));
QObject::connect(showFullScreenButton, SIGNAL(clicked()), widget, SLOT(showFullScreen()));
buttonLayout->addWidget(showFullScreenButton, 0, 3);
- QPushButton *updateInfoButton = new QPushButton(PreviewWindow::tr("&Update Info"));
+ QPushButton *updateInfoButton = new QPushButton(PreviewWidget::tr("&Update Info"));
QObject::connect(updateInfoButton, SIGNAL(clicked()), widget, SLOT(updateInfo()));
buttonLayout->addWidget(updateInfoButton, 1, 0);
- QPushButton *closeButton = new QPushButton(PreviewWindow::tr("&Close"));
+ QPushButton *closeButton = new QPushButton(PreviewWidget::tr("&Close"));
QObject::connect(closeButton, SIGNAL(clicked()), widget, SLOT(close()));
buttonLayout->addWidget(closeButton, 1, 3);
return textEdit;
}
-PreviewWindow::PreviewWindow(QWidget *parent)
+PreviewWidget::PreviewWidget(QWidget *parent)
: QWidget(parent)
{
textEdit = createControlPanel(this);
setWindowTitle(tr("Preview <QWidget> Qt %1").arg(QLatin1String(QT_VERSION_STR)));
}
-bool PreviewWindow::event(QEvent *event)
+bool PreviewWidget::event(QEvent *event)
{
const bool ret = QWidget::event(event);
@@ -219,7 +219,7 @@ bool PreviewWindow::event(QEvent *event)
return ret;
}
-void PreviewWindow::setWindowFlags(Qt::WindowFlags flags)
+void PreviewWidget::setWindowFlags(Qt::WindowFlags flags)
{
if (flags == windowFlags())
return;
@@ -227,7 +227,7 @@ void PreviewWindow::setWindowFlags(Qt::WindowFlags flags)
QTimer::singleShot(0, this, SLOT(updateInfo()));
}
-void PreviewWindow::updateInfo()
+void PreviewWidget::updateInfo()
{
textEdit->setPlainText(formatWidgetInfo(this));
}
diff --git a/tests/manual/windowflags/previewwindow.h b/tests/manual/windowflags/previewwindow.h
index 9730e7a3f9..023ddd910c 100644
--- a/tests/manual/windowflags/previewwindow.h
+++ b/tests/manual/windowflags/previewwindow.h
@@ -35,12 +35,12 @@ QT_BEGIN_NAMESPACE
class QPlainTextEdit;
QT_END_NAMESPACE
-class PreviewWindow : public QWidget
+class PreviewWidget : public QWidget
{
Q_OBJECT
public:
- PreviewWindow(QWidget *parent = 0);
+ PreviewWidget(QWidget *parent = 0);
void setWindowFlags(Qt::WindowFlags flags);
diff --git a/util/edid/qedidvendortable.py b/util/edid/qedidvendortable.py
new file mode 100755
index 0000000000..6d30f3a60d
--- /dev/null
+++ b/util/edid/qedidvendortable.py
@@ -0,0 +1,123 @@
+#!/usr/bin/env python3
+#############################################################################
+##
+## Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the plugins of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+import urllib.request
+
+url = 'https://git.fedorahosted.org/cgit/hwdata.git/plain/pnp.ids'
+
+copyright = """/****************************************************************************
+**
+** Copyright (C) 2017 Pier Luigi Fiorini <pierluigi.fiorini@gmail.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+"""
+
+notice = """/*
+ * This lookup table was generated from {}
+ *
+ * Do not change directly this file, instead edit the
+ * qtbase/util/edid/qedidvendortable.py script and regenerate this file.
+ */""".format(url)
+
+header = """
+#ifndef QEDIDVENDORTABLE_P_H
+#define QEDIDVENDORTABLE_P_H
+
+QT_BEGIN_NAMESPACE
+
+typedef struct VendorTable {
+ const char id[4];
+ const char name[%d];
+} VendorTable;
+
+static const struct VendorTable q_edidVendorTable[] = {"""
+
+footer = """};
+
+QT_END_NAMESPACE
+
+#endif // QEDIDVENDORTABLE_P_H"""
+
+vendors = {}
+
+max_vendor_length = 0
+
+response = urllib.request.urlopen(url)
+data = response.read().decode('utf-8')
+for line in data.split('\n'):
+ l = line.split()
+ if line.startswith('#'):
+ continue
+ elif len(l) == 0:
+ continue
+ else:
+ pnp_id = l[0].upper()
+ vendors[pnp_id] = ' '.join(l[1:])
+ if len(vendors[pnp_id]) > max_vendor_length:
+ max_vendor_length = len(vendors[pnp_id])
+
+print(copyright)
+print(notice)
+print(header % (max_vendor_length + 1))
+for pnp_id in vendors.keys():
+ print(' { "%s", "%s" },' % (pnp_id, vendors[pnp_id]))
+print(footer)
diff --git a/util/local_database/cldr2qlocalexml.py b/util/local_database/cldr2qlocalexml.py
index 41cfafab0d..58ea21edab 100755
--- a/util/local_database/cldr2qlocalexml.py
+++ b/util/local_database/cldr2qlocalexml.py
@@ -1,7 +1,7 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
#############################################################################
##
-## Copyright (C) 2016 The Qt Company Ltd.
+## Copyright (C) 2017 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of the test suite of the Qt Toolkit.
@@ -26,20 +26,31 @@
## $QT_END_LICENSE$
##
#############################################################################
+"""Convert CLDR data to qLocaleXML
+
+The CLDR data can be downloaded from CLDR_, which has a sub-directory
+for each version; you need the ``core.zip`` file for your version of
+choice (typically the latest). This script has had updates to cope up
+to v29; for later versions, we may need adaptations. Unpack the
+downloaded ``core.zip`` and check it has a common/main/ sub-directory:
+pass the path of that sub-directory to this script as its single
+command-line argument. Save its standard output (but not error) to a
+file for later processing by ``./qlocalexml2cpp.py``
+
+.. _CLDR: ftp://unicode.org/Public/cldr/
+"""
import os
import sys
+import re
+
import enumdata
import xpathlite
-from xpathlite import DraftResolution
+from xpathlite import DraftResolution, findAlias, findEntry, findTagsInFile
from dateconverter import convert_date
-from xml.sax.saxutils import escape, unescape
-import re
+from localexml import Locale
-findAlias = xpathlite.findAlias
-findEntry = xpathlite.findEntry
findEntryInFile = xpathlite._findEntryInFile
-findTagsInFile = xpathlite.findTagsInFile
def parse_number_format(patterns, data):
# this is a very limited parsing of the number format for currency only.
@@ -72,42 +83,49 @@ def parse_number_format(patterns, data):
return result
def parse_list_pattern_part_format(pattern):
- # this is a very limited parsing of the format for list pattern part only.
- result = ""
- result = pattern.replace("{0}", "%1")
- result = result.replace("{1}", "%2")
- result = result.replace("{2}", "%3")
- return result
-
-def ordStr(c):
- if len(c) == 1:
- return str(ord(c))
- raise xpathlite.Error("Unable to handle value \"%s\"" % addEscapes(c))
- return "##########"
-
-# the following functions are supposed to fix the problem with QLocale
-# returning a character instead of strings for QLocale::exponential()
-# and others. So we fallback to default values in these cases.
-def fixOrdStrMinus(c):
- if len(c) == 1:
- return str(ord(c))
- return str(ord('-'))
-def fixOrdStrPlus(c):
- if len(c) == 1:
- return str(ord(c))
- return str(ord('+'))
-def fixOrdStrExp(c):
- if len(c) == 1:
- return str(ord(c))
- return str(ord('e'))
-def fixOrdStrPercent(c):
- if len(c) == 1:
- return str(ord(c))
- return str(ord('%'))
-def fixOrdStrList(c):
- if len(c) == 1:
- return str(ord(c))
- return str(ord(';'))
+ # This is a very limited parsing of the format for list pattern part only.
+ return pattern.replace("{0}", "%1").replace("{1}", "%2").replace("{2}", "%3")
+
+def unit_quantifiers(find, path, stem, suffix, known,
+ # Stop at exa/exbi: 16 exbi = 2^{64} < zetta =
+ # 1000^7 < zebi = 2^{70}, the next quantifiers up:
+ si_quantifiers = ('kilo', 'mega', 'giga', 'tera', 'peta', 'exa')):
+ """Work out the unit quantifiers.
+
+ Unfortunately, the CLDR data only go up to terabytes and we want
+ all the way to exabytes; but we can recognize the SI quantifiers
+ as prefixes, strip and identify the tail as the localized
+ translation for 'B' (e.g. French has 'octet' for 'byte' and uses
+ ko, Mo, Go, To from which we can extrapolate Po, Eo).
+
+ Should be called first for the SI quantifiers, with suffix = 'B',
+ then for the IEC ones, with suffix = 'iB'; the list known
+ (initially empty before first call) is used to let the second call
+ know what the first learned about the localized unit.
+ """
+ if suffix == 'B': # first call, known = []
+ tail = suffix
+ for q in si_quantifiers:
+ it = find(path, stem % q)
+ # kB for kilobyte, in contrast with KiB for IEC:
+ q = q[0] if q == 'kilo' else q[0].upper()
+ if not it:
+ it = q + tail
+ elif it.startswith(q):
+ rest = it[1:]
+ tail = rest if all(rest == k for k in known) else suffix
+ known.append(rest)
+ yield it
+ else: # second call, re-using first's known
+ assert suffix == 'iB'
+ if known:
+ byte = known.pop()
+ if all(byte == k for k in known):
+ suffix = 'i' + byte
+ for q in si_quantifiers:
+ yield find(path, stem % q[:2],
+ # Those don't (yet, v31) exist in CLDR, so we always fall back to:
+ q[0].upper() + suffix)
def generateLocaleInfo(path):
if not path.endswith(".xml"):
@@ -116,14 +134,13 @@ def generateLocaleInfo(path):
# skip legacy/compatibility ones
alias = findAlias(path)
if alias:
- raise xpathlite.Error("alias to \"%s\"" % alias)
+ raise xpathlite.Error('alias to "%s"' % alias)
- language_code = findEntryInFile(path, "identity/language", attribute="type")[0]
- country_code = findEntryInFile(path, "identity/territory", attribute="type")[0]
- script_code = findEntryInFile(path, "identity/script", attribute="type")[0]
- variant_code = findEntryInFile(path, "identity/variant", attribute="type")[0]
+ def code(tag):
+ return findEntryInFile(path, 'identity/' + tag, attribute="type")[0]
- return _generateLocaleInfo(path, language_code, script_code, country_code, variant_code)
+ return _generateLocaleInfo(path, code('language'), code('script'),
+ code('territory'), code('variant'))
def _generateLocaleInfo(path, language_code, script_code, country_code, variant_code=""):
if not path.endswith(".xml"):
@@ -137,25 +154,22 @@ def _generateLocaleInfo(path, language_code, script_code, country_code, variant_
# ### actually there is only one locale with variant: en_US_POSIX
# does anybody care about it at all?
if variant_code:
- raise xpathlite.Error("we do not support variants (\"%s\")" % variant_code)
+ raise xpathlite.Error('we do not support variants ("%s")' % variant_code)
language_id = enumdata.languageCodeToId(language_code)
if language_id <= 0:
- raise xpathlite.Error("unknown language code \"%s\"" % language_code)
- language = enumdata.language_list[language_id][0]
+ raise xpathlite.Error('unknown language code "%s"' % language_code)
script_id = enumdata.scriptCodeToId(script_code)
if script_id == -1:
- raise xpathlite.Error("unknown script code \"%s\"" % script_code)
- script = enumdata.script_list[script_id][0]
+ raise xpathlite.Error('unknown script code "%s"' % script_code)
# we should handle fully qualified names with the territory
if not country_code:
return {}
country_id = enumdata.countryCodeToId(country_code)
if country_id <= 0:
- raise xpathlite.Error("unknown country code \"%s\"" % country_code)
- country = enumdata.country_list[country_id][0]
+ raise xpathlite.Error('unknown country code "%s"' % country_code)
# So we say we accept only those values that have "contributed" or
# "approved" resolution. see http://www.unicode.org/cldr/process.html
@@ -163,39 +177,39 @@ def _generateLocaleInfo(path, language_code, script_code, country_code, variant_
# compatibility.
draft = DraftResolution.contributed
- result = {}
- result['language'] = language
- result['script'] = script
- result['country'] = country
- result['language_code'] = language_code
- result['country_code'] = country_code
- result['script_code'] = script_code
- result['variant_code'] = variant_code
- result['language_id'] = language_id
- result['script_id'] = script_id
- result['country_id'] = country_id
+ result = dict(
+ language=enumdata.language_list[language_id][0],
+ language_code=language_code, language_id=language_id,
+ script=enumdata.script_list[script_id][0],
+ script_code=script_code, script_id=script_id,
+ country=enumdata.country_list[country_id][0],
+ country_code=country_code, country_id=country_id,
+ variant_code=variant_code)
(dir_name, file_name) = os.path.split(path)
- supplementalPath = dir_name + "/../supplemental/supplementalData.xml"
- currencies = findTagsInFile(supplementalPath, "currencyData/region[iso3166=%s]"%country_code);
+ def from_supplement(tag,
+ path=os.path.join(dir_name, '..', 'supplemental',
+ 'supplementalData.xml')):
+ return findTagsInFile(path, tag)
+ currencies = from_supplement('currencyData/region[iso3166=%s]' % country_code)
result['currencyIsoCode'] = ''
result['currencyDigits'] = 2
result['currencyRounding'] = 1
if currencies:
for e in currencies:
if e[0] == 'currency':
- tender = True
- t = filter(lambda x: x[0] == 'tender', e[1])
- if t and t[0][1] == 'false':
- tender = False;
- if tender and not filter(lambda x: x[0] == 'to', e[1]):
- result['currencyIsoCode'] = filter(lambda x: x[0] == 'iso4217', e[1])[0][1]
+ t = [x[1] == 'false' for x in e[1] if x[0] == 'tender']
+ if t and t[0]:
+ pass
+ elif not any(x[0] == 'to' for x in e[1]):
+ result['currencyIsoCode'] = (x[1] for x in e[1] if x[0] == 'iso4217').next()
break
if result['currencyIsoCode']:
- t = findTagsInFile(supplementalPath, "currencyData/fractions/info[iso4217=%s]"%result['currencyIsoCode']);
+ t = from_supplement("currencyData/fractions/info[iso4217=%s]"
+ % result['currencyIsoCode'])
if t and t[0][0] == 'info':
- result['currencyDigits'] = int(filter(lambda x: x[0] == 'digits', t[0][1])[0][1])
- result['currencyRounding'] = int(filter(lambda x: x[0] == 'rounding', t[0][1])[0][1])
+ result['currencyDigits'] = (int(x[1]) for x in t[0][1] if x[0] == 'digits').next()
+ result['currencyRounding'] = (int(x[1]) for x in t[0][1] if x[0] == 'rounding').next()
numbering_system = None
try:
numbering_system = findEntry(path, "numbers/defaultNumberingSystem")
@@ -226,7 +240,9 @@ def _generateLocaleInfo(path, language_code, script_code, country_code, variant_
result['percent'] = get_number_in_system(path, "numbers/symbols/percentSign", numbering_system)
try:
numbering_systems = {}
- for ns in findTagsInFile(cldr_dir + "/../supplemental/numberingSystems.xml", "numberingSystems"):
+ for ns in findTagsInFile(os.path.join(cldr_dir, '..', 'supplemental',
+ 'numberingSystems.xml'),
+ 'numberingSystems'):
tmp = {}
id = ""
for data in ns[1:][0]: # ns looks like this: [u'numberingSystem', [(u'digits', u'0123456789'), (u'type', u'numeric'), (u'id', u'latn')]]
@@ -279,167 +295,70 @@ def _generateLocaleInfo(path, language_code, script_code, country_code, variant_
result['currencyDisplayName'] = ''
if result['currencyIsoCode']:
result['currencySymbol'] = findEntryDef(path, "numbers/currencies/currency[%s]/symbol" % result['currencyIsoCode'])
- display_name_path = "numbers/currencies/currency[%s]/displayName" % result['currencyIsoCode']
- result['currencyDisplayName'] \
- = findEntryDef(path, display_name_path) + ";" \
- + findEntryDef(path, display_name_path + "[count=zero]") + ";" \
- + findEntryDef(path, display_name_path + "[count=one]") + ";" \
- + findEntryDef(path, display_name_path + "[count=two]") + ";" \
- + findEntryDef(path, display_name_path + "[count=few]") + ";" \
- + findEntryDef(path, display_name_path + "[count=many]") + ";" \
- + findEntryDef(path, display_name_path + "[count=other]") + ";"
-
- standalone_long_month_path = "dates/calendars/calendar[gregorian]/months/monthContext[stand-alone]/monthWidth[wide]/month"
- result['standaloneLongMonths'] \
- = findEntry(path, standalone_long_month_path + "[1]") + ";" \
- + findEntry(path, standalone_long_month_path + "[2]") + ";" \
- + findEntry(path, standalone_long_month_path + "[3]") + ";" \
- + findEntry(path, standalone_long_month_path + "[4]") + ";" \
- + findEntry(path, standalone_long_month_path + "[5]") + ";" \
- + findEntry(path, standalone_long_month_path + "[6]") + ";" \
- + findEntry(path, standalone_long_month_path + "[7]") + ";" \
- + findEntry(path, standalone_long_month_path + "[8]") + ";" \
- + findEntry(path, standalone_long_month_path + "[9]") + ";" \
- + findEntry(path, standalone_long_month_path + "[10]") + ";" \
- + findEntry(path, standalone_long_month_path + "[11]") + ";" \
- + findEntry(path, standalone_long_month_path + "[12]") + ";"
-
- standalone_short_month_path = "dates/calendars/calendar[gregorian]/months/monthContext[stand-alone]/monthWidth[abbreviated]/month"
- result['standaloneShortMonths'] \
- = findEntry(path, standalone_short_month_path + "[1]") + ";" \
- + findEntry(path, standalone_short_month_path + "[2]") + ";" \
- + findEntry(path, standalone_short_month_path + "[3]") + ";" \
- + findEntry(path, standalone_short_month_path + "[4]") + ";" \
- + findEntry(path, standalone_short_month_path + "[5]") + ";" \
- + findEntry(path, standalone_short_month_path + "[6]") + ";" \
- + findEntry(path, standalone_short_month_path + "[7]") + ";" \
- + findEntry(path, standalone_short_month_path + "[8]") + ";" \
- + findEntry(path, standalone_short_month_path + "[9]") + ";" \
- + findEntry(path, standalone_short_month_path + "[10]") + ";" \
- + findEntry(path, standalone_short_month_path + "[11]") + ";" \
- + findEntry(path, standalone_short_month_path + "[12]") + ";"
-
- standalone_narrow_month_path = "dates/calendars/calendar[gregorian]/months/monthContext[stand-alone]/monthWidth[narrow]/month"
- result['standaloneNarrowMonths'] \
- = findEntry(path, standalone_narrow_month_path + "[1]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[2]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[3]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[4]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[5]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[6]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[7]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[8]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[9]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[10]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[11]") + ";" \
- + findEntry(path, standalone_narrow_month_path + "[12]") + ";"
-
- long_month_path = "dates/calendars/calendar[gregorian]/months/monthContext[format]/monthWidth[wide]/month"
- result['longMonths'] \
- = findEntry(path, long_month_path + "[1]") + ";" \
- + findEntry(path, long_month_path + "[2]") + ";" \
- + findEntry(path, long_month_path + "[3]") + ";" \
- + findEntry(path, long_month_path + "[4]") + ";" \
- + findEntry(path, long_month_path + "[5]") + ";" \
- + findEntry(path, long_month_path + "[6]") + ";" \
- + findEntry(path, long_month_path + "[7]") + ";" \
- + findEntry(path, long_month_path + "[8]") + ";" \
- + findEntry(path, long_month_path + "[9]") + ";" \
- + findEntry(path, long_month_path + "[10]") + ";" \
- + findEntry(path, long_month_path + "[11]") + ";" \
- + findEntry(path, long_month_path + "[12]") + ";"
-
- short_month_path = "dates/calendars/calendar[gregorian]/months/monthContext[format]/monthWidth[abbreviated]/month"
- result['shortMonths'] \
- = findEntry(path, short_month_path + "[1]") + ";" \
- + findEntry(path, short_month_path + "[2]") + ";" \
- + findEntry(path, short_month_path + "[3]") + ";" \
- + findEntry(path, short_month_path + "[4]") + ";" \
- + findEntry(path, short_month_path + "[5]") + ";" \
- + findEntry(path, short_month_path + "[6]") + ";" \
- + findEntry(path, short_month_path + "[7]") + ";" \
- + findEntry(path, short_month_path + "[8]") + ";" \
- + findEntry(path, short_month_path + "[9]") + ";" \
- + findEntry(path, short_month_path + "[10]") + ";" \
- + findEntry(path, short_month_path + "[11]") + ";" \
- + findEntry(path, short_month_path + "[12]") + ";"
-
- narrow_month_path = "dates/calendars/calendar[gregorian]/months/monthContext[format]/monthWidth[narrow]/month"
- result['narrowMonths'] \
- = findEntry(path, narrow_month_path + "[1]") + ";" \
- + findEntry(path, narrow_month_path + "[2]") + ";" \
- + findEntry(path, narrow_month_path + "[3]") + ";" \
- + findEntry(path, narrow_month_path + "[4]") + ";" \
- + findEntry(path, narrow_month_path + "[5]") + ";" \
- + findEntry(path, narrow_month_path + "[6]") + ";" \
- + findEntry(path, narrow_month_path + "[7]") + ";" \
- + findEntry(path, narrow_month_path + "[8]") + ";" \
- + findEntry(path, narrow_month_path + "[9]") + ";" \
- + findEntry(path, narrow_month_path + "[10]") + ";" \
- + findEntry(path, narrow_month_path + "[11]") + ";" \
- + findEntry(path, narrow_month_path + "[12]") + ";"
-
- long_day_path = "dates/calendars/calendar[gregorian]/days/dayContext[format]/dayWidth[wide]/day"
- result['longDays'] \
- = findEntry(path, long_day_path + "[sun]") + ";" \
- + findEntry(path, long_day_path + "[mon]") + ";" \
- + findEntry(path, long_day_path + "[tue]") + ";" \
- + findEntry(path, long_day_path + "[wed]") + ";" \
- + findEntry(path, long_day_path + "[thu]") + ";" \
- + findEntry(path, long_day_path + "[fri]") + ";" \
- + findEntry(path, long_day_path + "[sat]") + ";"
-
- short_day_path = "dates/calendars/calendar[gregorian]/days/dayContext[format]/dayWidth[abbreviated]/day"
- result['shortDays'] \
- = findEntry(path, short_day_path + "[sun]") + ";" \
- + findEntry(path, short_day_path + "[mon]") + ";" \
- + findEntry(path, short_day_path + "[tue]") + ";" \
- + findEntry(path, short_day_path + "[wed]") + ";" \
- + findEntry(path, short_day_path + "[thu]") + ";" \
- + findEntry(path, short_day_path + "[fri]") + ";" \
- + findEntry(path, short_day_path + "[sat]") + ";"
-
- narrow_day_path = "dates/calendars/calendar[gregorian]/days/dayContext[format]/dayWidth[narrow]/day"
- result['narrowDays'] \
- = findEntry(path, narrow_day_path + "[sun]") + ";" \
- + findEntry(path, narrow_day_path + "[mon]") + ";" \
- + findEntry(path, narrow_day_path + "[tue]") + ";" \
- + findEntry(path, narrow_day_path + "[wed]") + ";" \
- + findEntry(path, narrow_day_path + "[thu]") + ";" \
- + findEntry(path, narrow_day_path + "[fri]") + ";" \
- + findEntry(path, narrow_day_path + "[sat]") + ";"
-
- standalone_long_day_path = "dates/calendars/calendar[gregorian]/days/dayContext[stand-alone]/dayWidth[wide]/day"
- result['standaloneLongDays'] \
- = findEntry(path, standalone_long_day_path + "[sun]") + ";" \
- + findEntry(path, standalone_long_day_path + "[mon]") + ";" \
- + findEntry(path, standalone_long_day_path + "[tue]") + ";" \
- + findEntry(path, standalone_long_day_path + "[wed]") + ";" \
- + findEntry(path, standalone_long_day_path + "[thu]") + ";" \
- + findEntry(path, standalone_long_day_path + "[fri]") + ";" \
- + findEntry(path, standalone_long_day_path + "[sat]") + ";"
-
- standalone_short_day_path = "dates/calendars/calendar[gregorian]/days/dayContext[stand-alone]/dayWidth[abbreviated]/day"
- result['standaloneShortDays'] \
- = findEntry(path, standalone_short_day_path + "[sun]") + ";" \
- + findEntry(path, standalone_short_day_path + "[mon]") + ";" \
- + findEntry(path, standalone_short_day_path + "[tue]") + ";" \
- + findEntry(path, standalone_short_day_path + "[wed]") + ";" \
- + findEntry(path, standalone_short_day_path + "[thu]") + ";" \
- + findEntry(path, standalone_short_day_path + "[fri]") + ";" \
- + findEntry(path, standalone_short_day_path + "[sat]") + ";"
-
- standalone_narrow_day_path = "dates/calendars/calendar[gregorian]/days/dayContext[stand-alone]/dayWidth[narrow]/day"
- result['standaloneNarrowDays'] \
- = findEntry(path, standalone_narrow_day_path + "[sun]") + ";" \
- + findEntry(path, standalone_narrow_day_path + "[mon]") + ";" \
- + findEntry(path, standalone_narrow_day_path + "[tue]") + ";" \
- + findEntry(path, standalone_narrow_day_path + "[wed]") + ";" \
- + findEntry(path, standalone_narrow_day_path + "[thu]") + ";" \
- + findEntry(path, standalone_narrow_day_path + "[fri]") + ";" \
- + findEntry(path, standalone_narrow_day_path + "[sat]") + ";"
-
- return result
+ result['currencyDisplayName'] = ';'.join(
+ findEntryDef(path, 'numbers/currencies/currency[' + result['currencyIsoCode']
+ + ']/displayName' + tail)
+ for tail in ['',] + [
+ '[count=%s]' % x for x in ('zero', 'one', 'two', 'few', 'many', 'other')
+ ]) + ';'
+
+ def findUnitDef(path, stem, fallback=''):
+ # The displayName for a quantified unit in en.xml is kByte
+ # instead of kB (etc.), so prefer any unitPattern provided:
+ for count in ('many', 'few', 'two', 'other', 'zero', 'one'):
+ try:
+ ans = findEntry(path, stem + 'unitPattern[count=%s]' % count)
+ except xpathlite.Error:
+ continue
+
+ # TODO: epxloit count-handling, instead of discarding placeholders
+ if ans.startswith('{0}'):
+ ans = ans[3:].lstrip()
+ if ans:
+ return ans
+
+ return findEntryDef(path, stem + 'displayName', fallback)
+
+ # First without quantifier, then quantified each way:
+ result['byte_unit'] = findEntryDef(
+ path, 'units/unitLength[type=long]/unit[type=digital-byte]/displayName',
+ 'bytes')
+ stem = 'units/unitLength[type=short]/unit[type=digital-%sbyte]/'
+ known = [] # cases where we *do* have a given version:
+ result['byte_si_quantified'] = ';'.join(unit_quantifiers(findUnitDef, path, stem, 'B', known))
+ # IEC 60027-2
+ # http://physics.nist.gov/cuu/Units/binary.html
+ result['byte_iec_quantified'] = ';'.join(unit_quantifiers(findUnitDef, path, stem % '%sbi', 'iB', known))
+
+ # Used for month and day data:
+ namings = (
+ ('standaloneLong', 'stand-alone', 'wide'),
+ ('standaloneShort', 'stand-alone', 'abbreviated'),
+ ('standaloneNarrow', 'stand-alone', 'narrow'),
+ ('long', 'format', 'wide'),
+ ('short', 'format', 'abbreviated'),
+ ('narrow', 'format', 'narrow'),
+ )
+
+ # Month data:
+ for cal in ('gregorian',): # We shall want to add to this
+ stem = 'dates/calendars/calendar[' + cal + ']/months/'
+ for (key, mode, size) in namings:
+ prop = 'monthContext[' + mode + ']/monthWidth[' + size + ']/'
+ result[key + 'Months'] = ';'.join(
+ findEntry(path, stem + prop + "month[%d]" % i)
+ for i in range(1, 13)) + ';'
+
+ # Day data (for Gregorian, at least):
+ stem = 'dates/calendars/calendar[gregorian]/days/'
+ days = ('sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat')
+ for (key, mode, size) in namings:
+ prop = 'dayContext[' + mode + ']/dayWidth[' + size + ']/day'
+ result[key + 'Days'] = ';'.join(
+ findEntry(path, stem + prop + '[' + day + ']')
+ for day in days) + ';'
+
+ return Locale(result)
def addEscapes(s):
result = ''
@@ -463,94 +382,42 @@ def usage():
def integrateWeekData(filePath):
if not filePath.endswith(".xml"):
return {}
- monFirstDayIn = findEntryInFile(filePath, "weekData/firstDay[day=mon]", attribute="territories")[0].split(" ")
- tueFirstDayIn = findEntryInFile(filePath, "weekData/firstDay[day=tue]", attribute="territories")[0].split(" ")
- wedFirstDayIn = findEntryInFile(filePath, "weekData/firstDay[day=wed]", attribute="territories")[0].split(" ")
- thuFirstDayIn = findEntryInFile(filePath, "weekData/firstDay[day=thu]", attribute="territories")[0].split(" ")
- friFirstDayIn = findEntryInFile(filePath, "weekData/firstDay[day=fri]", attribute="territories")[0].split(" ")
- satFirstDayIn = findEntryInFile(filePath, "weekData/firstDay[day=sat]", attribute="territories")[0].split(" ")
- sunFirstDayIn = findEntryInFile(filePath, "weekData/firstDay[day=sun]", attribute="territories")[0].split(" ")
-
- monWeekendStart = findEntryInFile(filePath, "weekData/weekendStart[day=mon]", attribute="territories")[0].split(" ")
- tueWeekendStart = findEntryInFile(filePath, "weekData/weekendStart[day=tue]", attribute="territories")[0].split(" ")
- wedWeekendStart = findEntryInFile(filePath, "weekData/weekendStart[day=wed]", attribute="territories")[0].split(" ")
- thuWeekendStart = findEntryInFile(filePath, "weekData/weekendStart[day=thu]", attribute="territories")[0].split(" ")
- friWeekendStart = findEntryInFile(filePath, "weekData/weekendStart[day=fri]", attribute="territories")[0].split(" ")
- satWeekendStart = findEntryInFile(filePath, "weekData/weekendStart[day=sat]", attribute="territories")[0].split(" ")
- sunWeekendStart = findEntryInFile(filePath, "weekData/weekendStart[day=sun]", attribute="territories")[0].split(" ")
-
- monWeekendEnd = findEntryInFile(filePath, "weekData/weekendEnd[day=mon]", attribute="territories")[0].split(" ")
- tueWeekendEnd = findEntryInFile(filePath, "weekData/weekendEnd[day=tue]", attribute="territories")[0].split(" ")
- wedWeekendEnd = findEntryInFile(filePath, "weekData/weekendEnd[day=wed]", attribute="territories")[0].split(" ")
- thuWeekendEnd = findEntryInFile(filePath, "weekData/weekendEnd[day=thu]", attribute="territories")[0].split(" ")
- friWeekendEnd = findEntryInFile(filePath, "weekData/weekendEnd[day=fri]", attribute="territories")[0].split(" ")
- satWeekendEnd = findEntryInFile(filePath, "weekData/weekendEnd[day=sat]", attribute="territories")[0].split(" ")
- sunWeekendEnd = findEntryInFile(filePath, "weekData/weekendEnd[day=sun]", attribute="territories")[0].split(" ")
+
+ def lookup(key):
+ return findEntryInFile(filePath, key, attribute='territories')[0].split()
+ days = ('mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun')
firstDayByCountryCode = {}
- for countryCode in monFirstDayIn:
- firstDayByCountryCode[countryCode] = "mon"
- for countryCode in tueFirstDayIn:
- firstDayByCountryCode[countryCode] = "tue"
- for countryCode in wedFirstDayIn:
- firstDayByCountryCode[countryCode] = "wed"
- for countryCode in thuFirstDayIn:
- firstDayByCountryCode[countryCode] = "thu"
- for countryCode in friFirstDayIn:
- firstDayByCountryCode[countryCode] = "fri"
- for countryCode in satFirstDayIn:
- firstDayByCountryCode[countryCode] = "sat"
- for countryCode in sunFirstDayIn:
- firstDayByCountryCode[countryCode] = "sun"
+ for day in days:
+ for countryCode in lookup('weekData/firstDay[day=%s]' % day):
+ firstDayByCountryCode[countryCode] = day
weekendStartByCountryCode = {}
- for countryCode in monWeekendStart:
- weekendStartByCountryCode[countryCode] = "mon"
- for countryCode in tueWeekendStart:
- weekendStartByCountryCode[countryCode] = "tue"
- for countryCode in wedWeekendStart:
- weekendStartByCountryCode[countryCode] = "wed"
- for countryCode in thuWeekendStart:
- weekendStartByCountryCode[countryCode] = "thu"
- for countryCode in friWeekendStart:
- weekendStartByCountryCode[countryCode] = "fri"
- for countryCode in satWeekendStart:
- weekendStartByCountryCode[countryCode] = "sat"
- for countryCode in sunWeekendStart:
- weekendStartByCountryCode[countryCode] = "sun"
+ for day in days:
+ for countryCode in lookup('weekData/weekendStart[day=%s]' % day):
+ weekendStartByCountryCode[countryCode] = day
weekendEndByCountryCode = {}
- for countryCode in monWeekendEnd:
- weekendEndByCountryCode[countryCode] = "mon"
- for countryCode in tueWeekendEnd:
- weekendEndByCountryCode[countryCode] = "tue"
- for countryCode in wedWeekendEnd:
- weekendEndByCountryCode[countryCode] = "wed"
- for countryCode in thuWeekendEnd:
- weekendEndByCountryCode[countryCode] = "thu"
- for countryCode in friWeekendEnd:
- weekendEndByCountryCode[countryCode] = "fri"
- for countryCode in satWeekendEnd:
- weekendEndByCountryCode[countryCode] = "sat"
- for countryCode in sunWeekendEnd:
- weekendEndByCountryCode[countryCode] = "sun"
-
- for (key,locale) in locale_database.iteritems():
- countryCode = locale['country_code']
+ for day in days:
+ for countryCode in lookup('weekData/weekendEnd[day=%s]' % day):
+ weekendEndByCountryCode[countryCode] = day
+
+ for (key, locale) in locale_database.iteritems():
+ countryCode = locale.country_code
if countryCode in firstDayByCountryCode:
- locale_database[key]['firstDayOfWeek'] = firstDayByCountryCode[countryCode]
+ locale.firstDayOfWeek = firstDayByCountryCode[countryCode]
else:
- locale_database[key]['firstDayOfWeek'] = firstDayByCountryCode["001"]
+ locale.firstDayOfWeek = firstDayByCountryCode["001"]
if countryCode in weekendStartByCountryCode:
- locale_database[key]['weekendStart'] = weekendStartByCountryCode[countryCode]
+ locale.weekendStart = weekendStartByCountryCode[countryCode]
else:
- locale_database[key]['weekendStart'] = weekendStartByCountryCode["001"]
+ locale.weekendStart = weekendStartByCountryCode["001"]
if countryCode in weekendEndByCountryCode:
- locale_database[key]['weekendEnd'] = weekendEndByCountryCode[countryCode]
+ locale.weekendEnd = weekendEndByCountryCode[countryCode]
else:
- locale_database[key]['weekendEnd'] = weekendEndByCountryCode["001"]
+ locale.weekendEnd = weekendEndByCountryCode["001"]
if len(sys.argv) != 2:
usage()
@@ -566,7 +433,9 @@ locale_database = {}
# see http://www.unicode.org/reports/tr35/tr35-info.html#Default_Content
defaultContent_locales = {}
-for ns in findTagsInFile(cldr_dir + "/../supplemental/supplementalMetadata.xml", "metadata/defaultContent"):
+for ns in findTagsInFile(os.path.join(cldr_dir, '..', 'supplemental',
+ 'supplementalMetadata.xml'),
+ 'metadata/defaultContent'):
for data in ns[1:][0]:
if data[0] == u"locales":
defaultContent_locales = data[1].split()
@@ -579,36 +448,36 @@ for file in defaultContent_locales:
country_code = items[2]
else:
if len(items) != 2:
- sys.stderr.write("skipping defaultContent locale \"" + file + "\"\n")
+ sys.stderr.write('skipping defaultContent locale "' + file + '" [neither lang_script_country nor lang_country]\n')
continue
language_code = items[0]
script_code = ""
country_code = items[1]
if len(country_code) == 4:
- sys.stderr.write("skipping defaultContent locale \"" + file + "\"\n")
+ sys.stderr.write('skipping defaultContent locale "' + file + '" [long country code]\n')
continue
try:
l = _generateLocaleInfo(cldr_dir + "/" + file + ".xml", language_code, script_code, country_code)
if not l:
- sys.stderr.write("skipping defaultContent locale \"" + file + "\"\n")
+ sys.stderr.write('skipping defaultContent locale "' + file + '" [no locale info generated]\n')
continue
except xpathlite.Error as e:
- sys.stderr.write("skipping defaultContent locale \"%s\" (%s)\n" % (file, str(e)))
+ sys.stderr.write('skipping defaultContent locale "%s" (%s)\n' % (file, str(e)))
continue
- locale_database[(l['language_id'], l['script_id'], l['country_id'], l['variant_code'])] = l
+ locale_database[(l.language_id, l.script_id, l.country_id, l.variant_code)] = l
for file in cldr_files:
try:
l = generateLocaleInfo(cldr_dir + "/" + file)
if not l:
- sys.stderr.write("skipping file \"" + file + "\"\n")
+ sys.stderr.write('skipping file "' + file + '" [no locale info generated]\n')
continue
except xpathlite.Error as e:
- sys.stderr.write("skipping file \"%s\" (%s)\n" % (file, str(e)))
+ sys.stderr.write('skipping file "%s" (%s)\n' % (file, str(e)))
continue
- locale_database[(l['language_id'], l['script_id'], l['country_id'], l['variant_code'])] = l
+ locale_database[(l.language_id, l.script_id, l.country_id, l.variant_code)] = l
integrateWeekData(cldr_dir+"/../supplemental/supplementalData.xml")
locale_keys = locale_database.keys()
@@ -665,7 +534,7 @@ def _parseLocale(l):
if language_code != "und":
language_id = enumdata.languageCodeToId(language_code)
if language_id == -1:
- raise xpathlite.Error("unknown language code \"%s\"" % language_code)
+ raise xpathlite.Error('unknown language code "%s"' % language_code)
language = enumdata.language_list[language_id][0]
if len(items) > 1:
@@ -676,14 +545,14 @@ def _parseLocale(l):
if len(script_code) == 4:
script_id = enumdata.scriptCodeToId(script_code)
if script_id == -1:
- raise xpathlite.Error("unknown script code \"%s\"" % script_code)
+ raise xpathlite.Error('unknown script code "%s"' % script_code)
script = enumdata.script_list[script_id][0]
else:
country_code = script_code
if country_code:
country_id = enumdata.countryCodeToId(country_code)
if country_id == -1:
- raise xpathlite.Error("unknown country code \"%s\"" % country_code)
+ raise xpathlite.Error('unknown country code "%s"' % country_code)
country = enumdata.country_list[country_id][0]
return (language, script, country)
@@ -697,12 +566,12 @@ for ns in findTagsInFile(cldr_dir + "/../supplemental/likelySubtags.xml", "likel
try:
(from_language, from_script, from_country) = _parseLocale(tmp[u"from"])
except xpathlite.Error as e:
- sys.stderr.write("skipping likelySubtag \"%s\" -> \"%s\" (%s)\n" % (tmp[u"from"], tmp[u"to"], str(e)))
+ sys.stderr.write('skipping likelySubtag "%s" -> "%s" (%s)\n' % (tmp[u"from"], tmp[u"to"], str(e)))
continue
try:
(to_language, to_script, to_country) = _parseLocale(tmp[u"to"])
except xpathlite.Error as e:
- sys.stderr.write("skipping likelySubtag \"%s\" -> \"%s\" (%s)\n" % (tmp[u"from"], tmp[u"to"], str(e)))
+ sys.stderr.write('skipping likelySubtag "%s" -> "%s" (%s)\n' % (tmp[u"from"], tmp[u"to"], str(e)))
continue
# substitute according to http://www.unicode.org/reports/tr35/#Likely_Subtags
if to_country == "AnyCountry" and from_country != to_country:
@@ -725,115 +594,10 @@ for ns in findTagsInFile(cldr_dir + "/../supplemental/likelySubtags.xml", "likel
print " </likelySubtags>"
print " <localeList>"
-print \
-" <locale>\n\
- <language>C</language>\n\
- <languageEndonym></languageEndonym>\n\
- <script>AnyScript</script>\n\
- <country>AnyCountry</country>\n\
- <countryEndonym></countryEndonym>\n\
- <decimal>46</decimal>\n\
- <group>44</group>\n\
- <list>59</list>\n\
- <percent>37</percent>\n\
- <zero>48</zero>\n\
- <minus>45</minus>\n\
- <plus>43</plus>\n\
- <exp>101</exp>\n\
- <quotationStart>\"</quotationStart>\n\
- <quotationEnd>\"</quotationEnd>\n\
- <alternateQuotationStart>\'</alternateQuotationStart>\n\
- <alternateQuotationEnd>\'</alternateQuotationEnd>\n\
- <listPatternPartStart>%1, %2</listPatternPartStart>\n\
- <listPatternPartMiddle>%1, %2</listPatternPartMiddle>\n\
- <listPatternPartEnd>%1, %2</listPatternPartEnd>\n\
- <listPatternPartTwo>%1, %2</listPatternPartTwo>\n\
- <am>AM</am>\n\
- <pm>PM</pm>\n\
- <firstDayOfWeek>mon</firstDayOfWeek>\n\
- <weekendStart>sat</weekendStart>\n\
- <weekendEnd>sun</weekendEnd>\n\
- <longDateFormat>EEEE, d MMMM yyyy</longDateFormat>\n\
- <shortDateFormat>d MMM yyyy</shortDateFormat>\n\
- <longTimeFormat>HH:mm:ss z</longTimeFormat>\n\
- <shortTimeFormat>HH:mm:ss</shortTimeFormat>\n\
- <standaloneLongMonths>January;February;March;April;May;June;July;August;September;October;November;December;</standaloneLongMonths>\n\
- <standaloneShortMonths>Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec;</standaloneShortMonths>\n\
- <standaloneNarrowMonths>J;F;M;A;M;J;J;A;S;O;N;D;</standaloneNarrowMonths>\n\
- <longMonths>January;February;March;April;May;June;July;August;September;October;November;December;</longMonths>\n\
- <shortMonths>Jan;Feb;Mar;Apr;May;Jun;Jul;Aug;Sep;Oct;Nov;Dec;</shortMonths>\n\
- <narrowMonths>1;2;3;4;5;6;7;8;9;10;11;12;</narrowMonths>\n\
- <longDays>Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday;</longDays>\n\
- <shortDays>Sun;Mon;Tue;Wed;Thu;Fri;Sat;</shortDays>\n\
- <narrowDays>7;1;2;3;4;5;6;</narrowDays>\n\
- <standaloneLongDays>Sunday;Monday;Tuesday;Wednesday;Thursday;Friday;Saturday;</standaloneLongDays>\n\
- <standaloneShortDays>Sun;Mon;Tue;Wed;Thu;Fri;Sat;</standaloneShortDays>\n\
- <standaloneNarrowDays>S;M;T;W;T;F;S;</standaloneNarrowDays>\n\
- <currencyIsoCode></currencyIsoCode>\n\
- <currencySymbol></currencySymbol>\n\
- <currencyDisplayName>;;;;;;;</currencyDisplayName>\n\
- <currencyDigits>2</currencyDigits>\n\
- <currencyRounding>1</currencyRounding>\n\
- <currencyFormat>%1%2</currencyFormat>\n\
- <currencyNegativeFormat></currencyNegativeFormat>\n\
- </locale>"
+Locale.C().toXml()
for key in locale_keys:
- l = locale_database[key]
-
- print " <locale>"
- print " <language>" + l['language'] + "</language>"
- print " <languageEndonym>" + escape(l['language_endonym']).encode('utf-8') + "</languageEndonym>"
- print " <script>" + l['script'] + "</script>"
- print " <country>" + l['country'] + "</country>"
- print " <countryEndonym>" + escape(l['country_endonym']).encode('utf-8') + "</countryEndonym>"
- print " <languagecode>" + l['language_code'] + "</languagecode>"
- print " <scriptcode>" + l['script_code'] + "</scriptcode>"
- print " <countrycode>" + l['country_code'] + "</countrycode>"
- print " <decimal>" + ordStr(l['decimal']) + "</decimal>"
- print " <group>" + ordStr(l['group']) + "</group>"
- print " <list>" + fixOrdStrList(l['list']) + "</list>"
- print " <percent>" + fixOrdStrPercent(l['percent']) + "</percent>"
- print " <zero>" + ordStr(l['zero']) + "</zero>"
- print " <minus>" + fixOrdStrMinus(l['minus']) + "</minus>"
- print " <plus>" + fixOrdStrPlus(l['plus']) + "</plus>"
- print " <exp>" + fixOrdStrExp(l['exp']) + "</exp>"
- print " <quotationStart>" + escape(l['quotationStart']).encode('utf-8') + "</quotationStart>"
- print " <quotationEnd>" + escape(l['quotationEnd']).encode('utf-8') + "</quotationEnd>"
- print " <alternateQuotationStart>" + escape(l['alternateQuotationStart']).encode('utf-8') + "</alternateQuotationStart>"
- print " <alternateQuotationEnd>" + escape(l['alternateQuotationEnd']).encode('utf-8') + "</alternateQuotationEnd>"
- print " <listPatternPartStart>" + escape(l['listPatternPartStart']).encode('utf-8') + "</listPatternPartStart>"
- print " <listPatternPartMiddle>" + escape(l['listPatternPartMiddle']).encode('utf-8') + "</listPatternPartMiddle>"
- print " <listPatternPartEnd>" + escape(l['listPatternPartEnd']).encode('utf-8') + "</listPatternPartEnd>"
- print " <listPatternPartTwo>" + escape(l['listPatternPartTwo']).encode('utf-8') + "</listPatternPartTwo>"
- print " <am>" + escape(l['am']).encode('utf-8') + "</am>"
- print " <pm>" + escape(l['pm']).encode('utf-8') + "</pm>"
- print " <firstDayOfWeek>" + escape(l['firstDayOfWeek']).encode('utf-8') + "</firstDayOfWeek>"
- print " <weekendStart>" + escape(l['weekendStart']).encode('utf-8') + "</weekendStart>"
- print " <weekendEnd>" + escape(l['weekendEnd']).encode('utf-8') + "</weekendEnd>"
- print " <longDateFormat>" + escape(l['longDateFormat']).encode('utf-8') + "</longDateFormat>"
- print " <shortDateFormat>" + escape(l['shortDateFormat']).encode('utf-8') + "</shortDateFormat>"
- print " <longTimeFormat>" + escape(l['longTimeFormat']).encode('utf-8') + "</longTimeFormat>"
- print " <shortTimeFormat>" + escape(l['shortTimeFormat']).encode('utf-8') + "</shortTimeFormat>"
- print " <standaloneLongMonths>" + escape(l['standaloneLongMonths']).encode('utf-8') + "</standaloneLongMonths>"
- print " <standaloneShortMonths>"+ escape(l['standaloneShortMonths']).encode('utf-8') + "</standaloneShortMonths>"
- print " <standaloneNarrowMonths>"+ escape(l['standaloneNarrowMonths']).encode('utf-8') + "</standaloneNarrowMonths>"
- print " <longMonths>" + escape(l['longMonths']).encode('utf-8') + "</longMonths>"
- print " <shortMonths>" + escape(l['shortMonths']).encode('utf-8') + "</shortMonths>"
- print " <narrowMonths>" + escape(l['narrowMonths']).encode('utf-8') + "</narrowMonths>"
- print " <longDays>" + escape(l['longDays']).encode('utf-8') + "</longDays>"
- print " <shortDays>" + escape(l['shortDays']).encode('utf-8') + "</shortDays>"
- print " <narrowDays>" + escape(l['narrowDays']).encode('utf-8') + "</narrowDays>"
- print " <standaloneLongDays>" + escape(l['standaloneLongDays']).encode('utf-8') + "</standaloneLongDays>"
- print " <standaloneShortDays>" + escape(l['standaloneShortDays']).encode('utf-8') + "</standaloneShortDays>"
- print " <standaloneNarrowDays>" + escape(l['standaloneNarrowDays']).encode('utf-8') + "</standaloneNarrowDays>"
- print " <currencyIsoCode>" + escape(l['currencyIsoCode']).encode('utf-8') + "</currencyIsoCode>"
- print " <currencySymbol>" + escape(l['currencySymbol']).encode('utf-8') + "</currencySymbol>"
- print " <currencyDisplayName>" + escape(l['currencyDisplayName']).encode('utf-8') + "</currencyDisplayName>"
- print " <currencyDigits>" + str(l['currencyDigits']) + "</currencyDigits>"
- print " <currencyRounding>" + str(l['currencyRounding']) + "</currencyRounding>"
- print " <currencyFormat>" + escape(l['currencyFormat']).encode('utf-8') + "</currencyFormat>"
- print " <currencyNegativeFormat>" + escape(l['currencyNegativeFormat']).encode('utf-8') + "</currencyNegativeFormat>"
- print " </locale>"
+ locale_database[key].toXml()
+
print " </localeList>"
print "</localeDatabase>"
diff --git a/util/local_database/cldr2qtimezone.py b/util/local_database/cldr2qtimezone.py
index 502ab92fd5..7c10b1dfd2 100644..100755
--- a/util/local_database/cldr2qtimezone.py
+++ b/util/local_database/cldr2qtimezone.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
#############################################################################
##
## Copyright (C) 2016 The Qt Company Ltd.
@@ -26,25 +26,32 @@
## $QT_END_LICENSE$
##
#############################################################################
-
-
-# Script to parse the CLDR supplemental/windowsZones.xml file and encode for use in QTimeZone
-# XML structure is as follows:
-#
-# <supplementalData>
-# <version number="$Revision: 7825 $"/>
-# <generation date="$Date: 2012-10-10 14:45:31 -0700 (Wed, 10 Oct 2012) $"/>
-# <windowsZones>
-# <mapTimezones otherVersion="7dc0101" typeVersion="2012f">
-# <!-- (UTC-08:00) Pacific Time (US & Canada) -->
-# <mapZone other="Pacific Standard Time" territory="001" type="America/Los_Angeles"/>
-# <mapZone other="Pacific Standard Time" territory="CA" type="America/Vancouver America/Dawson America/Whitehorse"/>
-# <mapZone other="Pacific Standard Time" territory="MX" type="America/Tijuana"/>
-# <mapZone other="Pacific Standard Time" territory="US" type="America/Los_Angeles"/>
-# <mapZone other="Pacific Standard Time" territory="ZZ" type="PST8PDT"/>
-# </mapTimezones>
-# </windowsZones>
-# </supplementalData>
+"""Parse CLDR data for QTimeZone use with MS-Windows
+
+Script to parse the CLDR supplemental/windowsZones.xml file and encode
+for use in QTimeZone. See ``./cldr2qlocalexml.py`` for where to get
+the CLDR data. Pass its common/ directory as first parameter to this
+script and the qtbase root directory as second parameter. It shall
+update qtbase's src/corelib/tools/qtimezoneprivate_data_p.h ready for
+use.
+
+The XML structure is as follows:
+
+ <supplementalData>
+ <version number="$Revision: 7825 $"/>
+ <generation date="$Date: 2012-10-10 14:45:31 -0700 (Wed, 10 Oct 2012) $"/>
+ <windowsZones>
+ <mapTimezones otherVersion="7dc0101" typeVersion="2012f">
+ <!-- (UTC-08:00) Pacific Time (US & Canada) -->
+ <mapZone other="Pacific Standard Time" territory="001" type="America/Los_Angeles"/>
+ <mapZone other="Pacific Standard Time" territory="CA" type="America/Vancouver America/Dawson America/Whitehorse"/>
+ <mapZone other="Pacific Standard Time" territory="MX" type="America/Tijuana"/>
+ <mapZone other="Pacific Standard Time" territory="US" type="America/Los_Angeles"/>
+ <mapZone other="Pacific Standard Time" territory="ZZ" type="PST8PDT"/>
+ </mapTimezones>
+ </windowsZones>
+ </supplementalData>
+"""
import os
import sys
@@ -328,15 +335,18 @@ while s and s != GENERATED_BLOCK_START:
# Write out generated block start tag and warning
newTempFile.write(GENERATED_BLOCK_START)
-newTempFile.write("\n\
-/*\n\
- This part of the file was generated on %s from the\n\
- Common Locale Data Repository v%s supplemental/windowsZones.xml file %s\n\
-\n\
- http://www.unicode.org/cldr/\n\
-\n\
- Do not change this data, only generate it using cldr2qtimezone.py.\n\
-*/\n\n" % (str(datetime.date.today()), cldr_version, versionNumber) )
+newTempFile.write("""
+/*
+ This part of the file was generated on %s from the
+ Common Locale Data Repository v%s supplemental/windowsZones.xml file %s
+
+ http://www.unicode.org/cldr/
+
+ Do not edit this code: run cldr2qtimezone.py on updated (or
+ edited) CLDR data; see qtbase/util/local_database/.
+*/
+
+""" % (str(datetime.date.today()), cldr_version, versionNumber) )
windowsIdData = ByteArrayData()
ianaIdData = ByteArrayData()
@@ -346,7 +356,7 @@ newTempFile.write("// Windows ID Key, Country Enum, IANA ID Index\n")
newTempFile.write("static const QZoneData zoneDataTable[] = {\n")
for index in windowsIdDict:
data = windowsIdDict[index]
- newTempFile.write(" { %6d,%6d,%6d }, // %s / %s\n" \
+ newTempFile.write(" { %6d,%6d,%6d }, // %s / %s\n"
% (data['windowsKey'],
data['countryId'],
ianaIdData.append(data['ianaList']),
@@ -361,7 +371,7 @@ print "Done Zone Data"
newTempFile.write("// Windows ID Key, Windows ID Index, IANA ID Index, UTC Offset\n")
newTempFile.write("static const QWindowsData windowsDataTable[] = {\n")
for windowsKey in windowsIdList:
- newTempFile.write(" { %6d,%6d,%6d,%6d }, // %s\n" \
+ newTempFile.write(" { %6d,%6d,%6d,%6d }, // %s\n"
% (windowsKey,
windowsIdData.append(windowsIdList[windowsKey][0]),
ianaIdData.append(defaultDict[windowsKey]),
@@ -377,7 +387,7 @@ newTempFile.write("// IANA ID Index, UTC Offset\n")
newTempFile.write("static const QUtcData utcDataTable[] = {\n")
for index in utcIdList:
data = utcIdList[index]
- newTempFile.write(" { %6d,%6d }, // %s\n" \
+ newTempFile.write(" { %6d,%6d }, // %s\n"
% (ianaIdData.append(data[0]),
data[1],
data[0]))
diff --git a/util/local_database/enumdata.py b/util/local_database/enumdata.py
index aa2adfa52f..2d16e5851d 100644
--- a/util/local_database/enumdata.py
+++ b/util/local_database/enumdata.py
@@ -798,7 +798,7 @@ script_list = {
137 : [ "Newa", "Newa" ],
138 : [ "Osage", "Osge" ],
139 : [ "Tangut", "Tang" ],
- 140 : [ "Han With Bopomofo", "Hanb" ],
+ 140 : [ "Han with Bopomofo", "Hanb" ],
141 : [ "Jamo", "Jamo" ]
}
diff --git a/util/local_database/localexml.py b/util/local_database/localexml.py
new file mode 100644
index 0000000000..a47fa6a5ff
--- /dev/null
+++ b/util/local_database/localexml.py
@@ -0,0 +1,239 @@
+#############################################################################
+##
+## Copyright (C) 2017 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of the test suite of the Qt Toolkit.
+##
+## $QT_BEGIN_LICENSE:GPL-EXCEPT$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 3 as published by the Free Software
+## Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+"""Shared serialization-scanning code for QLocaleXML format.
+
+The Locale class is written by cldr2qlocalexml.py and read by qlocalexml2cpp.py
+"""
+from xml.sax.saxutils import escape
+
+import xpathlite
+
+# Tools used by Locale:
+def camel(seq):
+ yield seq.next()
+ for word in seq:
+ yield word.capitalize()
+
+def camelCase(words):
+ return ''.join(camel(iter(words)))
+
+def ordStr(c):
+ if len(c) == 1:
+ return str(ord(c))
+ raise xpathlite.Error('Unable to handle value "%s"' % addEscapes(c))
+
+# Fix for a problem with QLocale returning a character instead of
+# strings for QLocale::exponential() and others. So we fallback to
+# default values in these cases.
+def fixOrdStr(c, d):
+ return str(ord(c if len(c) == 1 else d))
+
+def convertFormat(format):
+ result = ""
+ i = 0
+ while i < len(format):
+ if format[i] == "'":
+ result += "'"
+ i += 1
+ while i < len(format) and format[i] != "'":
+ result += format[i]
+ i += 1
+ if i < len(format):
+ result += "'"
+ i += 1
+ else:
+ s = format[i:]
+ if s.startswith("EEEE"):
+ result += "dddd"
+ i += 4
+ elif s.startswith("EEE"):
+ result += "ddd"
+ i += 3
+ elif s.startswith("a"):
+ result += "AP"
+ i += 1
+ elif s.startswith("z"):
+ result += "t"
+ i += 1
+ elif s.startswith("v"):
+ i += 1
+ else:
+ result += format[i]
+ i += 1
+
+ return result
+
+class Locale:
+ # Tool used during class body (see del below), not method:
+ def propsMonthDay(lengths=('long', 'short', 'narrow'), scale=('months', 'days')):
+ for L in lengths:
+ for S in scale:
+ yield camelCase((L, S))
+ yield camelCase(('standalone', L, S))
+
+ # Expected to be numbers, read with int():
+ __asint = ("decimal", "group", "zero",
+ "list", "percent", "minus", "plus", "exp",
+ "currencyDigits", "currencyRounding")
+ # Single character; use the code-point number for each:
+ __asord = ("quotationStart", "quotationEnd",
+ "alternateQuotationStart", "alternateQuotationEnd")
+ # Convert day-name to Qt day-of-week number:
+ __asdow = ("firstDayOfWeek", "weekendStart", "weekendEnd")
+ # Convert from CLDR format-strings to QDateTimeParser ones:
+ __asfmt = ("longDateFormat", "shortDateFormat", "longTimeFormat", "shortTimeFormat")
+ # Just use the raw text:
+ __astxt = ("language", "languageEndonym", "script", "country", "countryEndonym",
+ "listPatternPartStart", "listPatternPartMiddle",
+ "listPatternPartEnd", "listPatternPartTwo", "am", "pm",
+ 'byte_unit', 'byte_si_quantified', 'byte_iec_quantified',
+ "currencyIsoCode", "currencySymbol", "currencyDisplayName",
+ "currencyFormat", "currencyNegativeFormat"
+ ) + tuple(propsMonthDay())
+ del propsMonthDay
+
+ # Day-of-Week numbering used by Qt:
+ __qDoW = {"mon": 1, "tue": 2, "wed": 3, "thu": 4, "fri": 5, "sat": 6, "sun": 7}
+
+ @classmethod
+ def fromXmlData(cls, lookup):
+ """Constructor from the contents of XML elements.
+
+ Single parameter, lookup, is called with the names of XML
+ elements that should contain the relevant data, within a CLDR
+ locale element (within a localeList element); these names are
+ used for the attributes of the object constructed. Attribute
+ values are obtained by suitably digesting the returned element
+ texts.\n"""
+ data = {}
+ for k in cls.__asint:
+ data['listDelim' if k == 'list' else k] = int(lookup(k))
+
+ for k in cls.__asord:
+ value = lookup(k)
+ assert len(value) == 1, \
+ (k, value, 'value should be exactly one character')
+ data[k] = ord(value)
+
+ for k in cls.__asdow:
+ data[k] = cls.__qDoW[lookup(k)]
+
+ for k in cls.__asfmt:
+ data[k] = convertFormat(lookup(k))
+
+ for k in cls.__astxt:
+ data[k] = lookup(k)
+
+ return cls(data)
+
+ def toXml(self, indent=' ', tab=' '):
+ print indent + '<locale>'
+ inner = indent + tab
+ get = lambda k: getattr(self, k)
+ for key in ('language', 'script', 'country'):
+ print inner + "<%s>" % key + get(key) + "</%s>" % key
+ print inner + "<%scode>" % key + get(key + '_code') + "</%scode>" % key
+
+ for key in ('decimal', 'group', 'zero'):
+ print inner + "<%s>" % key + ordStr(get(key)) + "</%s>" % key
+ for key, std in (('list', ';'), ('percent', '%'),
+ ('minus', '-'), ('plus', '+'), ('exp', 'e')):
+ print inner + "<%s>" % key + fixOrdStr(get(key), std) + "</%s>" % key
+
+ for key in ('language_endonym', 'country_endonym',
+ 'quotationStart', 'quotationEnd',
+ 'alternateQuotationStart', 'alternateQuotationEnd',
+ 'listPatternPartStart', 'listPatternPartMiddle',
+ 'listPatternPartEnd', 'listPatternPartTwo',
+ 'byte_unit', 'byte_si_quantified', 'byte_iec_quantified',
+ 'am', 'pm', 'firstDayOfWeek',
+ 'weekendStart', 'weekendEnd',
+ 'longDateFormat', 'shortDateFormat',
+ 'longTimeFormat', 'shortTimeFormat',
+ 'standaloneLongMonths', 'standaloneShortMonths',
+ 'standaloneNarrowMonths',
+ 'longMonths', 'shortMonths', 'narrowMonths',
+ 'longDays', 'shortDays', 'narrowDays',
+ 'standaloneLongDays', 'standaloneShortDays', 'standaloneNarrowDays',
+ 'currencyIsoCode', 'currencySymbol', 'currencyDisplayName',
+ 'currencyFormat', 'currencyNegativeFormat'):
+ ent = camelCase(key.split('_')) if key.endswith('_endonym') else key
+ print inner + "<%s>%s</%s>" % (ent, escape(get(key)).encode('utf-8'), ent)
+
+ for key in ('currencyDigits', 'currencyRounding'):
+ print inner + "<%s>%d</%s>" % (key, get(key), key)
+
+ print indent + "</locale>"
+
+ def __init__(self, data=None, **kw):
+ if data: self.__dict__.update(data)
+ if kw: self.__dict__.update(kw)
+
+ @classmethod
+ def C(cls,
+ # Empty entries at end to ensure final separator when join()ed:
+ months = ('January', 'February', 'March', 'April', 'May', 'June', 'July',
+ 'August', 'September', 'October', 'November', 'December', ''),
+ days = ('Sunday', 'Monday', 'Tuesday', 'Wednesday',
+ 'Thursday', 'Friday', 'Saturday', ''),
+ quantifiers=('k', 'M', 'G', 'T', 'P', 'E')):
+ """Returns an object representing the C locale."""
+ return cls(language='C', language_code='0', language_endonym='',
+ script='AnyScript', script_code='0',
+ country='AnyCountry', country_code='0', country_endonym='',
+ decimal='.', group=',', list=';', percent='%',
+ zero='0', minus='-', plus='+', exp='e',
+ quotationStart='"', quotationEnd='"',
+ alternateQuotationStart='\'', alternateQuotationEnd='\'',
+ listPatternPartStart='%1, %2',
+ listPatternPartMiddle='%1, %2',
+ listPatternPartEnd='%1, %2',
+ listPatternPartTwo='%1, %2',
+ byte_unit='bytes',
+ byte_si_quantified=';'.join(q + 'B' for q in quantifiers),
+ byte_iec_quantified=';'.join(q.upper() + 'iB' for q in quantifiers),
+ am='AM', pm='PM', firstDayOfWeek='mon',
+ weekendStart='sat', weekendEnd='sun',
+ longDateFormat='EEEE, d MMMM yyyy', shortDateFormat='d MMM yyyy',
+ longTimeFormat='HH:mm:ss z', shortTimeFormat='HH:mm:ss',
+ longMonths=';'.join(months),
+ shortMonths=';'.join(m[:3] for m in months),
+ narrowMonths='1;2;3;4;5;6;7;8;9;10;11;12;',
+ standaloneLongMonths=';'.join(months),
+ standaloneShortMonths=';'.join(m[:3] for m in months),
+ standaloneNarrowMonths=';'.join(m[:1] for m in months),
+ longDays=';'.join(days),
+ shortDays=';'.join(d[:3] for d in days),
+ narrowDays='7;1;2;3;4;5;6;',
+ standaloneLongDays=';'.join(days),
+ standaloneShortDays=';'.join(d[:3] for d in days),
+ standaloneNarrowDays=';'.join(d[:1] for d in days),
+ currencyIsoCode='', currencySymbol='',
+ currencyDisplayName=';' * 7,
+ currencyDigits=2, currencyRounding=1,
+ currencyFormat='%1%2', currencyNegativeFormat='')
diff --git a/util/local_database/qlocalexml2cpp.py b/util/local_database/qlocalexml2cpp.py
index 9fd88c46fe..0f10f8ce2d 100755
--- a/util/local_database/qlocalexml2cpp.py
+++ b/util/local_database/qlocalexml2cpp.py
@@ -1,7 +1,7 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
#############################################################################
##
-## Copyright (C) 2016 The Qt Company Ltd.
+## Copyright (C) 2017 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of the test suite of the Qt Toolkit.
@@ -26,6 +26,12 @@
## $QT_END_LICENSE$
##
#############################################################################
+"""Script to generate C++ code from CLDR data in qLocaleXML form
+
+See ``cldr2qlocalexml.py`` for how to generate the qLocaleXML data itself.
+Pass the output file from that as first parameter to this script; pass
+the root of the qtbase check-out as second parameter.
+"""
import os
import sys
@@ -33,6 +39,8 @@ import tempfile
import datetime
import xml.dom.minidom
+from localexml import Locale
+
class Error:
def __init__(self, msg):
self.msg = msg
@@ -41,113 +49,68 @@ class Error:
def wrap_list(lst):
def split(lst, size):
- for i in range(len(lst)/size+1):
- yield lst[i*size:(i+1)*size]
- return ",\n".join(map(lambda x: ", ".join(x), split(lst, 20)))
+ while lst:
+ head, lst = lst[:size], lst[size:]
+ yield head
+ return ",\n".join(", ".join(x) for x in split(lst, 20))
+
+def isNodeNamed(elt, name, TYPE=xml.dom.minidom.Node.ELEMENT_NODE):
+ return elt.nodeType == TYPE and elt.nodeName == name
def firstChildElt(parent, name):
child = parent.firstChild
while child:
- if child.nodeType == parent.ELEMENT_NODE \
- and (not name or child.nodeName == name):
+ if isNodeNamed(child, name):
return child
child = child.nextSibling
- return False
-
-def nextSiblingElt(sibling, name):
- sib = sibling.nextSibling
- while sib:
- if sib.nodeType == sibling.ELEMENT_NODE \
- and (not name or sib.nodeName == name):
- return sib
- sib = sib.nextSibling
- return False
-
-def eltText(elt):
- result = ""
- child = elt.firstChild
- while child:
- if child.nodeType == elt.TEXT_NODE:
- if result:
- result += " "
- result += child.nodeValue
- child = child.nextSibling
- return result
-def loadLanguageMap(doc):
- result = {}
+ raise Error('No %s child found' % name)
- language_list_elt = firstChildElt(doc.documentElement, "languageList")
- language_elt = firstChildElt(language_list_elt, "language")
- while language_elt:
- language_id = int(eltText(firstChildElt(language_elt, "id")))
- language_name = eltText(firstChildElt(language_elt, "name"))
- language_code = eltText(firstChildElt(language_elt, "code"))
- result[language_id] = (language_name, language_code)
- language_elt = nextSiblingElt(language_elt, "language")
+def eachEltInGroup(parent, group, key):
+ try:
+ element = firstChildElt(parent, group).firstChild
+ except Error:
+ element = None
- return result
-
-def loadScriptMap(doc):
- result = {}
+ while element:
+ if isNodeNamed(element, key):
+ yield element
+ element = element.nextSibling
- script_list_elt = firstChildElt(doc.documentElement, "scriptList")
- script_elt = firstChildElt(script_list_elt, "script")
- while script_elt:
- script_id = int(eltText(firstChildElt(script_elt, "id")))
- script_name = eltText(firstChildElt(script_elt, "name"))
- script_code = eltText(firstChildElt(script_elt, "code"))
- result[script_id] = (script_name, script_code)
- script_elt = nextSiblingElt(script_elt, "script")
-
- return result
-
-def loadCountryMap(doc):
- result = {}
+def eltWords(elt):
+ child = elt.firstChild
+ while child:
+ if child.nodeType == elt.TEXT_NODE:
+ yield child.nodeValue
+ child = child.nextSibling
- country_list_elt = firstChildElt(doc.documentElement, "countryList")
- country_elt = firstChildElt(country_list_elt, "country")
- while country_elt:
- country_id = int(eltText(firstChildElt(country_elt, "id")))
- country_name = eltText(firstChildElt(country_elt, "name"))
- country_code = eltText(firstChildElt(country_elt, "code"))
- result[country_id] = (country_name, country_code)
- country_elt = nextSiblingElt(country_elt, "country")
+def firstChildText(elt, key):
+ return ' '.join(eltWords(firstChildElt(elt, key)))
- return result
+def loadMap(doc, category):
+ return dict((int(firstChildText(element, 'id')),
+ (firstChildText(element, 'name'),
+ firstChildText(element, 'code')))
+ for element in eachEltInGroup(doc.documentElement,
+ category + 'List', category))
def loadLikelySubtagsMap(doc):
- result = {}
+ def triplet(element, keys=('language', 'script', 'country')):
+ return tuple(firstChildText(element, key) for key in keys)
- i = 0
- list_elt = firstChildElt(doc.documentElement, "likelySubtags")
- elt = firstChildElt(list_elt, "likelySubtag")
- while elt:
- elt_from = firstChildElt(elt, "from")
- from_language = eltText(firstChildElt(elt_from, "language"));
- from_script = eltText(firstChildElt(elt_from, "script"));
- from_country = eltText(firstChildElt(elt_from, "country"));
-
- elt_to = firstChildElt(elt, "to")
- to_language = eltText(firstChildElt(elt_to, "language"));
- to_script = eltText(firstChildElt(elt_to, "script"));
- to_country = eltText(firstChildElt(elt_to, "country"));
-
- tmp = {}
- tmp["from"] = (from_language, from_script, from_country)
- tmp["to"] = (to_language, to_script, to_country)
- result[i] = tmp;
- i += 1
- elt = nextSiblingElt(elt, "likelySubtag");
- return result
+ return dict((i, {'from': triplet(firstChildElt(elt, "from")),
+ 'to': triplet(firstChildElt(elt, "to"))})
+ for i, elt in enumerate(eachEltInGroup(doc.documentElement,
+ 'likelySubtags', 'likelySubtag')))
def fixedScriptName(name, dupes):
- name = name.replace(" ", "")
+ # Don't .capitalize() as some names are already camel-case (see enumdata.py):
+ name = ''.join(word[0].upper() + word[1:] for word in name.split())
if name[-6:] != "Script":
- name = name + "Script";
+ name = name + "Script"
if name in dupes:
sys.stderr.write("\n\n\nERROR: The script name '%s' is messy" % name)
- sys.exit(1);
+ sys.exit(1)
return name
def fixedCountryName(name, dupes):
@@ -161,8 +124,8 @@ def fixedLanguageName(name, dupes):
return name.replace(" ", "")
def findDupes(country_map, language_map):
- country_set = set([ v[0] for a, v in country_map.iteritems() ])
- language_set = set([ v[0] for a, v in language_map.iteritems() ])
+ country_set = set(v[0] for a, v in country_map.iteritems())
+ language_set = set(v[0] for a, v in language_map.iteritems())
return country_set & language_set
def languageNameToId(name, language_map):
@@ -183,108 +146,11 @@ def countryNameToId(name, country_map):
return key
return -1
-def convertFormat(format):
- result = ""
- i = 0
- while i < len(format):
- if format[i] == "'":
- result += "'"
- i += 1
- while i < len(format) and format[i] != "'":
- result += format[i]
- i += 1
- if i < len(format):
- result += "'"
- i += 1
- else:
- s = format[i:]
- if s.startswith("EEEE"):
- result += "dddd"
- i += 4
- elif s.startswith("EEE"):
- result += "ddd"
- i += 3
- elif s.startswith("a"):
- result += "AP"
- i += 1
- elif s.startswith("z"):
- result += "t"
- i += 1
- elif s.startswith("v"):
- i += 1
- else:
- result += format[i]
- i += 1
-
- return result
-
-def convertToQtDayOfWeek(firstDay):
- qtDayOfWeek = {"mon":1, "tue":2, "wed":3, "thu":4, "fri":5, "sat":6, "sun":7}
- return qtDayOfWeek[firstDay]
-
-def assertSingleChar(string):
- assert len(string) == 1, "This string is not allowed to be longer than 1 character"
- return string
-
-class Locale:
- def __init__(self, elt):
- self.language = eltText(firstChildElt(elt, "language"))
- self.languageEndonym = eltText(firstChildElt(elt, "languageEndonym"))
- self.script = eltText(firstChildElt(elt, "script"))
- self.country = eltText(firstChildElt(elt, "country"))
- self.countryEndonym = eltText(firstChildElt(elt, "countryEndonym"))
- self.decimal = int(eltText(firstChildElt(elt, "decimal")))
- self.group = int(eltText(firstChildElt(elt, "group")))
- self.listDelim = int(eltText(firstChildElt(elt, "list")))
- self.percent = int(eltText(firstChildElt(elt, "percent")))
- self.zero = int(eltText(firstChildElt(elt, "zero")))
- self.minus = int(eltText(firstChildElt(elt, "minus")))
- self.plus = int(eltText(firstChildElt(elt, "plus")))
- self.exp = int(eltText(firstChildElt(elt, "exp")))
- self.quotationStart = ord(assertSingleChar(eltText(firstChildElt(elt, "quotationStart"))))
- self.quotationEnd = ord(assertSingleChar(eltText(firstChildElt(elt, "quotationEnd"))))
- self.alternateQuotationStart = ord(assertSingleChar(eltText(firstChildElt(elt, "alternateQuotationStart"))))
- self.alternateQuotationEnd = ord(assertSingleChar(eltText(firstChildElt(elt, "alternateQuotationEnd"))))
- self.listPatternPartStart = eltText(firstChildElt(elt, "listPatternPartStart"))
- self.listPatternPartMiddle = eltText(firstChildElt(elt, "listPatternPartMiddle"))
- self.listPatternPartEnd = eltText(firstChildElt(elt, "listPatternPartEnd"))
- self.listPatternPartTwo = eltText(firstChildElt(elt, "listPatternPartTwo"))
- self.am = eltText(firstChildElt(elt, "am"))
- self.pm = eltText(firstChildElt(elt, "pm"))
- self.firstDayOfWeek = convertToQtDayOfWeek(eltText(firstChildElt(elt, "firstDayOfWeek")))
- self.weekendStart = convertToQtDayOfWeek(eltText(firstChildElt(elt, "weekendStart")))
- self.weekendEnd = convertToQtDayOfWeek(eltText(firstChildElt(elt, "weekendEnd")))
- self.longDateFormat = convertFormat(eltText(firstChildElt(elt, "longDateFormat")))
- self.shortDateFormat = convertFormat(eltText(firstChildElt(elt, "shortDateFormat")))
- self.longTimeFormat = convertFormat(eltText(firstChildElt(elt, "longTimeFormat")))
- self.shortTimeFormat = convertFormat(eltText(firstChildElt(elt, "shortTimeFormat")))
- self.standaloneLongMonths = eltText(firstChildElt(elt, "standaloneLongMonths"))
- self.standaloneShortMonths = eltText(firstChildElt(elt, "standaloneShortMonths"))
- self.standaloneNarrowMonths = eltText(firstChildElt(elt, "standaloneNarrowMonths"))
- self.longMonths = eltText(firstChildElt(elt, "longMonths"))
- self.shortMonths = eltText(firstChildElt(elt, "shortMonths"))
- self.narrowMonths = eltText(firstChildElt(elt, "narrowMonths"))
- self.standaloneLongDays = eltText(firstChildElt(elt, "standaloneLongDays"))
- self.standaloneShortDays = eltText(firstChildElt(elt, "standaloneShortDays"))
- self.standaloneNarrowDays = eltText(firstChildElt(elt, "standaloneNarrowDays"))
- self.longDays = eltText(firstChildElt(elt, "longDays"))
- self.shortDays = eltText(firstChildElt(elt, "shortDays"))
- self.narrowDays = eltText(firstChildElt(elt, "narrowDays"))
- self.currencyIsoCode = eltText(firstChildElt(elt, "currencyIsoCode"))
- self.currencySymbol = eltText(firstChildElt(elt, "currencySymbol"))
- self.currencyDisplayName = eltText(firstChildElt(elt, "currencyDisplayName"))
- self.currencyDigits = int(eltText(firstChildElt(elt, "currencyDigits")))
- self.currencyRounding = int(eltText(firstChildElt(elt, "currencyRounding")))
- self.currencyFormat = eltText(firstChildElt(elt, "currencyFormat"))
- self.currencyNegativeFormat = eltText(firstChildElt(elt, "currencyNegativeFormat"))
-
def loadLocaleMap(doc, language_map, script_map, country_map, likely_subtags_map):
result = {}
- locale_list_elt = firstChildElt(doc.documentElement, "localeList")
- locale_elt = firstChildElt(locale_list_elt, "locale")
- while locale_elt:
- locale = Locale(locale_elt)
+ for locale_elt in eachEltInGroup(doc.documentElement, "localeList", "locale"):
+ locale = Locale.fromXmlData(lambda k: firstChildText(locale_elt, k))
language_id = languageNameToId(locale.language, language_map)
if language_id == -1:
sys.stderr.write("Cannot find a language id for '%s'\n" % locale.language)
@@ -318,8 +184,6 @@ def loadLocaleMap(doc, language_map, script_map, country_map, likely_subtags_map
result[(language_id, script_id, country_id)] = locale
- locale_elt = nextSiblingElt(locale_elt, "locale")
-
return result
def compareLocaleKeys(key1, key2):
@@ -385,9 +249,10 @@ class StringDataToken:
return " %d,%d " % (self.index, self.length)
class StringData:
- def __init__(self):
+ def __init__(self, name):
self.data = []
self.hash = {}
+ self.name = name
def append(self, s):
if s in self.hash:
return self.hash[s]
@@ -436,25 +301,24 @@ def escapedString(s):
line += "\\x%02x" % (ord(c))
need_escape = True
if len(line) > 80:
- result = result + "\n" + "\"" + line + "\""
+ result = result + "\n" + '"' + line + '"'
line = ""
line += "\\0"
- result = result + "\n" + "\"" + line + "\""
+ result = result + "\n" + '"' + line + '"'
if result[0] == "\n":
result = result[1:]
return result
def printEscapedString(s):
- print escapedString(s);
-
+ print escapedString(s)
def currencyIsoCodeData(s):
if s:
- return ",".join(map(lambda x: str(ord(x)), s))
- return "0,0,0"
+ return '{' + ",".join(str(ord(x)) for x in s) + '}'
+ return "{0,0,0}"
def usage():
- print "Usage: qlocalexml2cpp.py <path-to-locale.xml> <path-to-qt-src-tree>"
+ print "Usage: qlocalexml2cpp.py <path-to-locale.xml> <path-to-qtbase-src-tree>"
sys.exit(1)
GENERATED_BLOCK_START = "// GENERATED PART STARTS HERE\n"
@@ -467,13 +331,9 @@ def main():
localexml = sys.argv[1]
qtsrcdir = sys.argv[2]
- if not os.path.exists(qtsrcdir) or not os.path.exists(qtsrcdir):
- usage()
- if not os.path.isfile(qtsrcdir + "/src/corelib/tools/qlocale_data_p.h"):
- usage()
- if not os.path.isfile(qtsrcdir + "/src/corelib/tools/qlocale.h"):
- usage()
- if not os.path.isfile(qtsrcdir + "/src/corelib/tools/qlocale.qdoc"):
+ if not (os.path.isdir(qtsrcdir)
+ and all(os.path.isfile(os.path.join(qtsrcdir, 'src', 'corelib', 'tools', leaf))
+ for leaf in ('qlocale_data_p.h', 'qlocale.h', 'qlocale.qdoc'))):
usage()
(data_temp_file, data_temp_file_path) = tempfile.mkstemp("qlocale_data_p", dir=qtsrcdir)
@@ -486,9 +346,9 @@ def main():
data_temp_file.write(GENERATED_BLOCK_START)
doc = xml.dom.minidom.parse(localexml)
- language_map = loadLanguageMap(doc)
- script_map = loadScriptMap(doc)
- country_map = loadCountryMap(doc)
+ language_map = loadMap(doc, 'language')
+ script_map = loadMap(doc, 'script')
+ country_map = loadMap(doc, 'country')
likely_subtags_map = loadLikelySubtagsMap(doc)
default_map = {}
for key in likely_subtags_map.keys():
@@ -498,19 +358,21 @@ def main():
locale_map = loadLocaleMap(doc, language_map, script_map, country_map, likely_subtags_map)
dupes = findDupes(language_map, country_map)
- cldr_version = eltText(firstChildElt(doc.documentElement, "version"))
+ cldr_version = firstChildText(doc.documentElement, "version")
- data_temp_file.write("\n\
-/*\n\
- This part of the file was generated on %s from the\n\
- Common Locale Data Repository v%s\n\
-\n\
- http://www.unicode.org/cldr/\n\
-\n\
- Do not change it, instead edit CLDR data and regenerate this file using\n\
- cldr2qlocalexml.py and qlocalexml2cpp.py.\n\
-*/\n\n\n\
-" % (str(datetime.date.today()), cldr_version) )
+ data_temp_file.write("""
+/*
+ This part of the file was generated on %s from the
+ Common Locale Data Repository v%s
+
+ http://www.unicode.org/cldr/
+
+ Do not edit this section: instead regenerate it using
+ cldr2qlocalexml.py and qlocalexml2cpp.py on updated (or
+ edited) CLDR data; see qtbase/util/local_database/.
+*/
+
+""" % (str(datetime.date.today()), cldr_version) )
# Likely subtags map
data_temp_file.write("static const QLocaleId likely_subtags[] = {\n")
@@ -574,34 +436,116 @@ def main():
index += count
data_temp_file.write("%6d, // %s\n" % (i, language_map[key][0]))
data_temp_file.write(" 0 // trailing 0\n")
- data_temp_file.write("};\n")
-
- data_temp_file.write("\n")
-
- list_pattern_part_data = StringData()
- date_format_data = StringData()
- time_format_data = StringData()
- months_data = StringData()
- days_data = StringData()
- am_data = StringData()
- pm_data = StringData()
- currency_symbol_data = StringData()
- currency_display_name_data = StringData()
- currency_format_data = StringData()
- endonyms_data = StringData()
+ data_temp_file.write("};\n\n")
+
+ list_pattern_part_data = StringData('list_pattern_part_data')
+ date_format_data = StringData('date_format_data')
+ time_format_data = StringData('time_format_data')
+ months_data = StringData('months_data')
+ days_data = StringData('days_data')
+ am_data = StringData('am_data')
+ pm_data = StringData('pm_data')
+ byte_unit_data = StringData('byte_unit_data')
+ currency_symbol_data = StringData('currency_symbol_data')
+ currency_display_name_data = StringData('currency_display_name_data')
+ currency_format_data = StringData('currency_format_data')
+ endonyms_data = StringData('endonyms_data')
# Locale data
data_temp_file.write("static const QLocaleData locale_data[] = {\n")
- data_temp_file.write("// lang script terr dec group list prcnt zero minus plus exp quotStart quotEnd altQuotStart altQuotEnd lpStart lpMid lpEnd lpTwo sDtFmt lDtFmt sTmFmt lTmFmt ssMonth slMonth sMonth lMonth sDays lDays am,len pm,len\n")
+ # Table headings: keep each label centred in its field, matching line_format:
+ data_temp_file.write(' // '
+ # Width 6 + comma:
+ + ' lang ' # IDs
+ + 'script '
+ + ' terr '
+ + ' dec ' # Numeric punctuation:
+ + ' group '
+ + ' list ' # List delimiter
+ + ' prcnt ' # Arithmetic symbols:
+ + ' zero '
+ + ' minus '
+ + ' plus '
+ + ' exp '
+ # Width 8 + comma - to make space for these wide labels !
+ + ' quotOpn ' # Quotation marks
+ + ' quotEnd '
+ + 'altQtOpn '
+ + 'altQtEnd '
+ # Width 11 + comma:
+ + ' lpStart ' # List pattern
+ + ' lpMid '
+ + ' lpEnd '
+ + ' lpTwo '
+ + ' sDtFmt ' # Date format
+ + ' lDtFmt '
+ + ' sTmFmt ' # Time format
+ + ' lTmFmt '
+ + ' ssMonth ' # Months
+ + ' slMonth '
+ + ' snMonth '
+ + ' sMonth '
+ + ' lMonth '
+ + ' nMonth '
+ + ' ssDays ' # Days
+ + ' slDays '
+ + ' snDays '
+ + ' sDays '
+ + ' lDays '
+ + ' nDays '
+ + ' am ' # am/pm indicators
+ + ' pm '
+ # Width 8 + comma
+ + ' byte '
+ + ' siQuant '
+ + 'iecQuant '
+ # Width 8+4 + comma
+ + ' currISO '
+ # Width 11 + comma:
+ + ' currSym ' # Currency formatting:
+ + ' currDsply '
+ + ' currFmt '
+ + ' currFmtNeg '
+ + ' endoLang ' # Name of language in itself, and of country:
+ + ' endoCntry '
+ # Width 6 + comma:
+ + 'curDgt ' # Currency number representation:
+ + 'curRnd '
+ + 'dow1st ' # First day of week
+ + ' wknd+ ' # Week-end start/end days:
+ + ' wknd-'
+ # No trailing space on last entry (be sure to
+ # pad before adding anything after it).
+ + '\n')
locale_keys = locale_map.keys()
compareLocaleKeys.default_map = default_map
compareLocaleKeys.locale_map = locale_map
locale_keys.sort(compareLocaleKeys)
+ line_format = (' { '
+ # Locale-identifier:
+ + '%6d,' * 3
+ # Numeric formats, list delimiter:
+ + '%6d,' * 8
+ # Quotation marks:
+ + '%8d,' * 4
+ # List patterns, date/time formats, month/day names, am/pm:
+ + '%11s,' * 22
+ # SI/IEC byte-unit abbreviations:
+ + '%8s,' * 3
+ # Currency ISO code:
+ + ' %10s, '
+ # Currency and endonyms
+ + '%11s,' * 6
+ # Currency formatting:
+ + '%6d,%6d'
+ # Day of week and week-end:
+ + ',%6d' * 3
+ + ' }')
for key in locale_keys:
l = locale_map[key]
- data_temp_file.write(" { %6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%6d,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s, {%s}, %s,%s,%s,%s,%s,%s,%6d,%6d,%6d,%6d,%6d }, // %s/%s/%s\n" \
+ data_temp_file.write(line_format
% (key[0], key[1], key[2],
l.decimal,
l.group,
@@ -637,6 +581,9 @@ def main():
days_data.append(l.narrowDays),
am_data.append(l.am),
pm_data.append(l.pm),
+ byte_unit_data.append(l.byte_unit),
+ byte_unit_data.append(l.byte_si_quantified),
+ byte_unit_data.append(l.byte_iec_quantified),
currencyIsoCodeData(l.currencyIsoCode),
currency_symbol_data.append(l.currencySymbol),
currency_display_name_data.append(l.currencyDisplayName),
@@ -648,97 +595,34 @@ def main():
l.currencyRounding,
l.firstDayOfWeek,
l.weekendStart,
- l.weekendEnd,
- l.language,
- l.script,
- l.country))
- data_temp_file.write(" { 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,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,0, 0,0, {0,0,0}, 0,0, 0,0, 0,0, 0,0, 0, 0, 0, 0, 0, 0,0, 0,0 } // trailing 0s\n")
+ l.weekendEnd)
+ + ", // %s/%s/%s\n" % (l.language, l.script, l.country))
+ data_temp_file.write(line_format # All zeros, matching the format:
+ % ( (0,) * (3 + 8 + 4) + ("0,0",) * (22 + 3)
+ + (currencyIsoCodeData(0),)
+ + ("0,0",) * 6 + (0,) * (2 + 3))
+ + " // trailing 0s\n")
data_temp_file.write("};\n")
- data_temp_file.write("\n")
-
- # List patterns data
- data_temp_file.write("static const ushort list_pattern_part_data[] = {\n")
- data_temp_file.write(wrap_list(list_pattern_part_data.data))
- data_temp_file.write("\n};\n")
-
- data_temp_file.write("\n")
-
- # Date format data
- data_temp_file.write("static const ushort date_format_data[] = {\n")
- data_temp_file.write(wrap_list(date_format_data.data))
- data_temp_file.write("\n};\n")
-
- data_temp_file.write("\n")
-
- # Time format data
- data_temp_file.write("static const ushort time_format_data[] = {\n")
- data_temp_file.write(wrap_list(time_format_data.data))
- data_temp_file.write("\n};\n")
-
- data_temp_file.write("\n")
-
- # Months data
- data_temp_file.write("static const ushort months_data[] = {\n")
- data_temp_file.write(wrap_list(months_data.data))
- data_temp_file.write("\n};\n")
-
- data_temp_file.write("\n")
-
- # Days data
- data_temp_file.write("static const ushort days_data[] = {\n")
- data_temp_file.write(wrap_list(days_data.data))
- data_temp_file.write("\n};\n")
-
- data_temp_file.write("\n")
-
- # AM data
- data_temp_file.write("static const ushort am_data[] = {\n")
- data_temp_file.write(wrap_list(am_data.data))
- data_temp_file.write("\n};\n")
-
- data_temp_file.write("\n")
-
- # PM data
- data_temp_file.write("static const ushort pm_data[] = {\n")
- data_temp_file.write(wrap_list(pm_data.data))
- data_temp_file.write("\n};\n")
-
- data_temp_file.write("\n")
-
- # Currency symbol data
- data_temp_file.write("static const ushort currency_symbol_data[] = {\n")
- data_temp_file.write(wrap_list(currency_symbol_data.data))
- data_temp_file.write("\n};\n")
-
- data_temp_file.write("\n")
-
- # Currency display name data
- data_temp_file.write("static const ushort currency_display_name_data[] = {\n")
- data_temp_file.write(wrap_list(currency_display_name_data.data))
- data_temp_file.write("\n};\n")
-
- data_temp_file.write("\n")
-
- # Currency format data
- data_temp_file.write("static const ushort currency_format_data[] = {\n")
- data_temp_file.write(wrap_list(currency_format_data.data))
- data_temp_file.write("\n};\n")
-
- # Endonyms data
- data_temp_file.write("static const ushort endonyms_data[] = {\n")
- data_temp_file.write(wrap_list(endonyms_data.data))
- data_temp_file.write("\n};\n")
+ # StringData tables:
+ for data in (list_pattern_part_data, date_format_data,
+ time_format_data, months_data, days_data,
+ byte_unit_data, am_data, pm_data, currency_symbol_data,
+ currency_display_name_data, currency_format_data,
+ endonyms_data):
+ data_temp_file.write("\nstatic const ushort %s[] = {\n" % data.name)
+ data_temp_file.write(wrap_list(data.data))
+ data_temp_file.write("\n};\n")
data_temp_file.write("\n")
# Language name list
data_temp_file.write("static const char language_name_list[] =\n")
- data_temp_file.write("\"Default\\0\"\n")
+ data_temp_file.write('"Default\\0"\n')
for key in language_map.keys():
if key == 0:
continue
- data_temp_file.write("\"" + language_map[key][0] + "\\0\"\n")
+ data_temp_file.write('"' + language_map[key][0] + '\\0"\n')
data_temp_file.write(";\n")
data_temp_file.write("\n")
@@ -759,11 +643,11 @@ def main():
# Script name list
data_temp_file.write("static const char script_name_list[] =\n")
- data_temp_file.write("\"Default\\0\"\n")
+ data_temp_file.write('"Default\\0"\n')
for key in script_map.keys():
if key == 0:
continue
- data_temp_file.write("\"" + script_map[key][0] + "\\0\"\n")
+ data_temp_file.write('"' + script_map[key][0] + '\\0"\n')
data_temp_file.write(";\n")
data_temp_file.write("\n")
@@ -784,11 +668,11 @@ def main():
# Country name list
data_temp_file.write("static const char country_name_list[] =\n")
- data_temp_file.write("\"Default\\0\"\n")
+ data_temp_file.write('"Default\\0"\n')
for key in country_map.keys():
if key == 0:
continue
- data_temp_file.write("\"" + country_map[key][0] + "\\0\"\n")
+ data_temp_file.write('"' + country_map[key][0] + '\\0"\n')
data_temp_file.write(";\n")
data_temp_file.write("\n")
@@ -813,7 +697,7 @@ def main():
code = language_map[key][1]
if len(code) == 2:
code += r"\0"
- data_temp_file.write("\"%2s\" // %s\n" % (code, language_map[key][0]))
+ data_temp_file.write('"%2s" // %s\n' % (code, language_map[key][0]))
data_temp_file.write(";\n")
data_temp_file.write("\n")
@@ -824,7 +708,7 @@ def main():
code = script_map[key][1]
for i in range(4 - len(code)):
code += "\\0"
- data_temp_file.write("\"%2s\" // %s\n" % (code, script_map[key][0]))
+ data_temp_file.write('"%2s" // %s\n' % (code, script_map[key][0]))
data_temp_file.write(";\n")
# Country code list
@@ -833,13 +717,13 @@ def main():
code = country_map[key][1]
if len(code) == 2:
code += "\\0"
- data_temp_file.write("\"%2s\" // %s\n" % (code, country_map[key][0]))
+ data_temp_file.write('"%2s" // %s\n' % (code, country_map[key][0]))
data_temp_file.write(";\n")
data_temp_file.write("\n")
data_temp_file.write(GENERATED_BLOCK_END)
s = qlocaledata_file.readline()
- # skip until end of the block
+ # skip until end of the old block
while s and s != GENERATED_BLOCK_END:
s = qlocaledata_file.readline()
@@ -931,7 +815,7 @@ def main():
qlocaleh_temp_file.write(GENERATED_BLOCK_END)
s = qlocaleh_file.readline()
- # skip until end of the block
+ # skip until end of the old block
while s and s != GENERATED_BLOCK_END:
s = qlocaleh_file.readline()